Драйвер на 64 бит - PullRequest
       4

Драйвер на 64 бит

3 голосов
/ 23 августа 2011

У меня есть код драйвера, который хорошо работает на 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. Может кто-нибудь помочь мне с этим. Это проблема структуры IOCTL с 64 бит? Пожалуйста, помогите мне найти решение этой проблемы. Спасибо ..

Ответы [ 3 ]

2 голосов
/ 23 августа 2011

Если у вас нет опыта отладки драйверов, попробуйте диагностировать эту проблему с помощью трассировки.Добавьте строки 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 во все места, чтобы понять, что происходит.Соберите драйвер в проверенной конфигурации, установите его и запустите вашу программу.См. Вывод KdPrint в программе DbgView с включенной опцией ядра Caprure.

Вы можете использовать DbgPrint вместо KdPrint, в этом случае он также будет работать в свободной конфигурации драйвера.

Редактировать:

Как определяется PROCESS_CALLBACK_INFO?Что такое код клиента, который вызывает драйвер?Клиент скомпилирован как 32 или 64 бит?Передавая структуру между клиентом и драйвером, убедитесь, что она не содержит бит-зависимых полей (имеет одинаковый размер при компиляции как в 32-, так и в 64-битных системах), а заполнение структуры одинаково.

1 голос
/ 24 августа 2011

Я нашел ответ. Благодаря отладке. Как уже упоминалось ранее, 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, как и ожидалось. Спасибо за вашу помощь.

1 голос
/ 23 августа 2011

Здесь не слишком много информации, но вы всегда можете проверить, что размер ваших собственных определенных структур одинаков в скомпилированном клиенте пользовательского режима и в драйвере при работе в 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
...