Use New 64 bit Features On Older 32 bit Windows
One of the challenges for programmers is to continue to support all customers and still take advantage of new features available in operating systems. Instead of managing multiple code bases I’ve learned to support older versions while still taking advantage of new features. Recently, I learned it the hard way.
I thought it would be useful to share an example of code that I currently use that not only supports 64 bit Windows, but uses new functions that aren’t supported by the still popular 32 bit Windows XP.
1. Accessing 32 and 64 bit Registry Locations
In this example, I wanted to use a new function that Microsoft enhanced for 64 bit Windows. To remove registry keys I’ve used the following function.
The registry in 64 bit Windows has a special tree that is used to store registry values used by 32 bit applications. Many values under the global software registry is automatically redirected to be saved under the following key. See List of KeysRegDeleteKey( HKEY, LPCSTR)
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node
Most applications that store options in the registry don’t need to know if their registry calls are redirected. A utility like my WinPatrol absolutely needs to know which registry location is used and when Windows is redirecting values. Using the actual location is crucial for detecting malware or modifying legitimate software which may behave badly.
To allow programmers access to either the normal registry location or Wow6432Node many registry functions have been enhanced to specify the real location instead of being reflected or redirected. One new replacement function is
RegDeleteKeyEx( HKEY, LPCTSTR, REGSAM, DWORD);
The REGSAM value can be either KEY_WOW64_32KEY(0x200) for removing a key in the Wow6432Node tree used by 32 bit applications or KEY_WOW64_64KEY(0x100) which doesn’t get redirected.
2. Using new Windows Functions not supported by XP
In my WinPatrol program I need to use the function “RegDeleteKeyEx” which is located in a Windows library by the name “Advapi32”. Unfortunately, not all 32 bit versions of Windows support this function including Windows XP.
When I build WinPatrol.exe using Microsoft Visual Studio, it finds information needed to use RegDeleteKeyEx and includes the entry point address in my final code. It hard codes or “statically links” this function in my executable. When WinPatrol ran it expected to find the Advapi32dll file on the computer and expected to find the RegDeleteKeyEx function within it.
When WinPatrol or any program is launched Windows checks to make sure all the required DLL’s exist and they include any static links. The version of “Advapi32dll” on a 32 bit version of Windows XP has no knowledge of the RegDeleteKeyEx function. The resulting error message doesn’t make sense to most users but when I received this screen shot in Emails I knew immediately where I had screwed up.
Instead of making two versions of WinPatrol I created a replacement routine that uses a “run-time dynamic link”. By not having a static definition in my code Windows XP won’t detect the references to a function that doesn’t exist.
This is my own function to delete a key in the registry. It works for all the versions of Windows that are supported by WinPatrol. I’ve removed most comments, a branch for unicode systems and some error checking so you can see the required code which is explained under the example.
As with many type based languages, I begin my function by defining local variables. The 3rd one defines a the pointer(lpfRegDeleteKeyEx) to a Windows API that returns a long result. The name of this variable can be anything. I include parameters that RegDeleteKeyEx use for readability. This variable will contain the entry point address to the function so I can still call it but versions of Windows that don’t know about it won’t barf.
All the details on using this new function are available in documentation free from Microsoft Developer Network. This information will allow you to do similar operations with other languages.
The glx64 is just a global variable I set early on when I check to see if we’re running on a 64 bit system. If it’s not a 64 bit system I don’t need special code. I can just call the same old RegDeleteKey function which will have no trouble finding the Key because there isn’t an alternate Wow6432Node tree in the registry.
- If it is a 64 bit system I use run-time dynamic linking to call the new function.
* First I use LoadLibrary to access Advapi32.dll which has many Registry API’s including RegDeleteKeyEx. The call returns a “handle” to the library which I will need in future calls.
* If the library loads ok, then I call “GetProcAddress” to get a pointer to the entry point of the RegDeleteKeyEx function.
* If the entry point is found I can just use the pointer variable to call the function passing the same parameters required if we used static linking.
* Lastly I tell Windows I’m done with FreeLibrary. For this example I removed some checks if my call failed for some reason.
As one of the main components in Windows Advapi32.dll is most likely already in memory so it’s not like the disk is accessed each time this function is called. Calls to LoadLibrary will increment a counter for the library and FreeLibrary decrements the count. If it reaches zero then Windows knows it can be unloaded from memory.
When Microsoft documents an API function it will also include the name of which DLL is used and what versions of Windows are supported. If an older version of Windows isn’t supported you’ll want to use Run-time Dynamic Linking similar to this example.