【问题标题】:How to determine two dos devices is equals?如何判断两个dos设备是否相等?
【发布时间】:2020-09-11 09:30:36
【问题描述】:

我需要确定两个dos设备是否相同。

例如

\Device\Harddisk0\Partition1
\Device\HarddiskVolume2

如何解决?

最终目标是从 Dos Device Name 中获取 Volume Name。

但这是不可能的,所以我尝试通过 FindFirstVolume 进行比较。


(更详细)

我需要从 Dos 设备名中找到卷名。

例如\Device\Harddisk0\Partition1 到 \?\Volume{316eddba-0000-0000-0000-100000000000}。

QueryDosDevice 函数可以从 Volume Name 中获取 Dos Device Name。但是反过来是不行的。

所以,我尝试这样做。

  1. 通过 FindFirstVolume 枚举所有卷。
  2. 通过 QueryDosDevice 从卷名中查找每个 Dos 设备名称。
  3. 通过比较在 2 处找到的 dos 设备名称与输入的 Dos 设备名称来查找所需的卷名称。

现在,第 2 步是问题所在。

【问题讨论】:

  • 但这是不可能的 - 你确定吗?我不这么认为
  • "\Device\Harddisk0\Partition1" 不是 DOS 设备名称。这是一个本机 NT 对象路径,自 NT 5.0 起,它被实现为指向枚举卷设备(例如“\Device\HarddiskVolume2”)的对象符号链接。要打开本机设备路径,请使用“GLOBALROOT”对象符号链接,例如“\\?\GLOBALROOT\Device\Harddisk0\Partition1”。然后您可以查询挂载点管理器以获取 DOS 和 GUID 名称。如果卷是由文件系统挂载的,那么您还可以在路径后面附加一个反斜杠,打开一个句柄并调用GetFinalPathNameByHandleW(h, sz, cch, VOLUME_NAME_GUID)
  • 也许忽略了一点,OP 需要确定“\Device\Harddisk0\Partition1”(对象符号链接)是否与“\Device\HarddiskVolume2”相同。 WinAPI 卷枚举和QueryDosDeviceW 不足。您只会获得枚举的卷设备名称,例如“\Device\HarddiskVolume2”。要解析符号链接,最简单的方法是打开路径并查询挂载点管理器和卷设备之间的接口,例如 IOCTL_MOUNTDEV_QUERY_DEVICE_NAME,或者使用未记录的 NT API 查询 NtQueryObject : ObjectNameInformation (1)。
  • 没有记录,但 Windows XP 添加了IOCTL_MOUNTDEV_QUERY_STABLE_GUID,它允许直接查询用于“卷{GUID}”名称的 GUID。参见“km\mountdev.h”。
  • 1 - 如何获得 \Device\Harddisk0\Partition1 2 为什么需要将其转换为 \?\\Volume{...} 形式

标签: windows winapi


【解决方案1】:

最后,我通过下面得到了想要的结果!

谢谢大家。

#include <stdio.h>
#include <Windows.h>
#define MOUNTMGRCONTROLTYPE 0x0000006D// 'm'
#define MOUNTDEVCONTROLTYPE ((ULONG) 'M')

#define IOCTL_MOUNTMGR_QUERY_POINTS      CTL_CODE(MOUNTMGRCONTROLTYPE, 2, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_MOUNTDEV_QUERY_DEVICE_NAME CTL_CODE(MOUNTDEVCONTROLTYPE, 2, METHOD_BUFFERED,  FILE_ANY_ACCESS)

    typedef struct _MOUNTDEV_NAME {
  USHORT NameLength;
  WCHAR Name[1];
} MOUNTDEV_NAME, *PMOUNTDEV_NAME;

typedef struct _MOUNTMGR_MOUNT_POINT {
  ULONG SymbolicLinkNameOffset;
  USHORT SymbolicLinkNameLength;
  USHORT Reserved1;
  ULONG UniqueIdOffset;
  USHORT UniqueIdLength;
  USHORT Reserved2;
  ULONG DeviceNameOffset;
  USHORT DeviceNameLength;
  USHORT Reserved3;
} MOUNTMGR_MOUNT_POINT, *PMOUNTMGR_MOUNT_POINT;

typedef struct _MOUNTMGR_MOUNT_POINTS {
  ULONG Size;
  ULONG NumberOfMountPoints;
  MOUNTMGR_MOUNT_POINT MountPoints[1];
} MOUNTMGR_MOUNT_POINTS, *PMOUNTMGR_MOUNT_POINTS;

