diff options
| author | jan.nijtmans <nijtmans@users.sourceforge.net> | 2025-05-06 07:42:52 (GMT) |
|---|---|---|
| committer | jan.nijtmans <nijtmans@users.sourceforge.net> | 2025-05-06 07:42:52 (GMT) |
| commit | a034b5b04e8ef67c49d5d244d3f0e9c2eee2f3b8 (patch) | |
| tree | 59da6350b03f3ef9507ca6332c0f0627fa46c63b | |
| parent | a0ecb0cc3cd831eadbd8753d617e79524892a73e (diff) | |
| parent | ab8975174d31a3c53fb206a3e075613e60738dfa (diff) | |
| download | tcl-a034b5b04e8ef67c49d5d244d3f0e9c2eee2f3b8.zip tcl-a034b5b04e8ef67c49d5d244d3f0e9c2eee2f3b8.tar.gz tcl-a034b5b04e8ef67c49d5d244d3f0e9c2eee2f3b8.tar.bz2 | |
Fix [8ffd8cabd1]: "encoding system": wrong result without manifest
| -rw-r--r-- | changes.md | 1 | ||||
| -rw-r--r-- | win/tclWinInit.c | 62 |
2 files changed, 61 insertions, 2 deletions
@@ -24,6 +24,7 @@ to the userbase. - [Tcl_InitStubs compatibility for 9.1](https://core.tcl-lang.org/tcl/tktview/fd8341) - [proc with more than 2**31 variables](https://core.tcl-lang.org/tcl/tktview/92aeb8) - [scan "long mantissa" %g](https://core.tcl-lang.org/tcl/tktview/42d14c) + - ["encoding system": wrong result without manifest](https://core.tcl-lang.org/tcl/tktview/8ffd8c) # Incompatibilities - No known incompatibilities with the Tcl 9.0.0 public interface. diff --git a/win/tclWinInit.c b/win/tclWinInit.c index 141aff1..079b1c8 100644 --- a/win/tclWinInit.c +++ b/win/tclWinInit.c @@ -63,6 +63,62 @@ static ProcessGlobalValue defaultLibraryDir = {0, 0, NULL, NULL, InitializeDefaultLibraryDir, NULL, NULL}; static ProcessGlobalValue sourceLibraryDir = {0, 0, NULL, NULL, InitializeSourceLibraryDir, NULL, NULL}; + + +/* + * TclpGetWindowsVersionOnce -- + * + * Callback to retrieve Windows version information. To be invoked only + * through InitOnceExecuteOnce for thread safety. + * + * Results: + * None. + */ +static BOOL CALLBACK TclpGetWindowsVersionOnce( + TCL_UNUSED(PINIT_ONCE), + TCL_UNUSED(PVOID), + PVOID *lpContext) +{ + typedef int(__stdcall getVersionProc)(void *); + static OSVERSIONINFOW osInfo; + + /* + * GetVersionExW will not return the "real" Windows version so use + * RtlGetVersion if available and falling back. + */ + HMODULE handle = GetModuleHandleW(L"NTDLL"); + getVersionProc *getVersion = + (getVersionProc *)(void *)GetProcAddress(handle, "RtlGetVersion"); + + osInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW); + if (getVersion == NULL || getVersion(&osInfo)) { + if (!GetVersionExW(&osInfo)) { + /* Should never happen but ...*/ + return FALSE; + } + } + *lpContext = (LPVOID)&osInfo; + return TRUE; +} + +/* + * TclpGetWindowsVersion -- + * + * Returns a pointer to the OSVERSIONINFOW structure containing the + * version information for the current Windows version. + * + * Results: + * Pointer to OSVERSIONINFOW structure. + */ +static const OSVERSIONINFOW *TclpGetWindowsVersion(void) +{ + static INIT_ONCE osInfoOnce = INIT_ONCE_STATIC_INIT; + OSVERSIONINFOW *osInfoPtr = NULL; + BOOL result = InitOnceExecuteOnce( + &osInfoOnce, TclpGetWindowsVersionOnce, NULL, (LPVOID *)&osInfoPtr); + return result ? osInfoPtr : NULL; +} + /* *--------------------------------------------------------------------------- @@ -401,7 +457,9 @@ const char * Tcl_GetEncodingNameFromEnvironment( Tcl_DString *bufPtr) { - UINT acp = GetACP(); + const OSVERSIONINFOW *osInfoPtr = TclpGetWindowsVersion(); + UINT acp = (!osInfoPtr || osInfoPtr->dwBuildNumber < 18362) + ? GetACP() : CP_UTF8; Tcl_DStringInit(bufPtr); if (acp == CP_UTF8) { @@ -409,7 +467,7 @@ Tcl_GetEncodingNameFromEnvironment( } else { Tcl_DStringSetLength(bufPtr, 2 + TCL_INTEGER_SPACE); snprintf(Tcl_DStringValue(bufPtr), 2 + TCL_INTEGER_SPACE, "cp%d", - GetACP()); + acp); Tcl_DStringSetLength(bufPtr, strlen(Tcl_DStringValue(bufPtr))); } return Tcl_DStringValue(bufPtr); |
