64位驱动程序

时间:2011-08-23 05:56:51

标签: c++ winapi device-driver

我有一个在32位上运行良好的驱动程序代码。在64位我编译它并进行数字签名。驱动程序加载但无法正常工作。驱动程序的主要功能是在回调中将进程创建和终止注册到我的程序。所以我有两个IOCTL工作。代码如下..

NTSTATUS DispatchIoctl(
    IN PDEVICE_OBJECT DeviceObject, 
    IN PIRP           Irp
    )

{

 NTSTATUS               ntStatus = STATUS_UNSUCCESSFUL;

PIO_STACK_LOCATION     irpStack  = IoGetCurrentIrpStackLocation(Irp);
PDEVICE_EXTENSION      extension = DeviceObject->DeviceExtension;
PPROCESS_CALLBACK_INFO pProcCallbackInfo;
//
// These IOCTL handlers are the set and get interfaces between
// the driver and the user mode app
//
switch(irpStack->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_PROCOBSRV_ACTIVATE_MONITORING:
    {
        ntStatus = ActivateMonitoringHanlder( Irp );
        break;
    }
    case IOCTL_PROCOBSRV_GET_PROCINFO:
    {
        if (irpStack->Parameters.DeviceIoControl.OutputBufferLength >=                 sizeof(PROCESS_CALLBACK_INFO))
        {
        pProcCallbackInfo = Irp->AssociatedIrp.SystemBuffer;
        pProcCallbackInfo->hParentId  = extension->hParentId;
        pProcCallbackInfo->hProcessId = extension->hProcessId;
        pProcCallbackInfo->bCreate    = extension->bCreate;

        ntStatus = STATUS_SUCCESS;
        }
        break;
    }

    default:
        break;
}

Irp->IoStatus.Status = ntStatus;
//
// Set number of bytes to copy back to user-mode
//
if(ntStatus == STATUS_SUCCESS)
   Irp->IoStatus.Information = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
else
    Irp->IoStatus.Information = 0;

IoCompleteRequest(Irp, IO_NO_INCREMENT);
return ntStatus;

}

当我打电话

 bReturnCode = ::DeviceIoControl(
                hDriverFile,
                IOCTL_PROCOBSRV_ACTIVATE_MONITORING,
                &activateInfo, 
                sizeof(activateInfo),
                NULL, 
                0,
                &dwBytesReturned,
                NULL
                );

代码成功但我打电话

bReturnCode = ::DeviceIoControl(
        m_hDriverFile,
        IOCTL_PROCOBSRV_GET_PROCINFO,
        0, 
        0,
        &callbackInfo, sizeof(callbackInfo),
        &dwBytesReturned,
        &ov
        );

getLastError返回31.任何人都可以帮助我。这是64位IOCTL结构的问题吗?请帮我找到解决方案。感谢..

3 个答案:

答案 0 :(得分:2)

如果您没有驱动程序调试经验,请尝试使用跟踪来诊断此问题。在必要的所有位置将KdPrint行添加到代码中,例如:

case IOCTL_PROCOBSRV_GET_PROCINFO:     
{        
    KdPrint(("IOCTL_PROCOBSRV_GET_PROCINFO. OutputBufferLength = %d\n", irpStack->Parameters.DeviceIoControl.OutputBufferLength));
    KdPrint(("sizeof(PROCESS_CALLBACK_INFO) = %d\n", sizeof(PROCESS_CALLBACK_INFO)));

    if (irpStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(PROCESS_CALLBACK_INFO))         
    {
        pProcCallbackInfo = Irp->AssociatedIrp.SystemBuffer;         
        pProcCallbackInfo->hParentId  = extension->hParentId;         
        pProcCallbackInfo->hProcessId = extension->hProcessId;         
        pProcCallbackInfo->bCreate    = extension->bCreate; 

        KdPrint(("IOCTL_PROCOBSRV_GET_PROCINFO. STATUS_SUCCESS\n"));         
        ntStatus = STATUS_SUCCESS;         
    }         
    break;     
} 

这只是一个示例,将KdPrint行添加到所有地方以了解会发生什么。在已检查的配置中构建驱动程序,安装它并运行程序。请参阅DbgView程序中的KdPrint输出,并启用Caprure Kernel选项。

您可以使用DbgPrint而不是KdPrint,在这种情况下,它也可以在免费驱动程序配置中使用。

编辑:

如何定义PROCESS_CALLBACK_INFO?什么是调用驱动程序的客户端代码?客户端编译为32位还是64位?在客户端和驱动程序之间传递结构,确保它不包含与位数相关的字段(在32位和64位编译时具有相同的大小),并且结构填充是相同的。

答案 1 :(得分:1)

此处没有太多信息,但您可以随时检查编译的用户模式客户端和驱动程序在运行64位时自定义结构的大小是否相同。可能存在打包/对齐问题,可以通过使用#pragma pack(或编译器支持的任何内容)来修复结构。

作为一般规则,还尝试将状态代码设置为检测到的问题的更具体的值,例如如果检测到传递的缓冲区太小,则STATUS_BUFFER_TOO_SMALL。我怀疑在使用IOCTL_PROCOBSRV_GET_PROCINFO IOCTL时这不是实际问题,因为您回到Win32错误31,但它可以帮助客户解决他们的问题。

更新:由于差异实际上似乎与您的评论不匹配,请尝试用包装来包围结构定义,然后确保重新编译客户端和驱动程序。如果您使用的是Visual C ++编译器,请执行以下示例:

#pragma pack(push, 8) // Save current packing and set to 8-byte
typedef struct _PROCESS_CALLBACK_INFO
{
    // Whatever ...
} PROCESS_CALLBACK_INFO;
#pragma pack(pop)  // Restore previous packing

答案 2 :(得分:1)

我找到了答案。感谢调试。如前所述,outputBufferLength小于驱动程序失败的结构长度。

outputBufferLength会调用您在调用以下函数时传递的结构的大小。

bReturnCode = :: DeviceIoControl(         m_hDriverFile,         IOCTL_PROCOBSRV_GET_PROCINFO,         0,         0,         & callbackInfo,sizeof(callbackInfo),         &安培; dwBytesReturned,         &安培; OV         );

所以callbackInfo的大小是12,所以outputBufferLength = 12.结构callbackInfo有DWORD datamember,64位必须是DWORD64。当我更改结构中成员的数据类型然后调用DeviceIOControl函数时,驱动程序工作得很好,outputBufferLength是= 24,如预期的那样。谢谢你的帮助。