不正确的函数调用“IOCTL_DISK_GET_DRIVE_LAYOUT_EX”

问题描述:

我目前正在写一个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

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