Tutorial Determine 32-bit/64-bit architecture (Kernel-Mode, C)

D

Deleted member 65228

Guest
#1
Hello all.

I've seen some people asking how you can determine whether the architecture of the OS environment is 32-bit or 64-bit from kernel-mode before on the OSR mailing list and other places, and thought it could be a good idea to make a brief tutorial on doing this. I haven't seen anyone querying about how to do this recently, but the theory and practical demonstration being it is extremely straight forward for any kernel-mode developer to understand, so it couldn't hurt to put it out there as a dedicated tutorial.

To get started, we need to clear the air about kernel-mode device drivers and the architecture of the environment in general. A 32-bit compiled device driver cannot be ran on a 64-bit OS environment, and a 64-bit compiled device driver cannot be ran on a 32-bit OS environment. This means that you need to compile both for 32-bit and 64-bit, and use the correct compilation for the OS environment. This is the key to this entire tutorial.

The header file, ntddk.h, does an definition check with #ifdef to determine whether the compilation is for 32-bit or 64-bit from the Target Platform within Visual Studio. _WIN64 will be defined if the compilation is for 64-bit, and it won't be defined if the compilation is for 32-bit.



This notifies us that we can simply use #ifdef _WIN64 and then do our 64-bit supported code, and the 32-bit supported code in the #else. Or, we could use #ifndef and then do our 32-bit supported code... Throughout the device driver. However, if you're like me and prefer to use a BOOLEAN sometimes (e.g. if(g_OsArchitecture32) { ... } else { ... } then this won't be appropriate.

Below is an example source code.

Code:
/*++
    Routine Name:
        -    ReturnOsArch32.
    Routine Description:
        -    This routine is responsible for determining whether the Operating System environment
            architecture is 32-bit or 64-bit.
               
            The routine determines whether the architecture of the environment is 32-bit or
            64-bit by checking if _WIN64 is defined or not. This is the same definition which is
            checked in ntddk.h. The reason this is effective and sufficient for the check is because
            a 32-bit compiled driver can only run on a 32-bit environment, and a 64-bit compiled
            driver can only run on a 64-bit environment. Therefore, if _WIN64 is not defined then the 
            architecture of the environment must be 32-bit, and if it is defined then it must be 64-bit.
    Parameters:
        -    None.
    Return Value:
        -    BOOLEAN.
            -    TRUE represents that the architecture of the environment is 32-bit.
            -    FALSE represents that the architecture of the environment is 64-bit.
--*/
BOOLEAN ReturnOsArch32()
{
#ifdef _WIN64
    return FALSE;
#endif
    return TRUE;
}
Now you can use a global variable and set it to FALSE if the OS architecture is not 32-bit, and TRUE if it is.

Before I end this very brief and short tutorial, I want to note that it is better to use an #ifdef throughout your project instead of the BOOLEAN check. The reason for this is optimisation. If you have a very large project and need to do specific things depending on the OS architecture, by using an #ifdef you will only have the correct code for the target architecture used in compilation. This will cut down source code which is compiled to the end-result binary and thus the file size will be smaller. Therefore, when you compile for 32-bit, the 32-bit code gets compiled in, and the 64-bit code gets compiled in over the 32-bit code when you compile for 64-bit.

Thanks for reading as always. :) :alien: