开发者

Driver on 64 bit

I have a driver code which works good on 32 bit. On 64 bit i compiled it and also digitally signed it. The driver loads but fails to work properly. The main functionality of the driver to to register process creation and termination to my program in call back. So i have two IOCTL working. The code is as follows..

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;

}

when i call

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

The code succeeds but when i call

bReturnCode = ::DeviceIoControl(
        m_hDriverFile,
        IOCTL_PROCOBSRV_GET_PROCINFO,
        0, 
        0,
        &callbackInfo, sizeof(callbackInfo),
        &开发者_JAVA百科dwBytesReturned,
        &ov
        );

getLastError returns 31. Can anyone help me with this. Is it a problem of IOCTL structure with 64 bit? Please help me find a solution to this. Thanks..


If you don't have driver debugging experience, try to diagnose this problem using trace. Add KdPrint lines to your code in all places where it is necessary, for example:

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;     
} 

This is just a sample, add KdPrint lines to all places to understand what happens. Build the driver in checked configuration, install it and run your program. See KdPrint output in DbgView program, with Caprure Kernel option enabled.

You can use DbgPrint instead of KdPrint, in this case it will work also in free driver configuration.

Edit:

How is PROCESS_CALLBACK_INFO defined? What is client code that calls the driver? Is client compiled as 32 or 64 bit? Passing a structure between client and driver, ensure that it doesn't contain bitness-dependent fields (has the same size when compiled both in 32 and 64 bit), and structure padding is the same.


Not too much information here, but you could always check that the size of your own defined structures are the same in the compiled user-mode client and the driver when running 64-bit. There might be packing/alignment issues that can be fixed by using #pragma pack (or whatever your compiler supports) for your structs.

As a general rule also try to set the status code to a more specific value on detected problems, such as e.g. STATUS_BUFFER_TOO_SMALL if you detect that a passed buffer is too small. I suspect that this isn't the actual issue here when using the IOCTL_PROCOBSRV_GET_PROCINFO IOCTL as you are getting back Win32 error 31, but it helps clients to troubleshoot their problems in general.

Update: As the differences actually seem to mismatch judging from your comments, try to surround the struct definitions with packing and then make sure to recompile both the client and driver. Example if you are using the Visual C++ compiler:

#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


I found the answer. Thanks to the debugging. As mention earlier the outputBufferLength was less than the structure length due to which the driver was failing.

The outputBufferLength depands on the size of the struct you pass while calling the following function..

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

So callbackInfo size was 12 so the outputBufferLength = 12. The structure callbackInfo has DWORD datamember which for 64 bit had to be DWORD64. When i changed the datatype of the member in the structure and then called the DeviceIOControl function , the driver worked great and the outputBufferLength was = 24 as expected. Thanks for all your help.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