diff --git a/build_linux.sh b/build_linux.sh index b02831e4..e31dbee6 100644 --- a/build_linux.sh +++ b/build_linux.sh @@ -165,6 +165,7 @@ release_incs_both=( "sdk" "overlay_experimental" "crash_printer" + "helpers" ) release_incs32=( "${release_incs_both[@]}" @@ -216,7 +217,7 @@ release_src=( "dll/*.cpp" "$protoc_out_dir/*.cc" "crash_printer/linux.cpp" - "crash_printer/common.cpp" + "helpers/common_helpers.cpp" ) # additional #defines diff --git a/build_win.bat b/build_win.bat index be81496a..2c8b7efa 100644 --- a/build_win.bat +++ b/build_win.bat @@ -199,7 +199,7 @@ set mbedtls_lib32="%deps_dir%\mbedtls\install32\lib\mbedcrypto.lib" set mbedtls_lib64="%deps_dir%\mbedtls\install64\lib\mbedcrypto.lib" :: directories to use for #include -set release_incs_both=%ssq_inc% /I"%libs_dir%" /I"%protoc_out_dir%" /I"%libs_dir%\utfcpp" /I"controller" /I"dll" /I"sdk" /I"overlay_experimental" /I"crash_printer" +set release_incs_both=%ssq_inc% /I"%libs_dir%" /I"%protoc_out_dir%" /I"%libs_dir%\utfcpp" /I"controller" /I"dll" /I"sdk" /I"overlay_experimental" /I"crash_printer" /I"helpers" set release_incs32=%release_incs_both% %curl_inc32% %protob_inc32% %zlib_inc32% %mbedtls_inc32% set release_incs64=%release_incs_both% %curl_inc64% %protob_inc64% %zlib_inc64% %mbedtls_inc64% @@ -211,7 +211,7 @@ set release_libs32=%release_libs_both% %ssq_lib32% %curl_lib32% %protob_lib32% % set release_libs64=%release_libs_both% %ssq_lib64% %curl_lib64% %protob_lib64% %zlib_lib64% %mbedtls_lib64% :: common source files used everywhere, just for convinience, you still have to provide a complete list later -set release_src="dll/*.cpp" "%protoc_out_dir%/*.cc" "crash_printer/win.cpp" "crash_printer/common.cpp" +set release_src="dll/*.cpp" "%protoc_out_dir%/*.cc" "crash_printer/win.cpp" "helpers/common_helpers.cpp" :: additional #defines set "common_defs=/DUTF_CPP_CPLUSPLUS=201703L /DCURL_STATICLIB /DUNICODE /D_UNICODE" @@ -585,7 +585,7 @@ endlocal & exit /b %_exit% :compile_experimentalclient_ldr_32 setlocal echo // building executable steamclient_loader_32.exe - 32 - set src_files="%win_resources_out_dir%\rsrc-launcher-32.res" "%tools_src_dir%\steamclient_loader\win\*.cpp" "pe_helpers\pe_helpers.cpp" + set src_files="%win_resources_out_dir%\rsrc-launcher-32.res" "%tools_src_dir%\steamclient_loader\win\*.cpp" "helpers\pe_helpers.cpp" "helpers\common_helpers.cpp" set extra_inc_dirs=/I"%tools_src_dir%\steamclient_loader\win\extra_protection" /I"pe_helpers" set "extra_libs=user32.lib" call :build_for 1 2 "%steamclient_dir%\steamclient_loader_32.exe" src_files extra_inc_dirs "" "%extra_libs%" @@ -678,7 +678,7 @@ endlocal & exit /b %_exit% :compile_experimentalclient_ldr_64 setlocal echo // building executable steamclient_loader_64.exe - 64 - set src_files="%win_resources_out_dir%\rsrc-launcher-64.res" "%tools_src_dir%\steamclient_loader\win\*.cpp" "pe_helpers\pe_helpers.cpp" + set src_files="%win_resources_out_dir%\rsrc-launcher-64.res" "%tools_src_dir%\steamclient_loader\win\*.cpp" "helpers\pe_helpers.cpp" "helpers\common_helpers.cpp" set extra_inc_dirs=/I"%tools_src_dir%\steamclient_loader\win\extra_protection" /I"pe_helpers" set "extra_libs=user32.lib" call :build_for 0 2 "%steamclient_dir%\steamclient_loader_64.exe" src_files extra_inc_dirs "" "%extra_libs%" diff --git a/crash_printer/common.cpp b/crash_printer/common.cpp deleted file mode 100644 index b88179a9..00000000 --- a/crash_printer/common.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include "crash_printer/common.hpp" -#include -#include - -static bool create_dir_impl(std::filesystem::path &dirpath) -{ - if (std::filesystem::is_directory(dirpath)) - { - return true; - } - else if (std::filesystem::exists(dirpath)) // a file, we can't do anything - { - return false; - } - - return std::filesystem::create_directories(dirpath); -} - -bool crash_printer::create_dir(const std::string &filepath) -{ - std::filesystem::path dirpath = std::filesystem::path(filepath).parent_path(); - return create_dir_impl(dirpath); -} - -bool crash_printer::create_dir(const std::wstring &filepath) -{ - std::filesystem::path dirpath = std::filesystem::path(filepath).parent_path(); - return create_dir_impl(dirpath); -} - -void crash_printer::write(std::ofstream &file, const std::string &data) -{ - if (!file.is_open()) { - return; - } - - file << data << std::endl; -} diff --git a/crash_printer/crash_printer/common.hpp b/crash_printer/crash_printer/common.hpp deleted file mode 100644 index 4e4b93b5..00000000 --- a/crash_printer/crash_printer/common.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef _CRASH_PRINTER_COMMON_H -#define _CRASH_PRINTER_COMMON_H - - -#include -#include - -namespace crash_printer { - -bool create_dir(const std::string &dir); - -bool create_dir(const std::wstring &dir); - -void write(std::ofstream &file, const std::string &data); - -} - -#endif // _CRASH_PRINTER_COMMON_H diff --git a/crash_printer/linux.cpp b/crash_printer/linux.cpp index 5c9ca0ce..e9719a13 100644 --- a/crash_printer/linux.cpp +++ b/crash_printer/linux.cpp @@ -1,6 +1,6 @@ // https://stackoverflow.com/a/1925461 -#include "crash_printer/common.hpp" +#include "common_helpers/common_helpers.hpp" #include "crash_printer/linux.hpp" #include @@ -46,7 +46,7 @@ static void restore_handlers() static void exception_handler(int signal, siginfo_t *info, void *context, struct sigaction *oldact) { - if (!crash_printer::create_dir(logs_filepath)) { + if (!common_helpers::create_dir(logs_filepath)) { return; } @@ -57,12 +57,12 @@ static void exception_handler(int signal, siginfo_t *info, void *context, struct auto gm_time = std::gmtime(&t_now); auto time = std::string(std::asctime(gm_time)); time.pop_back(); // remove the trailing '\n' added by asctime - crash_printer::write(file, "[" + time + "]"); + common_helpers::write(file, "[" + time + "]"); { std::stringstream ss{}; ss << "Unhandled exception:" << std::endl << " code: " << std::dec << signal << " (" << strsignal(signal) << ")" << std::endl; - crash_printer::write(file, ss.str()); + common_helpers::write(file, ss.str()); } void* stack_frames[max_stack_frames]; int stack_size = backtrace(stack_frames, max_stack_frames); @@ -70,20 +70,20 @@ static void exception_handler(int signal, siginfo_t *info, void *context, struct if (stack_symbols != nullptr) { // fprintf(stderr, "Stack trace:\n"); - crash_printer::write(file, "*********** Stack trace ***********"); + common_helpers::write(file, "*********** Stack trace ***********"); for (int i = 1; i < stack_size; ++i) { char *symbol = stack_symbols[i]; std::stringstream ss{}; ss << "[frame " << std::dec << (stack_size - i - 1) << "]: " << std::hex << stack_frames[i] << " | " << symbol; - crash_printer::write(file, ss.str()); + common_helpers::write(file, ss.str()); } free(stack_symbols); } - crash_printer::write(file, "**********************************\n"); + common_helpers::write(file, "**********************************\n"); file.close(); } diff --git a/crash_printer/win.cpp b/crash_printer/win.cpp index 02c404d3..e9139f9f 100644 --- a/crash_printer/win.cpp +++ b/crash_printer/win.cpp @@ -1,4 +1,4 @@ -#include "crash_printer/common.hpp" +#include "common_helpers/common_helpers.hpp" #include "crash_printer/win.hpp" #include @@ -45,7 +45,7 @@ static void print_stacktrace(std::ofstream &file, CONTEXT* context) { stack_frame.AddrFrame.Mode = ADDRESS_MODE::AddrModeFlat; stack_frame.AddrStack.Mode = ADDRESS_MODE::AddrModeFlat; - crash_printer::write(file, "*********** Stack trace ***********"); + common_helpers::write(file, "*********** Stack trace ***********"); std::vector symbols{}; while (true) { BOOL res = StackWalk( @@ -92,14 +92,14 @@ static void print_stacktrace(std::ofstream &file, CONTEXT* context) { std::stringstream ss{}; ss << "[frame " << std::dec << (idx - 1) << "]: " << s; - crash_printer::write(file, ss.str()); + common_helpers::write(file, ss.str()); idx--; } } static void log_exception(LPEXCEPTION_POINTERS ex_pointers) { - if (!crash_printer::create_dir(logs_filepath)) { + if (!common_helpers::create_dir(logs_filepath)) { return; } @@ -110,17 +110,17 @@ static void log_exception(LPEXCEPTION_POINTERS ex_pointers) auto gm_time = std::gmtime(&t_now); auto time = std::string(std::asctime(gm_time)); time.pop_back(); // remove the trailing '\n' added by asctime - crash_printer::write(file, "[" + time + "]"); + common_helpers::write(file, "[" + time + "]"); { std::stringstream ss{}; ss << "Unhandled exception:" << std::endl << " code: 0x" << std::hex << ex_pointers->ExceptionRecord->ExceptionCode << std::endl << " @address = 0x" << std::hex << ex_pointers->ExceptionRecord->ExceptionAddress; - crash_printer::write(file, ss.str()); + common_helpers::write(file, ss.str()); } print_stacktrace(file, ex_pointers->ContextRecord); - crash_printer::write(file, "**********************************\n"); + common_helpers::write(file, "**********************************\n"); file.close(); } @@ -139,13 +139,13 @@ static LONG WINAPI exception_handler(LPEXCEPTION_POINTERS ex_pointers) bool crash_printer::init(const std::wstring &log_file) { logs_filepath = log_file; - originalExceptionFilter = SetUnhandledExceptionFilter(exception_handler); - return true; } void crash_printer::deinit() { - + if (originalExceptionFilter) { + SetUnhandledExceptionFilter(originalExceptionFilter); + } } diff --git a/helpers/common_helpers.cpp b/helpers/common_helpers.cpp new file mode 100644 index 00000000..651f9c20 --- /dev/null +++ b/helpers/common_helpers.cpp @@ -0,0 +1,106 @@ +#include "common_helpers/common_helpers.hpp" +#include +#include +#include +#include + +static bool create_dir_impl(std::filesystem::path &dirpath) +{ + if (std::filesystem::is_directory(dirpath)) + { + return true; + } + else if (std::filesystem::exists(dirpath)) // a file, we can't do anything + { + return false; + } + + return std::filesystem::create_directories(dirpath); +} + +bool common_helpers::create_dir(const std::string &filepath) +{ + std::filesystem::path parent = std::filesystem::path(filepath).parent_path(); + return create_dir_impl(parent); +} + +bool common_helpers::create_dir(const std::wstring &filepath) +{ + std::filesystem::path parent = std::filesystem::path(filepath).parent_path(); + return create_dir_impl(parent); +} + +void common_helpers::write(std::ofstream &file, const std::string &data) +{ + if (!file.is_open()) { + return; + } + + file << data << std::endl; +} + +std::wstring common_helpers::str_to_w(const std::string &str) +{ + auto cvt_state = std::mbstate_t(); + const char* src = &str[0]; + size_t conversion_bytes = std::mbsrtowcs(nullptr, &src, 0, &cvt_state); + std::wstring res(conversion_bytes + 1, L'\0'); + std::mbsrtowcs(&res[0], &src, res.size(), &cvt_state); + return res.substr(0, conversion_bytes); +} + +std::string common_helpers::wstr_to_a(const std::wstring &wstr) +{ + auto cvt_state = std::mbstate_t(); + const wchar_t* src = &wstr[0]; + size_t conversion_bytes = std::wcsrtombs(nullptr, &src, 0, &cvt_state); + std::string res(conversion_bytes + 1, '\0'); + std::wcsrtombs(&res[0], &src, res.size(), &cvt_state); + return res.substr(0, conversion_bytes); +} + +bool common_helpers::starts_with_i(const std::string &target, const std::string &query) +{ + return starts_with_i(str_to_w(target), str_to_w(query)); +} + +bool common_helpers::starts_with_i(const std::wstring &target, const std::wstring &query) +{ + if (target.size() < query.size()) { + return false; + } + + auto _target = std::wstring(target); + auto _query = std::wstring(query); + std::transform(_target.begin(), _target.end(), _target.begin(), + [](wchar_t c) { return std::tolower(c); }); + + std::transform(_query.begin(), _query.end(), _query.begin(), + [](wchar_t c) { return std::tolower(c); }); + + return _target.compare(0, _query.length(), _query) == 0; + +} + +bool common_helpers::ends_with_i(const std::string &target, const std::string &query) +{ + return ends_with_i(str_to_w(target), str_to_w(query)); +} + +bool common_helpers::ends_with_i(const std::wstring &target, const std::wstring &query) +{ + if (target.size() < query.size()) { + return false; + } + + auto _target = std::wstring(target); + auto _query = std::wstring(query); + std::transform(_target.begin(), _target.end(), _target.begin(), + [](wchar_t c) { return std::tolower(c); }); + + std::transform(_query.begin(), _query.end(), _query.begin(), + [](wchar_t c) { return std::tolower(c); }); + + return _target.compare(_target.length() - _query.length(), _query.length(), _query) == 0; + +} diff --git a/helpers/common_helpers/common_helpers.hpp b/helpers/common_helpers/common_helpers.hpp new file mode 100644 index 00000000..a6ca5860 --- /dev/null +++ b/helpers/common_helpers/common_helpers.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include +#include + +namespace common_helpers { + +bool create_dir(const std::string &dir); + +bool create_dir(const std::wstring &dir); + +void write(std::ofstream &file, const std::string &data); + +std::wstring str_to_w(const std::string &str); + +std::string wstr_to_a(const std::wstring &wstr); + +bool starts_with_i(const std::string &target, const std::string &query); + +bool starts_with_i(const std::wstring &target, const std::wstring &query); + +bool ends_with_i(const std::string &target, const std::string &query); + +bool ends_with_i(const std::wstring &target, const std::wstring &query); + +} diff --git a/helpers/dbg_log.cpp b/helpers/dbg_log.cpp new file mode 100644 index 00000000..4d888161 --- /dev/null +++ b/helpers/dbg_log.cpp @@ -0,0 +1,75 @@ +#include "dbg_log/dbg_log.hpp" + +#include +#include +#include +#include +#include +#include +#include + +static FILE* out_file = nullptr; +auto const static start_time = std::chrono::system_clock::now(); +static std::recursive_mutex f_mtx{}; + +bool dbg_log::init(const wchar_t *path) +{ + auto p = std::filesystem::path(path).string(); + return init(p.c_str()); +} + +bool dbg_log::init(const char *path) +{ +#ifndef EMU_RELEASE_BUILD + std::lock_guard lk(f_mtx); + if (!out_file) { + out_file = std::fopen(path, "a"); + if (!out_file) { + return false; + } + } + +#endif + + return true; +} + +void dbg_log::write(const char *fmt, ...) +{ + +#ifndef EMU_RELEASE_BUILD + std::lock_guard lk(f_mtx); + if (out_file) { + auto elapsed = std::chrono::system_clock::now() - start_time; + + std::stringstream ss{}; + ss << "[" << std::chrono::duration_cast(elapsed).count() << " ms] [tid: " << std::this_thread::get_id() << "] "; + auto ss_str = ss.str(); + + std::fprintf(out_file, ss_str.c_str()); + + std::va_list args; + va_start(args, fmt); + std::vfprintf(out_file, fmt, args); + va_end(args); + + std::fprintf(out_file, "\n"); + std::fflush(out_file); + } +#endif + +} + +void dbg_log::close() +{ + +#ifndef EMU_RELEASE_BUILD + std::lock_guard lk(f_mtx); + if (out_file) { + std::fprintf(out_file, "\nLog file closed\n\n"); + std::fclose(out_file); + out_file = nullptr; + } +#endif + +} diff --git a/helpers/dbg_log/dbg_log.hpp b/helpers/dbg_log/dbg_log.hpp new file mode 100644 index 00000000..95869624 --- /dev/null +++ b/helpers/dbg_log/dbg_log.hpp @@ -0,0 +1,14 @@ +#pragma once + +namespace dbg_log +{ + +bool init(const wchar_t *path); + +bool init(const char *path); + +void write(const char* fmt, ...); + +void close(); + +} diff --git a/pe_helpers/pe_helpers.cpp b/helpers/pe_helpers.cpp similarity index 83% rename from pe_helpers/pe_helpers.cpp rename to helpers/pe_helpers.cpp index ce49b3ba..7aa47e5d 100644 --- a/pe_helpers/pe_helpers.cpp +++ b/helpers/pe_helpers.cpp @@ -1,6 +1,9 @@ #include "pe_helpers/pe_helpers.hpp" +#include "common_helpers/common_helpers.hpp" #include #include +#include +#include static inline bool is_hex(const char c) { @@ -361,3 +364,58 @@ size_t pe_helpers::get_pe_size(HMODULE hModule) return size; } + +static std::wstring path_w{}; +static std::string path_a{}; +const std::string pe_helpers::get_current_exe_path() +{ + if (path_a.empty()) { + get_current_exe_path_w(); + } + + return path_a; +} + +const std::wstring pe_helpers::get_current_exe_path_w() +{ + static std::recursive_mutex path_mtx{}; + if (path_w.empty()) { + std::lock_guard lk(path_mtx); + + if (path_w.empty()) { + DWORD err = GetLastError(); + + path_w.resize(8192); + DWORD read_chars = GetModuleFileNameW(GetModuleHandleW(nullptr), &path_w[0], (DWORD)path_w.size()); + if (read_chars >= path_w.size()) { + path_w.resize(read_chars); + read_chars = GetModuleFileNameW(GetModuleHandleW(nullptr), &path_w[0], (DWORD)path_w.size()); + } + + if ((read_chars < path_w.size()) && path_w[0]) { + path_w = path_w.substr(0, path_w.find_last_of(L"\\/") + 1); + + auto cvt_state = std::mbstate_t(); + const wchar_t* src = &path_w[0]; + size_t conversion_bytes = std::wcsrtombs(nullptr, &src, 0, &cvt_state); + path_a.resize(conversion_bytes + 1); + std::wcsrtombs(&path_a[0], &src, path_a.size(), &cvt_state); + path_a = path_a.substr(0, conversion_bytes); + } else { + path_w.clear(); + } + + SetLastError(err); + } + } + + return path_w; +} + +bool pe_helpers::ends_with_i(PUNICODE_STRING target, const std::wstring &query) +{ + return common_helpers::ends_with_i( + std::wstring(target->Buffer, (PWSTR)((char*)target->Buffer + target->Length)), + query + ); +} diff --git a/pe_helpers/pe_helpers/pe_helpers.hpp b/helpers/pe_helpers/pe_helpers.hpp similarity index 78% rename from pe_helpers/pe_helpers/pe_helpers.hpp rename to helpers/pe_helpers/pe_helpers.hpp index b556134c..0005e9cd 100644 --- a/pe_helpers/pe_helpers/pe_helpers.hpp +++ b/helpers/pe_helpers/pe_helpers.hpp @@ -2,6 +2,7 @@ #define WIN32_LEAN_AND_MEAN #include +#include #include @@ -33,4 +34,10 @@ DWORD loadlib_remote(HANDLE hProcess, const std::wstring &lib_fullpath, const ch size_t get_pe_size(HMODULE hModule); +const std::string get_current_exe_path(); + +const std::wstring get_current_exe_path_w(); + +bool ends_with_i(PUNICODE_STRING target, const std::wstring &query); + } diff --git a/resources/win/file_dos_stub/build_file_dos_stub.bat b/resources/win/file_dos_stub/build_file_dos_stub.bat index eccde699..8dfa1c90 100644 --- a/resources/win/file_dos_stub/build_file_dos_stub.bat +++ b/resources/win/file_dos_stub/build_file_dos_stub.bat @@ -29,7 +29,7 @@ set "common_exe_linker_args_32=%common_linker_args%" set "common_exe_linker_args_64=%common_linker_args%" :: directories to use for #include -set release_incs_both=%ssq_inc% /I"../../../pe_helpers" +set release_incs_both=%ssq_inc% /I"../../../helpers" set release_incs32=%release_incs_both% set release_incs64=%release_incs_both% @@ -41,7 +41,7 @@ set release_libs32=%release_libs_both% set release_libs64=%release_libs_both% :: common source files used everywhere, just for convinience, you still have to provide a complete list later -set release_src="file_dos_stub.cpp" "../../../pe_helpers/pe_helpers.cpp" +set release_src="file_dos_stub.cpp" "../../../helpers/pe_helpers.cpp" "../../../helpers/common_helpers.cpp" :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: x32 diff --git a/resources/win/file_dos_stub/file_dos_stub.cpp b/resources/win/file_dos_stub/file_dos_stub.cpp index 1ff6f2c9..374a59c7 100644 --- a/resources/win/file_dos_stub/file_dos_stub.cpp +++ b/resources/win/file_dos_stub/file_dos_stub.cpp @@ -21,14 +21,15 @@ static size_t get_file_size(std::fstream &file) } -static std::vector load_file(std::fstream &file, size_t size) +static std::vector load_file_partial(std::fstream &file) { try { auto org_pos = file.tellg(); file.seekg(0, std::ios::beg); - std::vector data(size, 0); + // 2MB is enough + std::vector data(2 * 1024 * 1024, 0); file.read((char *)&data[0], data.size()); file.seekg(org_pos, std::ios::beg); @@ -67,7 +68,7 @@ int main(int argc, char* *argv) std::cerr << "Failed get file size for file: '" << arg << "'" << std::endl; return 1; } - auto data = load_file(file, file_size); + auto data = load_file_partial(file); if (data.empty()) { std::cerr << "Failed get file data for file: '" << arg << "'" << std::endl; return 1; diff --git a/resources/win/file_dos_stub/file_dos_stub_32.exe b/resources/win/file_dos_stub/file_dos_stub_32.exe index b45b24e7..3647f105 100644 Binary files a/resources/win/file_dos_stub/file_dos_stub_32.exe and b/resources/win/file_dos_stub/file_dos_stub_32.exe differ diff --git a/resources/win/file_dos_stub/file_dos_stub_64.exe b/resources/win/file_dos_stub/file_dos_stub_64.exe index f622283e..87ea849a 100644 Binary files a/resources/win/file_dos_stub/file_dos_stub_64.exe and b/resources/win/file_dos_stub/file_dos_stub_64.exe differ