How to get Visual C++ 2012 (VC 11 Beta) statically linked CRT and MFC applications to run on Windows XP

EDIT (April 14, 2013): If you’re having trouble with Microsoft’s XP support after installing Visual Studio 2012 Update 2 then please ignore this blog post! Read the new blog post instead.

EDIT (November 26, 2012): Microsoft has made their final release of Visual Studio 2012 Update 1 available which includes official XP targeting support!

EDIT (October 14, 2012): Microsoft has released their CTP of the XP targeting support, negating any further need for these wrappers.  Please use the official Microsoft solution from now on.

EDIT (June 20, 2012): Microsoft has announced XP targeting support will be added to Visual C++ 2012 in a post-RTM update.  Read the details here.  In the meantime you can use the below as a temporary workaround until the update has been released.

Source files and sample projects for this article located at:

Files last updated: 2012-07-10

XPSupport wrappers version 1.10

One of the major limitations of Visual C++ 2012 is that it does not create applications that can run on Windows XP.  As most of you already know, there is a connect item at Microsoft on this.  See:

Note that the connect item was closed as “by design” and it was stated that only Vista SP2 and above is supported.  So this leaves out XP and Server 2003.

As you can see from the comments, many users simply will not adopt VC 11 because of its lack of XP targeting support.  Whether the Visual Studio 11 tools run on XP is a whole other story.  I don’t need the IDE to run on XP. What I need is the ability to use VC 11 (and all of its powerful new language features) AND still be able to target XP as a platform to deploy my apps to.

If you’re a long time reader of my blog, you know that I have written another article in the past on how to target Windows 2000 when using Visual Studio 2010.   In that article I explained that there is a simple trick that we can use to “wrap” missing API functions.  This involves making a small assembly language forwarding directive that calls our own C++ wrapper function.  If we use this trick we can substitute our own versions of any API symbol that is linked into our app, without causing any multiple symbol errors in the linker.  This means we do not have to use /FORCE:MULTIPLE.

To summarize, if we run dependency walker (available from on a built executable that uses CRT and/or MFC 11 on Windows XP SP3, we’ll see a bunch of “red” icons beside the functions that are missing on XP (mostly in kernel32.dll). Our goal is to get rid of all of this red before it will run correctly on XP.

An aside: If it were truly a technical limitation to drop XP, then it would be impossible for us to “wrap” every instance of these functions without touching the original CRT and/or MFC static lib source code.  I’m about to show you a simple, elegant way to give your VC 11 apps the gift of XP support, while allowing the exact same binary to run on higher versions as well (e.g Vista, 7, Server 2008, etc)

There is another new roadblock that Microsoft has put in our way.  Previous to VC 11, we could override both the minimum operating system and subsystem version numbers using a linker command line option.  However in VC 11, they only allow specification of 6.0 (Vista) as a minimum.  That means there is NO way to write the necessary operating and subsystem versions to the built binary without a separate post-build tool.

Turns out that writing the operating system and subsystem version numbers can be acheived using EDITBIN.EXE (a tool that is included with VC11)  This means we can use this as post-build step just after linking occurs.

All that needs to be done is to run editbin.exe on the built executable itself, e.g.


It still throws a warning that the subsystem supplied is invalid but writes it anyway (unlike linking which refuses to write it when it’s invalid).

Note: if you’re trying these instructions with a console application, use



Notice that in the title of this blog post, I say “statically linked”.  There is good reason for that.  Microsoft no longer provides makefiles for their DLLs (since VC2010).  The last version to provide makefiles was VC2008.  That is unfortunate, as I could have provided a way to make dynamically linked apps run on XP as well.  But for now, we’ll have to do with a solution for statically linked apps only. I suggest you put pressure on Microsoft using the avenue of your choice to have them make available steps or makefiles that will allow us to rebuild the CRT and MFC DLLs.  If they agree, then I can provide a follow-up to this blog entry.

So, without further ado, here they are, two walkthroughs on how to create either a CRT or MFC statically linked app in Visual Studio 2012 that runs on Windows XP (resulting executable tested on a Windows XP SP3 machine that has been updated using Microsoft (Windows) Update with the various security fixes. This has not been tested on Windows XP x64 edition, and I don’t expect to be adding support for it as it’s a relatively underused operating system.

Simplified 4 step summary of solution:

(1) Add assembly language support to your existing project

(2) Add 4 files that I wrote that “wrap” the missing CRT and MFC functions (downloadable from my skydrive).  You only need 2 of these files if your app is not using MFC.

(3) Add a post-build event that runs EDITBIN.EXE to set the operating system and subsystem versions of your built app.

(4) Build your app, copy to XP and run it

That’s it. No complicated source code changes.  You simply need to add some wrapper code to your app and then use a tool to change a binary after it’s built.

In all cases, the wrapper code defers to the OS versions of the APIs (using GetProcAddress) when running on operating systems higher than XP/2003, and on XP/2003 uses either specific wrapper code (when needed) or appropriate return codes that allow the calling functions to continue.

Here’s a walkthrough that describes each of the above steps in detail (I’ve provided both CRT and MFC versions of the walkthrough, choose one or the other depending on whether your app uses MFC or not).

Grab the 3 zip files here first:

The first two zip files and are complete examples of CRT and MFC apps respectively.  Both of them contain the custom build step with editbin.exe that I mentioned and the changes mentioned in the walkthrough already applied.   The third, contain the 4 files required (only need 2 files if CRT project) to add to an existing project that you may have (or use them with newly created projects when going through the walkthroughs below)

IMPORTANT NOTE: if you use these wrappers with your existing projects, you must change both your WINVER and _WIN32_WINNT to 0x0600 in your stdafx.h files.  Otherwise a lot of Vista and later specific structures and defines that I use will not compile correctly.  I may fix this in a future release.

CRT (Win32 or console app) version of walkthrough:

1) Launch Visual Studio 11 Beta (could be named Visual Studio 2012 if this article being read after the RTM was released)

2) Create a Win32 app (Win32 Project), or console app, call it testapp, keep all the defaults and click finish (note: if you decide to create a console app in this step, please add an include for “windows.h” to your generated project’s stdafx.h file)