#pragma comment(lib, "Crypt32.lib")

int main() {
  HANDLE hDevice, hMountMgr;
  BYTE byBuffer[1024];
  PMOUNTDEV_NAME pMountDevName;
  DWORD cbBytesReturned, dwInBuffer, dwOutBuffer, ccb;
  PMOUNTMGR_MOUNT_POINT pMountPoint;
  BOOL bSuccess;
  PBYTE pbyInBuffer, pbyOutBuffer;
  LPTSTR pszLogicalDrives, pszDriveRoot;

  // MOUNTMGR_DOS_DEVICE_NAME is defined as L"\\\\.\\MountPointManager"
  hMountMgr = CreateFile(_T("\\\\.\\MountPointManager"),
                         0, FILE_SHARE_READ | FILE_SHARE_WRITE,
                         NULL, OPEN_EXISTING, 0, NULL);
  if (hMountMgr == INVALID_HANDLE_VALUE)
    return 1;

  LPCTSTR DOS_SYM_LINK = _T("\\\\?\\GLOBALROOT\\Device\\Harddisk0\\Partition1");
  //LPCTSTR DOS_SYM_LINK = _T("\\\\?\\GLOBALROOT\\Device\\HarddiskVolume1");
  hDevice = CreateFile(DOS_SYM_LINK, 0,
                       FILE_SHARE_READ | FILE_SHARE_WRITE,
                       NULL, OPEN_EXISTING, 0, NULL);

  bSuccess = DeviceIoControl(hDevice,
                             IOCTL_MOUNTDEV_QUERY_DEVICE_NAME,
                             NULL, 0,
                             (LPVOID) byBuffer, sizeof(byBuffer),
                             &cbBytesReturned,
                             (LPOVERLAPPED) NULL);
  pMountDevName = (PMOUNTDEV_NAME) byBuffer;
  _tprintf(TEXT("\n%.*ls\n"), pMountDevName->NameLength / sizeof(TCHAR), pMountDevName->Name);

  CloseHandle(hDevice);

  dwInBuffer = pMountDevName->NameLength + sizeof(MOUNTMGR_MOUNT_POINT);
  pbyInBuffer = (PBYTE) LocalAlloc(LMEM_ZEROINIT, dwInBuffer);
  pMountPoint = (PMOUNTMGR_MOUNT_POINT) pbyInBuffer;
  pMountPoint->DeviceNameLength = pMountDevName->NameLength;
  pMountPoint->DeviceNameOffset = sizeof(MOUNTMGR_MOUNT_POINT);
  CopyMemory(pbyInBuffer + sizeof(MOUNTMGR_MOUNT_POINT), pMountDevName->Name, pMountDevName->NameLength);

  dwOutBuffer = 1024 + sizeof(MOUNTMGR_MOUNT_POINTS);
  pbyOutBuffer = (PBYTE) LocalAlloc(LMEM_ZEROINIT, dwOutBuffer);
  bSuccess = DeviceIoControl(hMountMgr,
                             IOCTL_MOUNTMGR_QUERY_POINTS,
                             pbyInBuffer, dwInBuffer,
                             (LPVOID) pbyOutBuffer, dwOutBuffer,
                             &cbBytesReturned,
                             (LPOVERLAPPED) NULL);

  PMOUNTMGR_MOUNT_POINTS mount_points = (PMOUNTMGR_MOUNT_POINTS) pbyOutBuffer;
  printf("RESULT, %d: count = %d\n", bSuccess, mount_points->NumberOfMountPoints);

  for (int i = 0; i < mount_points->NumberOfMountPoints; i++) {
    auto item = mount_points->MountPoints[i];
    _tprintf(TEXT(" mountpoints[%d]: device name = %.*ls\n"), i, item.DeviceNameLength / sizeof(TCHAR), (LPCTSTR)(pbyOutBuffer + item.DeviceNameOffset));
    _tprintf(TEXT(" mountpoints[%d]: symbolic name = %.*ls\n"), i, item.SymbolicLinkNameLength/ sizeof(TCHAR), (LPCTSTR)(pbyOutBuffer + item.SymbolicLinkNameOffset));
  }

  return 0;
}
\Device\HarddiskVolume1
RESULT, 1: count = 1
 mountpoints[0]: device name = \Device\HarddiskVolume1
 mountpoints[0]: symbolic name = \??\Volume{0613c9d3-0000-0000-0000-100000000000}

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多