On Thursday 02 January 2025 11:00:43 Pali Rohár wrote:
> On Thursday 02 January 2025 11:36:26 Martin Storsjö wrote:
> > On Thu, 2 Jan 2025, Pali Rohár wrote:
> > 
> > > > No, 0x0601 for __MSVCRT_VERSION__ doesn't mean Windows 7. I think you've
> > > > made way too much conclusions based on the info in msvcrt.def.in, which 
> > > > does
> > > > not seem to be using the same numbering scheme as the headers.
> > > 
> > > I see, I was wrong, based on that file which I found...
> > > 
> > > > 
> > > > I believe the version numbering for __MSVCRT_VERSION__ in headers was 
> > > > meant
> > > > to use both the msvcrXX.dll version numbers, just like we do, but also 
> > > > based
> > > > on the actual embedded version number of the msvcrt.dll that shipped 
> > > > with
> > > > the OS.
> > > > 
> > > > I don't have a copy of msvcrt.dll from win9x or older versions handy for
> > > > looking at, but I have a set of the modern ones. Using "peres -v 
> > > > msvcrt.dll"
> > > > (the "peres" tool from the "pev" or "readpe" package on Ubuntu), I'm 
> > > > getting
> > > > the following version:
> > > > 
> > > > Win2k 6.1.8637.0
> > > > WinXP 7.0.2600.5512
> > > > Vista 7.0.6002.18551
> > > > Win7 7.0.7601.17744
> > > 
> > > So for completeness, I run peres -v on these system versions:
> > > 
> > > NT4.0    4.20.0.6201
> > > Win98    5.0.0.7128
> > > Win98SE  6.0.8397.0
> > > WinMe    6.1.8637.0
> > > Win2k    6.1.8637.0
> > > Win2ksp3 6.1.9359.0
> > > Win2ksp4 6.1.9844.0
> > > WinXP    7.0.2600.0
> > > WinXPsp1 7.0.2600.1106
> > > WinXPsp2 7.0.2600.2180
> > > WinXPsp3 7.0.2600.5512
> > > WinXPx64 7.0.3790.1830
> > > 
> > > NT4 msvcrt.dll has same set of symbols as VC4.2 msvcrt version, Win98 FE
> > > has same set as VC5.0SP1, and Win98 SE has same as as VC6.0. So it looks
> > > like that version numbers from peres for NT4/Win98 matches the VC++
> > > versions.
> > 
> > Yep. And to make things clear - msvcrt.dll in XP doesn't have the same set
> > of symbols as the real msvcr70.dll, right? So the divergence started at that
> > point (and/or at the 6.1 versions used in 2k and Me)
> 
> Yes. The correct list of symbols for msvcrt.dll in XP and in msvcr70.dll
> are already documented in mingw-w64 files:
> 
> mingw-w64-crt/lib-common/msvcrt.def.in
> mingw-w64-crt/lib32/msvcr70.def.in
> 
> > > > This also lines up perfectly with some of the ifdefs you referenced - 
> > > > e.g.
> > > > _aligned_malloc exists in msvcrt.dll since XP, and is guarded by
> > > > __MSVCRT_VERSION__ >= 0x0700. And _wstat64 which is guarded by
> > > > __MSVCRT_VERSION__ >= 0x0601 is available since Win2k.
> > > 
> > > That make sense. I checked in our msvcrt.def.in and _wstat64 symbol is in
> > > Windows ME/2000 section.
> > > 
> > > > So the mythical __MSVCR61_DLL means Win2k.
> > > 
> > > Yes, that would make sense.
> > > 
> > > > > So, based on this investigation, I think that changing default value 
> > > > > of
> > > > > __MSVCRT_VERSION__ again should not be needed. I would suggest to just
> > > > > adjust checks in mingw-w64 header files for:
> > > > > 
> > > > > * OS system msvcrt.dll version (any OS):
> > > > >  - #if __MSVCRT_VERSION__ > 0x400 && __MSVCRT_VERSION__ < 0x700
> > > > >  - This will match any mingw32 OS system msvcrt.dll version except 
> > > > > the Windows NT4
> > > > >  - It does not conflict with neither mingw-w64 msvcrt40 (== 0x400) 
> > > > > nor with msvcr70 (== 0x700)
> > > > 
> > > > I don't think they used __MSVCRT_VERSION__ < 0x600 for anything, other 
> > > > than
> > > > potentially msvcrXX.dll versions just like we do.
> > > 
> > > Probably yes. So the condition could be:
> > > 
> > > #if __MSVCRT_VERSION__ >= 0x600 && __MSVCRT_VERSION__ < 0x700
> > 
> > Yes, that sounds good to me.
> > 
> > > > > * msvcr100+:
> > > > >  - (__MSVCRT_VERSION__ >= 0xA00 && __MSVCRT_VERSION__ < 0x1000) || 
> > > > > (__MSVCRT_VERSION__ >= 0x1000)
> > > > >  - First part is for mingw-w64, second for mingw32
> > > > > 
> > > > > * msvcr110+:
> > > > >  - (__MSVCRT_VERSION__ >= 0xB00 && __MSVCRT_VERSION__ < 0x1000) || 
> > > > > (__MSVCRT_VERSION__ >= 0x1100)
> > > > >  - First part is for mingw-w64, second for mingw32
> > > > > 
> > > > > * msvcr120+:
> > > > >  - (__MSVCRT_VERSION__ >= 0xC00 && __MSVCRT_VERSION__ < 0x1000) || 
> > > > > (__MSVCRT_VERSION__ >= 0x1200)
> > > > >  - First part is for mingw-w64, second for mingw32
> > > > 
> > > > I don't think we should do anything to complicate things for numbered
> > > > msvcrXX.dll here - using anything other than msvcrt.dll and UCRT is
> > > > exceedingly rare. (I only practically know of two cases; you, and VLC 
> > > > did
> > > > need to target msvcr120*.dll for Windows Store distribution at some 
> > > > point,
> > > > and that's no longer relevant for them.)
> > > 
> > > Ok. It was just a suggestion for completeness. As nobody complained
> > > then it is not needed.
> > > 
> > > > > Would be this enough to finally fix those issues with 
> > > > > __MSVCRT_VERSION__?
> > > > 
> > > > I don't think this would make any difference here at all.
> > > > 
> > > > 
> > > > I believe that the issues that can be caused by our changes fall into 
> > > > two
> > > > classes: (Sorry, I didn't browse all the code search results to see what
> > > > other concrete cases there were.)
> > > > 
> > > > - Projects that look at __MSVCRT_VERSION__ and conditionally compile 
> > > > things.
> > > > This may lead to projects building with fewer features (by skipping 
> > > > things
> > > > that would require a newer msvcrt.dll), or trying to use extra compat
> > > > routines that wouldn't be necessary. Or there can be clashes, if they 
> > > > see
> > > > our __MSVCRT_VERSION__ and conclude that function X isn't provided, and 
> > > > they
> > > > try to provide their own replacement function X, and they can get 
> > > > duplicate
> > > > conflicting definitions.
> > > > 
> > > > Or the ifdefs are only tested in one configuration and simply break in 
> > > > the
> > > > other one, like I think was the case in the linked msys2 issue.
> > > > 
> > > > Addapting our header ifdefs to also recognize different values from
> > > > mingw.org toolchains won't make any difference here at all.
> > > > 
> > > > Most of the cases I saw in the code search I browsed earlier seemed to 
> > > > be
> > > > this case - e.g. trying to provide workarounds for 64 bit stat 
> > > > functions or
> > > > similar. I haven't tried compiling them to see if our new definitions
> > > > actually cause a problem or not.
> > > > 
> > > > - Projects that themselves try to change __MSVCRT_VERSION__ to expose 
> > > > more
> > > > features, e.g. setting __MSVCRT_VERSION__ to 0x700 to get XP level 
> > > > features
> > > > like _aligned_malloc available. This is mostly harmless for us, even if 
> > > > it
> > > > in corner cases could cause problems (by exposing msvcr70.dll features 
> > > > when
> > > > they actually meant msvcrt.dll/XP - but mingw.org headers also seem to
> > > > generally consider the two equal).
> > > > 
> > > > One such case is familiar to me,
> > > > https://github.com/FFmpeg/FFmpeg/blob/n7.1/configure#L6036-L6037. But 
> > > > that
> > > > one is only done if the headers are mingw.org headers, not mingw-w64, 
> > > > so it
> > > > doesn't make any difference for us. (It's used for getting specifically
> > > > _aligned_malloc.)
> > > > 
> > > > 
> > > > 
> > > > So I think the main source of problems for user code is that we used to
> > > > default to __MSVCRT_VERSION__ == 0x700 and now we default to something 
> > > > else.
> > > > 
> > > > We could consider defaulting to 0x0601 (or 0x06FF); this would pick the 
> > > > same
> > > > branch as before, for all the cases of __MSVCRT_VERSION__ >= 0x0601. So 
> > > > it
> > > > could reduce the amount of breakage that we cause.
> > > > 
> > > > For any code that checks __MSVCRT_VERSION__ >= 0x700 though, things 
> > > > would
> > > > unfortunately change.
> > > > 
> > > > // Martin
> > > 
> > > I see. But if we change the default value again then it would be
> > > necessary to updates also mingw-w64 headers with new check for system
> > > msvcrt.dll value. Something what I wrote above (just first two cases).
> > 
> > Yes - we could change that in any case, to allow any value between 0x600 and
> > 0x6FF, in case users override it.
> > 
> > Then for our default value; either 0x0601 or 0x06FF would be ok with me. At
> > this point, I'm actually leaning towards 0x06FF.
> > 
> > This makes it clearer that it's not specifically the 2k/Me version (not ==
> > 0x0601), and that it's "almost" the 0x0700 that we had before (even if that
> > "almost" wouldn't functionally have any effect anywhere). With 0x06FF we
> > would get the right behaviour if there's any condition which is "> 0x0601"
> > (not sure if that one exists anywhere though).
> 
> This makes sense. Better to use 0x06FF.
> 
> > (This also leaves the door open if we'd want to add more header ifdefs to
> > differentiate between the various versions of msvcrt.dll. Not saying that we
> > should, but it makes it possible.)
> > 
> > Then, the only issue is just that we no longer claim to be >= 0x0700 as we
> > did before - and this is by design, as we want to differentiate between the
> > real msvcr70.dll and the somewhat-similar-to-msvcr70.dll msvcrt.dll from XP
> > and similar.
> > 
> > // Martin

Another idea how to handle this problem, so the application would have
access to declaration of >= 0x0700 functions.

Remove all __MSVCRT_VERSION__ checks in mingw-w64 header files which
hide msvcr* functions, and then revert back the default
__MSVCRT_VERSION__ value to 0x0700.


_______________________________________________
Mingw-w64-public mailing list
Mingw-w64-public@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to