下面的程序还有一些问题,比如360的一些目录就用FindFirstFileA函数打开错误;还有 C:\Windows\System32\WebThreatDefSvc ,属性只有 DIRECTORY ,用 函数 _access 检查也没有问题,但是就是用FindFirstFileA打开的时候错误;至今没有想到解决办法,只能临时跳过这种目录。
#include <iostream>
#include <windows.h>
#include <strsafe.h>
#include <string>
#include <vector>
#include <stdio.h>
#include <aclapi.h>
#include <io.h>
#include <fileapi.h>
#include <winbase.h>
std::vector<std::string> v_files;
void ErrorExit(LPTSTR lpszFunction)
{
// Retrieve the system error message for the last-error code
LPVOID lpMsgBuf;
LPVOID lpDisplayBuf;
DWORD dw = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&lpMsgBuf,
0, NULL);
// Display the error message and exit the process
lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT,
(lstrlen((LPCTSTR)lpMsgBuf) + lstrlen((LPCTSTR)lpszFunction) + 40) * sizeof(TCHAR));
StringCchPrintf((LPTSTR)lpDisplayBuf,
LocalSize(lpDisplayBuf) / sizeof(TCHAR),
TEXT("%s failed with error %d: %s"),
lpszFunction, dw, lpMsgBuf);
MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK);
LocalFree(lpMsgBuf);
LocalFree(lpDisplayBuf);
ExitProcess(dw);
}
std::vector<std::string> printMasks(DWORD Mask)
{
// This evaluation of the ACCESS_MASK is an example.
// Applications should evaluate the ACCESS_MASK as necessary.
std::vector<std::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))
access.push_back("Write");
if (((Mask & GENERIC_EXECUTE) == GENERIC_EXECUTE)
|| ((Mask & FILE_GENERIC_EXECUTE) == FILE_GENERIC_EXECUTE))
access.push_back("Execute");
return access;
}
bool CanAccessFolder(LPCSTR folderName, DWORD genericAccessRights, DWORD& grantedRights)
{
bool bRet = false;
DWORD length = 0;
if (!::GetFileSecurityA(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 && ::GetFileSecurityA(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;
}
BOOL CheckFileReadAccess(char* filePath)
{
DWORD result = FALSE;
BOOL bret = FALSE;
DWORD infoLen = 0;
std::string wuname = "CURRENT_USER";
std::cout << " in CheckFileReadAccess file:" << filePath << std::endl
PSECURITY_DESCRIPTOR pSD = NULL;
if (!GetFileSecurityA(filePath, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, NULL, 0, &infoLen)&& ERROR_INSUFFICIENT_BUFFER == ::GetLastError())
{
std::cout << "infoLen:" << infoLen << std::endl;
pSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, infoLen /*dwSizeNeeded*/);
if (pSD && GetFileSecurityA(filePath, OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, pSD, infoLen /*dwSizeNeeded*/, &result))
{
if (result <= infoLen)
{
EXPLICIT_ACCESS_A ea;
ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
ea.grfAccessPermissions = GENERIC_READ;
ea.grfAccessMode = SET_ACCESS;
ea.grfInheritance = NO_INHERITANCE;
ea.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
ea.Trustee.TrusteeType = TRUSTEE_IS_USER;
ea.Trustee.ptstrName = (char *)wuname.c_str(); // 这里检查当前用户的权限,你可以根据需要更改
BOOL lpbDaclPresent;
PACL pOldDACL = NULL;
BOOL csdResult = FALSE;
PACL pNewDACL = NULL;
if (GetSecurityDescriptorDacl(pSD, &lpbDaclPresent, &pOldDACL , &csdResult))
{
if (SetEntriesInAclA(1, &ea, pOldDACL, &pNewDACL))
{
std::cout << __LINE__ << std::endl;
GENERIC_MAPPING genericMapping;
genericMapping.GenericRead = FILE_GENERIC_READ;
genericMapping.GenericWrite = FILE_GENERIC_WRITE;
genericMapping.GenericExecute = FILE_GENERIC_EXECUTE;
genericMapping.GenericAll = FILE_ALL_ACCESS;
PPRIVILEGE_SET pset = {0};
DWORD dwPrivSetSize = sizeof(PRIVILEGE_SET);
DWORD pdwAccessAllowed;
BOOL fAccessGranted = FALSE;
std::cout << " GetSecurityDescriptorDacl Ok, before AccessCheck" << std::endl;
if (AccessCheck(pSD, &ea.Trustee, GENERIC_READ, &genericMapping, pset, &dwPrivSetSize, &pdwAccessAllowed, &fAccessGranted)) {
if ((fAccessGranted & GENERIC_READ) == GENERIC_READ)
{
bret = TRUE; // 用户有读取权限
}
}
LocalFree(pNewDACL);
} else {
std::wstring wstr = L"SetEntriesInAclA";
ErrorExit((wchar_t *)wstr.c_str());
std::cout << "Err when SetEntriesInAclA" << std::endl;
}
} else {
std::wstring wstr = L"GetSecurityDescriptorDacl";
ErrorExit((wchar_t*)wstr.c_str());
std::cout << "err when GetSecurityDescriptorDacl" << std::endl;
}
} else {
std::wstring wstr = L"GetFileSecurityA";
ErrorExit((wchar_t*)wstr.c_str());
std::cout << "err when GetFileSecurityA" << std::endl;
}
}
LocalFree(pSD);
}
else {
std::cout << "Err when GetFileSecurityA" << std::endl;
}
// CloseHandle(hFile);
//}
//else {
// std::cout << "Err when CreateFileA" << std::endl;
//}
return bret;
}
int wstr2mstr(std::wstring &wstr, std::string& mstr)
{
size_t wlen = wstr.length();
if (wlen == 0)
{
std::cout << "wstr len is zero " << std::endl;
return 0;
}
int mlen = WideCharToMultiByte(CP_UTF8, 0, (const wchar_t*)wstr.c_str(),(int) wlen, NULL, 0, NULL, NULL);
std::cout << "mlen+" << mlen << std::endl;
char* buf = (char*)malloc(mlen * sizeof(char) + 1);
if (buf == NULL)
{
std::cout << "malloc err" << std::endl;
return 0;
}
memset(buf, 0, mlen * sizeof(char) + 1);
int result = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), wlen, buf, mlen, NULL, NULL);
mstr = buf;
free(buf);
std::cout << "wstr to str len is :" << mlen << " driv:" << mstr << std::endl;
return mlen;
}
int printAttr(DWORD attr)
{
std::cout << "attr: " << attr << " ATTR START:"; // << std::endl;
if (attr & FILE_ATTRIBUTE_READONLY)
std::cout << " READONLY"; // << std::endl;
if (attr & FILE_ATTRIBUTE_HIDDEN)
std::cout << " HIDDEN"; // << std::endl;
if (attr & FILE_ATTRIBUTE_SYSTEM)
std::cout << " SYSTEM"; // << std::endl;
if (attr & FILE_ATTRIBUTE_DIRECTORY)
std::cout << " DIRECTORY"; // << std::endl;
if (attr & FILE_ATTRIBUTE_ARCHIVE)
std::cout << " ARCHIVE"; // << std::endl;
if (attr & FILE_ATTRIBUTE_DEVICE)
std::cout << " DEVICE"; // << std::endl;
if (attr & FILE_ATTRIBUTE_NORMAL)
std::cout << " NORMAL"; // << std::endl;
if (attr & FILE_ATTRIBUTE_TEMPORARY)
std::cout << " TEMPORARY";// << std::endl;
if (attr & FILE_ATTRIBUTE_SPARSE_FILE)
std::cout << " SPARSE_FILE"; // << std::endl;
if (attr & FILE_ATTRIBUTE_REPARSE_POINT)
std::cout << " REPARSE_POINT"; // << std::endl;
if (attr & FILE_ATTRIBUTE_COMPRESSED)
std::cout << " COMPRESSED"; // << std::endl;
if (attr & FILE_ATTRIBUTE_OFFLINE)
std::cout << " OFFLINE"; // << std::endl;
if (attr & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED)
std::cout << " NOT_CONTENT_INDEXED"; // << std::endl;
if (attr & FILE_ATTRIBUTE_ENCRYPTED)
std::cout << " ENCRYPTED"; // << std::endl;
if (attr & FILE_ATTRIBUTE_INTEGRITY_STREAM)
std::cout << " INTEGRITY_STREAM"; // << std::endl;
if (attr & FILE_ATTRIBUTE_VIRTUAL)
std::cout << " VIRTUAL"; // << std::endl;
if (attr & FILE_ATTRIBUTE_NO_SCRUB_DATA)
std::cout << " NO_SCRUB_DATA"; // << std::endl;
if (attr & FILE_ATTRIBUTE_EA)
std::cout << " EA"; // << std::endl;
if (attr & FILE_ATTRIBUTE_PINNED)
std::cout << " PINNED"; // << std::endl;
if (attr & FILE_ATTRIBUTE_UNPINNED)
std::cout << " UNPINNED"; // << std::endl;
if (attr & FILE_ATTRIBUTE_RECALL_ON_OPEN)
std::cout << " RECALL_ON_OPEN"; // << std::endl;
if (attr & FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS)
std::cout << " ON_DATA_ACCESS"; // << std::endl;
std::cout << ": ATTR End " << std::endl;
return 1;
}
int notProcessfiles(DWORD attr)
{
DWORD rdonlyFile;
DWORD hiddenFile;
DWORD systemFile;
//DWORD archFile;
DWORD tmpFile;
DWORD offlineFile;
DWORD encryFile;
DWORD virtFile;
DWORD eaFile;
DWORD pinnedFile;
DWORD unpinedFile;
DWORD recallOpenFile;
DWORD recallAcceFile;
DWORD deviceFile;
DWORD sumAttr = 0;
DWORD notIndexed = 0;
rdonlyFile = attr & FILE_ATTRIBUTE_READONLY;
hiddenFile = attr & FILE_ATTRIBUTE_HIDDEN;
systemFile = attr & FILE_ATTRIBUTE_SYSTEM;
//archFile = attr & FILE_ATTRIBUTE_ARCHIVE;
tmpFile = attr & FILE_ATTRIBUTE_TEMPORARY;
offlineFile = attr & FILE_ATTRIBUTE_OFFLINE;
encryFile = attr & FILE_ATTRIBUTE_ENCRYPTED;
virtFile = attr & FILE_ATTRIBUTE_VIRTUAL;
eaFile = attr & FILE_ATTRIBUTE_EA;
pinnedFile = attr & FILE_ATTRIBUTE_PINNED;
unpinedFile = attr & FILE_ATTRIBUTE_UNPINNED;
recallOpenFile = attr & FILE_ATTRIBUTE_RECALL_ON_OPEN;
recallAcceFile = attr & FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS;
deviceFile = attr & FILE_ATTRIBUTE_DEVICE;
notIndexed = attr & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
sumAttr = rdonlyFile | systemFile | tmpFile | offlineFile | encryFile | virtFile | eaFile | pinnedFile | unpinedFile | recallOpenFile | recallAcceFile | deviceFile | notIndexed | hiddenFile;
printAttr(attr);
return sumAttr;
}
std::vector<std::string> gv_skip_dirs={"RtBackup","WebThreatDefSvc"};
BOOL isSkipDirs(std::string dir)
{
for (auto it : gv_skip_dirs)
{
if (it == dir)
{
return TRUE;
}
}
return FALSE;
}
//unsigned long long generail_file =
void ListFilesRecursively(const std::string path, const std::string& searchPattern = "*")
{
WIN32_FIND_DATAA findData;
HANDLE hFind;
std::cout << __LINE__ << std::endl;
std::string searchPath = path + "\\" + searchPattern;
//不检查诸如 c: d: 这样的盘符
if (path[path.length() - 1] != ':')
{
//BOOL bret = CheckFileReadAccess((char*)path.c_str());
/* DWORD access_mask = FILE_GENERIC_READ | FILE_GENERIC_WRITE | FILE_GENERIC_EXECUTE | FILE_ALL_ACCESS;
DWORD grant = 0;
BOOL bret = CanAccessFolder((char *)path.c_str(), access_mask, grant);
std::cout << path << "; access right:" << bret << std::endl;
*/
if (_access(path.c_str(), 6) != 0)
{
std::cout << path << ", cannot access" << std::endl;
return;
}
else {
std::cout << path << ", CAN access" << std::endl;
}
}
DWORD dwAttr = GetFileAttributesA(path.c_str());
std::cout << path << "; dwAttr:" << dwAttr << std::endl;
if (notProcessfiles(dwAttr) != 0)
{
std::cout << "Skip directory: " << path << std::endl;
return;
}
hFind = FindFirstFileA((char *)searchPath.c_str(), &findData);
std::cout << searchPath << ", hFind :" << hFind << "; dwAttr:" << dwAttr << std::endl;
if (hFind != INVALID_HANDLE_VALUE)
{
std::cout << __LINE__ << std::endl;
do
{
std::string wFullPathName = findData.cFileName;
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if(wFullPathName != "." && wFullPathName != ".." && !isSkipDirs(findData.cFileName))
{
std::string newPath = path + "\\" + std::string(findData.cFileName);
std::string mstrNewPath;
if (1 /*mlen > 0*/)
{
std::cout << "dir:" << newPath << std::endl;
//if (notProcessfiles(findData.dwFileAttributes) == 0)
if (_access(newPath.c_str(), 6) == 0)
{
std::cout << __LINE__ << std::endl;
ListFilesRecursively(newPath);
std::cout << __LINE__ << std::endl;
}
else
{
std::cout << "Cannot access for path" << std::endl;
}
}
}
} else {
std::string newFilePath = path + "\\" + std::string(findData.cFileName);
if(1)
{
std::cout << "FILE: " << newFilePath << "; Attr:" << findData.dwFileAttributes << std::endl;
if (notProcessfiles(findData.dwFileAttributes) == 0)
{
std::cout << "Gather FILE: " << newFilePath << std::endl;
v_files.push_back(newFilePath);
}
else {
std::cout << "Skip FILE: " << newFilePath << std::endl;
}
}
}
} while (FindNextFileA(hFind, &findData));
FindClose(hFind);
std::wcout << __LINE__ << std::endl;
}
else {
std::wstring wstr = L"ListFilesRecursivelyW";
//ErrorExit((wchar_t *)wstr.c_str());
}
std::wcout << __LINE__ << std::endl;
}
int main() {
// 获取所有磁盘的驱动器字母
DWORD bufferSize = GetLogicalDriveStringsW(0, nullptr);
std::vector<wchar_t> buffer(bufferSize);
GetLogicalDriveStringsW(bufferSize, buffer.data());
std::wstring drives(buffer.begin(), buffer.end());
size_t pos = 0;
std::wstring drive;
std::string mdrive;
PVOID OldValue = NULL;
if (1 /* Wow64DisableWow64FsRedirection(&OldValue)*/ )
{
// 遍历所有磁盘,并列出文件
while ((pos = drives.find(L'\\', pos)) != std::wstring::npos) {
drive = drives.substr(0, pos);
Sleep(4);
mdrive.clear();
int len = wstr2mstr(drive, mdrive);
if (len > 0)
{
std::cout << "Harddisk drive:" << mdrive << std::endl;
ListFilesRecursively(mdrive);
}
else {
std::cout << "Error when Get Harddisk drive" << std::endl;
}
drives.erase(0, pos + 2);
}
// 处理最后一个驱动器(如果有的话)
if (!drives.empty())
{
ListFilesRecursively(mdrive);
}
//Wow64RevertWow64FsRedirection(OldValue);
}
else {
std::cout << "WoW64 Err" << std::endl;
}
return 0;
}