How do I call SetWindowLong() in the 64-bit versions of Windows? - c++

In the header file WinUser.h, there is a part in which the constants of the second parameter of SetWindowLong() are defined.
// ...
#define GWL_WNDPROC (-4)
#define GWL_HINSTANCE (-6)
#define GWL_HWNDPARENT (-8)
#define GWL_STYLE (-16)
#define GWL_EXSTYLE (-20)
#define GWL_USERDATA (-21)
#define GWL_ID (-12)
#ifdef _WIN64
#undef GWL_WNDPROC
#undef GWL_HINSTANCE
#undef GWL_HWNDPARENT
#undef GWL_USERDATA
#endif /* _WIN64 */
#define GWLP_WNDPROC (-4)
#define GWLP_HINSTANCE (-6)
#define GWLP_HWNDPARENT (-8)
#define GWLP_USERDATA (-21)
#define GWLP_ID (-12)
// ...
But they are right after undefined if _WIN64 is defined; and it is defined in my 64-bit system.
As you see, there is also a GWLP_*** set of constants, but they are not documented in the page of SetWindowLong().
Why are these constants undefined in x64 systems?
What is the alternative way of calling SetWindowLong() in x64 systems?
My system:
OS: Windows 7 Ultimate x64 SP1
IDE: Visual Studio 2012 Ultimate Update 3

Some of the window data values (the ones that refer to "pointer sized" objects like the window procedure, for example) need to be 64 bit in an x64 build. The old SetWindowLong() and GetWindowLong() functions are limited to DWORD sized (32 bit) values for backwards compatibility, and Microsoft have introduced new versions, SetWindowLongPtr() and GetWindowLongPtr() that allow you to work with pointer-sized values (32 bit in a 32 bit build, and 64 bit in a 64 bit build).
These days it is recommended that you always use SetWindowLongPtr() and the GWLP_xxx constants, whether you are building for 32 or 64 bit, but in a 64 bit build you need to use the new functions and so the defines are #undefined to cause build errors that force you to fix your code.

As specified in <WinUser.h>
//If config is _WIN64 then use new versioned macro
#define GWLP_WNDPROC (-4)
#define GWLP_HINSTANCE (-6)
#define GWLP_HWNDPARENT (-8)
#define GWLP_USERDATA (-21)
#define GWLP_ID (-12)
//else for _WIN32
#undef GWL_WNDPROC
#undef GWL_HINSTANCE
#undef GWL_HWNDPARENT
#undef GWL_USERDATA

Also make sure you're NOT defining the following:
#define NOWINOFFSETS
which disables GWL_*, GCL_*, ie. GetWindowLongPtr and family, as well as associated routines.

Related

Windows SDK control available functions

Function AddDllDirectory was added to Windows 7 in one of the updates.
I'm using Windows 10 SDK headers in my c++ application. Is it possible to configure them to show only functions available in first Windows 7 version (without any updates) ?
I read about defines of:
WINVER, _WIN32_WINNT
I tried to set them to:
#define _WIN32_WINNT 0x601
#define NTDDI_VERSION 0x06010000
or even:
#define _WIN32_WINNT 0x600
#define NTDDI_VERSION 0x06000000
, but it doesn't work.
The NTDDI_VERSION macro uses a 32-bit number that includes service pack information. The older defines (WINVER, _WIN32_WINNT, _WIN32_WINDOWS, and _WIN32_IE) is just a 16-bit number, typically in hex: 0xaabb where aa is the Windows major version and bb is the minor version.
The correct value for Windows 7 is therefore 0x0601 for these defines and 0x06010000 is just for NTDDI_VERSION. The SdkDdkver.h header also provides macros like _WIN32_WINNT_WIN7 and NTDDI_WIN7 where the version numbers are listed for you.

identifier "PLVGROUP" is undefined afxcmn.h

I have a Visual Studio 2015 project which uses the afxcmn header and is having a lot of "is undefined" errors.
I read in the documentation those data types are included in commctrl.h which is already included in the Visual Studio project as external dependency.
// Adds a group to the control.
AFX_ANSI_DEPRECATED int InsertGroup(_In_ int index, _In_ PLVGROUP pgrp);
// Sets information about the specified group (by ID) in the control.
AFX_ANSI_DEPRECATED int SetGroupInfo(_In_ int iGroupId, _In_ PLVGROUP pGroup);
// Retrieves information for the specified group in the control.
AFX_ANSI_DEPRECATED int GetGroupInfo(_In_ int iGroupId, _Out_ PLVGROUP pgrp) const;
That is some code example of the afxcmn.h which gives those errors.
I dont know if I have to configure something else in the project to include the commctrl header
yes, PLVGROUP is defined in commctrl.h, but it depends on WINVER
#if (NTDDI_VERSION >= NTDDI_WINXP)
that means WINVER >= 501, see:
error-Direktive: MFC does not support WINVER less than 0x0501. Please change the definition of WINVER in your project properties or precompiled header.
So I had to change my stdafx.h
//#define WINVER 0x0500
#define WINVER NTDDI_WINXP //0x05010000
They are IntelliSense errors generated by Visual Studio 2015.
My environment is Windows 10 1903/VS2017
I don't know exactly why, but this solves the problem for me:
FYI, this is the original stdafx.h in my project that produce the error in the question:
#pragma once
#ifndef VC_EXTRALEAN
#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
#endif
// Modify the following defines if you have to target a platform prior to the ones specified below.
// Refer to MSDN for the latest info on corresponding values for different platforms.
#ifndef WINVER // Allow use of features specific to Windows 95 and Windows NT 4 or later.
#define WINVER 0x0400 // Change this to the appropriate value to target Windows 98 and Windows 2000 or later.
#endif
#ifndef _WIN32_WINNT // Allow use of features specific to Windows NT 4 or later.
#define _WIN32_WINNT 0x0400 // Change this to the appropriate value to target Windows 98 and Windows 2000 or later.
#endif
#ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later.
#define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later.
#endif
#ifndef _WIN32_IE // Allow use of features specific to IE 4.0 or later.
#define _WIN32_IE 0x0400 // Change this to the appropriate value to target IE 5.0 or later.
#endif
#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit
......
after adding these two lines bellow "#pragma once" the problem is solved:
#define WINVER 0x0603
#define _WIN32_WINNT 0x0603
Only adding the first line still produce those errors.

Warning C4005 'identifier' : macro redefinition

I want my application to work in win32 and x64 platform. I have added below code in header file but I am getting C4005 warning. How can I avoid this?
#ifdef WIN32
#define SIZEOF_ANALYSIS_INFO 168
#endif
#ifdef _WIN64
#define SIZEOF_ANALYSIS_INFO 172
#endif
The _WIN32 macro is always defined when compiling on Windows these days, even in 64 bit compiles. You'll want to rearrange your code a bit:
#ifdef _WIN64
#define SIZEOF_ANALYSIS_INFO 172
#elif defined(_WIN32)
#define SIZEOF_ANALYSIS_INFO 168
#endif
If you're always compiling this with VC, you can just use #else in the middle.
Better yet would to be to use the sizeof operator with whatever struct is holding the analysis info, if possible.

Targetting Windows XP from Visual Studio 2012

Good day everyone,
I recently upgraded to Visual Studio 2012 and I'm loving the improved C++11 support and the dark theme. However, I'm trying to write a program that runs on Windows XP and higher, and I'm running into some strange issue.
The first time I tried to run my program on a XP virtual machine I got the "This is not a valid Win32 program" error message. Some googling revealed that I needed to apply Update 1 to VS to be able to target Windows XP. I searched for that but found Update 2 instead. I applied that and set the platform toolset to v110_xp, then recompiled my program and tried to run it again. This time I got no error message, but upon trying to start the program I hear XP's error sound (the same one you hear when calling MessageBox with MB_ICONERROR) and then nothing else happens. No mention of anything in Windows XP's Event viewer either.
I thought perhaps Update 2 messed something else up, so I completely uninstalled VS2012, including all the MS SQL crap it leaves behind, reinstalled it and only applied Update 1. Compiled my code with the XP toolset again, but the same thing happens. An error sound but no message when trying to start my program.
Some more googling revealed that I had to define PSAPI_VERSION to 1 to target the pre Windows 7 version of the Process API so I did that, but the issue remains.
I began to think something was wrong with my code so I made the most basic Hello World program, but it STILL has the same issue. So I'm out of ideas now.
Here is the code I used to compile the Hello World program:
main.cpp:
#include "winapi.h"
int WINAPI wWinMain(HINSTANCE inst, HINSTANCE prev, wchar_t *cmdline, int show)
{
MessageBox(HWND_DESKTOP, L"Let's hope this works in Windows XP...", L"Testing 1... 2... 3...", MB_ICONERROR);
return 0;
}
winapi.h:
#ifndef WINAPI_H_INCLUDED
#define WINAPI_H_INCLUDED
#ifdef _WIN32
// WINDOWS DEFINES /////////////////////////////////////////////////////////////
// If this is not a console program, let the linker include a manifest to
// enable visual styles.
#ifndef _CONSOLE
# pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#endif // _CONSOLE
// Shorten compile time by only including the most basic Windows definitions.
#define WIN32_LEAN_AND_MEAN
#define NOGDICAPMASKS // CC_*, LC_*, PC_*, CP_*, TC_*, RC_
#define NOSYSMETRICS // SM_*
#define NOICONS // IDI_*
#define NOKEYSTATES // MK_*
#define NOSYSCOMMANDS // SC_*
#define NORASTEROPS // Binary and Tertiary raster ops
#define OEMRESOURCE // OEM Resource values (OCR_NORMAL and related constants)
#define NOATOM // Atom Manager routines
#define NOCLIPBOARD // Clipboard routines
#define NODRAWTEXT // DrawText() and DT_*
#define NOKERNEL // All KERNEL defines and routines
#define NONLS // All NLS defines and routines
#define NOMEMMGR // GMEM_*, LMEM_*, GHND, LHND, associated routines
#define NOMETAFILE // typedef METAFILEPICT
#define NOMINMAX // Macros min(a,b) and max(a,b)
#define NOOPENFILE // OpenFile(), OemToAnsi, AnsiToOem, and OF_*
#define NOSERVICE // All Service Controller routines, SERVICE_ equates, etc.
#define NOSOUND // Sound driver routines
#define NOTEXTMETRIC // typedef TEXTMETRIC and associated routines
#define NOWH // SetWindowsHook and WH_*
#define NOCOMM // COMM driver routines
#define NOKANJI // Kanji support stuff.
#define NOHELP // Help engine interface.
#define NOPROFILER // Profiler interface.
#define NODEFERWINDOWPOS // DeferWindowPos routines
#define NOMCX // Modem Configuration Extensions
// Enable strict typechecking on Windows types like HANDLE, HWND and HDC.
#define STRICT
// Enable targetting of pre-Win7 Process API functions when compiling on
// VS2012 or higher.
#if _MSC_VER >= 1700
# define PSAPI_VERSION 1
#endif // _MSC_VER
// Specify the minimum versions of Windows and Internet Explorer supported
// by this code.
#define NTDDI_VERSION NTDDI_WIN2K
#define _WIN32_WINNT _WIN32_WINNT_WIN2K
#define WINVER _WIN32_WINNT_WIN2K
#define _WIN32_IE _WIN32_IE_IE50
// WINDOWS INCLUDES ////////////////////////////////////////////////////////////
#include <Windows.h>
#else // _WIN32
// OTHER OS ////////////////////////////////////////////////////////////////////
#error This software has been written with Visual C++ in mind.
////////////////////////////////////////////////////////////////////////////////
#endif // _WIN32
#endif // WINAPI_H_INCLUDED
As I've said, I compile this code by targeting the v110_xp toolset, and I statically link the CRT with /MD using the project settings window. I compiled it as x86 code and it runs fine on my Windows 7 x64 machine. Running dumpbin on the resulting executable confirms that's it's compiled as 32 bit code for operating system version 5.01 and the Windows GUI subsystem.
To make this as complete as possible, here are the executable's imports:
D:\Projects\xptest\Release>dumpbin /imports xptest.exe
Microsoft (R) COFF/PE Dumper Version 11.00.51106.1
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file xptest.exe
File Type: EXECUTABLE IMAGE
Section contains the following imports:
USER32.dll
4070FC Import Address Table
40B19C Import Name Table
0 time date stamp
0 Index of first forwarder reference
215 MessageBoxW
KERNEL32.dll
407000 Import Address Table
40B0A0 Import Name Table
0 time date stamp
0 Index of first forwarder reference
218 GetModuleHandleW
8F CreateFileW
187 GetCommandLineW
300 IsDebuggerPresent
304 IsProcessorFeaturePresent
202 GetLastError
473 SetLastError
2EF InterlockedIncrement
2EB InterlockedDecrement
1C5 GetCurrentThreadId
EA EncodePointer
CA DecodePointer
119 ExitProcess
217 GetModuleHandleExW
245 GetProcAddress
367 MultiByteToWideChar
264 GetStdHandle
525 WriteFile
214 GetModuleFileNameW
24A GetProcessHeap
1F3 GetFileType
2E3 InitializeCriticalSectionAndSpinCount
D1 DeleteCriticalSection
263 GetStartupInfoW
3A7 QueryPerformanceCounter
1C1 GetCurrentProcessId
279 GetSystemTimeAsFileTime
1DA GetEnvironmentStringsW
161 FreeEnvironmentStringsW
4D3 UnhandledExceptionFilter
4A5 SetUnhandledExceptionFilter
1C0 GetCurrentProcess
4C0 TerminateProcess
4C5 TlsAlloc
4C7 TlsGetValue
4C8 TlsSetValue
4C6 TlsFree
EE EnterCriticalSection
339 LeaveCriticalSection
2CF HeapFree
4B2 Sleep
30A IsValidCodePage
168 GetACP
237 GetOEMCP
172 GetCPInfo
33E LoadLibraryExW
38A OutputDebugStringW
33F LoadLibraryW
418 RtlUnwind
2CB HeapAlloc
2D2 HeapReAlloc
511 WideCharToMultiByte
269 GetStringTypeW
2D4 HeapSize
32D LCMapStringW
157 FlushFileBuffers
19A GetConsoleCP
1AC GetConsoleMode
487 SetStdHandle
467 SetFilePointerEx
524 WriteConsoleW
52 CloseHandle
Summary
3000 .data
5000 .rdata
3000 .reloc
1000 .rsrc
6000 .text
As I said, I'm completely out of ideas here... I've tried everything I can think of. Any helpful comment would be very much appreciated!
Regards,
Gerard
Before you #include any of the Windows headers, make sure you have the following #define's:
#ifndef WINVER
#define WINVER 0x0501
#endif
#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows XP.
#define _WIN32_WINNT 0x0501
#endif
It's all explained on MSDN here, if you want to see other alternatives.

error C1189: #error : This file requires _WIN32_WINNT to be #defined at least to 0x0500. Value 0x0501 or higher is recommended

I create MFC project in VS2010(windows xp). And i take this error:
error C1189: #error : This file requires _WIN32_WINNT to be #defined at least to 0x0500. Value 0x0501 or higher is recommended.
if I added in afxcomctl32.h: #define _WIN32_WINNT 0x0501, i take 60+ errors.
In project i dont added anything. Use such as Visual Studio created.
What i need to do with this?
afxcomctl32.h is a wrong place I think, to fix this problem make your stdafx.h looking like this:
// Modify the following defines if you have to target a platform prior to the ones specified below.
// Refer to MSDN for the latest info on corresponding values for different platforms.
#ifndef WINVER // Allow use of features specific to Windows 95 and Windows NT 4 or later.
#define WINVER 0x0501 // Change this to the appropriate value to target Windows 98 and Windows 2000 or later.
#endif
#ifndef _WIN32_WINNT // Allow use of features specific to Windows NT 4 or later.
#define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target Windows 98 and Windows 2000 or later.
#endif
#ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later.
#define _WIN32_WINDOWS 0x0501 // Change this to the appropriate value to target Windows Me or later.
#endif
#ifndef _WIN32_IE // Allow use of features specific to IE 4.0 or later.
#define _WIN32_IE 0x0500 // Change this to the appropriate value to target IE 5.0 or later.
#endif
Try adding this to the TOP of your StdAfx.h file:
#include <sdkddkver.h>
In my application, I'm defining
_WIN32_WINNT=_WIN32_WINNT_WINXP
At first I had the same problem. I discovered that because when you use MFC, you're not allowed to include windows.h, _WIN32_WINNT_WINXP is never defined and so _WIN32_WINNT didn't have a valid value. By including the header that windows.h uses to define those values (sdkddkver.h), suddenly everything works!
Blech. I hate programming for Windows.
You don't need to modify afxcomctl32.h. You just need to include Windows.h before this file.
Should work.
I solved my problem. The fact was that the file atmcore.h was different from the standart in VS2010.