2011-08-23 105 views
3

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

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结构的问题吗?请帮我找到解决办法。谢谢..

+2

您的帖子中没有包含足够的信息来解决这个问题。调试驱动程序,看看里面发生了什么。或者将KdPrint语句添加到驱动程序,执行它并在DbgView程序中查看调试输出。 –

+0

好吧..我是新来的司机...你能帮我告诉我如何调试驱动程序? – Neha

+0

看看这个MSDN部分,它可能会帮助:[驱动程序开发工具](http://msdn.microsoft.com/en-us/library/ff545440(v = VS.85).aspx),特别是 - “调试驱动程序的工具“和”验证驱动程序的工具“。 – Eugene

回答

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 
+0

缓冲区较小是因为我得到OutputBufferLength = 12和sizeof(PROCESS_CALLBACK_INFO)= 24的问题。结构如下typedef struct _ProcessCallbackInfo { HANDLE hParentId; HANDLE hProcessId; BOOLEAN bCreate; } PROCESS_CALLBACK_INFO – Neha

+0

如何解决此问题。为什么outputBufferLenght在64位上更小? – Neha

+0

@neha:问题可能是因为编译驱动程序和客户端时,或者因为您使用的是32位客户端而有不同的默认值。至于OutputBufferLength,我猜想一个在32位系统上是一样的。 – rjnilsson

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位编译时具有相同的大小),并且结构填充相同。

+0

非常感谢..我会试试这个... – Neha

+0

我尝试了你建议的方式...并发现OutputBufferLength = 12和sizeof(PROCESS_CALLBACK_INFO)= 24。这就是为什么if循环无法执行。我如何解决这个问题?是因为我在64位? – Neha

1

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

outputBufferLength取决于您在调用以下函数时传递的结构体的大小。

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

因此,callbackInfo大小为12,因此outputBufferLength = 12。结构callbackInfo具有DWORD数据块,对于64位,该数据块必须是DWORD64。当我改变结构中成员的数据类型,然后调用DeviceIOControl函数时,驱动程序工作得很好,outputBufferLength = 24,如预期的那样。感谢你的帮助。

相关问题