IO设备控制操作
除了 讀設備和 ?寫設備 外 ?還可以有一個API DeviceIoControl 操作設備 創建一個IRP_MJ_DEVICE_CONTROL 類型的IRP?
DeviceIoControlhDevice Long,設備句柄 dwIoControlCode Long,應用程序調用驅動程序的控制命令,就是IOCTL_XXX IOCTLs。 lpInBuffer Any,應用程序傳遞給驅動程序的數據緩沖區地址。 nInBufferSize Long,應用程序傳遞給驅動程序的數據緩沖區大小,字節數。 lpOutBuffer Any,驅動程序返回給應用程序的數據緩沖區地址。 nOutBufferSize Long,驅動程序返回給應用程序的數據緩沖區大小,字節數。 lpBytesReturned Long,驅動程序實際返回給應用程序的數據字節數地址。 lpOverlapped OVERLAPPED,這個結構用于重疊操作。針對同步操作,請用ByVal As Long傳遞零值應用程序 源碼:
頭文件:
#ifndef IOCTLS_H #define IOCTLS_H#ifndef CTL_CODE#pragma message("CTL_CODE undefined. Include winioctl.h or wdm.h") #endif#define IOCTL_TEST1 CTL_CODE(\FILE_DEVICE_UNKNOWN, \0x800, \METHOD_BUFFERED, \FILE_ANY_ACCESS)#define IOCTL_TEST2 CTL_CODE(\FILE_DEVICE_UNKNOWN, \0x801, \METHOD_IN_DIRECT, \FILE_ANY_ACCESS)#define IOCTL_TEST3 CTL_CODE(\FILE_DEVICE_UNKNOWN, \0x802, \METHOD_NEITHER, \FILE_ANY_ACCESS)#endifCPP文件: #include <windows.h> #include <stdio.h> //使用CTL_CODE必須加入winioctl.h #include <winioctl.h> #include "..\NT_Driver\Ioctls.h"int main() {HANDLE hDevice = CreateFile("\\\\.\\HelloDDK",GENERIC_READ | GENERIC_WRITE,0, // share mode noneNULL, // no securityOPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL ); // no templateif (hDevice == INVALID_HANDLE_VALUE){printf("Failed to obtain file handle to device: ""%s with Win32 error code: %d\n","MyWDMDevice", GetLastError() );return 1;}UCHAR InputBuffer[10];UCHAR OutputBuffer[10];//將輸入緩沖區全部置成0XBBmemset(InputBuffer,0xBB,10);DWORD dwOutput;//輸入緩沖區作為輸入,輸出緩沖區作為輸出BOOL bRet;//緩沖內存模式 IOCTLbRet = DeviceIoControl(hDevice, IOCTL_TEST1, InputBuffer, 10, &OutputBuffer, 10, &dwOutput, NULL);//InputBuffer 為輸入緩沖區 OutputBuffer為接收的緩沖區if (bRet){printf("Output buffer:%d bytes\n",dwOutput);for (int i=0;i<(int)dwOutput;i++){printf("%02X ",OutputBuffer[i]);}printf("\n");}//直接內存模式 IOCTLbRet = DeviceIoControl(hDevice, IOCTL_TEST2, InputBuffer, 10, &OutputBuffer, 10, &dwOutput, NULL);if (bRet){printf("Output buffer:%d bytes\n",dwOutput);for (int i=0;i<(int)dwOutput;i++){printf("%02X ",OutputBuffer[i]);}printf("\n");}//其他內存模式 IOCTLbRet = DeviceIoControl(hDevice, IOCTL_TEST3, InputBuffer, 10, &OutputBuffer, 10, &dwOutput, NULL);if (bRet){printf("Output buffer:%d bytes\n",dwOutput);for (int i=0;i<(int)dwOutput;i++){printf("%02X ",OutputBuffer[i]);}printf("\n");}CloseHandle(hDevice);return 0; }內核模式 ?顯示 ?應用程序字符串: #pragma PAGEDCODE NTSTATUS HelloDDKDeviceIOControl(IN PDEVICE_OBJECT pDevObj,IN PIRP pIrp) {NTSTATUS status = STATUS_SUCCESS;KdPrint(("Enter HelloDDKDeviceIOControl\n"));//得到當前堆棧PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp);//得到輸入緩沖區大小ULONG cbin = stack->Parameters.DeviceIoControl.InputBufferLength;//得到輸出緩沖區大小ULONG cbout = stack->Parameters.DeviceIoControl.OutputBufferLength;//得到IOCTL碼ULONG code = stack->Parameters.DeviceIoControl.IoControlCode;ULONG info = 0;switch (code){ // process requestcase IOCTL_TEST1:{KdPrint(("IOCTL_TEST1\n"));//緩沖區方式IOCTL//顯示輸入緩沖區數據UCHAR* InputBuffer = (UCHAR*)pIrp->AssociatedIrp.SystemBuffer;for (ULONG i=0;i<cbin;i++){KdPrint(("%X\n",InputBuffer[i]));}//操作輸出緩沖區UCHAR* OutputBuffer = (UCHAR*)pIrp->AssociatedIrp.SystemBuffer;memset(OutputBuffer,0xAA,cbout);//設置實際操作輸出緩沖區長度info = cbout;break;}case IOCTL_TEST2:{KdPrint(("IOCTL_TEST2\n"));//緩沖區方式IOCTL//顯示輸入緩沖區數據//緩沖區方式IOCTL//顯示輸入緩沖區數據UCHAR* InputBuffer = (UCHAR*)pIrp->AssociatedIrp.SystemBuffer;for (ULONG i=0;i<cbin;i++){KdPrint(("%X\n",InputBuffer[i]));}//pIrp->MdlAddress為DeviceIoControl輸出緩沖區地址相同KdPrint(("User Address:0X%08X\n",MmGetMdlVirtualAddress(pIrp->MdlAddress)));UCHAR* OutputBuffer = (UCHAR*)MmGetSystemAddressForMdlSafe(pIrp->MdlAddress,NormalPagePriority);//InputBuffer被映射到內核模式下的內存地址,必定在0X80000000-0XFFFFFFFF之間memset(OutputBuffer,0xAA,cbout);//設置實際操作輸出緩沖區長度info = cbout;break;}case IOCTL_TEST3:{KdPrint(("IOCTL_TEST3\n"));//緩沖區方式IOCTL//顯示輸入緩沖區數據UCHAR* UserInputBuffer = (UCHAR*)stack->Parameters.DeviceIoControl.Type3InputBuffer;KdPrint(("UserInputBuffer:0X%0X\n",UserInputBuffer));//得到用戶模式地址PVOID UserOutputBuffer = pIrp->UserBuffer;KdPrint(("UserOutputBuffer:0X%0X\n",UserOutputBuffer));__try{KdPrint(("Enter __try block\n"));//判斷指針是否可讀ProbeForRead(UserInputBuffer,cbin,4);//顯示輸入緩沖區內容for (ULONG i=0;i<cbin;i++){KdPrint(("%X\n",UserInputBuffer[i]));}//判斷指針是否可寫ProbeForWrite(UserOutputBuffer,cbout,4);//操作輸出緩沖區memset(UserOutputBuffer,0xAA,cbout);//由于在上面引發異常,所以以后語句不會被執行!info = cbout;KdPrint(("Leave __try block\n"));}__except(EXCEPTION_EXECUTE_HANDLER){KdPrint(("Catch the exception\n"));KdPrint(("The program will keep going\n"));status = STATUS_UNSUCCESSFUL;}info = cbout;break;}default:status = STATUS_INVALID_VARIANT;}// 完成IRPpIrp->IoStatus.Status = status;pIrp->IoStatus.Information = info; // bytes xferedIoCompleteRequest( pIrp, IO_NO_INCREMENT );KdPrint(("Leave HelloDDKDeviceIOControl\n"));return status; }轉載于:https://www.cnblogs.com/zcc1414/p/3982508.html
總結
- 上一篇: 重装系统后键盘部份不能用是怎么回事 电脑
- 下一篇: 电脑开机后闪屏是怎么回事 电脑开机后屏幕