从文件句柄获得全路径
2016-06-20 00:00
351 查看
从文件句柄获得全路径这个问题,似乎是个“老大难”问题。
很久以前我就在水木清华见到过。最近又不断有人提到。
其实问题并不难,只是解决办法有点绕,不是调用一个API就能解决的。
问题的关键在于,形如”X:”的Dos设备名都是符号链接(SymblicLink),而文件打开后文件对象中保存的是逻辑卷设备名(如”\Device\HarddiskVolumeX”)。前者可以转换成后者,而后者却不能简单地转换成前者。以至于从句柄得到的路径总是“缺少”盘符这一部分。实际上,把所有的”X:”都变成设备名去匹配路径就可以了。
下面是演示代码,很简单,所以就不加注释啦 ^_^
#include <windows.h>
#include <ntsecapi.h>
#pragma comment (lib,"ntdll.lib") // Copy From DDK
NTSYSAPI
NTSTATUS
NTAPI
ZwQueryObject(
IN HANDLE ObjectHandle,
IN ULONG ObjectInformationClass,
OUT PVOID ObjectInformation,
IN ULONG ObjectInformationLength,
OUT PULONG ReturnLength OPTIONAL
);
BOOL GetPathByHandle(HANDLE hFile, LPWSTR lpBuf, DWORD nBuf)
{
ULONG m, n;
WCHAR lpPath[MAX_PATH+4];
WCHAR lpDrive[MAX_PATH];
WCHAR lpDevName[MAX_PATH];
if (ZwQueryObject(hFile, 1, lpPath, MAX_PATH+4, &m) >= 0 &&
(m = GetLogicalDriveStringsW(MAX_PATH, lpDrive)) && m < MAX_PATH)
{
WCHAR *p = lpDrive;
while (m = wcslen(p))
{
p[m-1] = L'\0';
n = QueryDosDeviceW(p, lpDevName, MAX_PATH);
if (n && n < MAX_PATH)
{
n = wcslen(lpDevName);
if (!wcsnicmp(lpPath+4, lpDevName, n))
{
wcsncpy(lpBuf, p, nBuf);
if (nBuf > 2) wcsncpy(lpBuf+2, lpPath+4+n, nBuf-2);
return TRUE;
}
}
p += m + 1;
}
}
return FALSE;
}
void main()
{
WCHAR buf[MAX_PATH];
HANDLE hFile = createFile("C:\\boot.ini", 0, 0, 0, OPEN_EXISTING, 0, 0);
if (hFile != INVALID_HANDLE_VALUE)
{
GetPathByHandle(hFile, buf, MAX_PATH);
printf("%ws\n", buf);
CloseHandle(hFile);
}
else
{
printf("createFile Failed: %d\n", GetLastError());
}
}
很久以前我就在水木清华见到过。最近又不断有人提到。
其实问题并不难,只是解决办法有点绕,不是调用一个API就能解决的。
问题的关键在于,形如”X:”的Dos设备名都是符号链接(SymblicLink),而文件打开后文件对象中保存的是逻辑卷设备名(如”\Device\HarddiskVolumeX”)。前者可以转换成后者,而后者却不能简单地转换成前者。以至于从句柄得到的路径总是“缺少”盘符这一部分。实际上,把所有的”X:”都变成设备名去匹配路径就可以了。
下面是演示代码,很简单,所以就不加注释啦 ^_^
#include <windows.h>
#include <ntsecapi.h>
#pragma comment (lib,"ntdll.lib") // Copy From DDK
NTSYSAPI
NTSTATUS
NTAPI
ZwQueryObject(
IN HANDLE ObjectHandle,
IN ULONG ObjectInformationClass,
OUT PVOID ObjectInformation,
IN ULONG ObjectInformationLength,
OUT PULONG ReturnLength OPTIONAL
);
BOOL GetPathByHandle(HANDLE hFile, LPWSTR lpBuf, DWORD nBuf)
{
ULONG m, n;
WCHAR lpPath[MAX_PATH+4];
WCHAR lpDrive[MAX_PATH];
WCHAR lpDevName[MAX_PATH];
if (ZwQueryObject(hFile, 1, lpPath, MAX_PATH+4, &m) >= 0 &&
(m = GetLogicalDriveStringsW(MAX_PATH, lpDrive)) && m < MAX_PATH)
{
WCHAR *p = lpDrive;
while (m = wcslen(p))
{
p[m-1] = L'\0';
n = QueryDosDeviceW(p, lpDevName, MAX_PATH);
if (n && n < MAX_PATH)
{
n = wcslen(lpDevName);
if (!wcsnicmp(lpPath+4, lpDevName, n))
{
wcsncpy(lpBuf, p, nBuf);
if (nBuf > 2) wcsncpy(lpBuf+2, lpPath+4+n, nBuf-2);
return TRUE;
}
}
p += m + 1;
}
}
return FALSE;
}
void main()
{
WCHAR buf[MAX_PATH];
HANDLE hFile = createFile("C:\\boot.ini", 0, 0, 0, OPEN_EXISTING, 0, 0);
if (hFile != INVALID_HANDLE_VALUE)
{
GetPathByHandle(hFile, buf, MAX_PATH);
printf("%ws\n", buf);
CloseHandle(hFile);
}
else
{
printf("createFile Failed: %d\n", GetLastError());
}
}
相关文章推荐
- 一个NOD32的升级补丁
- D3D中的光照(5)
- 码根码
- D3D中网格模型的运用
- OGame研究说明
- Symantec 的i32更新包与x86更新包的区别
- 微操教学
- 3D数学 ---- 矩阵的更多知识(4)
- PHP将uncode转utf8,一行代码解决问题
- 初次使用 git 的“核弹级选项”:filter-branch 从仓库中删除文件
- Windows NT/2000/XP下不用驱动的Ring0代码实现
- I Love You的真正含义
- ADSL知识合集
- 驱动级隐藏文件,注册表,进程
- 有一家银行每天早上都在你的帐户里存入86,400
- DirectX 9高层着色语言介绍4——语言基础(3)
- Game组首次超过Hack组
- 牛人与非牛人的对话
- 20145319 《java程序设计》课程总结
- 程序员的灯下黑:如果你想考研究生或是研究生