3) Right click on the project in solution explorer (not the solution, but the project – usually the second line from the top in the solution explorer view) and choose “Build Customizations…” menu item.

4) Click the checkbox (on) beside “MASM (.targets,.props), and hit OK.

5) Right click on the project and choose “Properties” menu item to bring up project properties

6) choose “release” configuration

7) change this project to statically link to the CRT (change to Release version of project, then using project properties – configuration properties – C/C++ – code generation: change runtime library to multithreaded (instead of multithreaded DLL),

8) choose “debug” then do the same in Debug as in step 7 (except change to multi-threaded Debug)

9) Choose “all configurations”

10) Choose Configuration Properties – Build Events – Post Build Event

11) If your app is a Win32 app add the following two steps to the “Command Line” section of the Post Build Event:

ping -n 3 -w 1000

editbin.exe "$(TargetPath)" /SUBSYSTEM:WINDOWS,5.01 /OSVERSION:5.1

otherwise, if your app is a console app, then add the following two steps instead  to the “Command Line” section of the Post Build Event:

ping -n 3 -w 1000

editbin.exe "$(TargetPath)" /SUBSYSTEM:CONSOLE,5.01 /OSVERSION:5.1

12) Hit OK

13) Get the file from my skydrive and extract 2 of the 4 files (xpcrt.cpp, xpcrtwrap.asm ) to the folder where your source code is ( stdafx.cpp, etc), e.g. at

c:\users\<user>\Documents\Visual Studio 11\Projects\testapp\testapp

14) Right click on Source Files folder, and choose Add – Existing Item

15) add the 2 files that you copied in step 13: xpcrt.cpp and  xpcrtwrap.asm to your project

16) Build your application.  The 2 files you added in step 15 should have compiled correctly, and the version should have been set by editbin.exe.

17) head over to a Windows XP SP3 machine (or VM) and copy your debug/release folder over there, and try running the app. If all steps above were performed correctly, you now have your first Win32 CRT 2012 app running on Windows XP SP3.

MFC version of walkthrough:

1) Launch Visual Studio 11 Beta (or Visual Studio 2012 if this article being read after the RTM was released)

2) Create an MFC app, call it testmfcapp, keep all the defaults except choose to use MFC in a static library and hit Finish

3) Right click on the project in solution explorer (not the solution, but the project – usually the second line from the top in the solution explorer view) and choose “Build Customizations…” menu item.

4) Click the checkbox (on) beside “MASM (.targets,.props), and hit OK.

5) Right click on the project and choose “Properties” menu item to bring up project properties

6) Choose “all configurations”

7) Choose Configuration Properties – Build Events – Post Build Event

8) Add the following two steps to the “Command Line” section of the Post Build Event:

ping -n 3 -w 1000

editbin.exe "$(TargetPath)" /SUBSYSTEM:WINDOWS,5.01 /OSVERSION:5.1

9) Hit OK

10) Get the file from my skydrive and extract the 4 files (xpcrt.cpp, xpcrtwrap.asm, xpmfc.cpp, and xpmfcwrap.asm ) to the folder where your source code is ( stdafx.cpp, etc), e.g. at

c:\users\<user>\Documents\Visual Studio 11\Projects\testmfcapp\testmfcapp

11) Right click on Source Files folder, and choose Add – Existing Item

12) add all 4 files that you copied in step 10: xpcrt.cpp, xpcrtwrap.asm, xpmfc.cpp, and xpmfcwrap.asm to your project

13) Build your application.  The 4 files you added in step 12 should have compiled correctly, and the version should have been set by editbin.exe.

14) head over to a Windows XP SP3 machine (or VM) and copy your debug/release folder over there, and try running the app. If all steps above were performed correctly, you now have your first MFC 2012 app running on Windows XP SP3.

Technical details of solution:

I’ve added comments to the code that describe the various wrapper functions that I had to write.  Several in particular I’d like to bring to your attention:

(1) Wrapper for GetTickCount64 uses some undocumented but well established Windows structures – please read over the definition of that function in the source code (xpcrt.cpp) for further comments about this.

(2) Wrapper for Locale name based APIs uses a DLL (nlsdl.dll) that ships with Internet Explorer 7 and above, or is available from Microsoft as a redistributable (see code comments for location and discussion of an alternative that does not require use of nlsdl.dll).  So basically if you can guarantee that IE7 or later or the nlsdl redist is installed on the XP SP3 machine, you can use this solution without any modifications whatsoever.


If you get the error: “Not a valid win32 application”, then the editbin.exe step failed during your build.  Please check to make sure the two steps mentioned (the ping and the editbin.exe are separate lines in the command line – click “edit…” when adding them)

If you get any errors that entry points cannot be found, then you’ve probably forgotten a step above or have called a Vista function that I haven’t wrapped.  It’s also possible that you inadvertently added the asm files to your project before you did the “Build Customizations” step.  Build customizations must be done before ANY assembly files are added, or they won’t be compiled.

Comments/questions welcome.  And keep voting on the Microsoft connect item (link above) :)

XPSupport wrappers – Update History

1.00 2012-03-11 Initial Release

