From 8a6aacb82dd3feb32fa5cd5e9a24066897a3ded4 Mon Sep 17 00:00:00 2001 From: Ethan Roseman Date: Fri, 22 Sep 2023 09:13:56 +0900 Subject: [PATCH] GetLocaleInfoW (#47) * GetLocaleInfoW for ee-as.exe 991111b * Try to do it the right way * 3rd time's the charm? * round 4 * it doesn't matter now what happens i will never give up the fight * comments * fin --- CMakeLists.txt | 3 +- common.h | 2 + dll/kernel32.cpp | 104 +++++++++++++++++++---------------------------- main.cpp | 4 ++ strutil.cpp | 44 ++++++++++++++++++++ strutil.h | 7 ++++ 6 files changed, 100 insertions(+), 64 deletions(-) create mode 100644 strutil.cpp create mode 100644 strutil.h diff --git a/CMakeLists.txt b/CMakeLists.txt index f3a9fc5..0aefc7e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,10 +28,11 @@ add_executable(wibo dll/vcruntime.cpp dll/version.cpp files.cpp - processes.cpp handles.cpp loader.cpp main.cpp + processes.cpp + strutil.cpp ) target_link_libraries(wibo PRIVATE std::filesystem) install(TARGETS wibo DESTINATION bin) diff --git a/common.h b/common.h index b467b09..e274462 100644 --- a/common.h +++ b/common.h @@ -6,6 +6,7 @@ #include #include #include +#include // On Windows, the incoming stack is aligned to a 4 byte boundary. // force_align_arg_pointer will realign the stack to match GCC's 16 byte alignment. @@ -74,6 +75,7 @@ namespace wibo { extern int argc; extern char *executableName; extern char *commandLine; + extern std::vector commandLineW; extern bool debugEnabled; extern unsigned int debugIndent; diff --git a/dll/kernel32.cpp b/dll/kernel32.cpp index 80c3d9c..e4e213c 100644 --- a/dll/kernel32.cpp +++ b/dll/kernel32.cpp @@ -8,6 +8,7 @@ #include #include #include +#include "strutil.h" #include #include #include @@ -15,6 +16,7 @@ #include #include #include +#include typedef union _RTL_RUN_ONCE { PVOID Ptr; @@ -38,24 +40,6 @@ typedef struct _EXCEPTION_POINTERS { typedef LONG (*PVECTORED_EXCEPTION_HANDLER)(PEXCEPTION_POINTERS ExceptionInfo); namespace kernel32 { - static size_t wstrlen(const uint16_t *str) { - size_t len = 0; - while (str[len] != 0) - ++len; - return len; - } - - static size_t wstrncpy(uint16_t *dst, const uint16_t *src, size_t n) { - size_t i = 0; - while (i < n && src[i] != 0) { - dst[i] = src[i]; - ++i; - } - if (i < n) - dst[i] = 0; - return i; - } - static void *doAlloc(unsigned int dwBytes, bool zero) { if (dwBytes == 0) dwBytes = 1; @@ -78,30 +62,6 @@ namespace kernel32 { return ret; } - static std::string wideStringToString(const uint16_t *src, int len = -1) { - if (len < 0) { - len = src ? wstrlen(src) : 0; - } - std::string res(len, '\0'); - for (int i = 0; i < len; i++) { - res[i] = src[i] & 0xFF; - } - return res; - } - - static uint16_t *stringToWideString(const char *src) { - uint16_t *res = nullptr; - - int len = strlen(src); - res = (uint16_t *)malloc((len + 1) * 2); - for (int i = 0; i < len; i++) { - res[i] = src[i] & 0xFF; - } - res[len] = 0; // NUL terminate - - return res; - } - static int doCompareString(const std::string &a, const std::string &b, unsigned int dwCmpFlags) { for (size_t i = 0; ; i++) { if (i == a.size()) { @@ -477,7 +437,7 @@ namespace kernel32 { LPWSTR WIN_FUNC GetCommandLineW() { DEBUG_LOG("GetCommandLineW -> "); - return stringToWideString(GetCommandLineA()); + return wibo::commandLineW.data(); } char *WIN_FUNC GetEnvironmentStrings() { @@ -627,14 +587,12 @@ namespace kernel32 { const auto absStrW = stringToWideString(absStr.c_str()); DEBUG_LOG("-> %s\n", absStr.c_str()); - const auto len = wstrlen(absStrW); + const auto len = wstrlen(absStrW.data()); if (nBufferLength < len + 1) { - free(absStrW); return len + 1; } - wstrncpy(lpBuffer, absStrW, len + 1); + wstrncpy(lpBuffer, absStrW.data(), len + 1); assert(!lpFilePart); - free(absStrW); return len; } @@ -1800,25 +1758,46 @@ namespace kernel32 { return 1; } - int WIN_FUNC GetLocaleInfoA(unsigned int Locale, int LCType, char *lpLCData, int cchData) { - DEBUG_LOG("GetLocaleInfoA %d %d\n", Locale, LCType); - std::string ret; + std::string str_for_LCType(int LCType) { // https://www.pinvoke.net/default.aspx/Enums/LCType.html if (LCType == 4100) { // LOCALE_IDEFAULTANSICODEPAGE // Latin1; ref GetACP - ret = "28591"; + return "28591"; } if (LCType == 4097) { // LOCALE_SENGLANGUAGE - ret = "Lang"; + return "Lang"; } if (LCType == 4098) { // LOCALE_SENGCOUNTRY - ret = "Country"; + return "Country"; } + assert(false); + } + + int WIN_FUNC GetLocaleInfoA(unsigned int Locale, int LCType, LPSTR lpLCData, int cchData) { + DEBUG_LOG("GetLocaleInfoA %d %d\n", Locale, LCType); + std::string ret = str_for_LCType(LCType); + size_t len = ret.size() + 1; if (!cchData) { - return ret.size() + 1; + return len; } else { - memcpy(lpLCData, ret.c_str(), ret.size() + 1); + assert(len <= (size_t) cchData); + memcpy(lpLCData, ret.c_str(), len); + return 1; + } + } + + int WIN_FUNC GetLocaleInfoW(unsigned int Locale, int LCType, LPWSTR lpLCData, int cchData) { + DEBUG_LOG("GetLocaleInfoW %d %d\n", Locale, LCType); + std::string info = str_for_LCType(LCType); + auto ret = stringToWideString(info.c_str()); + size_t len = ret.size(); + + if (!cchData) { + return len; + } else { + assert(len <= (size_t) cchData); + memcpy(lpLCData, ret.data(), len * sizeof(*ret.data())); return 1; } } @@ -1879,15 +1858,13 @@ namespace kernel32 { if (!value) { return 0; } - uint16_t *wideValue = stringToWideString(value); - const auto len = wstrlen(wideValue); - if (nSize < len + 1) { - free(wideValue); - return len + 1; + auto wideValue = stringToWideString(value); + const auto len = wideValue.size(); + if (nSize < len) { + return len; } - wstrncpy(lpBuffer, wideValue, len + 1); - free(wideValue); - return len; + wstrncpy(lpBuffer, wideValue.data(), len); + return len - 1; } unsigned int WIN_FUNC QueryPerformanceCounter(unsigned long int *lpPerformanceCount) { @@ -2007,6 +1984,7 @@ static void *resolveByName(const char *name) { if (strcmp(name, "LCMapStringW") == 0) return (void *) kernel32::LCMapStringW; if (strcmp(name, "LCMapStringA") == 0) return (void *) kernel32::LCMapStringA; if (strcmp(name, "GetLocaleInfoA") == 0) return (void *) kernel32::GetLocaleInfoA; + if (strcmp(name, "GetLocaleInfoW") == 0) return (void *) kernel32::GetLocaleInfoW; if (strcmp(name, "GetUserDefaultLCID") == 0) return (void *) kernel32::GetUserDefaultLCID; if (strcmp(name, "IsDBCSLeadByte") == 0) return (void *) kernel32::IsDBCSLeadByte; diff --git a/main.cpp b/main.cpp index c461071..5a29b55 100644 --- a/main.cpp +++ b/main.cpp @@ -4,17 +4,20 @@ #include #include #include +#include "strutil.h" #include #include #include #include #include +#include uint32_t wibo::lastError = 0; char** wibo::argv; int wibo::argc; char *wibo::executableName; char *wibo::commandLine; +std::vector wibo::commandLineW; wibo::Executable *wibo::mainModule = 0; bool wibo::debugEnabled = false; unsigned int wibo::debugIndent = 0; @@ -274,6 +277,7 @@ int main(int argc, char **argv) { cmdLine += '\0'; wibo::commandLine = cmdLine.data(); + wibo::commandLineW = stringToWideString(wibo::commandLine); DEBUG_LOG("Command line: %s\n", wibo::commandLine); wibo::executableName = argv[0]; diff --git a/strutil.cpp b/strutil.cpp new file mode 100644 index 0000000..c359512 --- /dev/null +++ b/strutil.cpp @@ -0,0 +1,44 @@ +#include "common.h" +#include "strings.h" +#include + +size_t wstrlen(const uint16_t *str) { + size_t len = 0; + while (str[len] != 0) + ++len; + return len; +} + +size_t wstrncpy(uint16_t *dst, const uint16_t *src, size_t n) { + size_t i = 0; + while (i < n && src[i] != 0) { + dst[i] = src[i]; + ++i; + } + if (i < n) + dst[i] = 0; + return i; +} + +std::string wideStringToString(const uint16_t *src, int len = -1) { + if (len < 0) { + len = src ? wstrlen(src) : 0; + } + std::string res(len, '\0'); + for (int i = 0; i < len; i++) { + res[i] = src[i] & 0xFF; + } + return res; +} + +std::vector stringToWideString(const char *src) { + int len = strlen(src); + std::vector res(len + 1); + + for (size_t i = 0; i < res.size(); i++) { + res[i] = src[i] & 0xFF; + } + res[len] = 0; // NUL terminate + + return res; +} \ No newline at end of file diff --git a/strutil.h b/strutil.h new file mode 100644 index 0000000..3cdc117 --- /dev/null +++ b/strutil.h @@ -0,0 +1,7 @@ +#include +#include + +size_t wstrlen(const uint16_t *str); +size_t wstrncpy(uint16_t *dst, const uint16_t *src, size_t n); +std::string wideStringToString(const uint16_t *src, int len = -1); +std::vector stringToWideString(const char *src); \ No newline at end of file