你看到的\Device\0000010f这是由某些总线驱动程序创建的PDO(物理设备对象)(它有标志DO_BUS_ENUMERATED_DEVICE)
可以附加一些FDO(功能设备对象)。如果这是来自存储堆栈(基于总线设备为此 PDO 返回的 CompatibleIDs 字符串)典型的 FDO 名称的格式为 \Device\Harddisk%d\DR%d 并且很好到它的已知符号链接\Device\Harddisk%d\Partition0
磁盘驱动程序 FDO 枚举卷上的分区并为每个分区创建 PDO 设备对象(具有众所周知的符号链接 \Device\Harddisk%d\Partition%d 其中分区号始终 > 0,Partition0 是指整个磁盘 FDO)
通常的分区与卷相同,但并不总是 (Partitions and Volumes) 还要注意 IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS - 它返回 DISK_EXTENT 结构的数组 - 在此处查找 DiskNumber -The number of the disk that contains this extent. 以便卷可以放置在多个磁盘上。但在 99%+ IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS 只返回给你一个 DISK_EXTENT
如果您在存储堆栈中有 PDO 的路径,您可以做什么?
- 打开设备-如果使用
ZwOpenFile(当然这在
用户模式)我们可以按原样使用\Device\0000010f。如果我们想使用 win32
api 我们需要为所有名称使用前缀\\?\GLOBALROOT。我们真的是通过这条总线打开 PDO 但是因为磁盘 FDO 连接到 PDO 我们所有的请求都将通过 FDO 并在这里处理。想要访问? SYNCHRONIZE 就足够了(如果 CreateFile 我们没有设置 FILE_FLAG_OVERLAPPED api 隐式将此标志添加到 DESIRED_ACCESS )
- 发送
IOCTL_STORAGE_GET_DEVICE_NUMBER 到设备。检查
DeviceType == FILE_DEVICE_DISK && sdn.PartitionNumber == 0
- 发送
IOCTL_DISK_GET_DRIVE_LAYOUT_EX 获取可变大小
PARTITION_INFORMATION_EX 结构数组
- 基于
DeviceNumber(我们在第2步得到)和
PartitionNumber(我们在第 3 步得到)将符号链接格式化为
分区 PDO - \\?\GLOBALROOT\Device\Harddisk%d\Partition%d
- 用
SYNCHRONIZE 访问打开分区PDO(足够了,因为所有
我们使用的IOCTL有FILE_ANY_ACCESS类型
- 发送
IOCTL_MOUNTDEV_QUERY_DEVICE_NAME到分区
- 现在我们需要 MountManager 设备的句柄 (
\\.\MountPointManager)
发送给他IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH这个IOCTL定义在mountmgr.h输入它需要MOUNTDEV_NAME
我们在第 6 步得到。在输出中我们收到MOUNTMGR_VOLUME_PATHS
结构(也在mountmgr.h中定义)或者我们可以使用
IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATHS - 如果一切正常,我们得到了列表
驱动器号,如C:、D: 等。
- 我们可以使用枚举系统中的磁盘驱动器
CM_Get_Device_ID_ListW 与
{4d36e967-e325-11ce-bfc1-08002be10318}过滤器,打开所有设备
以CM_Locate_DevNodeW 举例,最后查询
DEVPKEY_Device_PDOName 致电
CM_Get_DevNode_Property
好的,这里的代码示例是正确的:
#include <mountmgr.h>
// guz == 0 always, volatile for prevent CL "optimization" - it can drop alloca(0) call
static volatile UCHAR guz;
ULONG QueryPartitionW32(HANDLE hPartition, HANDLE hMountManager)
{
MOUNTDEV_STABLE_GUID guid;
ULONG dwBytesRet;
if (DeviceIoControl(hPartition, IOCTL_MOUNTDEV_QUERY_STABLE_GUID, 0, 0, &guid, sizeof(guid), &dwBytesRet, NULL))
{
DbgPrint("StableGuid = \\\\?\\Volume{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n",
guid.StableGuid.Data1, guid.StableGuid.Data2, guid.StableGuid.Data3,
guid.StableGuid.Data4[0],
guid.StableGuid.Data4[1],
guid.StableGuid.Data4[2],
guid.StableGuid.Data4[3],
guid.StableGuid.Data4[4],
guid.StableGuid.Data4[5],
guid.StableGuid.Data4[6],
guid.StableGuid.Data4[7]
);
}
// assume NumberOfDiskExtents == 1
VOLUME_DISK_EXTENTS vde;
if (DeviceIoControl(hPartition, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, 0, 0, &vde, sizeof(vde), &dwBytesRet, 0))
{
if (vde.NumberOfDiskExtents)
{
DbgPrint("ofs=%I64u, len=%I64u\n", vde.Extents->StartingOffset.QuadPart, vde.Extents->ExtentLength.QuadPart);
}
}
PVOID stack = alloca(guz);
union {
PVOID buf;
PMOUNTDEV_NAME pmdn;
};
ULONG err;
ULONG cb = 0, rcb = sizeof(MOUNTDEV_NAME) + 0x10, InputBufferLength;
do
{
if (cb < rcb)
{
cb = RtlPointerToOffset(buf = alloca(rcb - cb), stack);
}
if (DeviceIoControl(hPartition, IOCTL_MOUNTDEV_QUERY_DEVICE_NAME, 0, 0, buf, cb, &dwBytesRet, NULL))
{
DbgPrint("%.*S\n", pmdn->NameLength >> 1, pmdn->Name);
union {
PVOID pv;
PMOUNTMGR_VOLUME_PATHS pmvp;
};
cb = 0, rcb = sizeof(MOUNTMGR_VOLUME_PATHS) + 0x10, InputBufferLength = sizeof(MOUNTDEV_NAME) + pmdn->NameLength;
do
{
if (cb < rcb)
{
cb = RtlPointerToOffset(pv = alloca(rcb - cb), pmdn);
}
if (DeviceIoControl(hMountManager, IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH,
pmdn, InputBufferLength, pv, cb, &dwBytesRet, NULL))
{
PWSTR sz = pmvp->MultiSz;
while(*sz)
{
DbgPrint("%S\n", sz);
sz += 1 + wcslen(sz);
}
return NOERROR;
}
rcb = sizeof(MOUNTMGR_VOLUME_PATHS) + pmvp->MultiSzLength;
} while ((err = GetLastError()) == ERROR_MORE_DATA);
break;
}
rcb = sizeof(MOUNTDEV_NAME) + pmdn->NameLength;
} while ((err = GetLastError()) == ERROR_MORE_DATA);
return err;
}
ULONG EnumDiskPartitionsW32(HANDLE hDisk, HANDLE hMountManager)
{
STORAGE_DEVICE_NUMBER sdn;
ULONG dwBytesRet;
if (!DeviceIoControl(hDisk, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &sdn, sizeof(sdn), &dwBytesRet, NULL))
{
return GetLastError();
}
if (sdn.DeviceType != FILE_DEVICE_DISK || sdn.PartitionNumber != 0)
{
return ERROR_GEN_FAILURE;
}
WCHAR sz[128], *c = sz + swprintf(sz, L"\\\\?\\GLOBALROOT\\Device\\Harddisk%d\\Partition", sdn.DeviceNumber);
PVOID stack = alloca(guz);
union {
PVOID buf;
PDRIVE_LAYOUT_INFORMATION_EX pdli;
};
ULONG cb = 0, rcb, PartitionCount = 4;
for (;;)
{
if (cb < (rcb = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION_EX, PartitionEntry[PartitionCount])))
{
cb = RtlPointerToOffset(buf = alloca(rcb - cb), stack);
}
if (DeviceIoControl(hDisk, IOCTL_DISK_GET_DRIVE_LAYOUT_EX, NULL, 0, buf, cb, &dwBytesRet, NULL))
{
if (PartitionCount = pdli->PartitionCount)
{
PPARTITION_INFORMATION_EX PartitionEntry = pdli->PartitionEntry;
do
{
if (!PartitionEntry->PartitionNumber)
{
continue;
}
_itow(PartitionEntry->PartitionNumber, c, 10);
DbgPrint("%S\n", sz);
HANDLE hPartition = CreateFile(sz, 0, FILE_SHARE_VALID_FLAGS, 0, OPEN_EXISTING, 0, 0);
if (hPartition != INVALID_HANDLE_VALUE)
{
QueryPartitionW32(hPartition, hMountManager);
CloseHandle(hPartition);
}
} while (PartitionEntry++, --PartitionCount);
}
return NOERROR;
}
switch (ULONG err = GetLastError())
{
case ERROR_MORE_DATA:
PartitionCount = pdli->PartitionCount;
continue;
case ERROR_BAD_LENGTH:
case ERROR_INSUFFICIENT_BUFFER:
PartitionCount <<= 1;
continue;
default:
return err;
}
}
}
void DiskEnumW32(HANDLE hMountManager)
{
static const WCHAR DEVCLASS_DISK[] = L"{4d36e967-e325-11ce-bfc1-08002be10318}";
enum { flags = CM_GETIDLIST_FILTER_CLASS|CM_GETIDLIST_FILTER_PRESENT };
ULONG len;
if (!CM_Get_Device_ID_List_SizeW(&len, DEVCLASS_DISK, flags))
{
PWSTR buf = (PWSTR)alloca(len * sizeof(WCHAR));
if (!CM_Get_Device_ID_ListW(DEVCLASS_DISK, buf, len, flags))
{
PVOID stack = buf;
static const WCHAR prefix[] = L"\\\\?\\GLOBALROOT";
ULONG cb = 0, rcb = sizeof(prefix) + 0x20;
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);
}
rcb -= sizeof(prefix) - sizeof(WCHAR);
if (!(err = CM_Get_DevNode_PropertyW(dnDevInst, &DEVPKEY_Device_PDOName, &PropertyType,
pb + sizeof(prefix) - sizeof(WCHAR), &rcb, 0)))
{
if (PropertyType == DEVPROP_TYPE_STRING)
{
memcpy(pv, prefix, sizeof(prefix) - sizeof(WCHAR));
DbgPrint("%S\n", sz);
HANDLE hDisk = CreateFile(sz, 0, FILE_SHARE_VALID_FLAGS, 0, OPEN_EXISTING, 0, 0);
if (hDisk != INVALID_HANDLE_VALUE)
{
EnumDiskPartitionsW32(hDisk, hMountManager);
CloseHandle(hDisk);
}
}
else
{
err = ERROR_GEN_FAILURE;
}
break;
}
rcb += sizeof(prefix) - sizeof(WCHAR);
} while (err == CR_BUFFER_SMALL);
}
buf += 1 + wcslen(buf);
}
}
}
}
void DiskEnumW32()
{
HANDLE hMountManager = CreateFile(MOUNTMGR_DOS_DEVICE_NAME, 0, FILE_SHARE_VALID_FLAGS, 0, OPEN_EXISTING, 0, 0);
if (hMountManager != INVALID_HANDLE_VALUE)
{
DiskEnumW32(hMountManager);
CloseHandle(hMountManager);
}
}