2010-10-15 7 views
0

Je suis très nouveau pour la communication avec les pilotes de périphériques Windows. A12) J'ai besoin de communiquer avec un pilote tiers. Je vois que CreateFile() accepte à la fois le nom du périphérique (tel que \\\\.\\DeviceName) et aussi je peux appeler le nom de fichier complet (tel que \\\\.\\C:\\MyPath\\DriverName.sys). Quelle est la meilleure option? Pourquoi? Les deux fonctionnent de la même manière?DeviceIOControl() donne une erreur 50

B) Je vois que beaucoup de pilotes de périphériques a deux noms, par exemple:

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

Si je tente ouvert par exemple ouvert VrSerialrs232 avec CreateFile() il échoue. Alors, pourquoi utiliser le VrSerialrs232 si je dois toujours appeler le SymbolicLink(VirtualSerial)? C) J'ai installé un moniteur DeviceIOControl pour vérifier pourquoi mon code échoue avec Error 50 (la demande n'est pas supportée) et je ne peux pas comprendre pourquoi.

La sortie du DeviceIOControl moniteur est here

Ceux de test.exe sont mon code, l'autre (protégé) est l'application d'origine appelant le même appareil.

Mon code est comme ceci:

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

Je reçois toujours cette erreur:

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

Pourquoi? Je ne connais pas le nom des commandes IOCTL, mais je connais les numéros. Il existe un moyen de traduire un numéro IOCTL à un nom?

Ceci est une demande valide et réelle que j'ai capturé avec un moniteur 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. 

Ce que je manque à reproduire/clone/reproduire exactement le même message au même pilote par de ma propre application?

Merci

+0

Eh bien, le code de contrôle est faux, le conducteur ne le reconnaît pas. Cela semble étrange, le code de la méthode de passage de tampon est 3, METHOD_NEITHER. –

Répondre

2

En règle générale, les pilotes de périphériques Windows se présentent aux applications en mode utilisateur en créant un lien symbolique pour eux-mêmes dans l'espace de noms global via IoCreateSymbolicLink(). Il semblerait donc que l'auteur du pilote en question ait décidé d'exposer cet appareil aux applications en mode utilisateur, en utilisant le nom "GLOBAL ?? \ VirtualSerial". Ainsi, "\\. \ VirtualSerial" (échappé) est le nom que votre application doit utiliser pour obtenir des handles sur le périphérique.

Les services en mode utilisateur n'ont pas accès à l'espace de noms "\ Device" pour des raisons de sécurité. C'est pourquoi vos applications en mode utilisateur ne peuvent pas ouvrir "\ Device \ VrSerialrs232".

Maintenant, le code de retour de DeviceIOControl() indique que la commande que vous envoyez le périphérique n'est pas prise en charge. Les commandes IOCTL sont des valeurs DWORD dont les bits décrivent le format de la commande (buffer/unbuffered, droits d'accès requis, etc.). Votre meilleur pari serait d'obtenir une liste des commandes IOCTL pour l'appareil en question avant de commencer à travailler avec cet appareil.S'il s'agit d'un périphérique de type port série, this would be a good place to start.

Bonne chance!

+0

@Hans, j'ai corrigé le numéro de code IOCTL, maintenant c'est correct. @Hans, I f ret = DeviceIoControl (hDevice, 0x86DB3F68, tcode, 0x04, 0, NULL, & cb, (LPOVERLAPPED) NULL); Et le problème persiste. Une autre idée? Où vous voyez sur la capture d'écran que la méthode est 3? Je ne peux pas le voir. Et pourquoi c'est bizarre? Merci – Fred

+0

merci pour l'explication, très utile. La commande que j'envoie? Dans ce cas, le contenu de la variable tcode? Le tampon/unbuffered, droits d'accès requis, etc ne devrait pas être défini quand j'appelle CreateFileW()? Merci – Fred

+0

Et non, ce n'est pas un périphérique série ou connexes. C'est une sorte de filtre de système de fichiers. Merci – Fred