LiteLoaderBDS-1.16.40/LiteLoader/Kernel/Utils/WinHelper.cpp
2022-09-21 19:47:03 +08:00

200 lines
6.1 KiB
C++

#include <Utils/StringHelper.h>
#include <Utils/WinHelper.h>
#include <Main/LiteLoader.h>
#include <Utils/DbgHelper.h>
#include <LoggerAPI.h>
#include <I18nAPI.h>
#include <Psapi.h>
#include <string>
#include <Main/Config.h>
using namespace std;
string GetLastErrorMessage(DWORD error_message_id) {
if (error_message_id == 0)
return "";
LPWSTR message_buffer = nullptr;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
nullptr, error_message_id, MAKELANGID(0x09, SUBLANG_DEFAULT), (LPWSTR)&message_buffer, 0, nullptr);
string res = wstr2str(wstring(message_buffer));
LocalFree(message_buffer);
return res;
}
string GetLastErrorMessage() {
DWORD error_message_id = ::GetLastError();
if (error_message_id == 0)
return "";
LPWSTR message_buffer = nullptr;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM,
nullptr, error_message_id, MAKELANGID(0x09, SUBLANG_DEFAULT), (LPWSTR)&message_buffer, 0, nullptr);
string res = wstr2str(wstring(message_buffer));
LocalFree(message_buffer);
return res;
}
// Tool
wchar_t* str2cwstr(const string& str) {
auto len = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, nullptr, 0);
auto* buffer = new wchar_t[len + 1];
MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, buffer, len + 1);
buffer[len] = L'\0';
return buffer;
}
#define READ_BUFFER_SIZE 4096
bool NewProcess(const std::string& process, std::function<void(int, std::string)> callback, int timeLimit) {
SECURITY_ATTRIBUTES sa;
HANDLE hRead, hWrite;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = nullptr;
sa.bInheritHandle = TRUE;
if (!CreatePipe(&hRead, &hWrite, &sa, 0))
return false;
STARTUPINFOW si = {0};
PROCESS_INFORMATION pi;
si.cb = sizeof(STARTUPINFO);
GetStartupInfoW(&si);
si.hStdOutput = si.hStdError = hWrite;
si.dwFlags = STARTF_USESTDHANDLES;
auto wCmd = str2cwstr(process);
if (!CreateProcessW(nullptr, wCmd, nullptr, nullptr, TRUE, 0, nullptr, nullptr, &si, &pi)) {
delete[] wCmd;
return false;
}
CloseHandle(hWrite);
CloseHandle(pi.hThread);
std::thread([hRead{hRead}, hProcess{pi.hProcess},
callback{std::move(callback)}, timeLimit{timeLimit}, wCmd{wCmd}]() {
if (!LL::isDebugMode())
_set_se_translator(seh_exception::TranslateSEHtoCE);
if (timeLimit == -1)
WaitForSingleObject(hProcess, INFINITE);
else {
WaitForSingleObject(hProcess, timeLimit);
TerminateProcess(hProcess, -1);
}
char buffer[READ_BUFFER_SIZE];
string strOutput;
DWORD bytesRead, exitCode;
delete[] wCmd;
GetExitCodeProcess(hProcess, &exitCode);
while (true) {
ZeroMemory(buffer, READ_BUFFER_SIZE);
if (!ReadFile(hRead, buffer, READ_BUFFER_SIZE, &bytesRead, nullptr))
break;
strOutput.append(buffer, bytesRead);
}
CloseHandle(hRead);
CloseHandle(hProcess);
try {
if (callback)
callback((int)exitCode, strOutput);
} catch (const seh_exception& e) {
logger.error("SEH Uncaught Exception Detected!\n{}", TextEncoding::toUTF8(e.what()));
logger.error("In NewProcess callback");
PrintCurrentStackTraceback();
} catch (...) {
logger.error("NewProcess Callback Failed!");
logger.error("Uncaught Exception Detected!");
PrintCurrentStackTraceback();
}
}).detach();
return true;
}
std::pair<int, string> NewProcessSync(const std::string& process, int timeLimit, bool noReadOutput) {
SECURITY_ATTRIBUTES sa;
HANDLE hRead, hWrite;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = nullptr;
sa.bInheritHandle = TRUE;
if (!CreatePipe(&hRead, &hWrite, &sa, 0))
return {-1, ""};
STARTUPINFOW si = {0};
PROCESS_INFORMATION pi;
si.cb = sizeof(STARTUPINFO);
GetStartupInfoW(&si);
si.hStdOutput = si.hStdError = hWrite;
si.dwFlags = STARTF_USESTDHANDLES;
auto wCmd = str2cwstr(process);
if (!CreateProcessW(nullptr, wCmd, nullptr, nullptr, TRUE, 0, nullptr, nullptr, &si, &pi)) {
delete[] wCmd;
return {-1, ""};
}
CloseHandle(hWrite);
CloseHandle(pi.hThread);
if (timeLimit == -1)
WaitForSingleObject(pi.hProcess, INFINITE);
else {
WaitForSingleObject(pi.hProcess, timeLimit);
TerminateProcess(pi.hProcess, -1);
}
char buffer[READ_BUFFER_SIZE];
string strOutput;
DWORD bytesRead, exitCode;
delete[] wCmd;
GetExitCodeProcess(pi.hProcess, &exitCode);
if (!noReadOutput) {
while (true) {
ZeroMemory(buffer, READ_BUFFER_SIZE);
if (!ReadFile(hRead, buffer, READ_BUFFER_SIZE, &bytesRead, nullptr))
break;
strOutput.append(buffer, bytesRead);
}
}
CloseHandle(hRead);
CloseHandle(pi.hProcess);
return {exitCode, strOutput};
}
string GetModulePath(HMODULE handle) {
wchar_t buf[MAX_PATH] = {0};
GetModuleFileNameEx(GetCurrentProcess(), handle, buf, MAX_PATH);
return wstr2str(std::wstring(buf));
}
string GetModuleName(HMODULE handle) {
wchar_t buf[MAX_PATH] = {0};
GetModuleFileNameEx(GetCurrentProcess(), handle, buf, MAX_PATH);
return UTF82String(std::filesystem::path(buf).filename().u8string());
}
std::string GetSystemLocaleName() {
wchar_t buf[256] = {0};
auto lcid = GetSystemDefaultLCID();
GetSystemDefaultLocaleName(buf, lcid);
auto str = wstr2str(buf);
std::replace(str.begin(), str.end(), '-', '_');
return str;
}
inline bool isWine() {
HMODULE ntdll = GetModuleHandle(L"ntdll.dll");
auto pwine_get_version = GetProcAddress(ntdll, "wine_get_version");
if (pwine_get_version)
return true;
else
return false;
}
bool IsWineEnvironment() {
static bool result = isWine();
return result;
}