diff --git a/dll/kernel32/winnls.cpp b/dll/kernel32/winnls.cpp index 6d684c0..fd6598f 100644 --- a/dll/kernel32/winnls.cpp +++ b/dll/kernel32/winnls.cpp @@ -97,6 +97,24 @@ UINT WINAPI GetACP() { return 28591; // Latin1 (ISO/IEC 8859-1) } +UINT WINAPI GetOEMCP() { + HOST_CONTEXT_GUARD(); + // IBM PC US (codepage 437) is the canonical OEM codepage for NT-era + // tools built on English locales; matches what Wine and NT return by + // default when no locale override is present. + DEBUG_LOG("GetOEMCP() -> %u\n", 437); + return 437; +} + +BOOL WINAPI SetFileApisToOEM() { + // Switches kernel32 Ansi<->Oem conversion for file-path APIs. Since + // our codepages are effectively 1:1 mappings for ASCII, there's + // nothing to configure; returning success is safe. + HOST_CONTEXT_GUARD(); + DEBUG_LOG("SetFileApisToOEM() -> TRUE (no-op)\n"); + return TRUE; +} + LANGID WINAPI GetSystemDefaultLangID() { HOST_CONTEXT_GUARD(); DEBUG_LOG("STUB: GetSystemDefaultLangID()\n"); diff --git a/dll/kernel32/winnls.h b/dll/kernel32/winnls.h index 3700351..a74eb42 100644 --- a/dll/kernel32/winnls.h +++ b/dll/kernel32/winnls.h @@ -17,6 +17,8 @@ typedef BOOL(_CC_STDCALL *LOCALE_ENUMPROCA)(LPSTR); namespace kernel32 { UINT WINAPI GetACP(); +UINT WINAPI GetOEMCP(); +BOOL WINAPI SetFileApisToOEM(); LANGID WINAPI GetSystemDefaultLangID(); LANGID WINAPI GetUserDefaultUILanguage(); int WINAPI GetUserDefaultLocaleName(LPWSTR lpLocaleName, int cchLocaleName); diff --git a/dll/user32.cpp b/dll/user32.cpp index 1d30c1d..bb7c6e2 100644 --- a/dll/user32.cpp +++ b/dll/user32.cpp @@ -175,6 +175,48 @@ HWND WINAPI GetActiveWindow() { return NO_HANDLE; } +/* + * CharToOem / OemToChar conversion between the "ANSI" and "OEM" codepages. + * For the codepages wibo exposes (GetACP=1252 Latin1 / 28591, GetOEMCP=437) + * the ASCII range 0x00-0x7F is identity in both directions; the high-half + * differs but NT-era build tools (MC, RC) only feed these APIs argv + * strings and filenames, which in practice are ASCII. We implement + * identity mapping: correct for ASCII, safe fallback for high-bytes, and + * sufficient for our build pipeline. + */ +static BOOL charToOemA_impl(LPCSTR src, LPSTR dst, DWORD length, BOOL counted) { + if (!src || !dst) return FALSE; + if (counted) { + for (DWORD i = 0; i < length; i++) dst[i] = src[i]; + } else { + while (*src) *dst++ = *src++; + *dst = 0; + } + return TRUE; +} + +BOOL WINAPI CharToOemA(LPCSTR lpszSrc, LPSTR lpszDst) { + DEBUG_LOG("CharToOemA(%p, %p) (identity)\n", lpszSrc, lpszDst); + return charToOemA_impl(lpszSrc, lpszDst, 0, FALSE); +} + +BOOL WINAPI CharToOemBuffA(LPCSTR lpszSrc, LPSTR lpszDst, DWORD cchDstLength) { + DEBUG_LOG("CharToOemBuffA(%p, %p, %lu)\n", lpszSrc, lpszDst, + static_cast(cchDstLength)); + return charToOemA_impl(lpszSrc, lpszDst, cchDstLength, TRUE); +} + +BOOL WINAPI OemToCharA(LPCSTR lpszSrc, LPSTR lpszDst) { + DEBUG_LOG("OemToCharA(%p, %p) (identity)\n", lpszSrc, lpszDst); + return charToOemA_impl(lpszSrc, lpszDst, 0, FALSE); +} + +BOOL WINAPI OemToCharBuffA(LPCSTR lpszSrc, LPSTR lpszDst, DWORD cchDstLength) { + DEBUG_LOG("OemToCharBuffA(%p, %p, %lu)\n", lpszSrc, lpszDst, + static_cast(cchDstLength)); + return charToOemA_impl(lpszSrc, lpszDst, cchDstLength, TRUE); +} + } // namespace user32 #include "user32_trampolines.h" diff --git a/dll/user32.h b/dll/user32.h index 2fdd833..e64adb1 100644 --- a/dll/user32.h +++ b/dll/user32.h @@ -11,5 +11,9 @@ HKL WINAPI GetKeyboardLayout(DWORD idThread); HWINSTA WINAPI GetProcessWindowStation(); BOOL WINAPI GetUserObjectInformationA(HANDLE hObj, int nIndex, PVOID pvInfo, DWORD nLength, LPDWORD lpnLengthNeeded); HWND WINAPI GetActiveWindow(); +BOOL WINAPI CharToOemA(LPCSTR lpszSrc, LPSTR lpszDst); +BOOL WINAPI CharToOemBuffA(LPCSTR lpszSrc, LPSTR lpszDst, DWORD cchDstLength); +BOOL WINAPI OemToCharA(LPCSTR lpszSrc, LPSTR lpszDst); +BOOL WINAPI OemToCharBuffA(LPCSTR lpszSrc, LPSTR lpszDst, DWORD cchDstLength); } // namespace user32