问题
I am using FindFirstVolume/FindNextVolume to get a list of all volumes on a machine. That works well enough, but strangely the EFI system partition is skipped for some reason. Diskpart, on the other hand, returns the EFI system partition and the Disk Management UI shows it, too.
Here is diskpart's output:
DISKPART> list volume
Volume ### Ltr Label Fs Type Size Status Info
---------- --- ----------- ----- ---------- ------- --------- --------
Volume 0 C NTFS Partition 476 GB Healthy Boot
Volume 1 Recovery NTFS Partition 450 MB Healthy Hidden
Volume 2 FAT32 Partition 100 MB Healthy System
Volume 3 D Data NTFS Partition 953 GB Healthy
Volume 4 E ESD-USB FAT32 Removable 14 GB Healthy
In that list the EFI system partition is Volume 2.
FindFirstVolume/FindNextVolume give me the other four volumes, but omit the EFI system partition.
Any ideas how I can get a volume GUID path for the EFI system parition or some other way to programmatically access it?
回答1:
volume GUID path (i.e. \??\Volume{..}) not exist if not returned by FindFirstVolume
/FindNextVolume
but we can enumerate all volumes in system by different ways. we say can use Virtual Disk Service com api . DISKPART> list volume
use exactly this. another way(more 'low' and fast) - use CM_Get_Device_ID_ListW with pszFilter = "{71a27cdd-812a-11d0-bec7-08002be2092f}" (look GUID_DEVCLASS_VOLUME
in devguid.h
) than obtain a device instance handle by CM_Locate_DevNodeW and query for DEVPKEY_Device_PDOName with CM_Get_DevNode_PropertyW - we got string (like \Device\HarddiskVolume<X>
) which we can use in ZwOpenFile and then use some ioctls (IOCTL_DISK_GET_PARTITION_INFO_EX and other) for get volume properties. code example:
#include <initguid.h>
#include <cfgmgr32.h>
#include <devguid.h>
#include <devpkey.h>
#include <diskguid.h>
void DumpVolume(HANDLE hFile);
void VolEnum()
{
STATIC_WSTRING(DEVCLASS_VOLUME, "{71a27cdd-812a-11d0-bec7-08002be2092f}");
enum { flags = CM_GETIDLIST_FILTER_CLASS|CM_GETIDLIST_FILTER_PRESENT };
ULONG len;
ULONG cb = 0, rcb = 64;
HANDLE hFile;
IO_STATUS_BLOCK iosb;
UNICODE_STRING ObjectName;
OBJECT_ATTRIBUTES oa = { sizeof(oa), 0, &ObjectName, OBJ_CASE_INSENSITIVE };
if (!CM_Get_Device_ID_List_SizeW(&len, DEVCLASS_VOLUME, flags))
{
PWSTR buf = (PWSTR)alloca(len << 1);
if (!CM_Get_Device_ID_ListW(DEVCLASS_VOLUME, buf, len, flags))
{
PVOID stack = buf;
while (*buf)
{
DbgPrint("%S\n", buf);
DEVINST dnDevInst;
if (!CM_Locate_DevNodeW(&dnDevInst, buf, CM_LOCATE_DEVNODE_NORMAL))
{
DEVPROPTYPE PropertyType;
int err;
union {
PVOID pv;
PWSTR sz;
PBYTE pb;
};
do
{
if (cb < rcb)
{
rcb = cb = RtlPointerToOffset(pv = alloca(rcb - cb), stack);
}
if (!(err = CM_Get_DevNode_PropertyW(dnDevInst, &DEVPKEY_Device_PDOName, &PropertyType, pb, &rcb, 0)))
{
if (PropertyType == DEVPROP_TYPE_STRING)
{
DbgPrint("%S\n", sz);
RtlInitUnicodeString(&ObjectName, sz);
if (0 <= ZwOpenFile(&hFile, FILE_GENERIC_READ, &oa, &iosb, FILE_SHARE_VALID_FLAGS, 0))
{
DumpVolume(hFile);
ZwClose(hFile);
}
}
}
} while (err == CR_BUFFER_SMALL);
}
buf += 1 + wcslen(buf);
}
}
}
}
void DumpVolume(HANDLE hFile)
{
NTSTATUS status;
PARTITION_INFORMATION_EX pi;
IO_STATUS_BLOCK iosb;
if (0 <= (status = ZwDeviceIoControlFile(hFile, 0, 0, 0, &iosb, IOCTL_DISK_GET_PARTITION_INFO_EX, 0, 0, &pi, sizeof(pi))))
{
CHAR PartitionName[40], *szPartitionName;
PCSTR szps = "??";
switch (pi.PartitionStyle)
{
case PARTITION_STYLE_MBR: szps = "MBR";
break;
case PARTITION_STYLE_GPT: szps = "GPT";
break;
}
DbgPrint("%u %s %I64u(%I64x) %I64u ",
pi.PartitionNumber,
szps,
pi.StartingOffset.QuadPart, pi.StartingOffset.QuadPart,
pi.PartitionLength.QuadPart);
switch (pi.PartitionStyle)
{
case PARTITION_STYLE_MBR:
DbgPrint("type=%x boot=%x", pi.Mbr.PartitionType, pi.Mbr.BootIndicator);
break;
case PARTITION_STYLE_GPT:
if (IsEqualGUID(pi.Gpt.PartitionType, PARTITION_ENTRY_UNUSED_GUID))
{
szPartitionName = "UNUSED";
}
else if (IsEqualGUID(pi.Gpt.PartitionType, PARTITION_SYSTEM_GUID))
{
szPartitionName = "SYSTEM";
}
else if (IsEqualGUID(pi.Gpt.PartitionType, PARTITION_MSFT_RESERVED_GUID))
{
szPartitionName = "RESERVED";
}
else if (IsEqualGUID(pi.Gpt.PartitionType, PARTITION_BASIC_DATA_GUID))
{
szPartitionName = "DATA";
}
else if (IsEqualGUID(pi.Gpt.PartitionType, PARTITION_MSFT_RECOVERY_GUID))
{
szPartitionName = "RECOVERY";
}
else if (IsEqualGUID(pi.Gpt.PartitionType, PARTITION_MSFT_SNAPSHOT_GUID))
{
szPartitionName = "SNAPSHOT";
}
else
{
sprintf(szPartitionName = PartitionName, "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}",
pi.Gpt.PartitionType.Data1,
pi.Gpt.PartitionType.Data2,
pi.Gpt.PartitionType.Data3,
pi.Gpt.PartitionType.Data4[0],
pi.Gpt.PartitionType.Data4[1],
pi.Gpt.PartitionType.Data4[2],
pi.Gpt.PartitionType.Data4[3],
pi.Gpt.PartitionType.Data4[4],
pi.Gpt.PartitionType.Data4[5],
pi.Gpt.PartitionType.Data4[6],
pi.Gpt.PartitionType.Data4[7]);
}
DbgPrint("[%s] %I64x \"%S\"",
szPartitionName,
pi.Gpt.Attributes,
pi.Gpt.Name);
break;
}
ULONG cb = FIELD_OFFSET(FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName[32]);
PFILE_FS_ATTRIBUTE_INFORMATION pffai = (PFILE_FS_ATTRIBUTE_INFORMATION)alloca(cb);
switch (ZwQueryVolumeInformationFile(hFile, &iosb, pffai, cb, FileFsAttributeInformation))
{
case STATUS_SUCCESS:
case STATUS_BUFFER_OVERFLOW:
DbgPrint(" \"%.*S\"", pffai->FileSystemNameLength >> 1 , pffai->FileSystemName);
break;
}
DbgPrint("\n");
}
else
{
DbgPrint("status=%x\n", status);
}
}
and debug output
STORAGE\Volume\{d2bfdb30-4d04-11e5-824e-806e6f6e6963}#0000000012D00000
\Device\HarddiskVolume2
2 GPT 315621376(12d00000) 104857600 [SYSTEM] 8000000000000000 "EFI system partition" "FAT32"
STORAGE\Volume\{d2bfdb30-4d04-11e5-824e-806e6f6e6963}#0000000000100000
\Device\HarddiskVolume1
1 GPT 1048576(100000) 314572800 [RECOVERY] 8000000000000001 "Basic data partition" "NTFS"
STORAGE\Volume\{d2bfdb30-4d04-11e5-824e-806e6f6e6963}#0000000021100000
\Device\HarddiskVolume4
4 GPT 554696704(21100000) 255506513920 [DATA] 0 "Basic data partition" "NTFS"
STORAGE\Volume\{d2bfdb30-4d04-11e5-824e-806e6f6e6963}#0000000019100000
\Device\HarddiskVolume3
3 GPT 420478976(19100000) 134217728 [RESERVED] 8000000000000000 "Microsoft reserved partition" "RAW"
STORAGE\Volume\{a4d55aa5-4d7f-11e5-8256-5cc5d4ea6270}#0000000000007E00
\Device\HarddiskVolume5
1 MBR 32256(7e00) 32017013248 type=7 boot=1 "NTFS"
for attributes look - https://msdn.microsoft.com/en-us/library/windows/desktop/aa365449(v=vs.85).aspx
来源:https://stackoverflow.com/questions/40208794/findfirstvolume-does-not-return-efi-system-partition