summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjan.nijtmans <nijtmans@users.sourceforge.net>2025-05-06 07:42:52 (GMT)
committerjan.nijtmans <nijtmans@users.sourceforge.net>2025-05-06 07:42:52 (GMT)
commita034b5b04e8ef67c49d5d244d3f0e9c2eee2f3b8 (patch)
tree59da6350b03f3ef9507ca6332c0f0627fa46c63b
parenta0ecb0cc3cd831eadbd8753d617e79524892a73e (diff)
parentab8975174d31a3c53fb206a3e075613e60738dfa (diff)
downloadtcl-a034b5b04e8ef67c49d5d244d3f0e9c2eee2f3b8.zip
tcl-a034b5b04e8ef67c49d5d244d3f0e9c2eee2f3b8.tar.gz
tcl-a034b5b04e8ef67c49d5d244d3f0e9c2eee2f3b8.tar.bz2
Fix [8ffd8cabd1]: "encoding system": wrong result without manifest
-rw-r--r--changes.md1
-rw-r--r--win/tclWinInit.c62
2 files changed, 61 insertions, 2 deletions
diff --git a/changes.md b/changes.md
index 27f0fc0..04e0b2c 100644
--- a/changes.md
+++ b/changes.md
@@ -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);