Each locale also has a EBCDIC code page associated with it (LOCALE_IDEFAULTEBCDICCODEPAGE[1]).
Unlike ANSI and OEM code pages, there is no way to request locale's default MAC or EBCDIC code page with setlocale (other than explicitly specifying it). SetThreadLocale is really funny. I know that MultiByteToWideChar and WideCharToMultiByte accept CP_THREAD_ACP to use thread's ANSI code page. It seems that functions like lstrcmpA[2] are using current thread's locale. (does anyone even use them?) [1] https://learn.microsoft.com/en-us/windows/win32/intl/locale-idefault-constants [2] https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-lstrcmpa ________________________________ From: Pali Rohár <[email protected]> Sent: Tuesday, September 23, 2025 8:57 PM To: Kirill Makurin <[email protected]> Cc: mingw-w64-public <[email protected]> Subject: Re: Always map assert to _wassert for msvcr80.dll and later? There is also CP_MACCP (The current system Macintosh code page) but I have no idea which API uses it. SetThreadLocale looks to be funny function. It changes CP_THREAD_ACP but it is unknown which WinAPI functions uses CP_THREAD_ACP internally on modern systems. >From different sources it can be deduced that CP_THREAD_ACP affects resource selection but only on WinNT 3.1-4.0. (On Win9x it is unsupported and on Win2000+ it does not affect resource selection). https://stackoverflow.com/a/74225289 http://www.jasinskionline.com/windowsapi/ref/s/setthreadlocale.html https://archives.miloush.net/michkap/archive/2005/08/22/454360.html On WinXP the SetThreadUILanguage() function changes also CP_THREAD_ACP but on Win10 it does not. And then there is also SetThreadPreferredUILanguages() function. So I'm not sure which function to call. On following page is some testing application. https://github.com/chjfth/trivials/tree/master/mswin/About2-muires Right now I spent some time to compile above application under mingw-w64 but seems that it is impossible. The GNU LD linker is crashing. Seems like I would have to report bug. It is inside the rsrc_merge --> rsrc_sort_entries --> rsrc_cmp call chain. On Tuesday 23 September 2025 08:58:18 Kirill Makurin wrote: > ``` > IMHO that CRT global locale, CRT thread locale, CRT mbcp, WinAPI ACP, > WinAPI OEMCP, WinAPI ThreadLocale CP, WinAPI FileApis CP, > WinAPI ConsoleCP, WinAPI ConsoleOutputCP is a mess. Have I forgot some? > ``` > > None that I'm aware of :) > > Now that I'm think of it, should I ever consider using SetThreadLocale[1] in > my implementation of uselocale? Interesting that there is no version that > uses locale names introduced in Windows Vista. (I guess > SetThreadPreferredUILanguages is used for this?). I'll leave this as a > question for future me. > > [1]https://learn.microsoft.com/en-us/windows/win32/api/winnls/nf-winnls-setthreadlocale > ________________________________ > From: Pali Rohár <[email protected]> > Sent: Tuesday, September 23, 2025 5:43 PM > To: Kirill Makurin <[email protected]> > Cc: mingw-w64-public <[email protected]> > Subject: Re: Always map assert to _wassert for msvcr80.dll and later? > > Sure, the fflush is needed. I also used it in my freopen change before > calling _setmode. Otherwise remaining part of FILE* buffer is processed > by the _O_TEXT together with the new string printed by assert. > > If the output is GUI then the narrow assert string is interpreted in > ACP because it is printed via MessageBoxA. > > If the output is stderr then it depends on where the stderr points. > If it is file then it is printed as-is with the _O_TEXT conversion. > If it is console then the assert string is interpreted according to > Output console codepage (retrieved by GetConsoleOutputCP()). > > IMHO that CRT global locale, CRT thread locale, CRT mbcp, WinAPI ACP, > WinAPI OEMCP, WinAPI ThreadLocale CP, WinAPI FileApis CP, > WinAPI ConsoleCP, WinAPI ConsoleOutputCP is a mess. Have I forgot some? > > On Tuesday 23 September 2025 08:15:13 Kirill Makurin wrote: > > That actually sounds like a better and simpler approach. > > > > If you think about, it is possible that assert's expression contains > > Unicode characters (I have a few cases like this). I wonder if narrow I/O > > functions in old CRTs would just write UTF-8 encoded strings as-is without > > any special interpretation of its bytes. Conversion from char to wchar_t > > would lose them (in most cases interpret them as single-byte characters for > > the active locale, since all 255 bytes represent a valid character). > > > > I think it would good to add a call to fflush(stderr) before calling > > _setmode. > > ________________________________ > > From: Pali Rohár <[email protected]> > > Sent: Tuesday, September 23, 2025 5:01 PM > > To: Kirill Makurin <[email protected]> > > Cc: mingw-w64-public <[email protected]> > > Subject: Re: Always map assert to _wassert for msvcr80.dll and later? > > > > I have an another idea what could mingw-w64 _assert do. What about just > > calling the _setmode(_fileno(stderr), _O_TEXT); and then directly jumps > > to CRT's _assert? This can avoid dynamic allocation (required for > > converting the ANSI buffer to UNICODE) and also avoid logic which needs > > to determinate if the CRT's assert would work with ANSI or not. > > > > On Monday 08 September 2025 20:48:35 Pali Rohár wrote: > > > Feel free to take it. > > > > > > On Monday 08 September 2025 18:47:04 Kirill Makurin wrote: > > > > Tricky but doable. Thanks to Microsoft for complicating things. > > > > > > > > Would you like me to take care of this, or would you prefer to do it > > > > yourself? > > > > ________________________________ > > > > From: Pali Rohár <[email protected]> > > > > Sent: Tuesday, September 9, 2025 3:42 AM > > > > To: Kirill Makurin <[email protected]> > > > > Cc: mingw-w64-public <[email protected]> > > > > Subject: Re: Always map assert to _wassert for msvcr80.dll and later? > > > > > > > > Yes, this is also my observation. > > > > > > > > For msvcrt40.dll it would be quite tricky as msvcrt40.dll itself does > > > > not export _wassert. So it would be needed via GetModuleHandleA to get > > > > the msvcrt.dll and call msvcrt's _wassert even for msvcrt40.dll builds. > > > > In case msvcrt.dll is not loaded or does not provide _wassert, then > > > > calling msvcrt40.dll's _assert should be safe. > > > > > > > > On Monday 08 September 2025 18:32:19 Kirill Makurin wrote: > > > > > I see, so all affected CRTs should also have _wassert. Then it should > > > > > to be easy enough to _fix_ _assert. > > > > > ________________________________ > > > > > From: Pali Rohár <[email protected]> > > > > > Sent: Tuesday, September 9, 2025 3:26 AM > > > > > To: Kirill Makurin <[email protected]> > > > > > Cc: mingw-w64-public <[email protected]> > > > > > Subject: Re: Always map assert to _wassert for msvcr80.dll and later? > > > > > > > > > > It looks like that those translation modes were introduced in msvcr80 > > > > > and are not available in older VC++ versions (like msvcr71, 70, 40, > > > > > ...). > > > > > They were included into msvcrt.dll system os library in some Windows > > > > > version. And because system os msvcrt40.dll just redirects calls to > > > > > system os msvcrt.dll, they may be available also in msvcrt40.dll. > > > > > > > > > > So non-affected should be: crtdll.dll, msvcrt10.dll, msvcrt20.dll, > > > > > msvcr40d.dll, msvcrtd.dll, msvcr70.dll, msvcr70d.dll, msvcr71.dll, > > > > > msvcr71d.dll. > > > > > > > > > > Conditionally affected based-on OS are: msvcrt40.dll and msvcrt.dll. > > > > > > > > > > And all other libs are always affected. > > > > > > > > > > On Monday 08 September 2025 18:04:55 Kirill Makurin wrote: > > > > > > I think this issue will occur in all CRTs which allows to set > > > > > > translation mode to any of _O_{W|U8|U16}TEXT. I mentioned that > > > > > > these translation modes seem to work starting with msvcrt40.dll, so > > > > > > anything other than crtdll.dll, msvcrt10.dll and msvcrt20.dll > > > > > > should be affected. > > > > > > ________________________________ > > > > > > From: Pali Rohár <[email protected]> > > > > > > Sent: Tuesday, September 9, 2025 2:59 AM > > > > > > To: Kirill Makurin <[email protected]> > > > > > > Cc: mingw-w64-public <[email protected]> > > > > > > Subject: Re: Always map assert to _wassert for msvcr80.dll and > > > > > > later? > > > > > > > > > > > > Thanks for info about availability of _wassert. > > > > > > > > > > > > Do you have exact list of CRT DLL libs which have "broken" _assert > > > > > > in > > > > > > this way? I think that it is important to know which CRT DLLs are > > > > > > affected as only based on that we can say what is harder or easier > > > > > > to > > > > > > implement. > > > > > > > > > > > > On Monday 08 September 2025 17:54:48 Kirill Makurin wrote: > > > > > > > Yes, it possible to change assert's behavior with > > > > > > > _set_error_mode[1] functions. > > > > > > > > > > > > > > Keep in mind that native _wassert is only available starting with > > > > > > > msvcr80.dll and in some msvcrt.dll. If we want to do it for all > > > > > > > affected CRTs, for CRTs which do not have _wassert, we probably > > > > > > > would need to provide our version which mimics CRT behavior and > > > > > > > takes _set_error_mode into account. > > > > > > > > > > > > > > Are you sure it is easier to _fix_ _assert? > > > > > > > > > > > > > > [1] > > > > > > > https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/set-error-mode > > > > > > > ________________________________ > > > > > > > From: Pali Rohár <[email protected]> > > > > > > > Sent: Tuesday, September 9, 2025 2:45 AM > > > > > > > To: Kirill Makurin <[email protected]> > > > > > > > Cc: mingw-w64-public <[email protected]> > > > > > > > Subject: Re: Always map assert to _wassert for msvcr80.dll and > > > > > > > later? > > > > > > > > > > > > > > assert does not have to print error to console. For GUI > > > > > > > applications it > > > > > > > prints error via MessageBox. And the default console output can be > > > > > > > changed to GUI MessageBox also for console application some CRT > > > > > > > call > > > > > > > (I do not not right now how is that function called but there is > > > > > > > some > > > > > > > option). > > > > > > > > > > > > > > My idea was that _assert replacement would just convert its narrow > > > > > > > strings to wide strings and call _wassert function. > > > > > > > > > > > > > > On Monday 08 September 2025 17:42:10 Kirill Makurin wrote: > > > > > > > > I wonder how many people would call _assert function directly, > > > > > > > > since it is Microsoft-specific stuff. If such usage is a thing, > > > > > > > > it would make sense. > > > > > > > > > > > > > > > > Maybe we could always map assert to _wassert and provide a > > > > > > > > working replacement (for CRTs which do not have it) which > > > > > > > > prints message using fwprintf and calls abort()? > > > > > > > > ________________________________ > > > > > > > > From: Pali Rohár <[email protected]> > > > > > > > > Sent: Tuesday, September 9, 2025 2:36 AM > > > > > > > > To: Kirill Makurin <[email protected]> > > > > > > > > Cc: mingw-w64-public <[email protected]> > > > > > > > > Subject: Re: Always map assert to _wassert for msvcr80.dll and > > > > > > > > later? > > > > > > > > > > > > > > > > Personally I do not like those #ifdes for specific CRT version > > > > > > > > in header > > > > > > > > files and in past I tried to remove them as many as possible to > > > > > > > > make > > > > > > > > header files code more cleaner and not dependent on msvcrt vs > > > > > > > > UCRT > > > > > > > > changes. That is why I rather suggested to "fix" the _assert > > > > > > > > function, > > > > > > > > so also manual call to _assert function would work (which may > > > > > > > > be useful > > > > > > > > when wrapping assert into custom function and want to propagate > > > > > > > > line/file of the caller). > > > > > > > > > > > > > > > > I do not think that the wchar_t[] vs char[] array size is a > > > > > > > > problem. > > > > > > > > Assert strings are not such huge. > > > > > > > > > > > > > > > > On Monday 08 September 2025 17:29:19 Kirill Makurin wrote: > > > > > > > > > I did a very quick test and it seems that _O_{U8|U16|W}TEXT > > > > > > > > > translation modes are working starting with msvcrt40.dll, so > > > > > > > > > we shouldn't bother about this being an issue for > > > > > > > > > msvcrt20.dll and older. > > > > > > > > > > > > > > > > > > assert.h already maps assert to _wassert when _UNICODE or > > > > > > > > > UNICODE macros are defined. I think we could just extend this > > > > > > > > > condition to include `__MSVCRT_VERSION__ >= 0x0800 || defined > > > > > > > > > (_UCRT)`, and if we want to do it for msvcrt.dll, > > > > > > > > > `__MSVCRT_VERSION__ == 0x0600`. > > > > > > > > > > > > > > > > > > The only drawback I see is that stored strings will be > > > > > > > > > wchar[] instead of char[], resulting in larger binaries. > > > > > > > > > > > > > > > > > > ________________________________ > > > > > > > > > From: Pali Rohár <[email protected]> > > > > > > > > > Sent: Tuesday, September 9, 2025 2:15 AM > > > > > > > > > To: Kirill Makurin <[email protected]> > > > > > > > > > Cc: mingw-w64-public <[email protected]> > > > > > > > > > Subject: Re: Always map assert to _wassert for msvcr80.dll > > > > > > > > > and later? > > > > > > > > > > > > > > > > > > Now I see that MS documents that _O_U8TEXT does not work > > > > > > > > > together with > > > > > > > > > printf and hence the assert does not print anything when > > > > > > > > > _O_U8TEXT is > > > > > > > > > set on stderr. > > > > > > > > > > > > > > > > > > https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/setmode > > > > > > > > > > > > > > > > > > Instead of redirecting the assert via #define to _wassert, I > > > > > > > > > would > > > > > > > > > rather propose to overrride _assert symbol for those affected > > > > > > > > > import > > > > > > > > > libraries and fix it to work also for _O_U8TEXT. > > > > > > > > > > > > > > > > > > On Monday 08 September 2025 19:03:09 Pali Rohár wrote: > > > > > > > > > > Hello, > > > > > > > > > > > > > > > > > > > > This is not problem of assert, but rather of the fprintf > > > > > > > > > > which assert > > > > > > > > > > calls. Same problem can be triggered by using the plain > > > > > > > > > > fprintf(stderr,...) > > > > > > > > > > instead of assert(0). > > > > > > > > > > > > > > > > > > > > So I do not think that it makes sense to remap assert as > > > > > > > > > > basically all > > > > > > > > > > functions which calls fprintf(stderr,...) are affected. > > > > > > > > > > > > > > > > > > > > Is not it just the _O_U8TEXT which is broken? > > > > > > > > > > > > > > > > > > > > On Monday 08 September 2025 15:38:09 Kirill Makurin wrote: > > > > > > > > > > > Consider the following code: > > > > > > > > > > > > > > > > > > > > > > ``` > > > > > > > > > > > #include <assert.h> > > > > > > > > > > > #include <fcntl.h> > > > > > > > > > > > #include <io.h> > > > > > > > > > > > #include <stdio.h> > > > > > > > > > > > > > > > > > > > > > > int main (void) { > > > > > > > > > > > _setmode (_fileno (stderr), _O_U8TEXT); > > > > > > > > > > > assert (0); > > > > > > > > > > > return 0; > > > > > > > > > > > } > > > > > > > > > > > ``` > > > > > > > > > > > > > > > > > > > > > > When compiled with MSVC, it properly prints message about > > > > > > > > > > > failed assertion. When it is compiled with mingw-w64's > > > > > > > > > > > headers (Msys2/UCRT64) it produces no output. > > > > > > > > > > > > > > > > > > > > > > mingw-w64's assert.h maps assert() macro to _wassert only > > > > > > > > > > > when _UNICODE or UNICODE is defined. MSVC's assert.h > > > > > > > > > > > always maps assert() macro to _wassert and even no longer > > > > > > > > > > > exposes _assert function. > > > > > > > > > > > > > > > > > > > > > > How about we always map assert() macro to _wassert for > > > > > > > > > > > msvcr80.dll and later? Since we also emulate _wassert for > > > > > > > > > > > msvcrt.dll, it should be OK to map it to _wassert for > > > > > > > > > > > msvcrt.dll as well. > > > > > > > > > > > > > > > > > > > > > > - Kirill Makurin _______________________________________________ Mingw-w64-public mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/mingw-w64-public
