Skip to content

Instantly share code, notes, and snippets.

@Jamesits
Forked from m13253/preload.cpp
Created September 8, 2017 06:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Jamesits/d8a0dd8e96c1a0dbff579aa807f70fd7 to your computer and use it in GitHub Desktop.
Save Jamesits/d8a0dd8e96c1a0dbff579aa807f70fd7 to your computer and use it in GitHub Desktop.
Preload files into memory cache, for example IME database, in case you have a slow HDD.
#include <windows.h>
#include <string>
using namespace std::string_literals;
constexpr size_t buffer_size = 64*1024;
static char buffer[buffer_size];
static DWORD PrintString(HANDLE h_stdout, std::wstring const& string) {
DWORD count;
WriteConsoleW(h_stdout, string.c_str(), string.length(), &count, NULL);
return count;
}
static HRESULT ReportError(HANDLE h_stdout, HRESULT error) {
LPWSTR msgbuf = NULL;
if(FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR) &msgbuf, 0, NULL) == 0) {
PrintString(h_stdout, L"Unknown error.\r\n"s);
return error;
}
PrintString(h_stdout, msgbuf);
LocalFree(msgbuf);
return error;
}
static HRESULT FirstNonzero(HRESULT first, HRESULT second) {
return first ? first : second;
}
static std::wstring CombinePath(std::wstring const& first, std::wstring const& second) {
std::wstring result;
result.reserve(first.length() + 1 + second.length());
result += first;
result += L'\\';
result += second;
return result;
}
static HRESULT PreloadFile(HANDLE h_stdout, std::wstring const& path) {
PrintString(h_stdout, path + L"\r\n"s);
HANDLE file = CreateFileW(path.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if(file == INVALID_HANDLE_VALUE) {
return ReportError(h_stdout, GetLastError());
}
DWORD ncharsread;
do {
if(!ReadFile(file, buffer, buffer_size, &ncharsread, NULL)) {
HRESULT error = GetLastError();
CloseHandle(file);
return ReportError(h_stdout, error);
}
} while(ncharsread != 0);
CloseHandle(file);
return 0;
}
static HRESULT IterPath(HANDLE h_stdout, std::wstring const& path, std::wstring const& pattern) {
HRESULT retval = 0;
std::wstring combined = CombinePath(path, pattern);
PrintString(h_stdout, L"Search: "s + combined + L"\r\n"s);
WIN32_FIND_DATAW find_data;
HANDLE find = FindFirstFileW(combined.c_str(), &find_data);
if(find == INVALID_HANDLE_VALUE) {
return ReportError(h_stdout, GetLastError());
}
do {
if(find_data.cFileName == L"."s || find_data.cFileName == L".."s) {
continue;
}
std::wstring sub_path = path + L'\\' + find_data.cFileName;
if((find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
retval = FirstNonzero(retval, IterPath(h_stdout, sub_path, L"*"s));
} else {
retval = FirstNonzero(retval, PreloadFile(h_stdout, sub_path));
}
} while(FindNextFileW(find, &find_data));
HRESULT error = GetLastError();
FindClose(find);
if(error != ERROR_NO_MORE_FILES) {
return ReportError(h_stdout, error);
}
return retval;
}
int main(void) {
HRESULT error = 0;
HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE);
LPCWSTR cmdline = GetCommandLineW();
int argc;
LPWSTR *argv = CommandLineToArgvW(cmdline, &argc);
if(argc > 1) {
for(int argi = 1; argi < argc; ++argi) {
std::wstring path = argv[argi];
size_t sep = path.rfind(L'\\');
std::wstring pattern;
if(sep != path.npos) {
pattern = path.substr(sep+1);
path = path.substr(0, sep);
} else {
pattern = path;
path = L"."s;
}
if(pattern.empty()) {
pattern = L"*"s;
}
error = FirstNonzero(error, IterPath(h_stdout, path, pattern));
}
} else {
PrintString(h_stdout, L"Usage: preload PATH [PATH ...]\r\n\r\nThis program preloads files into memory cache, for example IME database, in case you have a slow HDD.\r\n\r\n"s);
error = 1;
}
LocalFree(argv);
ExitProcess(error);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment