Why MUIRCT is so cool (aka separating Win32 resources into satellite DLLs, the easy way)

MUIRCT is a utility that Microsoft made available starting with the Windows Vista SDK.  It’s a localization utility that allows you to “split” resources from a DLL that has already been built.

Let’s give an example.  You have a large legacy app with dozens of DLLs, all using the model of code+resources in the same module.  After all, up to this point there has been really no good techniques within Visual Studio itself to use the satellite DLL approach, without doing a lot of manual work.  Things like creating dialog boxes, etc are simply easier to do with the built in wizards (class wizards, event handlers, etc) if the code and the resources reside in the same EXE/DLL.  Unfortunately this is the exact opposite of what we need from a translation/localization perspective.    The satellite DLL approach allows you to keep your code and your resources separate, but it involves a lot of manual work, especially if you have a complex app with many EXEs and DLLs.

What if there was a way to continue with the old style code+resources in the same module approach during development, but then separate out the resources after the fact, and require only minor changes to your code?  How is that possible?  When you load a resource from a handle (e.g. let’s say your app is test.exe, and you pass in the HINSTANCE of test to LoadString, how does the operating system know to look elsewhere for the resources?  A single handle can’t represent two separate modules behind the scenes can it?

Turns out, in Vista and higher, MUIRCT can separate these resources for you, and the operating system will load them automatically when you do a resource load.  And you have control at the individual resource level as to what is treated as language neutral (what stays in test.exe) and what is localizable (what goes into the satellite DLL)

Example:

Create a new MFC app, test.exe using all the defaults

Compile the app, then run the following on the output:

muirct -q test.rcconfig test.exe test2.exe test2.exe.mui

The above commmand splits up the app test.exe into two components, a language neutral part (the EXE) and a DLL named test.exe.mui which contains the localized parts. Now translating this test.exe.mui using a resource editor, your code is separate from your resources.

Then you would store for example your app in two folders:

test2.exe en-us\test2.exe.mui

When you run your app, the operating system knows to look for your resources in en-us folder (or what ever your ultimate fallback language is selected to be)

So if you have a bug fix to test.exe, you don’t need to redo all the languages because the resources and the code are separate.

I’ve only just scratched the surface on this topic, there are many more technical details you’ll need to learn, fortunately this whole process (including a full example of an rcconfig file) is provided by Microsoft in a walkthrough and sample code here:

http://archive.msdn.microsoft.com/hellomui

and

http://archive.msdn.microsoft.com/MUIIzer

Note: this approach works in Vista and higher.  if you need XP support, you’ll need much more extensive changes to your application as there is no support for this technique at the OS level, so you end up writing a lot of extra code, which makes the whole thing pointless.  So I would recommend only using this if you are able to drop XP support from your list of supported operating systems.

Advertisements

Finding the kernel32.dll module handle in a Windows Store app using approved APIs

As there are a lot of forbidden Win32 APIs in Windows Store apps (i.e. APIs that, if you call them, will cause your app to fail app certification), there are often other alternative APIs that you have to call instead.  For example, the CreateFile API is banned, but for Windows Store apps they made CreateFile2.

But what about if I wanted to get the module handle of a DLL? Specifically of kernel32?  Well, looking at the help for GetModuleHandle we see the unfortunate info:

Minimum supported client Windows XP [desktop apps only]

So we can only use this with desktop apps.  For your own packaged libraries you can use LoadPackagedLibrary API.  But this doesn’t work for system DLLs.  So how can you the the handle to kernel32.dll, for example, by using only approved store APIs?

This is where VirtualQuery comes in.  Interestingly, the API’s help page lists the following info:

Minimum supported client Windows XP [desktop apps | Windows Store apps]

This is great news, because VirtualQuery can get you the module handle of any DLL just by querying any particular known function in the DLL you want the handle to.

I discovered this trick a while ago – previously I used it to find the module handle of the DLL any code is being called from.  See:

http://www.codeguru.com/cpp/w-p/dll/tips/article.php/c3635/Tip-Detecting-a-HMODULEHINSTANCE-Handle-Within-the-Module-Youre-Running-In.htm

You probably know where I’m going here, but VirtualQuery itself is a function exported from kernel32.dll!

So all we need to do to get the module handle of kernel32.dll is to do a VirtualQuery of VirtualQuery:

HMODULE GetKernelModule()
{
    MEMORY_BASIC_INFORMATION mbi = {0};
    VirtualQuery( VirtualQuery, &mbi, sizeof(mbi) );
    return reinterpret_cast<HMODULE>(mbi.AllocationBase);
}

And then from your own code:

HMODULE kernelHandle = GetKernelModule();

You can now pass this into functions such as GetProcAddress (which is also approved).  As you can see, we have a powerful way to get the module handles of any particular DLL that we have in our process address space, and then use that to get function pointers to any particular function.

Note you should only use this technique on approved APIs in Windows Store apps.   But for debugging purposes (and just to have some fun), it might be cool to do something like the following:

Generate a blank XAML (C++ Windows Store) app, add a button to the blank form. Double click on the button. Add this code in place of the event handler:


typedef int (WINAPI *pMessageBox)( __in_opt HWND hWnd,
  __in_opt LPCTSTR lpText, __in_opt LPCTSTR lpCaption, __in UINT uType);

typedef HWND (WINAPI *pGetActiveWindow)(void);

typedef HMODULE (WINAPI *pGetModuleHandle)(__in_opt LPCTSTR lpModuleName);

void App1::MainPage::Button_Click_1(Platform::Object^ sender,
  Windows::UI::Xaml::RoutedEventArgs^ e)
{
 static pMessageBox MessageBox_p = 0;
 static pGetActiveWindow GetActiveWindow_p = 0;
 static pGetModuleHandle GetModuleHandle_p = 0;

 HMODULE kmod = GetKernelModule();

 GetModuleHandle_p = (pGetModuleHandle)GetProcAddress(kmod, "GetModuleHandleW");

 HMODULE mod = GetModuleHandle_p(L"user32.dll");

 MessageBox_p = (pMessageBox)GetProcAddress(mod, "MessageBoxW");
 GetActiveWindow_p = (pGetActiveWindow)GetProcAddress(mod, "GetActiveWindow");

 MessageBox_p(GetActiveWindow_p(), L"Hello", L"Hello", MB_OK);
}

Build and deploy your app, run it, and the press the button and see what happens.  Something you don’t ever want to do in a production app :)

Porting Win32 code to 64 bit: watch out for pointers

During the porting of an application to 64 bit, I recently found out about a very interesting registry key value, that, when set, will force the Windows memory manager to give you a high address (greater than 32 bit).  This is useful if you’re dealing with a lot of code that may inadvertently store pointers in 32 bit values.  Normally you’d get a 32 bit pointer in a 64 bit program, unless you specifically ask for it using the MEM_TOP_DOWN flag for VirtualAlloc API, but there is a way to force this behavior upon all apps:

In your registry, under:

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Memory Management

Just create a DWORD value named AllocationPreference and set it to hexadecimal value 100000.   (hex value 0x100000)

Even if you’ve been super careful writing code, for example, using DWORD_PTR instead of DWORD everywhere it matters, you’ll be surprised how quickly you’ll find previously hidden problems lurking in your code.  I recommend that this value be set on all of your QA team’s machines as well.    The site I link to above gives a great explanation as to what the key value actually does.  You can find more information from Microsoft about the value here:

http://msdn.microsoft.com/en-us/library/bb613473.aspx

 

How do my API wrapper functions avoid triggering linker errors?

Now that we have a stable (VS2012+Update 3) solution for XP support, there is no longer a need for these wrappers.

I was going to make a general write-up on how all of my API wrapper classes work, but in searching around, I found out that Antony, who graciously contributed the x64 version of the xpsupport wrappers, already wrote up an excellent article a while back describing how the linker resolves symbols.  Please read:

http://blog.macrium.com/2012/05/upgrading-to-vnext-yet-supporting-windows-xp/

Thanks to Antony for his contributions to this project and his great description.

So using assembly allows us to avoid the dreaded “duplicate symbol” error, if we had tried to do this in C/C++.   Interestingly, GCC has a much more elegant way of doing this:

http://sourceforge.net/p/mingw-w64/code/HEAD/tree/trunk/mingw-w64-libraries/winstorecompat/src/GetTickCount.c

notice the last line (edited to avoid use of a macro):

DWORD (WINAPI *__imp_GetTickCount)(void) asm(“__imp__GetTickCount@0”) = GetTickCount;

The asm keyword can be used to define a symbol that can be overridden by an arbitrary symbol.  This functionality is not available in MSVC.

I’ll be talking more about wrappers in the near future, specifically in the area of forbidden Win32 APIs in Windows Store apps.

How to get Visual C++ 2012 Update 2 statically linked applications to run on Windows XP

EDIT (June 26, 2013) – Microsoft has released the final version of Visual Studio 2012 Update 3 that completely fixes this issue.  For more information on Update 3, please click here.

EDIT (May 11, 2013) – Microsoft has released an RC of Visual Studio 2012 Update 3 that fixes this issue which is “go live”, meaning if you can’t wait for the final Update 3 and need a Microsoft supported solution immediately, you can use it with production releases.  For more info look here and to download look here. For a solution to use with Update 2, see below.

Due to a regression in Visual C++ 2012 Update 2, applications using ATL will no longer be able to run on XP, even if using built-in XP targeting support.  This is due to a new dependency on InitializeCriticalSectionEx.  Running an app on XP that was built with Visual C++ 2012 Update 2 will give you the following error message:

Entry Point Not Found

The procedure entry point InitializeCriticalSectionEx could not be located in the dynamic link library KERNEL32.dll

To fix this, I’ve published a new version of the xpsupport tool, namely XPSupport for VC11 Update 2 Version 1.02, on my skydrive.  It simply wraps the InitializeCriticalSectionEx function with an XP compatible replacement, using techniques I’ve used in previous blog entries.

To use this solution, simply add build customizations (masm) to your project by right clicking on the project in solution explorer and choosing “build customizations” and check masm (targets, props) on, then add the three files (xpatl.cpp, xpatlwrap.asm, and xpatlwrap64.asm) contained in the zip file named: xpsupportvc11upd2v102.zip found here:

https://skydrive.live.com/redir?resid=1B361BF333E9AB82!153&authkey=!AEAOQJ4-LCqWQiw

Build your app, and now your app will run under XP.

EDIT: despite the title of this blog post, I received reports that this works also for dynamically linked apps (i.e. linking to MFC and the CRT dynamically)

More info about the cause found here:

http://social.msdn.microsoft.com/Forums/en-US/visualstudiogeneral/thread/f0477c9f-8a2c-4e6b-9f5a-cd2469e216c4

credits to VSBs and others for reporting and researching this issue.

changelog:

1.00 2013-04-14 Initial Release

1.01 2013-04-15 added x64 support

1.02 2013-04-17 cleaned up Vista check

Visual Studio 2012 Update 1 released: real, official XP targeting support

I’m happy to announce that the Visual C++ 2012 XP targeting solution is finally available as part of Visual Studio 2012 Update 1.  As you know from previous posts, I tried to fill in the gap by providing wrapper functions (XPSupport wrappers) until the official Microsoft solution was ready.    No need to use those any more, you can definitely remove those files from your project if you’ve been using them up to now.

Thanks to those at Microsoft, especially Steve Teixeira and Herb Sutter for believing that this was a worthwhile thing to provide users.  It definitely will increase adoption of Visual C++ 2012, and C++11 in general, because it’s one less thing to have to worry about when making the decision to adopt the new toolset provided by Visual C++ 2012.    Thanks also, to all those people that provided feedback through blog comments, connect bug comments, uservoice comments and various other ways that they expressed their opinion that this was an absolute adoption blocker for them.

One of the things you may notice is that you have to choose a new “Platform Toolset” if you want XP support, i.e. it’s not just a simple recompile, you actually have to change project settings.  The reason this was done was that the Developer division cannot dictate the OS support level of the Platform SDK.  Since the Platform SDK 8.0 dropped support for XP, developer division decided to ship the 7.1 SDK and redirect the include paths to that instead of using the existing 8.0 SDK.   You only get the 7.1 SDK include paths if you choose the appropriate XP targeting platform toolset, that is, vc110_xp.

Just to be clear, this doesn’t mean that by choosing the 7.1 SDK you’re all of a sudden using inferior (older) versions of the C++ compiler and runtime libraries.  On the contrary, you are now using a newer version of the CRT, MFC etc, that have been enhanced to remove any Vista+ specific API calls (i.e API calls not available on XP), along with the exact same C++ compilers and linkers that the normal 8.0 SDK toolset provides.

And another clarification: with Update 1 there is only one set of CRT/MFC DLLs and libs.  There’s no separate redistributable for XP vs other operating systems.  The single vcredist_x86.exe/vcredist_x64.exe files have been updated to work on ALL platforms.  This simplifies things from a distribution perspective.  No worry about having the incorrect redist installed on the incorrect OS.

Note: currently there is nothing stopping you from using the 8.0 SDK with your project (i.e leave your platform toolset setting alone) and still run the resultant binaries on XP.  The difference is, that it’s not officially supported and could break at any time (e.g. if Windows team delivers an update to 8.0 SDK that causes incompatibilities with XP – this hasn’t happened yet but be forewarned).  If you decide to take this approach, be sure to update the subsystem version as described in my earlier blog post.  In summary, in the IDE you can just go to project properites, then linker settings – system, and set minimum required version to 5.01.

In conclusion, happy XP targeting with VC2012 + Update 1!

Visual Studio 2012 Express for Windows Desktop released

Visual Studio 2012 Express for Windows Desktop has been released.  This means that Win32 apps can now be developed using 2012 without buying a Proefessional license.  Previously, only WinRT apps were supported and Express 2012 was only supported on Windows 8.  This version can be installed on Windows 7 as well.  Of course, testing the XPSupport 1.10 wrappers was the first thing I tried.  And I’m happy to report that they work fine.