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

  • This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn more.

Opcode

Level 26
Content Creator
Aug 17, 2017
1,527
9,582
Installed Antivirus
Qihoo 360
#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: