Windows XP下NT设备路径短名扩展为长名的实现方案咨询
兼容Windows XP的可行实现方案
核心逻辑:利用CreateFile可直接识别原生NT路径的特性,通过文件句柄查询长名称,绕开Win32 API路径解析层对NT路径的格式限制。
具体实现步骤
- 第一步:调用CreateFileW打开目标NT路径,使用最低权限参数避免占用或无法打开文件,同时兼容目录场景:
HANDLE hFile = CreateFileW( ntPath, // 从NtQueryObject拿到的原始NT路径,例如\Device\HarddiskVolume1\Users\ADMINI~1\... FILE_READ_ATTRIBUTES, // 仅需读取属性,权限要求最低 FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, // 不独占文件 NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, // 支持打开目录句柄,适配路径为目录的场景 NULL ); if (hFile == INVALID_HANDLE_VALUE) { // 自定义错误处理,如权限不足、文件已删除时可降级保留原始短名 return; }
- 第二步:动态导入ntdll.dll中的
NtQueryInformationFile函数,XP及以上系统均自带该导出,函数原型如下:
// 先定义需要用到的结构体和枚举 typedef enum _FILE_INFORMATION_CLASS { FileFullNameInformation = 14 } FILE_INFORMATION_CLASS; typedef struct _IO_STATUS_BLOCK { union { NTSTATUS Status; PVOID Pointer; }; ULONG_PTR Information; } IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; typedef struct _FILE_FULL_NAME_INFORMATION { ULONG FileNameLength; WCHAR FileName[1]; } FILE_FULL_NAME_INFORMATION, *PFILE_FULL_NAME_INFORMATION; // 导入函数 typedef NTSTATUS (WINAPI *PFN_NtQueryInformationFile)( HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock, PVOID FileInformation, ULONG Length, FILE_INFORMATION_CLASS FileInformationClass ); PFN_NtQueryInformationFile pNtQueryInformationFile = (PFN_NtQueryInformationFile)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtQueryInformationFile");
- 第三步:调用函数查询长路径,拼接得到完整NT长路径:
// 分配足够的缓冲区存储路径,最大路径长度设为32767即可覆盖所有合法路径 ULONG bufSize = 32767 * sizeof(WCHAR) + FIELD_OFFSET(FILE_FULL_NAME_INFORMATION, FileName); PFILE_FULL_NAME_INFORMATION pNameInfo = (PFILE_FULL_NAME_INFORMATION)malloc(bufSize); IO_STATUS_BLOCK iosb; NTSTATUS status = pNtQueryInformationFile( hFile, &iosb, pNameInfo, bufSize, FileFullNameInformation ); if (NT_SUCCESS(status)) { // 拆分原始NT路径,获取卷设备前缀(如\Device\HarddiskVolume1) WCHAR* pThirdBackslash = wcsstr(wcsstr(wcsstr(ntPath, L"\\"), L"\\") + 1, L"\\"); if (pThirdBackslash) { WCHAR fullNtPath[32767]; // 拼接卷前缀 + 查询到的长路径 size_t prefixLen = pThirdBackslash - ntPath; wcsncpy(fullNtPath, ntPath, prefixLen); fullNtPath[prefixLen] = 0; wcsncat(fullNtPath, pNameInfo->FileName, pNameInfo->FileNameLength / sizeof(WCHAR)); // fullNtPath即为转换完成的完整长名NT路径 } } // 资源释放 free(pNameInfo); CloseHandle(hFile);
可选兜底方案
如果目标文件被独占打开无法调用CreateFile,可以逐段解析路径:将路径按\分割,从卷根开始逐段调用NtQueryDirectoryObject枚举目录项,匹配短名得到对应长名后拼接,该方案无需打开目标文件,只是实现复杂度稍高。
内容的提问来源于stack exchange,提问作者DavidZi
相关产品推荐
相关产品推荐

