C++ 带DWORD的设备控制

C++ 带DWORD的设备控制,c++,deviceiocontrol,C++,Deviceiocontrol,我的操作系统是Win7 64位。我试图通过DeviceIoControl将变量的值而不是进程id的地址DWORD传递给我的驱动程序。我试过好几次了,但只得到了蓝色荧光屏或错误代码998 在usermode端,我确保hDevice有效,CTL_代码如下所示: #define SENDPID CTL_CODE(FILE_DEVICE_UNKNOWN, 0x808, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA) 然后我就这样做了: DWORD

我的操作系统是Win7 64位。我试图通过DeviceIoControl将变量的值而不是进程id的地址DWORD传递给我的驱动程序。我试过好几次了,但只得到了蓝色荧光屏或错误代码998

在usermode端,我确保hDevice有效,CTL_代码如下所示:

#define SENDPID CTL_CODE(FILE_DEVICE_UNKNOWN, 0x808, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA)
然后我就这样做了:

DWORD pID = FindProcessName("someprocess.exe");
if (!pID) return false;
if (!DeviceIoControl(hDevice, SENDPID, &pID, sizeof(pID), NULL, 0, &BytesIO, 0))
{
    cout << GetLastError() << endl;
    return false;
}
和我的IOCTL函数:

NTSTATUS IOCTL(PDEVICE_OBJECT Object, PIRP IRP)
{
PIO_STACK_LOCATION StackLocation = IoGetCurrentIrpStackLocation(IRP);
size_t size = 0;
DWORD pID = 0;

if (StackLocation->Parameters.DeviceIoControl.IoControlCode == SENDPID)
{
    pID = IRP->AssociatedIrp.SystemBuffer;
    size = sizeof(pID);
}

IRP->IoStatus.Status = STATUS_SUCCESS;
IRP->IoStatus.Information = size;
IofCompleteRequest(IRP, IO_NO_INCREMENT);
return(STATUS_SUCCESS);
}
如果有人能告诉我要更改什么,请告诉我:

在应用程序端,为什么FindProcessName返回的是DWORD*指针而不是DWORD值?或者,它是否真的返回了一个DWORD值,而您只是错误地将其类型转换为DWORD*指针

通过将pID定义为DWORD*指针,sizeofpID是传递给DeviceIoControl的错误值。它在32位上传递指针本身的大小4,在64位上传递8,而不是指向SizeOfWord的DWORD值的大小始终为4

如果pID是指向内存中DWORD的实指针,则需要使用sizeof*pID而不是sizeofpID。但是如果FindProcessName返回0呢?然后,您将向DeviceIoControl传递一个空指针,即使您告诉DeviceIoControl要传递它4个字节

如果尚未返回DWORD值而不是DWORD*指针,则应更改FindProcessName以返回DWORD值,然后使用&运算符将该DWORD的地址传递给DeviceIoControl,例如:

然后在内核端,在确认SystemBuffer至少包含4个字节后,只需键入cast the SystemBuffer以访问该值,当然:

NTSTATUS IOCTL(PDEVICE_OBJECT Object, PIRP IRP)
{
    PIO_STACK_LOCATION StackLocation = IoGetCurrentIrpStackLocation(IRP);
    size_t size = 0;
    DWORD pID = 0;

    if ((StackLocation->Parameters.DeviceIoControl.IoControlCode == SENDPID) &&
        (StackLocation->Parameters.DeviceIoControl.InputBufferLength >= sizeof(pID)))
    {
        pID = *(DWORD*)(IRP->AssociatedIrp.SystemBuffer);
        size = sizeof(pID);
    }

    IRP->IoStatus.Status = STATUS_SUCCESS;
    IRP->IoStatus.Information = size;
    IofCompleteRequest(IRP, IO_NO_INCREMENT);

    return STATUS_SUCCESS;
}

谢谢你的高级回答。FindProcessName实际上返回了一个DWORD。由于我一直在四处寻找,我想我已经尝试了你的版本和BOSD,但我明天会尝试一下。那么你可能没有正确处理IRP缓冲区。请回答您的问题,以显示处理SENDPID的实际驱动程序代码。@MarcelMar:您更改了应用程序代码,将pID定义为DWORD good,但您正在通过值将其传递给DeviceIoControl的lpInBuffer参数,该参数将不会编译,因为该参数需要一个void*指针。您需要通过&pID。此外,您的应用程序代码正在使用SENDPID,但您的驱动程序代码正在寻找PUSHPID,它需要指向IDCONTAINER结构的指针,而不是DWORD。IDCONTAINER的定义是什么?为什么要用PUSHPID而不是SENDPID?哎呀,对不起,我试了一些东西,复制和粘贴都弄糟了,这是最新的代码。@MarcelMar:现在传递pID看起来还可以。但是你使用SystemBuffer是错误的。正如我在回答中所说,您的驱动程序代码需要使用pID=*DWORD*IRP->AssociatedIrp.SystemBuffer;相反
DWORD pID = FindProcessName("DayZ.exe");
if (!DeviceIoControl(hDevice, SENDPID, &pID, sizeof(pID), NULL, 0, &BytesIO, 0))
NTSTATUS IOCTL(PDEVICE_OBJECT Object, PIRP IRP)
{
    PIO_STACK_LOCATION StackLocation = IoGetCurrentIrpStackLocation(IRP);
    size_t size = 0;
    DWORD pID = 0;

    if ((StackLocation->Parameters.DeviceIoControl.IoControlCode == SENDPID) &&
        (StackLocation->Parameters.DeviceIoControl.InputBufferLength >= sizeof(pID)))
    {
        pID = *(DWORD*)(IRP->AssociatedIrp.SystemBuffer);
        size = sizeof(pID);
    }

    IRP->IoStatus.Status = STATUS_SUCCESS;
    IRP->IoStatus.Information = size;
    IofCompleteRequest(IRP, IO_NO_INCREMENT);

    return STATUS_SUCCESS;
}