2016-11-07 2 views
0

Code pertinente est la suivante:DeviceIoControl() avec IOCTL_DISK_GET_DRIVE_GEOMETRY échoue et renvoie le code d'erreur 87. Pourquoi?

std::wstring path = ApplicationData::Current->LocalFolder->Path->Data(); 

std::wstring testFileName = path + std::wstring(L"\\TestVariablySized"); 
this->hMappedFile = CreateFile2(
    testFileName.c_str(), 
    GENERIC_READ | GENERIC_WRITE, 
    0, 
    OPEN_ALWAYS, 
    NULL); 

uint32_t checkF = GetLastError(); 

DISK_GEOMETRY geo = { 0 }; 
DWORD bReturned = 0; 

bool controlCheck = DeviceIoControl(
    (HANDLE)hMappedFile,    // handle to device 
    IOCTL_DISK_GET_DRIVE_GEOMETRY, // dwIoControlCode 
    NULL,       // lpInBuffer 
    0,        // nInBufferSize 
    (LPVOID)&geo,   // output buffer 
    (DWORD)sizeof(geo),  // size of output buffer 
    (LPDWORD)&bReturned,  // number of bytes returned 
    NULL); 

uint32_t check = GetLastError(); 

Après cela, controlCheck est faux et check est ERROR_INVALID_PARAMETER. checkF est ERROR_ALREADY_EXISTS, ce qui ne devrait pas poser de problème ici.

Pour autant que je sache, j'ai appelé DeviceIoControl() d'une manière cohérente avec le IOCTL_DISK_GET_DRIVE_GEOMETRY documentation. , mais il me manque quelque chose. Votre aide est la plus appréciée.

Edit:

par les réponses reçues, je modifié les choses soient comme suit:

HANDLE hDevice = CreateFile2(
    L"\\.\PhysicalDrive0", 
    GENERIC_READ | GENERIC_WRITE, 
    FILE_SHARE_READ | FILE_SHARE_WRITE, 
    OPEN_EXISTING, 
    NULL); 

uint32_t checkF = GetLastError(); 

DISK_GEOMETRY geo = { 0 }; 
DWORD bReturned = 0; 

bool controlCheck = DeviceIoControl(
    hDevice,    // handle to device 
    IOCTL_DISK_GET_DRIVE_GEOMETRY, // dwIoControlCode 
    NULL,       // lpInBuffer 
    0,        // nInBufferSize 
    (LPVOID)&geo,   // output buffer 
    (DWORD)sizeof(geo),  // size of output buffer 
    (LPDWORD)&bReturned,  // number of bytes returned 
    NULL); 

uint32_t check = GetLastError(); 

CloseHandle(hDevice); 

qui devrait être plus proche d'être correct, même si ce n'est pas encore tout à fait correct. checkF est ERROR_FILE_NOT_FOUND, que j'ai trouvé étrange. J'ai aussi essayé "\\.\PhysicalDrive1" et "\\.\PhysicalDrive2", mais j'ai reçu le même résultat. controlCheck est toujours faux, mais vérifiez maintenant ERROR_INVALID_HANDLE.

+0

AFAIK, '' IOCTL_DISK_ * ne fonctionne que si vous ouvrez le disque lui-même, vous ne pouvez pas envoyer ceux pour ouvrir les poignées pour les fichiers à l'intérieur des volumes à l'intérieur du disque. –

Répondre

1

Pour autant que je peux dire, je l'ai appelé DeviceIoControl() de manière cohérente avec la documentation IOCTL_DISK_GET_DRIVE_GEOMETRY

En fait, vous n'êtes pas, parce que vous ne faites pas attention à cette friandise de la documentation :

hDevice
Une poignée pour le dispositif de disque à partir de laquelle le ge l'ométrie doit être récupérée. Pour récupérer une poignée de périphérique, appelez la fonction CreateFile.

Vous n'êtes pas passer un manche à un dispositif de disque , vous passez une poignée sur un chemin de système de fichiers à la place.

Lorsque vous appelez CreateFile2() pour obtenir une poignée à un dispositif de disque , vous devez spécifier un périphérique physique dans le format \\.\PhysicalDriveX à la place, pas un chemin du système de fichiers.

En outre, comme la documentation CreateFile2() dit:

Les conditions suivantes doivent être réunies pour un tel appel pour réussir:

  • L'appelant doit avoir des privilèges d'administrateur. Pour plus d'informations, consultez la section Exécution avec des privilèges spéciaux. Le paramètre dwCreationDisposition doit avoir l'indicateur OPEN_EXISTING.Lorsque vous ouvrez un volume ou une disquette, le paramètre dwShareMode doit porter l'indicateur FILE_SHARE_WRITE.

Vous utilisez OPEN_ALWAYS au lieu de OPEN_EXISTING.

Veuillez lire attentivement la section "Disques physiques et volumes" de la documentation CreateFile2().

Essayez quelque chose comme ceci:

std::wstring path = L"\\\\.\\PhysicalDrive0"; 
DWORD errCode; 

hMappedFile = CreateFile2(
    path.c_str(), 
    GENERIC_READ | GENERIC_WRITE, 
    0, 
    OPEN_EXISTING, 
    NULL); 

if (this->hMappedFile == INVALID_HANDLE_VALUE) 
{ 
    errCode = GetLastError(); 
    // handle error as needed... 
} 
else 
{ 
    DISK_GEOMETRY geo = { 0 }; 
    DWORD dwReturned = 0; 

    bool controlCheck = DeviceIoControl(
     hMappedFile,     // handle to device 
     IOCTL_DISK_GET_DRIVE_GEOMETRY, // dwIoControlCode 
     NULL,       // lpInBuffer 
     0,        // nInBufferSize 
     &geo,       // output buffer 
     sizeof(geo),     // size of output buffer 
     &dwReturned,     // number of bytes returned 
     NULL); 

    if (!controlCheck) 
    { 
     errCode = GetLastError(); 
     // handle error as needed... 
    } 
    else 
    { 
     // use drive as needed... 
    } 

    CloseHandle(hMappedFile); 
} 
+0

Modifications effectuées, mais une nouvelle erreur apparaît – MNagy

+0

@MNagy: c'est parce que votre chaîne d'entrée 'CreateFile2()' est incorrecte, donc elle échoue, renvoyant 'INVALID_HANDLE_VALUE' et définissant le code d'erreur à' ERROR_FILE_NOT_FOUND'. Vous ne vérifiez pas l'échec, vous passez donc ce handle invalide à 'DeviceIoControl()', c'est pourquoi il signale une erreur 'ERROR_INVALID_HANDLE'. Votre chaîne d'entrée utilise un ** chaîne littérale **, vous devez donc échapper les barres obliques en les doublant, par exemple: 'L '\\\\. \\ PhysicalDrive0" '. –