METHOD_BUFFERED 缓冲输入输出I/O

使用CTL_CODE宏定义来定义一个控制码:
#define MY_PORT CTL_CODE(\
    FILE_DEVICE_UNKNOWN, \
    0x801, \
    METHOD_BUFFERED, \
    FILE_ANY_ACCESS)
//向内核传递一个用户的等待事件
#define IOCTL_SET_EVENT CTL_CODE(\
    FILE_DEVICE_UNKNOWN, \
    0x802, \
    METHOD_BUFFERED, \
    FILE_ANY_ACCESS)

1.驱动层处理:

在 DriverEntry 入口函数中添加:

pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DDKDispatchDvCtl;

全局变量:

struct _MY_FUNCTION_INFO
{
    CHAR FunctionName[150];
    ULONG FunctionAddr;
};

HANDLE hUserEvent = NULL;
PKEVENT pEvent = NULL;
_MY_FUNCTION_INFO* InputBuffer = NULL;

DDKDispatchDvCtl 函数:

 1 #pragma PAGEDCODE
 2 NTSTATUS DDKDispatchDvCtl (
 3     IN PDEVICE_OBJECT pDevObj,
 4     IN PIRP pIrp)
 5 {
 6     KdPrint(("Entry DDKDispatchDvCtl\r\n"));
 7     NTSTATUS status;
 8     PIO_STACK_LOCATION io_stack;
 9     io_stack = IoGetCurrentIrpStackLocation(pIrp);
10 
11     //得到输入缓冲区大小
12     ULONG cbin = io_stack->Parameters.DeviceIoControl.InputBufferLength;
13     //得到输出缓冲区大小
14     ULONG cbout = io_stack->Parameters.DeviceIoControl.OutputBufferLength;
15     //得到IOCTL码
16     ULONG code = io_stack->Parameters.DeviceIoControl.IoControlCode;
17 
18     if (io_stack->MajorFunction == IRP_MJ_DEVICE_CONTROL)
19     {
20       switch (code)
21       {
22         case IOCTL_SET_EVENT:
23           //把传递进来的用户层等待事件取出来
24           hUserEvent = *(HANDLE *)pIrp->AssociatedIrp.SystemBuffer;
25 
26           //将用户层事件转化为内核等待对象
27           status = ObReferenceObjectByHandle(hUserEvent, EVENT_MODIFY_STATE,
28             *ExEventObjectType, KernelMode, (PVOID*)&pEvent, NULL);
29 
30           KdPrint(("[IOCTL_SET_EVENT] status = %d\n", status));//status应该为0才对
31 
32           ObDereferenceObject(pEvent);
33           break;
34         case INITIALIZE_TO_R0_PORT:
35         {
         //METHOD_BUFFERED 方式: 输入输出都共用一个缓冲区
36   //得到 InputBuffer 37   InputBuffer = (_MY_FUNCTION_INFO*)pIrp->AssociatedIrp.SystemBuffer; 38   //获得从应用层传递的信息 39   KdPrint(("[INITIALIZE_TO_R0_PORT] Initialize Name : %s", InputBuffer->FunctionName)); 40   KdPrint(("[INITIALIZE_TO_R0_PORT] Initialize Addr : 0x%08x", InputBuffer->FunctionAddr)); 41 42   //将需要输出到应用层的信息复制到缓冲区, 系统会自动将缓冲区的内容复制到应用层的输出Buffer 43   CHAR* OutputChar = (CHAR*)pIrp->AssociatedIrp.SystemBuffer;
44   strcpy(OutputChar, "DbgkpMarkProcessPeb"); 45   //激活Event事件 46   KeSetEvent(pEvent, IO_NO_INCREMENT, FALSE); 47 48        //pIrp->IoStatus.Information 设置为 输出缓冲区大小 cbout, METHOD_OUT_DIRECT模式不用设置,设置为0就行了 49   pIrp->IoStatus.Information = cbout; 50   pIrp->IoStatus.Status = STATUS_SUCCESS; 51   KdPrint(("[INITIALIZE_TO_R0_PORT] Success.\r\n")); 52 } 53 break; 54 default: 55 pIrp->IoStatus.Information = 0; 56 pIrp->IoStatus.Status = STATUS_INVALID_PARAMETER; 57 break; 58 } 59 } 60 IoCompleteRequest(pIrp, IO_NO_INCREMENT); 61 return pIrp->IoStatus.Status; 62 }

2.用户层处理:

全局变量:

_MY_FUNCTION_INFO myOutputFuncInfo;
CHAR myInputFuncName[150] = {0};
HANDLE hDevice = NULL;
 1 void myFunction()
 2 {
 3     BOOL ret = FALSE;
 4     DWORD ret_length = 0;
 5     hDevice = CreateFile(
 6         L"\\\\.\\Legend1900",        //Legend1900为自定义设备名
 7         GENERIC_READ | GENERIC_WRITE,
 8         0,
 9         0,
10         OPEN_EXISTING,
11         FILE_ATTRIBUTE_NORMAL,
12         0);
13     if (hDevice == INVALID_HANDLE_VALUE)
14     {
15         OutputDebugString(L"Open Device Fail");
16         return FALSE;
17     }
18 
19     //
20     //    1. 创建用户层的等待事件,传入内核 
21     //    2. 创建线程,用于监测内核事件的到来
22     //
23     HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
24     HANDLE hThread = (HANDLE)_beginthreadex(
25         NULL,
26         0,
27         R3ToR0ThreadProc,    //自定义函数
28         hEvent,          //自定义函数的参数
29         0,
30         NULL);
31     
32     //先将用户层的等待 Event 传入内核
33     DeviceIoControl(
34         hDevice,
35         IOCTL_SET_EVENT,
36         &hEvent,
37         sizeof(hEvent),
38         NULL,
39         0,
40         &ret_length,
41         NULL);
42 
43     strcpy_s(myOutputFuncInfo.FunctionName, "我是传奇.");
44     myOutputFuncInfo.FunctionAddr = 0xFFFFFFFF;
45     ret = DeviceIoControl(
46         hDevice,
47         INITIALIZE_TO_R0_PORT,
48         &myOutputFuncInfo,
49         sizeof(_MY_FUNCTION_INFO),
50         &myInputFuncName,
51         150,
52         &ret_length,
53         NULL);
54     if (!ret)
55     {
56         OutputDebugString(L"DeviceIoControl Fail");
57         return FALSE;
58     }
59 }

 

 1 //通信线程
 2 UINT _stdcall R3ToR0ThreadProc(LPVOID para)
 3 {
 4     BOOL ret = FALSE;
 5     TCHAR FuncName[150] = {0};
 6      while (1)
 7     {
 8         WaitForSingleObject((HANDLE)para, INFINITE);
 9         ResetEvent((HANDLE)para);
10  
11          OutputDebugStringA("In [R3ToR0ThreadProc]");
12          //将内核文件名(不包含目录) 由char* 转 wchar_t*
13         MultiByteToWideChar(
14             CP_ACP,
15             0,
16             myInputFuncName,
17             strlen(myInputFuncName) + 1,
18             FuncName,
19             150);
20          OutputDebugString(FuncName);
21     }
22 
23     return 0;
24 }

 

输出打印信息为:

 

posted @ 2015-01-19 22:40  银河彼岸  阅读(1050)  评论(0编辑  收藏  举报