64-bit development, it's no Fad

Have you been considering porting your existing 32-bit application to a native 64-bit build?

Before diving in, there are a few key things to keep in mind. I’ll walk through some of my own experiences to help you navigate what can seem like a daunting process.

First things first: despite what you might have read elsewhere - Porting existing applications to 64-bit really isn’t that difficult, provided the original project followed even loosely recognized coding practices.

Registry

On a 32-bit system, your application's registry entries typically go into HKEY_LOCAL_MACHINE\Software or HKEY_CURRENT_USER\Software. However, on a 64-bit system, when your 32-bit application runs, it is automatically redirected to HKEY_LOCAL_MACHINE\Software\Wow6432Node or HKEY_CURRENT_USER\Software\Wow6432Node.

This redirection is handled transparently by the Windows API - and for the most part, it’s dead simple. The only time things get tricky is when you have a product that includes both 32-bit and 64-bit components that need to share the same registry keys. In those cases, you'll need to handle cross-access carefully.

Program Files

A similar redirection principle applies to the Program Files directory:

On 64-bit Windows:

  • 64-bit applications use: C:\Program Files\
  • 32-bit applications are redirected to: C:\Program Files (x86)\

This also applies to the Common Files directory, which exists in both locations:

  • 64-bit applications use: C:\Program Files\Common Files\
  • 32-bit applications are redirected to: C:\Program Files (x86)\Common Files\

So be aware that file paths can shift depending on your application's "bitness".

Other Folders

This redirection behavior is also used in various system folders. One of the most infamous examples:

  • C:\Windows\System32 → contains 64-bit binaries
  • C:\Windows\SysWOW64 → contains 32-bit binaries

Yep, it’s confusing at first glance - but that's how Microsoft implemented the WOW64 (Windows-on-Windows 64-bit) subsystem. It’ll make perfect sense eventually... maybe.

Integers

Let’s talk about size_t.

When compiling as 64-bit, any function returning a size (like strlen()) now returns a 64-bit value. Technically, this means you could pass a string with 18 quintillion characters to strlen() - but in practice, please don’t.

You’ll want to pay attention to whether you're:

  • Storing these sizes in int or long (which may be 32-bit)
  • Or safely casting the result from size_t when appropriate

Consciously decide whether to update all your usages of size_t return values to full 64-bit variables - or ensure you're safely truncating the value where it makes sense.

Pointers

In 64-bit builds, pointers are now 64-bits wide. This gives you access to larger memory spaces - but it also exposes issues in any legacy code that assumes pointer size equals int size.

For example, this callback works fine in 32-bit, but not in 64-bit:

// Works fine in 32-bit, breaks in 64-bit due to return value size
int CALLBACK dialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    // ...
}
DialogBox(GetAppInstance(), MAKEINTRESOURCE(IDD_TEMPLATE), NULL, dialogProc);

To fix this, update your callback to return INT_PTR, which is correctly sized for both 32-bit and 64-bit:

// Correct for both 32-bit and 64-bit
INT_PTR CALLBACK dialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    // ...
}
DialogBox(GetAppInstance(), MAKEINTRESOURCE(IDD_TEMPLATE), NULL, dialogProc);

Shell Integration and Explorer Context Menus

You cannot load a 64-bit shell extension into a 32-bit version of Windows - which makes sense. But here's the catch: you also can’t load a 32-bit shell extension into Windows Explorer on a 64-bit system.

Why? Because Explorer.exe itself is a 64-bit process, and it cannot load 32-bit DLLs. This is a hard architectural boundary - so if your app integrates with the shell, make sure your shell extensions are compiled for 64-bit as well.