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)
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 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
_______________________________________________
Mingw-w64-public mailing list
Mingw-w64-public@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public