I am coding a simple replacement for std::filesystem::exists()
function using Windows API. Surprisingly, it turned out to be pretty hard. I want to keep my code simple, so I am using minimum functions. My function of choice is GetFileAttributesW()
. Code is tested with fs::recursive_directory_iterator()
function. My function thinks that all files in “C:\Windows\servicing\LCU*” don’t exist (ERROR_PATH_NOT_FOUND). This directory is responsible for storing Windows Update Caches and is famous for having extremely long file names. I couldn’t find anything else about this directory. Example of filenames and my code are included below. Hope this helps!
Edited: The solution to this problem is to prepend absolute file path with “\\?\” char sequence. It makes Windows handle short files correctly!
C:\Windows\servicing\LCU\Package_for_RollupFix~31bf3856ad364e35~amd64~~19041.2006.1.7\amd64_microsoft-windows-a..g-whatsnew.appxmain_31bf3856ad364e35_10.0.19041.1741_none_ee5d4a8d060d7653\f\new360videossquare44x44logo.targetsize-16_altform-unplated_contrast-black.png
C:\Windows\servicing\LCU\Package_for_RollupFix~31bf3856ad364e35~amd64~~19041.2006.1.7\amd64_microsoft-windows-a..g-whatsnew.appxmain_31bf3856ad364e35_10.0.19041.1741_none_ee5d4a8d060d7653\f\new360videossquare44x44logo.targetsize-16_altform-unplated_contrast-white.png
C:\Windows\servicing\LCU\Package_for_RollupFix~31bf3856ad364e35~amd64~~19041.2006.1.7\amd64_microsoft-windows-a..g-whatsnew.appxmain_31bf3856ad364e35_10.0.19041.1741_none_ee5d4a8d060d7653\f\new360videossquare44x44logo.targetsize-20_altform-unplated_contrast-black.png
C:\Windows\servicing\LCU\Package_for_RollupFix~31bf3856ad364e35~amd64~~19041.2006.1.7\amd64_microsoft-windows-a..g-whatsnew.appxmain_31bf3856ad364e35_10.0.19041.1741_none_ee5d4a8d060d7653\f\new360videossquare44x44logo.targetsize-20_altform-unplated_contrast-white.png
#include <windows.h>
#include <filesystem>
#include <iostream>
#include <string>
using namespace std;
namespace fs = std::filesystem;
int FileExists(wstring file_path) {
/* TODO:
1. Doesn't work with "C:\\Windows\\servicing\\LCU\\*".
2. Improve error system.
*/
DWORD attributes = GetFileAttributesW(file_path.c_str());
// Valid attributes => File exists
if (attributes != INVALID_FILE_ATTRIBUTES) {
return true;
}
DWORD error_code = GetLastError();
wcout << error_code << ' ' << file_path << '\n';
// Path related error => File doesn't exist
if (error_code == ERROR_PATH_NOT_FOUND || error_code == ERROR_INVALID_NAME ||
error_code == ERROR_FILE_NOT_FOUND || error_code == ERROR_BAD_NETPATH)
{
return false;
}
// Other errors are logged before if statement
// File is busy with IO operations, etc.
return error_code;
}
int main() {
for (fs::path path : fs::recursive_directory_iterator("C:\\", fs::directory_options::skip_permission_denied)) {
FileExists(path);
}
return 0;
}