[开源]NT路径转DOS路径的简单办法
以前也曾为NT路径转DOS路径而烦恼,网上翻了很久,总觉得那些操作太过繁琐,我本人比较懒,就一直想找个简单的办法,现在终于找到了。ring3下的NT路径转DOS路径,通常所采用的套路是查询符号链接,ring0下就好搞了,有IoVolumeDeviceToDosName ,IoQueryFileDosDeviceName 。看某位大表哥的博客,IoQueryFileDosDeviceName 接口在某个情况下会导致系统卡死。
现在在提供一种办法,简单又粗暴,改改可以放到ring0下跑,粗略测试还是很靠谱的。套路如下:
typedef struct _MOUNTDEV_NAME {
USHORTNameLength;
WCHAR Name;
} MOUNTDEV_NAME, *PMOUNTDEV_NAME;
typedef struct _MOUNTMGR_VOLUME_PATHS {
ULONG MultiSzLength;
WCHAR MultiSz;
} MOUNTMGR_VOLUME_PATHS, *PMOUNTMGR_VOLUME_PATHS;
#define MOUNTMGRCONTROLTYPE ((ULONG) 'm')
#define IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH \
CTL_CODE(MOUNTMGRCONTROLTYPE, 12, METHOD_BUFFERED, FILE_ANY_ACCESS)
DWORD VolumeDeviceNameToDosName( IN LPCWSTR DeviceName, OUT LPWSTR DosName )
{
PMOUNTDEV_NAME MountName = NULL;
CHAR buffer1 = { 0 };
CHAR buffer2 = { 0 };
HANDLE MountPointMgr = NULL;
DWORD BytesReturned = 0;
MountPointMgr = CreateFile(
L"\\\\.\\MountPointManager",
0,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
0,
NULL
);
if( MountPointMgr == INVALID_HANDLE_VALUE )
return GetLastError();
MountName = ( PMOUNTDEV_NAME )buffer1;
wcscpy( MountName->Name, DeviceName );
MountName->NameLength = wcslen( MountName->Name ) * 2;
DeviceIoControl(
MountPointMgr,
IOCTL_MOUNTMGR_QUERY_DOS_VOLUME_PATH,
MountName,
512,
buffer2,
512,
&BytesReturned,
NULL
);
if( ! GetLastError() )
wcscpy( DosName, ( ( PMOUNTMGR_VOLUME_PATHS )buffer2 )->MultiSz );
CloseHandle( MountPointMgr );
return GetLastError();
}输入:\Device\HarddiskVolume1
输出:C: 直接用QueryDosDevice可以兼容R3和R0:http://www.m5home.com/bbs/thread-7622-1-1.html
PS:杭州潜水艇(hzqst),出来走两步。 其实这个就是IoVolumeDeviceToDosName 的R3版本 //发个r0的
PWSTR _GetSymbolicTarget(PCWSTR pwSymbolic)
{
OBJECT_ATTRIBUTES oa;
UNICODE_STRING uSymbolic;
NTSTATUS status;
HANDLE hSymbolic;
UNICODE_STRING uTarget;
ULONG len = 0;
WCHAR buf;
PWSTR pwTarget;
RtlInitUnicodeString(&uSymbolic, pwSymbolic);
InitializeObjectAttributes(&oa, &uSymbolic, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL,NULL);
status = ZwOpenSymbolicLinkObject(&hSymbolic, GENERIC_READ, &oa);
if (!NT_SUCCESS(status))
{
DbgPrint(("hpsafe:%-4d ZwOpenSymbolicLinkObject failed with 0x%08X.\n", __LINE__, status));
return NULL;
}
RtlInitEmptyUnicodeString(&uTarget, buf, 0);
status = ZwQuerySymbolicLinkObject(hSymbolic, &uTarget, &len);
if (status != STATUS_BUFFER_TOO_SMALL)
{
DbgPrint(("hpsafe:%-4d ZwQuerySymbolicLinkObject failed with 0x%08X.\n", __LINE__, status));
return NULL;
}
pwTarget = ExAllocatePoolWithTag(NonPagedPool, len + sizeof(WCHAR), '_EL_');
if (!pwTarget)
{
DbgPrint(("hpsafe:%-4d ExAllocatePoolWithTag failed.\n", __LINE__));
ZwClose(hSymbolic);
return NULL;
}
RtlInitEmptyUnicodeString(&uTarget, pwTarget, (USHORT)len + sizeof(WCHAR));
status = ZwQuerySymbolicLinkObject(hSymbolic, &uTarget, &len);
ZwClose(hSymbolic);
if (!NT_SUCCESS(status))
{
DbgPrint(("hpsafe:%-4d ZwQuerySymbolicLinkObject failed with 0x%08X.\n", __LINE__, status));
ExFreePoolWithTag(pwTarget, '_EL_');
return NULL;
}
return pwTarget;
}
PWSTR _DosPathToNtPath(PCWSTR pwDosPath)
{
PWSTR pwTarget, pNtPath;
SIZE_T l1, l2;
WCHAR pwDosDrive[] = L"\\DosDevices\\X:";
if ((*pwDosPath >= L'a' && *pwDosPath <= L'z' ||
*pwDosPath >= L'A' && *pwDosPath <= L'Z') &&
pwDosPath == L':' && pwDosPath == L'\\')
{
/* get nt drive path */
pwDosDrive = pwDosPath;
pwTarget = _GetSymbolicTarget(pwDosDrive);
if (!pwTarget)
return NULL;
/* concat two part */
RtlStringCbLengthW(pwTarget, NTSTRSAFE_MAX_CCH * sizeof(WCHAR), &l1);
RtlStringCbLengthW(pwDosPath + 2, NTSTRSAFE_MAX_CCH * sizeof(WCHAR), &l2);
pNtPath = ExAllocatePoolWithTag(NonPagedPool, l1 + l2 + sizeof(WCHAR), '_EL_');
if (pNtPath)
{
RtlStringCbCopyW(pNtPath, l1 + sizeof(WCHAR), pwTarget);
RtlStringCbCopyW(pNtPath + l1 / sizeof(WCHAR), l2 + sizeof(WCHAR), pwDosPath + 2);
}
else
{
DbgPrint(("hpsafe:%-4d ExAllocatePoolWithTag failed.\n", __LINE__));
}
ExFreePoolWithTag(pwTarget, '_EL_');
return pNtPath;
}
else
{
DbgPrint(("hpsafe:%-4d unsupported path: %ws.\n", __LINE__, pwDosPath));
return NULL;
}
}
PWSTR _NtPathToDosPath(PCWSTR pwNtPath)
{
PWSTR pwDosPath;
WCHAR pwDosDrive[] = L"\\DosDevices\\X:";
PWSTR pwTarget;
WCHAR c;
USHORT len;
UNICODE_STRING usTarget;
UNICODE_STRING usNtPath;
UNICODE_STRING usDosPath;
RtlInitUnicodeString(&usNtPath, pwNtPath);
for (c = L'A'; c <= L'Z'; ++ c)
{
pwDosDrive = c;
pwTarget = _GetSymbolicTarget(pwDosDrive);
if (!pwTarget)
continue;
/*
DbgPrint(("hpsafe:%-4d %c:\\ -> %ws.\n", __LINE__,
(CHAR)c, pwTarget));
*/
RtlInitUnicodeString(&usTarget, pwTarget);
if (RtlPrefixUnicodeString(&usTarget, &usNtPath, TRUE))
{
len = (wcslen(pwNtPath) - wcslen(pwTarget) + 4) * sizeof(WCHAR);
pwDosPath = ExAllocatePoolWithTag(NonPagedPool, len, '_EL_');
if (!pwDosPath)
{
DbgPrint(("hpsafe:%-4d ExAllocatePoolWithTag failed.\n", __LINE__));
return NULL;
}
memset(pwDosPath, 0, len);
RtlInitEmptyUnicodeString(&usDosPath, pwDosPath, len);
RtlUnicodeStringCopyString(&usDosPath, L"x:");
*pwDosPath = c;
RtlUnicodeStringCatString(&usDosPath, pwNtPath + wcslen(pwTarget) );
return pwDosPath;
}
}
return NULL;
}
感谢分享,看看怎么实现的
页:
[1]