I'm writing a hook dll, which handles window drawing messages.
I found for Vista and above, some unknown message id are received by the hook dll, specifically 0x90 ~ 0x95.
I did some googling and found an msdn link and this, which told me what message they're:
#define WM_UAHDESTROYWINDOW 0x0090
#define WM_UAHDRAWMENU 0x0091
#define WM_UAHDRAWMENUITEM 0x0092
#define WM_UAHINITMENU 0x0093
#define WM_UAHMEASUREMENUITEM 0x0094
#define WM_UAHNCPAINTMENUPOPUP 0x0095
But I can't find definition of macro WM_UAHDRAWMENUITEM in any header files, the compiler complains about "undefined symbols". I did a global search on "WM_UAHDRAWMENUITEM" but found nothing.
At present I'm using 0x92 to handle this message.
My question is: how to nicely replace hard-coded 0x92 with a Windows-defined macro?
how to nicely replace hard-coded 0x92 with a Windows-defined macro?
Obviously, your installed version of the Win32 SDK does not have the macros, so you can't use them. But you have the #define values, so just copy/paste them directly into your own code. If you want, you can wrap them in an #ifdef so that if you ever upgrade to an SDK version that has them natively, the native macros will be used, otherwise the compiler will keep using your manual ones.
#ifndef WM_UAHDRAWMENUITEM
#define WM_UAHDRAWMENUITEM 0x0092
#endif
Related
I have a VS (C++) project that relies on OpenCV and TBB, so I created property sheets for each library and included them in the project. Everything worked fine and the code compiled.
Yesterday, I have started using vcpkg package manager. I installed OpenCV and TBB via vcpkg and everything seemed to work. I created an empty project, included the headers of both and tested if the new compiled libraries work. After verifying that, I went back to my main project and removed the property sheets, so I can use the libraries from vcpkg. I did not change the code in any way since the last successful compilation.
But when I try to compile the code now I get this error two times (in main.cpp and in a submodule)
tbb\critical_section.h(53): error C3861: 'InitializeCriticalSectionEx': identifier not found
Does anybody know what is going on here or why this error occurs?
Update
I found the error myself. I'm adding the poco-libraries tag, because it's actually a conflict between TBB and Poco.
I found the source of the problem and it has actually nothing to do with TBB but with the Poco library.
Consider the minimum example:
#include <Poco/Poco.h>
#include <tbb/tbb.h>
void main()
{
}
This will throw an compiler error.
Tracing down the path
When including tbb.h, critical_section.h is included in line 51 of tbb.h. However, ciritcal_section.hpp includes machine/winwdows_api.h which looks like this (unnecessary stuff is cut out):
tbb/machine/winwdows_api.h:
#if _WIN32 || _WIN64
#include <windows.h>
#if _WIN32_WINNT < 0x0600
#define InitializeCriticalSectionEx inlineInitializeCriticalSectionEx
inline BOOL WINAPI inlineInitializeCriticalSectionEx( LPCRITICAL_SECTION lpCriticalSection, DWORD dwSpinCount, DWORD )
{
return InitializeCriticalSectionAndSpinCount( lpCriticalSection, dwSpinCount );
}
#endif
As you can see, windows.h is included before the check of the _WIN32_WINNT macro. This macro is defined in sdkddkver.h (which is included in windows.h), iff it's not already defined (in my case it's set to Win10):
sdkddkver.h:
#if !defined(_WIN32_WINNT) && !defined(_CHICAGO_)
#define _WIN32_WINNT 0x0A00
#endif
In windows.h, the _WIN32_WINNT macro controls which version of the windows header files are actually included. If _WIN32_WINNT is set to an earlier version than Windows Vista, the function InitializeCriticalSectionEx is not defined.
This issue is catched by machine/winwdows_api.h (as you can see in the code block of that file) by simply defining a macro InitializeCriticalSectionEx that calls an appropriate alternative function.
So far so good.
The problem
The root of all evil lies in Poco/UnWindows.h of the Poco library. When including a poco header, at some point UnWindows.h will be included.
Poco/UnWindows.h (shortened):
#if defined(_WIN32_WINNT)
#if (_WIN32_WINNT < 0x0501)
#error Unsupported Windows version.
#endif
#elif defined(NTDDI_VERSION)
#if (NTDDI_VERSION < 0x05010100)
#error Unsupported Windows version.
#endif
#elif !defined(_WIN32_WINNT)
#define _WIN32_WINNT 0x0501
#define NTDDI_VERSION 0x05010100
#endif
#endif
#include <windows.h>
The preprocessor checks, if _WIN32_WINNT is already defined, and if not, sets it to 0x0501 which is Windows XP. After that, windows.h is included. In the previous chapter I mentioned that _WIN32_WINNT controls which version of the windows header files are actually included.
Now imagine, the very first include in our project is a header from Poco. This means, that _WIN32_WINNT will be set to Windows XP and windows.h will include the windows headers of Windows XP (which imo is already a bad sign).
But don't worry, it gets worse.
If we trace the include hierarchy one level up, we reach Poco/Platform_WIN32.h.
Poco/Platform_WIN32.h (shortened):
#include "Poco/UnWindows.h"
...
#if defined (_WIN32_WINNT_WINBLUE)
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#endif
#define _WIN32_WINNT _WIN32_WINNT_WINBLUE
...
Funny, isn't it? First, it includes UnWindows.h, which sets _WIN32_WINNT and causes Windows XP headers to be included, and next it redefines _WIN32_WINNT to be Windows 8.1. I have no clue why it does that, maybe there is a good reason, idk.
If we now look at the minimum example at the very top we see that Poco is included before TBB. What now happens is:
Include Poco headers
Set _WIN32_WINNT to Windows XP
Include windows headers (Windows XP version, because of 2)
Reset _WIN32_WINNT to Windows 8.1
Include TBB headers (windows headers are already included, so TBB doesn't need to include them again in tbb/windows_api.h)
TBB checks the windows version via _WIN32_WINNT and recognizes Windows 8.1 (as set by Poco)
TBB thinks InitializeCriticalSectionEx is defined, because the Windows version is 8.1 (or is it? Poco says: get rekt) and InitializeCriticalSectionEx is defined since Windows Vista.
Unfortunately Poco ensured that the Windows XP headers are loaded, so compiler says: no.
The solution
Either include windows.h yourself beforehand, or set _WIN32_WINNT yourself beforehand:
#define _WIN32_WINNT 0x0A00 // either this
#include <Windows.h> // or this
#include <Poco/Poco.h>
#include <tbb/tbb.h>
void main()
{
}
Maybe someone of the Poco contributors can clarify some things here. The Poco version is 1.8.1-1 built with x64 (via vcpkg).
Update
Poco is on the issue. Updates can be found here.
i'm trying to use the CheckTokenMembership function, i copied the example piece of code on Microsofts website ( https://msdn.microsoft.com/pt-br/library/windows/desktop/aa376389(v=vs.85).aspx ), but i just can't get it to work!
I get "error: 'CheckTokenMembership' was not declared in this scope" (on CodeBlocks) no matter what i do.
I am including Windows.h and even Winbase.h as the website says. Does anyone have any idea on how to fix this?
Before including windows.h you need to specify the minimum version of Windows your application will support. The idea here is that the build will fail if you use an API function that isn't available in the specified Windows version.
You can do this by defining the _WIN32_WINNT macro, e.g., for Windows 7:
#define _WIN32_WINNT _WIN32_WINNT_WIN7
If you need to be more specific you can also define the NTDDI_VERSION macro, e.g., for Windows 10 version 1607:
#define _WIN32_WINNT _WIN32_WINNT_WIN10
#define NTDDI_VERSION NTDDI_WIN10_RS1
The documentation tends to lag behind, but you can find the definitions in sdkddkver.h in the SDK.
Addendum:
In some cases, e.g., if using an old or third-party version of the SDK, the named constants may not work and you will have to resort to magic values, e.g., the examples above would become
#define _WIN32_WINNT 0x0601
and
#define _WIN32_WINNT 0x0A00
#define NTDDI_VERSION 0x0A000002
You can look these up by obtaining a recent version of sdkddkver.h from Microsoft or you could try the search engine of your choice. :-)
Porting my project from Qt4 to Qt5.1, I get this error from a Qt file:
C:\Qt\Qt5.1.1\5.1.1\mingw48_32\include\QtGui\qopenglversionfunctions.h:785: error: expected unqualified-id before ')' token
void (QOPENGLF_APIENTRYP MemoryBarrier)(GLbitfield barriers);
^
This is the chain of defines:
#define QOPENGLF_APIENTRYP QOPENGLF_APIENTRY *
#define QOPENGLF_APIENTRY APIENTRY
#define APIENTRY WINAPI
#define WINAPI __stdcall
I noticed that the "MemoryBarrier" token is present in the libQt5OpenGLExtensionsd.a library. Should I include it, even if in the original Qt4 project nothing related to OpenGL was used?
Platform:
Windows 7
MinGW 4.8
Qt 4.8 --> Qt 5.1
Besides the bug in MinGW 4.8.1 with uint64_t in io.h, there is also this one in QT 5.2.1 still. I came across this today when trying to compile QT 5.2.1 with MinGW 4.8.1, so I thought I would post my solution as well.
I don't know what the official fix will be for QT, but for my needs I did it like this:
in src/gui/opengl/qopengl.h line 49:
// Windows always needs this to ensure that APIENTRY gets defined
#if defined(Q_OS_WIN)
# include <QtCore/qt_windows.h>
#endif
I just undefined the windows MemoryBarrier macro there:
// Windows always needs this to ensure that APIENTRY gets defined
#if defined(Q_OS_WIN)
# include <QtCore/qt_windows.h>
# undef MemoryBarrier
#endif
I noticed that the "MemoryBarrier" token is present in the
libQt5OpenGLExtensionsd.a library. Should I include it, even if in the
original Qt4 project nothing related to OpenGL was used?
No, those are not related. OpenGLExtension is compiled after QtGui.
What you are hitting unfortunately is that there is a MemoryBarrier() already defined on Windows, and hence there is a clash for that and what qt is having. You can find the official Windows documentation for that:
http://msdn.microsoft.com/en-us/library/windows/apps/ms684208(v=vs.85).aspx
I have just discussed this with Gunnar, the QtGui maintainer, and I am planning to submit a change to Gerrit to address your issue.
We had used something like this in our project a couple of years ago when we were writing thread-safe singletons based on QtCore:
#if defined __GNUC__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 4
#define __MEMBARRIER __sync_synchronize();
#elif defined _MSC_VER && defined _WIN64
#define __MEMBARRIER MemoryBarrier();
#else
#define __MEMBARRIER
#endif
Qt may need to check ifdef MINGW/GCC/VERSION and undef the MemoryBarrier define.
EDIT: This was fixed about half a year ago. See the following Gerrit review and the corresponding bug report for details:
https://codereview.qt-project.org/#change,68156
and
https://bugreports.qt.io/browse/QTBUG-34080
So, update to Qt 5.2.0 and it will work. Failing that, you can try to backport it.
I run into the same problem. I could compile and run with just commenting out the problematic line:
// void (QOPENGLF_APIENTRYP MemoryBarrier)(GLbitfield barriers);
In file C:/Qt/Qt5.1.1/5.1.1/mingw48_32/include/QtGui/qopenglversionfunctions.h:785
My application does not use any OpenGL stuff. Let's hope they fix it soon ;-)
Since the accepted answer doesn't seem to help when one tries to build the QT library on it's own and Laszlo Pap claims that thie other solution is not a proper fix, I tried to find a way to fix it correctly. On Google I found a posting where it was said that MemoryBarrier is not implemented in MingW and there was a patch for it.
So I tried to incorporate the fix into opengl.h and hope that this is the correct way as simply commenting out the lines may cause problems later on.
#ifndef QT_NO_OPENGL
// Windows always needs this to ensure that APIENTRY gets defined
#if defined(Q_OS_WIN)
# include <QtCore/qt_windows.h>
#if defined(__MINGW32__) && defined(MemoryBarrier)
#undef MemoryBarrier
__CRT_INLINE void MemoryBarrier(void)
{
long Barrier = 0;
__asm__ __volatile__("xchgl %%eax,%0 "
:"=r" (Barrier));
}
#endif
#endif
EDIT 2: Ok so I changed to Orwell DevC++ which contains the "winnt.h" that contains #define KEY_WOW64_64KEY 0x0100 but it still is not working. (Refer to EDIT 1:)
EDIT 1: I looked into the "winnt.h" which came along the CodeBlock and DevC++ and the DevC++'s is missing the following lines:
#if (_WIN32_WINNT >= 0x0502)
#define KEY_WOW64_64KEY 0x0100
#define KEY_WOW64_32KEY 0x0200
#endif
And putting the above code in the wint.h of DevC++ doesn't work.
Original Post:
I have a 32bit application (developing in DevC++ and Windows 7 64bit) which reads a 64bit app's registry as one of its task, so I am trying to use "KEY_WOW64_64KEY" flag in RegOpenKeyEx, and found few posts regarding how to use it with _WIN32_WINNT : this and this
It worked like charm when I used it in a CodeBlock Project(a test project) but the same code is not working with DevC++, I can't port it to codeblock now since codeblock presents other problems.
How do I make it work with DevC++ ?
Thanks
It defines the version of the windows header files to use. It must be declared before you #include <Windows.h>.
There are a few other similar variables you should probably set if you're going to modify it:
MSDN Using Windows Headers
_WIN32_WINNT is a preprocessor token, which is replaced by (0x0601) wherever _WIN32_WINNT is used. The preprocessor just scans the whole file and replaces _WIN32_WINNT with (0x0601) everywhere it is found.
Chances are, there could be ifdef preprocessor guards that will enable/disable a preprocessor constant. Like:
#ifdef _WIN32_WINNT
#define KEY32 32
#endif
There, KEY32 will only be defined IF _WIN32_WINNT is defined.
It already works with DevC++.
I am trying to migrate existing c++ 32 code to 64 code on windows7 with visual studio 2010.i never did 64bit compilation before. with the help of internet references i did the setup for 64 bit compilation. like VS2010 with 64 bit compiler etc and other configuration changes.
In the preprocessor i removed WIN32 and added WIN64. i have some other pre-processors like OS_WIN_32 and some other which are specific in my code.
In the code wherever WIN32 was getting used i added extra condition as || WIN64 this is just to ensure that application should get compiled with win32 as well as win64.
When i am trying to compile the code i am getting the compilation error saying
fatal error C1189: #error : Only one of the WIN32 and WIN64 symbols should be defined
this error is coming from the local code where we have a check whether both WIN32 and WIN64 are defined. that code is as shown below.
#if defined WIN32 && defined WIN64
# error Only one of the WIN32 and WIN64 symbols should be defined
#endif
in VS2010 if macros are not enabled then the code inside the macro gets greyed out. in my code also the above error is greyed out. but still i am getting that error.
The code where i added WIN64 is including windows.h. for reference givine it below.
#if defined WIN32 || defined WIN64
#include <windows.h>
#include <process.h>
#endif
So my question is why i am getting this error? shouldnt we add windows.h for 64bit compilation.? i tried by commenting this inclusion but i am getting other errors wrt HANDLE which are used in the code.
If i go to WIN32 definition VS2010 is pointing to a definition in windef.h file. This file is present in Microsoft SDKs\windows\v7.0A\include folder i.e. not my local code.
for referance that definition is given below.
#ifndef WIN32
#define WIN32
#endif
So i want to know why compiler is getting both pre-processors WIN32 and WIN64.
Thanks in advance for your help.
You shouldn't define either yourself. The macro's that should be used to check this are
_WIN32 // always defined for Windows apps
_WIN64 // only defined for x64 compilation
These are defined by the compiler (see here).
Often, the IDE adds the unprefixed macros to the commandline to not let legacy projects which use the non-documented unprefixed versions fail to build. The fact that they work is not a reason to use them, when documented alternatives are present.
It boils down to this:
#ifdef _WIN32
// We're on Windows, yay!
#ifdef _WIN64
// We're on x64! Yay!
#else // _WIN64
// We're on x86 (or perhaps IA64, but that one doesn't matter anymore). Yay!
#endif // _WIN64
#else // _WIN32
// We're not on Windows, maybe WindowsCE or WindowsPhone stuff, otherwise some other platform
#endif