I'm performing some testing on Windows 7 x64 using Visual Studio 2012. It appears Microsoft's toolchain is setting _WIN32_WINNT
to 0x602
(_WIN32_WINNT_WIN8
). Running our test program results in The procedure entry point GetOverlappedResultEx could not be located in the dynamic link library KERNEL32.dll
:
I have two questions. First, out of morbid curiosity, why is Microsoft setting _WIN32_WINNT
to a value that's not valid for the execution environment? I can understand if a user wants to do it, but not Microsoft since it breaks things (q.v.).
Second, how do we set WINVER
or _WIN32_WINNT
to the symbolic "This Platform"? In this case, "this platform" is Windows 7. When I test on Windows Vista, it will be a different platform. When I test on Windows 8, it will be another platform. And when I test under ARM developer prompt for Windows Phone and Windows Store, it will be yet another platform.
The problem is very easy to duplicate. Here are the steps. I imagine anyone with a good testing environment already has the first eight steps.
- Stand up a Windows 7, x64 machine
- Fully patch the Windows 7 machine
- Install Visual Studio 2008
- Fully patch Visual Studio 2008
- Install Visual Studio 2010
- Fully patch Visual Studio 2010
- Install Visual Studio 2012
- Fully patch Visual Studio 2012
Then:
- Create an empty "Hello World" project under VS2008
- Delete everything except
hello_world.cpp
(this should leave 1 solution file, and 1 project file, 1 source file) - Convert it to VS2010
- Open with VS2012
I can post the MCVE, which is an empty source file, to appease some folks. It seems like a waste of time since the problem is with the toolchain and not the source file. Is an empty main
really crucial to this problem? The wrong WINVER
and _WIN32_WINNT
will be set regardless of what's in the file.
I know the origin of the error. Our code changed recently to better support for Windows 8, Phone 8, Store 8, Server 2012, Windows 10, Phone 10, Store 10 and Windows Universal Platform. The changes look like so:
#if defined(CRYPTOPP_WIN32_AVAILABLE)
# if ((WINVER >= 0x0602 /*_WIN32_WINNT_WIN8*/) || (_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/))
# include <synchapi.h>
# include <ioapiset.h>
# define USE_WINDOWS8_API
# endif
#endif
...
#if defined(USE_WINDOWS8_API)
BOOL result = GetOverlappedResultEx(GetHandle(), &m_overlapped, &m_lastResult, INFINITE, FALSE);
#else
BOOL result = GetOverlappedResult(GetHandle(), &m_overlapped, &m_lastResult, FALSE);
#endif
Ironically, we added USE_WINDOWS8_API
, the additional includes and the calls to GetOverlappedResultEx
to appease the tools in the first place. They were complaining about deprecated functions and causing dirty compiles. The dirty compiles were creating governance, C&A and ST&E problems for users.
I audited the code to ensure we are not unintentionally or incorrectly setting the values. I verified we do it in one place, and the code path is not activated because Microsoft's toolchain is setting the value to 0x602
:
#ifdef CRYPTOPP_WIN32_AVAILABLE
# ifndef _WIN32_WINNT
# define _WIN32_WINNT 0x0400
# endif
#endif
Here's a related Stack overflow question: What is WINVER?, but it does not discuss how to set it to "this platform".
Here's Microsoft's docs on the subject: Using the Windows Headers and Modifying WINVER and _WIN32_WINNT. Ironically, they don't really discuss the problem or Windows 10, Windows Phone 10, Windows Store 10 or Windows Universal Platform.
As an aside, GCC has a quasi-similar -march=native
that basically provides "this platform".