On Mon, 28 Dec 2020, Jacek Caban wrote:
On 26.12.2020 22:44, Martin Storsjö wrote:
On Sat, 26 Dec 2020, Jacek Caban wrote:
A concrete case is psapi.h: I can include psapi.h and call
EnumProcessModules. If NTDDI_VERSION >= NTDDI_WIN7 when including the
header, the call to EnumProcessModules gets redirected to
K32EnumProcessModules which exists in kernel32.dll from win7. If I include
the header with a lower version defined, it ends up calling
EnumProcessModules in psapi.dll instead.
Right, I missed this, I was concentrated on deciding if use win10 or
something older. I think it was a mistake how MS dealt with it, esp. the
version check, but if you want to link to psapi.dll, the solution is well
documented and supported: –DPSAPI_VERSION=1. There is no need to touch
NTDDI_VERSION or _WIN32_WINNT. Projects need to be aware of -lpsapi anyway. I
realize that some projects don't do it right, but the alternative is to
default to XP forever.
Yeah, this particular case can be worked around, with some effort. The
more open question is whether there's other similar cases hiding in the
headers, where one can keep calling an API that used to work before, that
ends up requiring a newer version.
BTW, if impact of the problem is too bad, we could just place K32* aliases to
non K32-prefixed functions inside psapi importlib. This way projects that use
headers in version 2, but link to psapi will keep consistent behaviour. I'm
not sure it's needed nor better.
That's a neat fix, in case it ends up needed indeed!
Likewise, the optional IPv6 APIs end up called via GetProcAddress based
wrappers. At least in official WinSDK (if I remember correctly and read the
headers right), these end up skipped if _WIN32_WINNT targets a high enough
version (but I think mingw-w64 headers always end up using the compat
wrappers).
I don't know about it. A quick grep in mingw-w64 didn't find that.
mingw-w64 headers don't have this mechanism, but you can see it in WinSDK
headers. ws2tcpip.h first declares getaddrinfo. Then at the end, there's a
version specific fallback:
#if !defined(_WIN32_WINNT) || (_WIN32_WINNT <= 0x0500)
#include <wspiapi.h>
#endif
wspiapi.h then contains a "#define getaddrinfo WspiapiGetAddrInfo" (which
is a function that tries to GetProcAddress the real getaddrinfo, and if
not found, falls back to an IPv4-only stub implementation of getaddrinfo).
mingw-w64 headers doesn't have this conditional though. And it only
matters for Win2k which mingw-w64 doesn't really support anyway.
So it's not entirely relevant for raising the define from XP in this case,
but it's another example of cases where _WIN32_WINNT acts like the minimum
supported version, where raising the define can cause code that used to
work before to silently break on older platforms, arguing against this
part of the reasoning in the patch:
As long as the application does not use new APIs, its compatibility with
older Windows will not change.
And this bit:
This value is commonly mistaken with 'minimum version supported in
runtime', which is simply not the case. It's only a version that headers
will provide declarations for.
https://docs.microsoft.com/en-us/cpp/porting/modifying-winver-and-win32-winnt
says
The preprocessor macros WINVER and _WIN32_WINNT specify the minimum
operating system version your code supports.
configure)
- The project's configure script. At least for the case of VLC, currently
it doesn't IIRC set anything if it's already predefined e.g. in CFLAGS, but
sets a higher version if the toolchain's default is lower than what the
project itself strictly requires. If the toolchain's default is higher than
the project required level, the version is not overridden to a lower
version.
I don't know the logic behind it, it looks buggy to me, but sounds like it
would do what author meant... The alternative is to never rise it to anything
higher than VLC allows us.
Good point, that's a good argument.
I guess this is a matter of declaring the role of the define better, and
adapting that code. Right now, the define is set to the minimum value that
the toolset supports (XP, or Win7 in the case of llv-mingw) and there's no
point in trying to set it to a lower value in user code. If we can expect
to be able to meaningfully set the define to a lower version than the
default, this code will indeed need to change.
So at least VLC would need some amount of tweaks to cope with the toolchain
defaulting to a higher version, or require everyone building it to override
the desired target version in CFLAGS.
Yes, unfortunately it may need some adaptation. I think that wrong
assumptions are spread around the ecosystem because the value was so
conservative archaic for years.
But yeah, in practice this only affects projects that have optional
codepaths that can use newer features - except for the cases with e.g.
psapi.h.
I think that the change reflects expectations of majority of users.
I'm not entierely sure I agree with this - I think different ecosystems
have different expectations here.(It'd be interesting to e.g. rebuild all
of msys2's mingw package repository with such headers, and see how many of
them fail to run on the previous minimum version.)
Yes, it would be interesting.
If users still want headers to not provide Win10-only declarations, they
may just set _WIN32_WINNT explicitly in build system to the exact version
they want. If packagers prefer it the old way, they can use the configure
stitch for that.
Yeah, it's good that we're able to override the default - I think I'd still
keep doing that. But I think there's at least some amount of projects
(mingw centric projects primarily, as the default in MSVC is different)
that expect and rely on the current norm of it being set to the minimum.
Those are bugs in these projects. I'm not keen to break them, but I also
don't think that we should keep current situation forever.
I'd like users, who just installed a default mingw-w64, to be able to just
#include <windows.h> and have the best of mingw-w64 available. Right now,
when they try to use any recent API (as in younger than 19 years), they have
to learn about _WIN32_WINNT and mess with it. In my opinion, they should not
be required to do that. (Once they have some specific expectations about OS
version, they may still want/need to do that, but mistakes of unrelated
projects should not be among reasons to mess with _WIN32_WINNT).
That sounds like a sensible goal to have - but I'm a little undecided
about the practicalities.
Then again, I can agree with the argument that projects that are built for
distribution across older versions maybe should take care to specifically
set the define themselves anyway.
Regarding the current archaic default, an alternative path (that doesn't
take us all the way, but at least a bit on the way) would be to bump it to
Win7. I also faintly remember somebody suggesting that we'd formally drop
support for XP altogether.
// Martin
_______________________________________________
Mingw-w64-public mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public