You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Windows编程:如何获取文件信息与权限?GetFileSecurityA报错998求解

Windows下无需预打开文件即可获取文件权限的解决方案

先解决你GetFileSecurityA的报错问题

错误码998(ERROR_NOACCESS)的核心问题有两个:

  1. minNeedWords参数传了0,这个参数必须是有效的DWORD指针,用来接收函数所需的最小缓冲区大小,不能传空指针。
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 02:20:36