title: Targetting Windows XP from Visual Studio 2012
body: <p>Good day everyone,</p>
  
  <p>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.</p>
  
  <p>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.</p>
  
  <p>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.</p>
  
  <p>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.</p>
  
  <p>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.</p>
  
  <p>Here is the code I used to compile the Hello World program:</p>
  
  <p>main.cpp:</p>
  
  <pre><code>#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;
  }
  </code></pre>
  
  <p>winapi.h:</p>
  
  <pre><code>#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 &gt;= 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 &lt;Windows.h&gt;
  
  #else // _WIN32
  // OTHER OS ////////////////////////////////////////////////////////////////////
  #error This software has been written with Visual C++ in mind.
  ////////////////////////////////////////////////////////////////////////////////
  
  #endif // _WIN32
  
  #endif // WINAPI_H_INCLUDED
  </code></pre>
  
  <p>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.</p>
  
  <p>To make this as complete as possible, here are the executable's imports:</p>
  
  <pre><code>D:\Projects\xptest\Release&gt;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
  </code></pre>
  
  <p>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!</p>
  
  <p>Regards,</p>
  
  <p>Gerard</p>