簡體   English   中英

使用 C++ 和 api 在 Windows 中獲取文件權限的確切方法

[英]Exact way to get permissions of a file in windows using C++ and api

我的項目就像我需要從 Web 應用程序修改文件權限 我在后端使用 java,在客戶端使用 emberjs。 為了獲得文件權限,我將 C++ 本機代碼與帶有 JNI 的 Windows api 一起使用。 這是我的問題,

我需要使用 api 獲取 windows 目錄中文件的權限。 我是 windows api 的新手,所以我用谷歌搜索並獲得了以下代碼並根據我的需要對其進行了修改。 現在的問題是當我運行它時,它會在文件具有“完全控制”權限時給我結果,否則權限不顯示 請幫我解決一下這個。 這里需要修改什么或者如果有任何其他可能的解決方案,也請給我建議。 提前致謝。

這是我的代碼,

#include <Windows.h>
#include <vector>
#include <map>
#include <iostream>
#include <aclapi.h>
#include <windows.h>
#include <string>
#include <memory>
#include <tchar.h>


using namespace std;

bool CanAccessFolder(LPCTSTR folderName, DWORD genericAccessRights,DWORD& grantedRights)
{
    bool bRet = false;
    DWORD length = 0;
    if (!::GetFileSecurity(folderName, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION
        | DACL_SECURITY_INFORMATION, NULL, NULL, &length) &&
        ERROR_INSUFFICIENT_BUFFER == ::GetLastError()) {
        PSECURITY_DESCRIPTOR security = static_cast< PSECURITY_DESCRIPTOR >(::malloc(length));
        if (security && ::GetFileSecurity(folderName, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION
            | DACL_SECURITY_INFORMATION, security, length, &length)) {
            HANDLE hToken = NULL;
            if (::OpenProcessToken(::GetCurrentProcess(), TOKEN_IMPERSONATE | TOKEN_QUERY |
                TOKEN_DUPLICATE | STANDARD_RIGHTS_READ, &hToken)) {
                HANDLE hImpersonatedToken = NULL;
                if (::DuplicateToken(hToken, SecurityImpersonation, &hImpersonatedToken)) {
                    GENERIC_MAPPING mapping = { 0xFFFFFFFF };
                    PRIVILEGE_SET privileges = { 0 };
                    DWORD grantedAccess = 0, privilegesLength = sizeof(privileges);
                    BOOL result = FALSE;

                    mapping.GenericRead = FILE_GENERIC_READ;
                    mapping.GenericWrite = FILE_GENERIC_WRITE;
                    mapping.GenericExecute = FILE_GENERIC_EXECUTE;
                    mapping.GenericAll = FILE_ALL_ACCESS;

                    ::MapGenericMask(&genericAccessRights, &mapping);
                    if (::AccessCheck(security, hImpersonatedToken, genericAccessRights,
                        &mapping, &privileges, &privilegesLength, &grantedAccess, &result)) 
                    {
                        bRet = (result == TRUE);
                        grantedRights = grantedAccess;
                    }
                    ::CloseHandle(hImpersonatedToken);
                }
                ::CloseHandle(hToken);
            }
            ::free(security);
        }
    }

    return bRet;
}

 vector<string> printMasks(DWORD Mask)
 {
     // This evaluation of the ACCESS_MASK is an example.
     // Applications should evaluate the ACCESS_MASK as necessary.
     vector<string> access;
    std::wcout << "Effective Allowed Access Mask :  "<< Mask << std::hex << std::endl;
     if (((Mask & GENERIC_ALL) == GENERIC_ALL)
         || ((Mask & FILE_ALL_ACCESS) == FILE_ALL_ACCESS))
     {
        //  wprintf_s(L"Full Control\n");
         access.push_back("Full Control");
        //  return access;
     }
     if (((Mask & GENERIC_READ) == GENERIC_READ)
         || ((Mask & FILE_GENERIC_READ) == FILE_GENERIC_READ))
        //  wprintf_s(L"Read\n");
         access.push_back("Read");
     if (((Mask & GENERIC_WRITE) == GENERIC_WRITE)
         || ((Mask & FILE_GENERIC_WRITE) == FILE_GENERIC_WRITE))
        //  wprintf_s(L"Write\n");
         access.push_back("Write");
     if (((Mask & GENERIC_EXECUTE) == GENERIC_EXECUTE)
         || ((Mask & FILE_GENERIC_EXECUTE) == FILE_GENERIC_EXECUTE))
        //  wprintf_s(L"Execute\n");
         access.push_back("Execute");

    return access;
 }


std::map<std::string, std::vector<std::string>>
list_directory(const std::string &directory)
{
    DWORD access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE | FILE_GENERIC_EXECUTE | FILE_ALL_ACCESS;
    std::map<std::string, std::vector<std::string>> files;
    WIN32_FIND_DATAA findData;
    HANDLE hFind = INVALID_HANDLE_VALUE;
    std::string full_path = directory + "\\*";

    hFind = FindFirstFileA(full_path.c_str(), &findData);

    if (hFind == INVALID_HANDLE_VALUE)
        throw std::runtime_error("Invalid handle value! Please check your path...");

    while (FindNextFileA(hFind, &findData) != 0)
    {
        std::string file = findData.cFileName;
        std::string filepath = directory + "/" + file;
        DWORD grant = 0;
        bool b = CanAccessFolder(filepath.c_str(), access_mask, grant);
        files[file] = printMasks(grant);
    }

    FindClose(hFind);

    return files;
}


int main() {
    std::map<std::string, std::vector<std::string>> files;
    files = list_directory("C:/Users/Vicky/Desktop/samples");

    int i = 1;

    map<string, vector<string>> :: iterator it=files.begin();
    //iteration using traditional for loop
    for(it=files.begin();it!=files.end();it++)
    {
        //accessing keys
        cout << it->first << " : \t";
        //accessing values (vectors)
        for (auto &&i : it->second)
        {
            cout << i << "\t";
        }
        cout << endl;
    }
}

以下是結果,

結果截圖

sample1.txt 權限

sample2.txt 權限

當您執行訪問檢查線路

    DWORD access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE | FILE_GENERIC_EXECUTE | FILE_ALL_ACCESS;

指定您正在檢查您是否對正在檢查的每個項目具有讀/寫/執行/完全控制訪問權限。

因此,當您在沒有所有這些權限的 sample2.txt 上調用AccessCheck時, AccessCheck在其最后一個參數中報告您無權訪問。 在那種情況下,GrantedAccess 參數狀態的 MSDN

[出] 授予訪問權限

指向接收授予的訪問權限的訪問掩碼的指針。 如果 >AccessStatus 設置為 FALSE,則該函數將訪問掩碼設置為零。 如果函數失敗,它不會設置訪問掩碼。

全零的訪問掩碼是您為 sample2.txt 打印的內容

如果您想查看每個文件實際上可以做什么,請將上面的行更改為

DWORD access_mask = MAXIMUM_ALLOWED;

這會導致檢查文件是否有任何訪問權限,而不是它沒有的完全控制權。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM