开发者

DeviceIOControl() gives Error 50

I'm very new to communication with Windows Device Drivers.

A) I need to communicate with a third-party driver. I see that CreateFile() accept both the device name (such as \\\\.\\DeviceName) and also I can call the full file name (such as \\\\.\\C:\\MyPath\\DriverName.sys). What is the best option? Why? Both works on the same way?

B) I see that many device drivers has two names, for example:

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

If I try open for example open VrSerialrs232 with CreateFile() it fails. So, why is used the VrSerialrs232 if I always have to call the SymbolicLink(VirtualSerial)?

C) I installed a DeviceIOControl monitor to check why my code is failing with Error 50 (The request is not supported) and I can't figure why.

The output of the DeviceIOControl monitor is here

The ones from test.exe are my code, the other (protected) is the original application calling the same device.

My code is like this:

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

I always get this error:

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

Why?

I don't know the name of the IOCTL commands, but I know the numbers. There is a way to translate a IOCTL number to a name?

This is a valid and real request that I captured with a IOCTL monitor.

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.

What I'm missing to reproduce / clone / replicate the exact same message to the same driver by from my own application?

Thanks


Typically, Windows device drivers present themselves to user mode applications by creating a symbolic link to themselves in the global namespace via IoCreateSymbolicLink().

So, it woud appear that the author of the driver in question has decided to expose this device to user mode applications, using the name "GLOBAL??\VirtualSerial". So, "\\.\VirtualSerial" (escaped) is the name your application should be using to obtain handles to the device.

User mode services do not have access to the "\Device" namespace for security reasons. This is why your user mode applications cannot open "\Device\VrSerialrs232".

Now, the return code from DeviceIOControl() indicates that the command that you're sending the device is not supported. IOCTL commands are DWORD values whose bits describe the format of the command (buffered/unbuffered, access rights required, etc.). Your best bet would be to obtain a list of the IOCTL commands for the device in question before you start working with this device. If this is a serial port type device, this would be a good place to start.

Good luck!

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