2013-03-15 3 views
1

현재 샘플 하드 드라이브 이미지의 파티션에 대한 정보 검색을 자동화하는 C++ 프로그램을 작성하려고합니다.이 정보는 디스크의 파티션 수와 각 파티션의 정보입니다. 섹터, 크기 및 파일 시스템 유형을 시작합니다.잘못된 함수 호출 "IOCTL_DISK_GET_DRIVE_LAYOUT_EX"

저는이 시점에서 MSDN 기능, microsofts inbuilt 명령을 사용하는 것이 가장 좋은 방법이라고 확신합니다. "IOCTL_DISK_GET_DRIVE_LAYOUT_EX"함수를 사용하려고하는데 내 오류 호출에 따라 함수가 올바르지 않습니다. 내가 프로그램을 디버깅 할 때 bool 값이 "IOCTL_DISK_GET_DRIVE_LAYOUT_EX"호출 후에 변경되지 않은 것으로 나타나면 bResult 값을 반환하지 않는다는 의미입니다.

Microsoft Visual C++ Express Edition을 사용하고 있습니다. 사람들이 내 코드를보고 내가 뭘 잘못했다고 생각하는지 말해 주면 많은 도움이 될 것입니다.

#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'를 호출하고 문제가 무엇인지를 참조하십시오? –

+0

오류 122는 "시스템 호출로 전달 된 데이터 오류가 너무 작음"을 의미합니다 ... 구조체를 먼저 초기화해야합니까? –

+0

의견을 주셔서 감사합니다. 가능한 한 빨리 시도해 보겠습니다. 결과가보고됩니다. –

답변

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 ]; 
} 

로 정의되어 있지만 일반적으로 PartitionEntryPartitionCount 항목으로, 훨씬 더 큰 배열로 처리됩니다. 이는 C99 VLA 메커니즘과 유사합니다. you'va는 단지 sizeof(*pdg) 바이트를 할당 했으므로 두 번째 PartitionEntry를위한 공간이 없습니다.

C++ 해킹 :

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

답장 MSalters에 감사드립니다. 제공 한 솔루션을 구현하는 방법을 설명해 주시겠습니까? 성가심에 대한 사과,하지만 나는 C++에 비교적 익숙하지 않다. –

+0

@DavidRyan : Windows 구조는 C++이 아니지만 Windows는 이론상 언어 중립적 인 것으로 간주해야합니다. API가 항상 C++에 잘 맵핑되는 것은 아닙니다. 이 경우 두 개 이상의 PartitionEntry 멤버가있는 객체가 필요합니다. 나는 C++ 파생물을 사용하여 추가 구성원을 추가하고 컴파일러를 사용하여 레이아웃을 올바르게 작성합니다. 이제 프로그램에서'DRIVE_LAYOUT_INFOMARTION_EX'을'ExtraEntries'로 대체하십시오. 파생 된 타입이기 때문에, Windows API에'ExtraEntries * '를 넘겨 주면, 컴파일러는 필요한'DRIVE_LAYOUT_INFORMATION_EX *'를 제공하기 위해 cast-to-base를 자동으로 삽입 할 것입니다. – MSalters