GETDXVER.CPP
/************************************************************************** 
 
    GetDXVer.cpp 
 
    Demonstrates how applications can detect what version of DirectX 
    is installed. 
 
 **************************************************************************/ 
/************************************************************************** 
 
    (C) Copyright 1995-1997 Microsoft Corp.  All rights reserved. 
 
    You have a royalty-free right to use, modify, reproduce and 
    distribute the Sample Files (and/or any modified version) in 
    any way you find useful, provided that you agree that 
    Microsoft has no warranty obligations or liability for any 
    Sample Application Files which are modified. 
 
 **************************************************************************/ 
 
#include <windows.h> 
#include <windowsx.h> 
#include <ddraw.h> 
#include <dinput.h> 
 
/**************************************************************************** 
 * 
 *      GetDXVersion 
 * 
 *  This function returns two arguments: 
 *dwDXVersion: 
 *    0    No DirectX installed 
 *    0x100   DirectX version 1 installed 
 *    0x200   DirectX 2 installed 
 *    0x300   DirectX 3 installed 
 *    0x500   At least DirectX 5 installed. 
 *    0x501   At least DirectX 5a installed. 
 *dwDXPlatform: 
 *    0                            Unknown (This is a failure case. Should never happen) 
 *    VER_PLATFORM_WIN32_WINDOWS    Windows 9X platform 
 *    VER_PLATFORM_WIN32_NT    Windows NT platform 
 * 
 ****************************************************************************/ 
 
typedef HRESULT (WINAPI *DIRECTDRAWCREATE)(GUID *, LPDIRECTDRAW *, IUnknown *); 
typedef HRESULT (WINAPI *DIRECTINPUTCREATE)(HINSTANCE, DWORD, LPDIRECTINPUT *, IUnknown *); 
 
void GetDXVersion (LPDWORD pdwDXVersion, LPDWORD pdwDXPlatform) 
{ 
    HRESULT    hr; 
    HINSTANCE    DDHinst = 0; 
    HINSTANCE    DIHinst = 0; 
    LPDIRECTDRAW    pDDraw = 0; 
    LPDIRECTDRAW2    pDDraw2 = 0; 
    DIRECTDRAWCREATE    DirectDrawCreate = 0; 
    DIRECTINPUTCREATE    DirectInputCreate = 0; 
    OSVERSIONINFO    osVer; 
    LPDIRECTDRAWSURFACE    pSurf = 0; 
    LPDIRECTDRAWSURFACE3    pSurf3 = 0; 
 
    /* 
     * First get the windows platform 
     */ 
    osVer.dwOSVersionInfoSize = sizeof(osVer); 
    if (!GetVersionEx(&osVer)) 
    { 
*pdwDXVersion = 0; 
*pdwDXPlatform = 0; 
return; 
    } 
 
    if (osVer.dwPlatformId == VER_PLATFORM_WIN32_NT) 
    { 
*pdwDXPlatform = VER_PLATFORM_WIN32_NT; 
/* 
 * NT is easy... NT 4.0 is DX2, 4.0 SP3 is DX3, 5.0 is DX5 
 * and no DX on earlier versions. 
 */ 
if (osVer.dwMajorVersion < 4) 
{ 
    *pdwDXPlatform = 0;//No DX on NT3.51 or earlier 
    return; 
} 
if (osVer.dwMajorVersion == 4) 
{ 
    /* 
     * NT4 up to SP2 is DX2, and SP3 onwards is DX3, so we are at least DX2 
     */ 
    *pdwDXVersion = 0x200; 
 
            /* 
             * We're not supposed to be able to tell which SP we're on, so check for dinput 
             */ 
            DIHinst = LoadLibrary("DINPUT.DLL"); 
            if (DIHinst == 0)  
            { 
                /* 
                 * No DInput... must be DX2 on NT 4 pre-SP3 
                 */ 
                OutputDebugString("Couldn't LoadLibrary DInput\r\n"); 
        return; 
            } 
 
            DirectInputCreate = (DIRECTINPUTCREATE) 
                                    GetProcAddress(DIHinst, "DirectInputCreateA"); 
            FreeLibrary(DIHinst); 
 
            if (DirectInputCreate == 0)  
            { 
                /* 
                 * No DInput... must be pre-SP3 DX2 
                 */ 
                OutputDebugString("Couldn't GetProcAddress DInputCreate\r\n"); 
        return; 
            } 
 
    /* 
     * It must be NT4, DX2 
     */ 
    *pdwDXVersion = 0x300; //DX3 on NT4 SP3 or higher 
    return; 
} 
/* 
 * Else it's NT5 or higher, and it's DX5a or higher: 
 */ 
*pdwDXVersion = 0x501; //DX5a on NT5 
return; 
    } 
 
    /* 
     * Not NT... must be Win9x 
     */ 
    *pdwDXPlatform = VER_PLATFORM_WIN32_WINDOWS; 
 
    /* 
     * If we are on Memphis or higher, then we are at least DX5a 
     */ 
    if ( (osVer.dwBuildNumber & 0xffff) > 1353) //Check for higher than developer release 
    { 
*pdwDXVersion = 0x501; //DX5a on Memphis or higher 
return; 
    } 
 
    /* 
     * Now we know we are in Windows 9x (or maybe 3.1), so anything's possible. 
     * First see if DDRAW.DLL even exists. 
     */ 
    DDHinst = LoadLibrary("DDRAW.DLL"); 
    if (DDHinst == 0)  
    { 
*pdwDXVersion = 0; 
*pdwDXPlatform = 0; 
FreeLibrary(DDHinst); 
return; 
    } 
 
    /* 
     *  See if we can create the DirectDraw object. 
     */ 
    DirectDrawCreate = (DIRECTDRAWCREATE) 
                            GetProcAddress(DDHinst, "DirectDrawCreate"); 
    if (DirectDrawCreate == 0)  
    { 
*pdwDXVersion = 0; 
*pdwDXPlatform = 0; 
FreeLibrary(DDHinst); 
        OutputDebugString("Couldn't LoadLibrary DDraw\r\n"); 
return; 
    } 
 
    hr = DirectDrawCreate(NULL, &pDDraw, NULL); 
    if (FAILED(hr))  
    { 
*pdwDXVersion = 0; 
*pdwDXPlatform = 0; 
FreeLibrary(DDHinst); 
        OutputDebugString("Couldn't create DDraw\r\n"); 
return; 
    } 
 
    /* 
     *  So DirectDraw exists.  We are at least DX1. 
     */ 
    *pdwDXVersion = 0x100; 
 
    /* 
     *  Let's see if IID_IDirectDraw2 exists. 
     */ 
    hr = pDDraw->QueryInterface(IID_IDirectDraw2, (LPVOID *)&pDDraw2); 
    if (FAILED(hr))  
    { 
/* 
 * No IDirectDraw2 exists... must be DX1 
 */ 
pDDraw->Release(); 
FreeLibrary(DDHinst); 
        OutputDebugString("Couldn't QI DDraw2\r\n"); 
return; 
    } 
    /* 
     * IDirectDraw2 exists. We must be at least DX2 
     */ 
    pDDraw2->Release(); 
    *pdwDXVersion = 0x200; 
 
    /* 
     *  See if we can create the DirectInput object. 
     */ 
    DIHinst = LoadLibrary("DINPUT.DLL"); 
    if (DIHinst == 0)  
    { 
        /* 
         * No DInput... must be DX2 
         */ 
        OutputDebugString("Couldn't LoadLibrary DInput\r\n"); 
pDDraw->Release(); 
FreeLibrary(DDHinst); 
return; 
    } 
 
    DirectInputCreate = (DIRECTINPUTCREATE) 
                            GetProcAddress(DIHinst, "DirectInputCreateA"); 
    FreeLibrary(DIHinst); 
 
    if (DirectInputCreate == 0)  
    { 
        /* 
         * No DInput... must be DX2 
         */ 
FreeLibrary(DDHinst); 
pDDraw->Release(); 
        OutputDebugString("Couldn't GetProcAddress DInputCreate\r\n"); 
return; 
    } 
 
    /* 
     * DirectInputCreate exists. That's enough to tell us that we are at least DX3 
     */ 
    *pdwDXVersion = 0x300; 
 
    /* 
     * Checks for 3a vs 3b? 
     */ 
 
    /* 
     * We can tell if DX5 is present by checking for the existence of IDirectDrawSurface3. 
     * First we need a surface to QI off of. 
     */ 
    DDSURFACEDESC desc; 
 
    ZeroMemory(&desc, sizeof(desc)); 
    desc.dwSize = sizeof(desc); 
    desc.dwFlags = DDSD_CAPS; 
    desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; 
 
    hr = pDDraw->SetCooperativeLevel(NULL,DDSCL_NORMAL); 
    if (FAILED(hr))  
    { 
/* 
 * Failure. This means DDraw isn't properly installed. 
 */ 
pDDraw->Release(); 
FreeLibrary(DDHinst); 
*pdwDXVersion = 0; 
        OutputDebugString("Couldn't Set coop level\r\n"); 
return; 
    } 
 
    hr = pDDraw->CreateSurface(&desc, &pSurf, NULL); 
    if (FAILED(hr))  
    { 
/* 
 * Failure. This means DDraw isn't properly installed. 
 */ 
pDDraw->Release(); 
FreeLibrary(DDHinst); 
*pdwDXVersion = 0; 
        OutputDebugString("Couldn't CreateSurface\r\n"); 
return; 
    } 
 
    /* 
     * Try for the IDirectDrawSurface3 interface. If it works, we're on DX5 at least 
     */ 
    if ( FAILED(pSurf->QueryInterface(IID_IDirectDrawSurface3,(LPVOID*)&pSurf3)) ) 
    { 
        pDDraw->Release(); 
        FreeLibrary(DDHinst); 
 
        return; 
    } 
 
    /* 
     * QI for IDirectDrawSurface3 succeeded. We must be at least DX5 
     */ 
    *pdwDXVersion = 0x500; 
 
    pSurf->Release(); 
    pDDraw->Release(); 
    FreeLibrary(DDHinst); 
 
    return; 
}