DeviceIOControl () выдает ошибку 50 - PullRequest
       20

DeviceIOControl () выдает ошибку 50

0 голосов
/ 15 октября 2010

Я очень новичок в общении с драйверами устройств Windows.

A) Мне нужно связаться со сторонним драйвером.Я вижу, что CreateFile() принимает как имя устройства (например, \\\\.\\DeviceName), так и я могу назвать полное имя файла (например, \\\\.\\C:\\MyPath\\DriverName.sys).Какой самый лучший вариант?Зачем?Оба работают одинаково?

B) Я вижу, что у многих драйверов устройств есть два имени, например:

SymbolicLink "\GLOBAL??\VirtualSerial"
Destination "\Device\VrSerialrs232"

Если я попытаюсь открыть, например, открыть VrSerialrs232 с помощью CreateFile() это не удается.Итак, почему используется VrSerialrs232, если мне всегда нужно вызывать SymbolicLink(VirtualSerial)?

C) Я установил монитор DeviceIOControl, чтобы проверить, почему мой код не работает с Error 50 (Запросне поддерживается) и я не могу понять, почему.

Выход DeviceIOControl монитора здесь

Те из test.exe - мой код, другое (защищенное) - исходное приложение, вызывающее то же самоеустройство.

Мой код такой:

#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include <strsafe.h>

void ErrorExit(LPTSTR lpszFunction){ 
    // Retrieve the system error message for the last-error code

    LPVOID lpMsgBuf;
    LPVOID lpDisplayBuf;
    DWORD dw = GetLastError(); 

    FormatMessage(
        FORMAT_MESSAGE_ALLOCATE_BUFFER | 
        FORMAT_MESSAGE_FROM_SYSTEM |
        FORMAT_MESSAGE_IGNORE_INSERTS,
        NULL,
        dw,
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        (LPTSTR) &lpMsgBuf,
        0, NULL );

    // Display the error message and exit the process

    lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, 
        (lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR)); 
    StringCchPrintf((LPTSTR)lpDisplayBuf, 
        LocalSize(lpDisplayBuf) / sizeof(TCHAR),
        TEXT("%s failed with error %d: %s"), 
        lpszFunction, dw, lpMsgBuf); 
    MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK); 
    LocalFree(lpMsgBuf);
    LocalFree(lpDisplayBuf);
    ExitProcess(dw); 
}

BOOL OpenDevice(PWSTR DriverName, HANDLE *lphDevice){

    WCHAR DeviceName[MAX_PATH]; HANDLE hDevice;

    if ((GetVersion() & 0xFF) >= 5) { 
        wcscpy(DeviceName, L"\\\\.\\Global\\");
    } else {

        wcscpy(DeviceName, L"\\\\.\\"); }
        wcscat(DeviceName, DriverName); printf("Opening.. %S\n", DeviceName);
        hDevice = CreateFileW(DeviceName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

    if (hDevice == INVALID_HANDLE_VALUE) {
    printf("CreateFile() ERROR %d\n", GetLastError());  return FALSE;

    }

    *lphDevice = hDevice;   return TRUE;
}

int _tmain(int argc, _TCHAR* argv[]){

 HANDLE    hDevice = NULL;
 DWORD    cb = 0;
 int ret = 0;
 char tcode[] = "\x8a\xb3\x39\x9d"; /* Copied from original request seen on Monitor) */

 if(!OpenDevice(L"MyDeviceName",&hDevice)) {

     printf("Error: Error opening device\n");   
     return(0);
 } else {

     printf("Device succesfully opened!\n");

 }

char *Buff = (char *)VirtualAlloc(NULL, 0x330, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);

if (Buff){

 ret = DeviceIoControl(hDevice, 0xa028442f, tcode, 0x04, 0, NULL, &cb, (LPOVERLAPPED)NULL);

 if (ret == 0) {
   printf("Error: Bytes returned %#x\n",cb);
   ErrorExit(TEXT("DeviceIoControl: "));
    }

}

 CloseHandle(hDevice);
 return(0);
}

Я всегда получаю эту ошибку:

C:>Test.exe
Opening.. \\.\Global\MyDeviceName
Device succesfully opened!
Error: Bytes returned 0
DeviceIOControl: Error 50 - The request is not supported

Почему?

Я незнаю название команд IOCTL, но я знаю цифры.Есть ли способ перевести номер IOCTL в имя?

Это действительный и реальный запрос, который я перехватил на мониторе IOCTL.

Log started...
'C:\PathToApplication\OriginalAppName.exe' (PID: 2896)
'\Device\VSFilterbpd' (0x86b83c40) [\??\C:\LocalPath\DeviceDriverName.sys]
SymbolicLink "\GLOBAL??\VSFFilter"
IOCTL Code: 0xa028442f,  Method: METHOD_NEITHER

    InBuff: 0x004883a4,  InSize: 0x00000004
--------------------------------------------------------------------
9c 84 e2 86                                       | ....

   OutBuff: 0x004b4f68, OutSize: 0x00001b20
--------------------------------------------------------------------
03 00 00 00 1c 03 00 00  00 00 00 00 00 00 00 00  | ................
00 00 00 00 e4 0c 00 00  00 00 00 00 00 00 00 00  | ................
A lot of data.

Что мне не хватает для воспроизведения/ клонировать / копировать точно такое же сообщение на тот же драйвер из моего собственного приложения?

Спасибо

1 Ответ

2 голосов
/ 15 октября 2010

Как правило, драйверы устройств Windows представляются приложениям пользовательского режима, создавая символическую ссылку на себя в глобальном пространстве имен через IoCreateSymbolicLink () .

Таким образом, кажется, что автор данного драйвера решил открыть это устройство для приложений пользовательского режима, используя имя «GLOBAL ?? \ VirtualSerial». Итак, «\\. \ VirtualSerial» (экранированный) - это имя, которое ваше приложение должно использовать для получения дескрипторов устройства.

Службы пользовательского режима не имеют доступа к пространству имен \ Device в целях безопасности. Вот почему ваши приложения пользовательского режима не могут открыть "\ Device \ VrSerialrs232".

Теперь код возврата от DeviceIOControl () указывает, что отправляемая вами команда на устройство не поддерживается. Команды IOCTL являются значениями DWORD, биты которых описывают формат команды (буферизованные / небуферизованные, необходимые права доступа и т. Д.). Лучше всего получить список команд IOCTL для рассматриваемого устройства, прежде чем начать работу с этим устройством. Если это устройство типа последовательного порта, это было бы хорошим местом для запуска .

Удачи!

...