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

Reply via email to