2013-03-15 121 views
1

我目前正在寫一個C++程序來自動獲取關於樣本的分區信息的硬盤驅動器的形象,問題是在磁盤上,併爲每個分區的分區數量的信息其起始扇區,大小和文件系統類型。不正確的函數調用「IOCTL_DISK_GET_DRIVE_LAYOUT_EX」

我敢肯定,在這一點上,以實現這一目標是通過MSDN的功能,微軟內置命令的最佳方式。我試圖使用「IOCTL_DISK_GET_DRIVE_LAYOUT_EX」函數,但根據我的錯誤調用我的函數是不正確的。當我調試程序看來,布爾值也是「IOCTL_DISK_GET_DRIVE_LAYOUT_EX」呼叫後保持不變,這意味着它不會返回bResult值。

我使用Microsoft Visual C++速成版。如果人們可以看看我的代碼,並告訴我他們認爲我做錯了什麼,這將非常感激。

#define UNICODE 1 
#define _UNICODE 1 

#include <windows.h> 
#include <winioctl.h> 
#include <stdio.h> 

#define wszDrive L"\\\\.\\PhysicalDrive6" 

BOOL GetDriveParition(LPWSTR wszPath, DRIVE_LAYOUT_INFORMATION_EX *pdg) 
{ 

    HANDLE hDevice = INVALID_HANDLE_VALUE; // handle to the drive to be examined 
    BOOL bResult = FALSE;     // results flag 
    DWORD junk  = 0;      // discard results 


    hDevice = CreateFileW(wszPath,   // drive to open 
        0,    // no access to the drive 
        FILE_SHARE_READ | // share mode 
        FILE_SHARE_WRITE, 
        NULL,    // default security attributes 
        OPEN_EXISTING, // disposition 
        0,    // file attributes 
        NULL);   // do not copy file attributes 

    if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive 
    { 
return (FALSE); 
    } 

bResult = DeviceIoControl( 
        hDevice,      // handle to device 
        IOCTL_DISK_GET_DRIVE_LAYOUT_EX, // dwIoControlCode 
        NULL,       // lpInBuffer 
        0,        // nInBufferSize 
        pdg,       // lpOutBuffer 
        sizeof(*pdg),     // nOutBufferSize 
        &junk,       // lpBytesReturned 
        NULL);       // lpOverlapped 

CloseHandle(hDevice); 

return (bResult); 


} 

int wmain(int argc, wchar_t *argv[]) 
{ 
DRIVE_LAYOUT_INFORMATION_EX pdg; // disk drive partition structure 
    BOOL bResult = FALSE;  // generic results flag 

    bResult = GetDriveParition (wszDrive, &pdg); 

    if (bResult) 
    { 
    wprintf(L"Drive path   = %ws\n", wszDrive); 
    wprintf(L"Partition Style  = %I64d\n", pdg.PartitionStyle); 
    wprintf(L"Partition Count  = %ld\n", pdg.PartitionCount); 

    system("Pause"); 
    } 
    else 
    { 
    wprintf (L"GetDrivePartition failed. Error %ld.\n", GetLastError()); 
    system("Pause"); 
    } 

    return ((int)bResult); 
} 
+0

請致電'GetLastError'的功能之後,看看是什麼問題? – 2013-03-15 13:48:04

+0

錯誤122意味着「傳遞給系統調用的數據錯誤太小」......您是否需要首先初始化結構? – 2013-03-15 13:53:40

+0

感謝您的評論,只要我能夠,我會嘗試一下。將報告結果。 – 2013-03-15 14:36:06

回答

3

DRIVE_LAYOUT_INFORMATION_EX是一個奇怪的結構。它定義爲

struct { 
    DWORD     PartitionStyle; 
    DWORD     PartitionCount; 
    union { 
    DRIVE_LAYOUT_INFORMATION_MBR Mbr; 
    DRIVE_LAYOUT_INFORMATION_GPT Gpt; 
    }; 
    PARTITION_INFORMATION_EX PartitionEntry[ 1 ]; 
} 

但通常PartitionEntry被視爲一個大得多的陣列,其中PartitionCount條目。這與C99 VLA機制相似。由於您只分配了sizeof(*pdg)字節,因此即使是第二個PartitionEntry也沒有空間。

C++黑客:

struct ExtraEntries : DRIVE_LAYOUT_INFORMATION_EX 
{ 
    PARTITION_INFORMATION_EX PartitionEntry[ 9 ]; // Or some other reasonable value 
}; 
+0

感謝您的答覆MSalters。您能否解釋如何實施您提供的解決方案?對這種煩惱抱歉,但我對C++來說比較新。 – 2013-03-15 15:42:49

+0

@DavidRyan:在Windows結構不乾淨C++,但你必須要考慮,Windows是在理論上與語言無關。它的API並不總是很好地映射到C++。在這種情況下,您需要一個具有多於1個'PartitionEntry'成員的對象。我使用C++派生來添加額外的成員,並依靠編譯器來獲得正確的佈局。現在在程序中用'ExtraEntries'替換'DRIVE_LAYOUT_INFOMARTION_EX'。因爲它是一個派生類型,當你傳遞一個'ExtraEntries *'到Windows API,編譯器會自動插入鑄 - 底部給你所需要的'DRIVE_LAYOUT_INFORMATION_EX *'。 – MSalters 2013-03-18 10:53:55