使用 C++ 和 api 在 windows 中获取文件权限的确切方法
Exact way to get permissions of a file in windows using C++ and api
我的项目就像我需要从网络应用程序修改文件权限一样。我在后端使用 java,在客户端使用 emberjs。为了获得文件权限,我使用带有 windows api 和 JNI 的 C++ 本机代码。这是我的问题,
我需要使用 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;
指定您正在检查如果您有 read/write/execute/full 控制对您正在检查的每个项目的访问权限。
因此,当您在没有所有这些权限的 sample2.txt 上调用 AccessCheck
时,AccessCheck
在其最后一个参数中报告您没有访问权限。在那种情况下,GrantedAccess 参数的 MSDN 状态
[out] GrantedAccess
A pointer to an access mask that receives the granted access rights. If >AccessStatus is set to FALSE, the function sets the access mask to zero. If
the function fails, it does not set the access mask.
全零的访问掩码就是您为 sample2.txt
打印的内容
如果您想查看每个文件的实际操作,请将上面的行更改为
DWORD access_mask = MAXIMUM_ALLOWED;
这会导致检查文件的任何访问权限,而不是检查它没有的完全控制权限。
我的项目就像我需要从网络应用程序修改文件权限一样。我在后端使用 java,在客户端使用 emberjs。为了获得文件权限,我使用带有 windows api 和 JNI 的 C++ 本机代码。这是我的问题,
我需要使用 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;
指定您正在检查如果您有 read/write/execute/full 控制对您正在检查的每个项目的访问权限。
因此,当您在没有所有这些权限的 sample2.txt 上调用 AccessCheck
时,AccessCheck
在其最后一个参数中报告您没有访问权限。在那种情况下,GrantedAccess 参数的 MSDN 状态
[out] GrantedAccess
A pointer to an access mask that receives the granted access rights. If >AccessStatus is set to FALSE, the function sets the access mask to zero. If the function fails, it does not set the access mask.
全零的访问掩码就是您为 sample2.txt
打印的内容如果您想查看每个文件的实际操作,请将上面的行更改为
DWORD access_mask = MAXIMUM_ALLOWED;
这会导致检查文件的任何访问权限,而不是检查它没有的完全控制权限。