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

Reply via email to