1.01 2012-03-13 added msvcp110 stuff (InitializeCriticalSectionEx, CreateSymbolicLink(A/W)

1.02 2012-03-15 added DwmExtendFrameIntoClientArea

1.03 2012-03-15 added fix for ConCRT runtime resource manager initialization (so std::thread can now be used)

1.04 2012-03-16 added PSGetPropertyDescriptionListFromString

1.05 2012-03-29 added wrapper for EnumSystemLocalesEx

website update: 2012-03-30 updated steps to use editbin.exe to set versions instead of a custom executable (to avoid needing a special EXE to set the version)

1.06 2012-05-05 added wrapper for GetLogicalProcessorInformation (for XP SP2 support – thanks Michael Chourdakis for this implementation)

1.07 2012-05-18 added wrapper for InitOnceExecuteOnce

1.08 2012-05-26 added x64 support – thanks to Antony Vennard ( for testing and correcting several errors in my initial test x64 release

1.09 2012-05-27 fixed non-Unicode (MBCS) builds and updated instructions to clarify usage with console apps (thanks to Latency and Antony for suggesting and helping with these fixes)

1.10 2012-07-10 added support for more recent builds of Visual Studio 2012 (CRT uses several API functions related to thread pooling) and updated source code to include a standard MIT license

About tedwvc
On this blog you'll find some tips and tricks for dealing with Visual C++ issues.

48 Responses to How to get Visual C++ 2012 (VC 11 Beta) statically linked CRT and MFC applications to run on Windows XP

  1. Ben Hanson says:

    I’ve not tried this out, but I wanted to thank you for your efforts.

  2. Jake says:

    This works, but when creating a thread with std::thread the application crashes on XP (but not Windows 7).

    • tedwvc says:

      I know the problem – the Concurrency ResourceManager is written in such a way that the version of the OS is being detected as Windows 8. This is because it only checks for Vista, Windows 7, and Windows 8 and anything else it assumes Windows 8. This causes crashes when it tries to do GetProcAddresses on functions that only exist on Windows 8. I need to find a way to force the Concurrency OS version to Vista before it reaches the RetrieveSystemVersionInformation function in resourcemanager.cpp.

    • tedwvc says:

      Updated version on skydrive with a fix for std::thread – please grab

  3. Just me says:

    Thanks for your work. Hopefully Microsoft will do something about this…

  4. Pingback: Linking to the static CRT libraries is the only way to support XP (for now…) « SupportXP blog

  5. Thanks for your work, but it still fails. GetLogicalProcessorInformation() missing … is there a possibility I can wrap it as well?

    It seems that that’s the only one that we need.

  6. I fixed it.l

    bool GetLogicalProcessorInformationXP(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION Buffer,PDWORD dwLength)
    if (!dwLength)
    return 0;
    return false;

    if (Buffer == 0)
    return false;

    g1.ProcessorMask = 0x1;
    g1.Relationship = RelationProcessorCore;
    g1.ProcessorCore.Flags = 0;
    return true;

    And then I 've defined the function in the same way as the others in your asm/cpp. You may want to include my code as well.

    • tedwvc says:

      Thanks! I only tested the XPSupport wrappers under XP SP3 where the GetLogicalProcessorInformation function is available. I’ll definitely add your implementation in the next version (1.06), thanks for providing it. I know a lot of people still use XP SP2 so it may be useful to others.

  7. Mat Jaggard says:

    How do I tell VS not to try and assemble the asm code if I’m targetting x64?

    I’m aiming at having a binary for all versions of windows 32bit and another for as many 64bit versions as possible (is 2003 x64 supported?)

    • tedwvc says:

      You can make sure that the files are excluded from builds in your project properties (choose configuration x64 when excluding them and exclude from Debug and Release)

      I have x64 versions of the asm files but they’re currently unpublished. Let me know if you’d be interested in testing them and I’ll publish them to my skydrive as a separate zip file. The CPP files are the same for both x86 and x64 compiles.

      • Michael Chourdakis says:

        I think that Windows XP x64 is dead anyway. Those that still run XP are restricted to the x86 version. I ‘ve excluded your files from x64 builds (and soon from x86 builds for new projects anyway).

      • tedwvc says:

        I agree XP x64 is dead, but 2003 Server x64 may be interesting to support for various reasons.

  8. Swapnil99pro says:

    Though I am only a beginner C++ developer, big salute to you for you efforts.

  9. steven says:

    Thanks for your great work, but it fails. InitOnceExecuteOnce() missing …

    VS version 11.0.50503.1 RCREL


  10. Ninefingers says:

    I’ve used this successfully for XP 32-bit support – although I had to replace a few bits for xp sp 2 support (this is before you released 106).

    I’d be interested in the x64 asm files for server 2k3 – I’ve already tried my own, but the linker ignores these and instead links against the usual libs, which is no good.

    • tedwvc says:

      Thanks for your interest – for x64 builds, I’ll clean up what I have shortly and post it as a separate zip to my skydrive.

    • tedwvc says:

      I placed an initial version of the ASM files on my skydrive.

      • Ninefingers says:

        Thanks a lot for that.

        I made some tweaks; some of the functions had __imp__ rather than __imp_ prefixes, which causes link to link to dwmapi.dll – which doesn’t exist pre Vista.

        I also modified the function arguments to qwords where pointer types were used in both sources. Happy to send these back to you, if you want.

        To contribute back and make other people’s lives a little easier, we use this as a lib, and include it via property sheets. From our snippets, probably the most useful is this:


        The first part creates a build event after Linking which runs editbin for you on the executable, so you don’t have to afterwards. The second part is a hack of mine to define X64 for the ml64.exe so I don’t assemble the wrong portion of the code – I use ifdef X64 as a guard for X64/non X64 code.

        Thanks for your work :)

      • tedwvc says:

        Thanks a lot Ninefingers for testing my initial release and finding those problems. I’ve incorporated your x64 asm fixes and have made a new 1.08 release that combines the x86 and x64 versions into a single zip file.

  11. Latency says:

    I have tried to compile this and have had to made several changes to get mine to work. Using the latest v108:

    Replace all occurring instances of _T to TEXT
    Replace your “stdafx.h” with

    Line 290: or around there:
    Add: TCHAR lpStr[512];
    WideCharToMultiByte(CP_ACP, 0, lpLCData, -1, lpStr, 511, 0, 0);
    Replace w/: return GetLocaleInfo(lcid, LCType, lpStr, cchData);

    Line 323: or around there.. TCHAR[] to LPWSTR yields improper conversion.
    Add: LPWSTR lpwStr;
    int nLen = MultiByteToWideChar(CP_ACP, 0, localeName, -1, NULL, NULL);
    MultiByteToWideChar(CP_ACP, 0, localeName, -1, lpwStr, nLen);
    Replace w/: AfxLCIDToLocaleName(localeID, lpwStr, _countof(localeName), 0);
    return pLocaleEnumProcEx(lpwStr, 0, 0);

    ‘_stscanf_s’ identifier not found: #include
    ‘_taccess’ identifier not found: #include


    Let me know if this looks okay.. going to test it out now!

    • tedwvc says:

      Thanks so much Latency, I forgot test this with non-Unicode builds. Sorry some of the text didn’t come through in your message as you can see, but I get the overall jist of it.

      There may be some slight improvements to your suggested solution
      – include tchar.h in your stdafx.h so you don’t need them elsewhere
      – where there are multi-byte to Unicode conversion problems, call the “W” version of the Win32 API function directly (e.g. EnumSystemLocalesW instead of EnumSystemLocales, or GetLocaleInfoW instead of GetLocaleInfo)

      I’ll make a new release that incorporates these fixes.

      • Latency says:

        I am having some probs getting it to do anything. I can get it to compile.. and earlier in my main build.. I just had some instance of it looping.. like it would constantly exec the app.

        Now I started over with a new stock Console c++ project.. followed the directions, dropped in the v109 .. had to add a few headers to stdafx.h

        io.h – wchar.h – Windows.h .. Nothing happens.. when I click on the .exe
        Dropped it into XP SP3 .. same thing.. nothing. If I run it on Win7 with the IDE.. my hello world doesn’t even print.. just get the .. ‘press any key to continue’ built into the con.

        Can you send me a working build project please or can you test it out with console Win32 mode? Do you have instant messenger I can add you real quick?

      • Antony says:

        Latency – the editbin line:

        editbin.exe “$(TargetPath)” /SUBSYSTEM:WINDOWS,5.01 /OSVERSION:5.1

        sets the application subsystem to Windows. Windows EXEs broadly speaking belong to one of a number of subsystems – WINDOWS, CONSOLE, NATIVE, OS2 and a few others. WINDOWS and CONSOLE subsystems are both part of the Win32 subsystem (what you’re used to) except that CONSOLE displays a console window (as the name implies). What you might not know is that WINDOWS not only does not display a console window, but the standard library does not open handles 0, 1, 2 (stdin, stdout, stderr) in those mode either.

        So long story short, if you’re setting a console app to /SUBSYSTEM:WINDOWS, you’re hiding your output. However, if you’re not seeing “Function SomethingW in Kernel32.dll cannot be found” (or some variation thereof) this is working for you.

        To fix it, change /SUBSYSTEM:WINDOWS to /SUBSYSTEM:CONSOLE. Your output should then appear.

      • tedwvc says:

        Antony, thanks, very good point, I should make a note in the instructions to use /SUBSYSTEM:CONSOLE,5.01 instead when doing a console app.

        Hi Latency, I also added a testconsoleapp zip file to my skydrive.

  12. Latency says:

    Brilliant. This has to be the best tutorial I have almost never read. You did very good work Ted. Thank you so much and just in time for Monday. I tried it on a hello world console build and it worked with the notes from Antony.. Never did try out your test project yet… Very good instructions indeed.. and yes, please include that in the instructions. Also I had to add Windows.h into the stdafx.h and wonder if the pchs’ work just the same if moved to the xpcrt.cpp file? That’s all I had to add this round.. new version worked good. Thanks everyone!!!

    • tedwvc says:

      Thanks Latency, I’ve updated the instructions with your suggestion (adding the include for windows.h for console apps), and also mentioned using the correct subsystem switch.

  13. Pingback: XPSupport wrappers updated to 1.09 – now with x64 and non-Unicode build support! « SupportXP blog

  14. Michael Chourdakis says:

    New error :(

    VS 2012 RC: InitOnceExecuteOnce failed.

    MS playing once more bad games.

    • Michael Chourdakis says:

      Ah sorry, I didn’t notice that newer versions have it wrapped as well. Keep going. :)

  15. Michael Chourdakis says:

    I guess that there’s another culprit now.

    • tedwvc says:

      LCMapStringEx has been supported by XPSupport wrappers since the first version. However, I suspect you are running into another problem: you are probably including a file that gives you an error at compile time, rather than a particular entry point not found error. In this case you have to increase your _WIN32_WINNT to 0x0600. If this is not the problem, please take a look at dependency walker (running on XP) and see where this function is being referenced (maybe it’s in a DLL that you haven’t properly wrapped). If that doesn’t lead to anything, please post a test project somewhere and I’ll take a look.

      • Michael Chourdakis says:

        Hmm. That’s weird. LcMapStringEx is indeed included in the cpp/asm and yet it’s a problem with kernel32.dll export. And in other projects it worked fine, andalso _WIN32_WINNT is for win 7 (should i put it specifically to 0x600?).

      • tedwvc says:

        I would say, there must be a reference to this that is in one of your modules, can you ensure that no static libs are using this. Try doing a find in files to see where all the places you are calling LCMapStringEx. if you could make a small test project that shows the problem we can figure out where it’s going wrong (maybe linker ordering)

  16. Michael Chourdakis says:

    Hmm yes, it seems that some of my static libraries use it. Good point.

    Somewhere I read that ms plans to add XP support with a post-rtm update to VS 2012?

  17. Mahesh says:

    Hi Ted !

    I installed VS 2012 Professional and the XP update as well. When I run the .msi of my project, I get a popup window saying – “The procedure entry point FlushProcessWriteBuffers could not be located in Kernel32.dll”

    I am running with the platform tool set “v110_xp” in Visual Studio. My project’s .msi is running fine on Windows 7. Any help is highly appreciated.


    • tedwvc says:

      You’re including the incorrect versions of msvcr110.dll, msvcp110.dll, etc. Ensure you are including the ones found at C:\Program Files (x86)\Microsoft Visual Studio 11.0\vc\redist\x86\Microsoft.VC110.CRT or use the vcredist_x86.exe. Ensure you are taking these from a machine that has Update 1 already installed.

  18. Michael Chourdakis says:

    Good job to all of you.
    Remember: without all people here working on the “patch”, Microsoft would -NOT- had released an update.

    Best Regrds

  19. Pingback: Dez anos » VC2012部署到早期Windows

  20. Sonny says:

    Hello, Ive got this exact problem and am trying to use your solution but I cannot get the zip files from your skydrive because the link you provide doesn’t work. Do you have an updated link?

  21. Sonny says:

    Hi again, Ive got the requred files and followed your instructions. My project built fine and everything, but when I tried running the .exe in Windows XP I still get an error saying that “The procedure entry point GetTickCount64 could not be located in the Kernell32.dll”. Do you know how to work around this?

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: