Search code examples
windowsbackwards-compatibility

How to conditionally execute function if operating system supports it?


I'd like to build an application that invokes CancelIoEx on Windows Vista and newer (where it is supported) and does something else on Windows XP (where it is not).

  1. What happens if I compile the application under Windows 7 but run it under Windows XP? What will happen at runtime? Will I get some sort of load error?

  2. How do I get my application to pick one code path or another (avoiding load errors) depending on what operating system is being used at runtime? Please provide sample code.

UPDATE: Please note that the DLL exists on Windows XP but the function does not.


Solution

  • Yes, an application that references a non-existent DLL export will fail to load.

    Adding code to take different paths based on the OS version won't help much, because you'll still have the reference to the non-existent function.

    Instead, you need to resolve the reference at run-time.

    One option is Delay Load Import (with the /DELAYLOAD linker flag), but I don't think this is supported for the core system DLLs (like kernel32).

    The other is to use LoadLibrary and GetProcAddress. The code is something like this, though in reality you'd do the lookup once when your app starts, not each time you call the function.

    // Declare type of pointer to CancelIoEx function
    typedef BOOL (WINAPI *CancelIoExType)(HANDLE hFile, LPOVERLAPPED lpOverlapped);
    
    // Load module; won't fail because it's already imported
    HMODULE hKernel32 = LoadLibrary(L"kernel32.dll");
    // Look up function address
    CancelIoExType pCancelIoEx = (CancelIoExType)GetProcAddress(hKernel32, "CancelIoEx");
    // Do something with it
    if (pCancelIoEx)
    {
        // Function exists so call it
        pCancelIoEx(hMyFile, pMyOverlapped);
    }
    else
    {
        // Function doesn't exist
    }