Windows编程:如何获取文件信息与权限?GetFileSecurityA报错998求解
Windows下无需预打开文件即可获取文件权限的解决方案
先解决你GetFileSecurityA的报错问题
错误码998(ERROR_NOACCESS)的核心问题有两个:
minNeedWords参数传了0,这个参数必须是有效的DWORD指针,用来接收函数所需的最小缓冲区大小,不能传空指针。file_security_descriptor是安全描述符结构体指针,不是字符串,直接cout输出会导致非法内存访问,毫无意义。
修正后的GetFileSecurityA示例代码:
#include <windows.h> #include <iostream> #include <string> void error_die(const char* msg) { DWORD err = GetLastError(); std::cout << msg << " failed, error code: " << err << std::endl; exit(1); } void GetFilesInfo(std::string& path) { SECURITY_INFORMATION flags = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION; DWORD buf_size = 1024; PSECURITY_DESCRIPTOR sd = static_cast<PSECURITY_DESCRIPTOR>(malloc(buf_size)); DWORD needed_size = 0; // 先尝试获取,若缓冲区不够则重新分配 if (!GetFileSecurityA(path.c_str(), flags, sd, buf_size, &needed_size)) { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { free(sd); sd = static_cast<PSECURITY_DESCRIPTOR>(malloc(needed_size)); buf_size = needed_size; if (!GetFileSecurityA(path.c_str(), flags, sd, buf_size, &needed_size)) { error_die("GetFileSecurityA"); } } else { error_die("GetFileSecurityA"); } } // 提取DACL检查当前用户权限 BOOL dacl_present, dacl_defaulted; PACL dacl = nullptr; if (GetSecurityDescriptorDacl(sd, &dacl_present, &dacl, &dacl_defaulted) && dacl_present && dacl) { HANDLE token; if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE, &token)) { PRIVILEGE_SET priv_set = {0}; DWORD priv_set_size = sizeof(priv_set); BOOL priv_needed = FALSE; DWORD access_rights = GENERIC_READ; BOOL access_granted = AccessCheck(sd, token, access_rights, &priv_set, &priv_set_size, &needed_size, &access_granted, &priv_needed); std::cout << (access_granted ? "当前用户拥有文件读取权限" : "当前用户无文件读取权限") << std::endl; CloseHandle(token); } } free(sd); } int main() { std::string path = "C:\\test.txt"; GetFilesInfo(path); return 0; }
更推荐的方案:使用GetNamedSecurityInfo
如果你不想手动处理缓冲区大小问题,GetNamedSecurityInfo更适配需求——它直接通过文件路径获取安全信息,无需提前打开文件,还能自动处理内存分配:
#include <windows.h> #include <iostream> #include <string> void error_die(const char* msg) { DWORD err = GetLastError(); std::cout << msg << " failed, error code: " << err << std::endl; exit(1); } void CheckFilePermissions(std::string& path) { PACL dacl = nullptr; PSECURITY_DESCRIPTOR sd = nullptr; DWORD err = GetNamedSecurityInfoA(path.c_str(), SE_FILE_OBJECT, DACL_SECURITY_INFORMATION, nullptr, nullptr, &dacl, nullptr, &sd); if (err != ERROR_SUCCESS) { error_die("GetNamedSecurityInfoA"); } if (dacl) { // 检查当前用户是否有写入权限 HANDLE token; if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_IMPERSONATE, &token)) { PRIVILEGE_SET priv_set = {0}; DWORD priv_set_size = sizeof(priv_set); BOOL priv_needed = FALSE; DWORD access_rights = GENERIC_WRITE; BOOL access_granted = AccessCheck(sd, token, access_rights, &priv_set, &priv_set_size, &err, &access_granted, &priv_needed); std::cout << (access_granted ? "当前用户拥有文件写入权限" : "当前用户无文件写入权限") << std::endl; CloseHandle(token); } } if (sd) { LocalFree(sd); } } int main() { std::string path = "C:\\test.txt"; CheckFilePermissions(path); return 0; }
关键说明
- 以上两个函数都支持直接通过文件路径获取安全信息,完全不需要提前用
fopen或CreateFile打开文件,满足你“先判断权限再执行实质性操作”的需求。 - 权限判断的核心是
AccessCheck函数,它会根据文件的DACL(自由访问控制列表)结合当前用户的令牌,判断是否拥有指定权限(如GENERIC_READ、GENERIC_WRITE、DELETE等)。
内容的提问来源于stack exchange,提问作者hello CPP
相关产品推荐
相关产品推荐

