如何用C++获取NTFS特殊$Extend文件夹文件列表并解决权限报错
解决NTFS特殊文件夹/文件访问被拒绝的问题
核心问题分析
打开$Extend或$MFT这类NTFS元数据对象时,仅拥有SE_BACKUP_NAME权限和管理员身份还不够,必须正确启用权限并使用特定的文件打开参数,还要注意路径格式的正确性。
具体步骤与代码实现
1. 启用SE_BACKUP_NAME和SE_RESTORE_NAME权限
即使是管理员,这些特权默认也是禁用的,必须显式启用:
#include <windows.h> #include <sddl.h> BOOL EnablePrivilege(LPCWSTR privilegeName) { HANDLE tokenHandle; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &tokenHandle)) { return FALSE; } TOKEN_PRIVILEGES tp{}; tp.PrivilegeCount = 1; if (!LookupPrivilegeValueW(nullptr, privilegeName, &tp.Privileges[0].Luid)) { CloseHandle(tokenHandle); return FALSE; } tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; BOOL result = AdjustTokenPrivileges(tokenHandle, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), nullptr, nullptr); CloseHandle(tokenHandle); return result && GetLastError() == ERROR_SUCCESS; }
调用时需同时启用两个特权:
EnablePrivilege(SE_BACKUP_NAME); EnablePrivilege(SE_RESTORE_NAME);
2. 正确使用CreateFile打开元数据文件
打开$MFT时,需注意:
- 路径必须使用原生NT路径格式(
\\?\C:\$MFT),避免Win32路径解析限制 - 必须指定
FILE_FLAG_OPEN_REPARSE_POINT(防止解析符号链接),结合FILE_FLAG_BACKUP_SEMANTICS - 共享模式需包含
FILE_SHARE_DELETE,覆盖系统可能的锁定场景
修正后的代码:
HANDLE hMft = CreateFileW( L"\\\\?\\C:\\$MFT", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, nullptr ); if (hMft == INVALID_HANDLE_VALUE) { DWORD err = GetLastError(); // 处理错误,比如打印错误码 } else { // 成功打开,执行后续操作 CloseHandle(hMft); }
3. 枚举$Extend文件夹内容
使用FindFirstFileExW替代FindFirstFile,搭配原生NT路径和必要的标志位:
WIN32_FIND_DATAW findData{}; HANDLE hFind = FindFirstFileExW( L"\\\\?\\C:\\$Extend\\*", FindExInfoBasic, &findData, FindExSearchNameMatch, nullptr, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT ); if (hFind != INVALID_HANDLE_VALUE) { do { // 处理枚举到的文件/文件夹:findData.cFileName } while (FindNextFileW(hFind, &findData)); FindClose(hFind); } else { DWORD err = GetLastError(); // 处理错误 }
关键注意事项
- 若系统启用了BitLocker加密,加密卷的元数据文件无法通过此方式直接访问
- 部分NTFS元数据对象(如$LogFile)可能被系统独占锁定,此时需通过
FSCTL_GET_NTFS_VOLUME_DATA等API间接获取信息 - 测试时必须以本地管理员身份运行程序,远程桌面管理员可能受UAC权限限制
内容的提问来源于stack exchange,提问作者user3161924
相关产品推荐
相关产品推荐

