home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / graphics / directx / misc / getdxver.cpp < prev    next >
C/C++ Source or Header  |  1997-07-14  |  9KB  |  314 lines

  1. /**************************************************************************
  2.  
  3.     GetDXVer.cpp
  4.  
  5.     Demonstrates how applications can detect what version of DirectX
  6.     is installed.
  7.  
  8.  **************************************************************************/
  9. /**************************************************************************
  10.  
  11.     (C) Copyright 1995-1997 Microsoft Corp.  All rights reserved.
  12.  
  13.     You have a royalty-free right to use, modify, reproduce and
  14.     distribute the Sample Files (and/or any modified version) in
  15.     any way you find useful, provided that you agree that
  16.     Microsoft has no warranty obligations or liability for any
  17.     Sample Application Files which are modified.
  18.  
  19.  **************************************************************************/
  20.  
  21. #define INITGUID
  22. #include <windows.h>
  23. #include <windowsx.h>
  24. #include <ddraw.h>
  25. #include <dinput.h>
  26.  
  27. /****************************************************************************
  28.  *
  29.  *      GetDXVersion
  30.  *
  31.  *  This function returns two arguments:
  32.  *    dwDXVersion:
  33.  *        0        No DirectX installed
  34.  *        0x100   DirectX version 1 installed
  35.  *        0x200   DirectX 2 installed
  36.  *        0x300   DirectX 3 installed
  37.  *        0x500   At least DirectX 5 installed.
  38.  *        0x501   At least DirectX 5a installed.
  39.  *    dwDXPlatform:
  40.  *        0                                Unknown (This is a failure case. Should never happen)
  41.  *        VER_PLATFORM_WIN32_WINDOWS        Windows 9X platform
  42.  *        VER_PLATFORM_WIN32_NT        Windows NT platform
  43.  * 
  44.  * Please note that this code is intended as a general guideline. Your app will
  45.  * probably be able to simply query for functionality (via COM's QueryInterface)
  46.  * for one or two components.
  47.  * Please also note:
  48.  *      "if (dxVer != 0x500) return FALSE;" is BAD. 
  49.  *      "if (dxVer < 0x500) return FALSE;" is MUCH BETTER.
  50.  * to ensure your app will run on future releases of DirectX.
  51.  *
  52.  ****************************************************************************/
  53.  
  54. typedef HRESULT (WINAPI *DIRECTDRAWCREATE)(GUID *, LPDIRECTDRAW *, IUnknown *);
  55. typedef HRESULT (WINAPI *DIRECTINPUTCREATE)(HINSTANCE, DWORD, LPDIRECTINPUT *, IUnknown *);
  56.  
  57. void GetDXVersion(LPDWORD pdwDXVersion, LPDWORD pdwDXPlatform)
  58. {
  59.     HRESULT            hr;
  60.     HINSTANCE            DDHinst = 0;
  61.     HINSTANCE            DIHinst = 0;
  62.     LPDIRECTDRAW        pDDraw = 0;
  63.     LPDIRECTDRAW2        pDDraw2 = 0;
  64.     DIRECTDRAWCREATE        DirectDrawCreate = 0;
  65.     DIRECTINPUTCREATE        DirectInputCreate = 0;
  66.     OSVERSIONINFO        osVer;
  67.     LPDIRECTDRAWSURFACE        pSurf = 0;
  68.     LPDIRECTDRAWSURFACE3    pSurf3 = 0;
  69.  
  70.     /*
  71.      * First get the windows platform
  72.      */
  73.     osVer.dwOSVersionInfoSize = sizeof(osVer);
  74.     if (!GetVersionEx(&osVer))
  75.     {
  76.     *pdwDXVersion = 0;
  77.     *pdwDXPlatform = 0;
  78.     return;
  79.     }
  80.  
  81.     if (osVer.dwPlatformId == VER_PLATFORM_WIN32_NT)
  82.     {
  83.     *pdwDXPlatform = VER_PLATFORM_WIN32_NT;
  84.     /*
  85.      * NT is easy... NT 4.0 is DX2, 4.0 SP3 is DX3, 5.0 is DX5
  86.      * and no DX on earlier versions.
  87.      */
  88.     if (osVer.dwMajorVersion < 4)
  89.     {
  90.         *pdwDXPlatform = 0;    //No DX on NT3.51 or earlier
  91.         return;
  92.     }
  93.     if (osVer.dwMajorVersion == 4)
  94.     {
  95.         /*
  96.          * NT4 up to SP2 is DX2, and SP3 onwards is DX3, so we are at least DX2
  97.          */
  98.         *pdwDXVersion = 0x200;
  99.  
  100.             /*
  101.              * We're not supposed to be able to tell which SP we're on, so check for dinput
  102.              */
  103.             DIHinst = LoadLibrary("DINPUT.DLL");
  104.             if (DIHinst == 0) 
  105.             {
  106.                 /*
  107.                  * No DInput... must be DX2 on NT 4 pre-SP3
  108.                  */
  109.                 OutputDebugString("Couldn't LoadLibrary DInput\r\n");
  110.             return;
  111.             }
  112.  
  113.             DirectInputCreate = (DIRECTINPUTCREATE)
  114.                                     GetProcAddress(DIHinst, "DirectInputCreateA");
  115.             FreeLibrary(DIHinst);
  116.  
  117.             if (DirectInputCreate == 0) 
  118.             {
  119.                 /*
  120.                  * No DInput... must be pre-SP3 DX2
  121.                  */
  122.                 OutputDebugString("Couldn't GetProcAddress DInputCreate\r\n");
  123.             return;
  124.             }
  125.  
  126.         /*
  127.          * It must be NT4, DX2
  128.          */
  129.         *pdwDXVersion = 0x300; //DX3 on NT4 SP3 or higher
  130.         return;
  131.     }
  132.     /*
  133.      * Else it's NT5 or higher, and it's DX5a or higher:
  134.      */
  135.     *pdwDXVersion = 0x501; //DX5a on NT5
  136.     return;
  137.     }
  138.  
  139.     /*
  140.      * Not NT... must be Win9x
  141.      */
  142.     *pdwDXPlatform = VER_PLATFORM_WIN32_WINDOWS;
  143.  
  144.     /*
  145.      * If we are on Memphis or higher, then we are at least DX5a
  146.      */
  147.     if ( (osVer.dwBuildNumber & 0xffff) > 1353) //Check for higher than developer release
  148.     {
  149.     *pdwDXVersion = 0x501; //DX5a on Memphis or higher
  150.     return;
  151.     }
  152.  
  153.     /*
  154.      * Now we know we are in Windows 9x (or maybe 3.1), so anything's possible.
  155.      * First see if DDRAW.DLL even exists.
  156.      */
  157.     DDHinst = LoadLibrary("DDRAW.DLL");
  158.     if (DDHinst == 0) 
  159.     {
  160.     *pdwDXVersion = 0;
  161.     *pdwDXPlatform = 0;
  162.     FreeLibrary(DDHinst);
  163.     return;
  164.     }
  165.  
  166.     /*
  167.      *  See if we can create the DirectDraw object.
  168.      */
  169.     DirectDrawCreate = (DIRECTDRAWCREATE)
  170.                             GetProcAddress(DDHinst, "DirectDrawCreate");
  171.     if (DirectDrawCreate == 0) 
  172.     {
  173.     *pdwDXVersion = 0;
  174.     *pdwDXPlatform = 0;
  175.     FreeLibrary(DDHinst);
  176.         OutputDebugString("Couldn't LoadLibrary DDraw\r\n");
  177.     return;
  178.     }
  179.  
  180.     hr = DirectDrawCreate(NULL, &pDDraw, NULL);
  181.     if (FAILED(hr)) 
  182.     {
  183.     *pdwDXVersion = 0;
  184.     *pdwDXPlatform = 0;
  185.     FreeLibrary(DDHinst);
  186.         OutputDebugString("Couldn't create DDraw\r\n");
  187.     return;
  188.     }
  189.  
  190.     /*
  191.      *  So DirectDraw exists.  We are at least DX1.
  192.      */
  193.     *pdwDXVersion = 0x100;
  194.  
  195.     /*
  196.      *  Let's see if IID_IDirectDraw2 exists.
  197.      */
  198.     hr = pDDraw->QueryInterface(IID_IDirectDraw2, (LPVOID *)&pDDraw2);
  199.     if (FAILED(hr)) 
  200.     {
  201.     /*
  202.      * No IDirectDraw2 exists... must be DX1
  203.      */
  204.     pDDraw->Release();
  205.     FreeLibrary(DDHinst);
  206.         OutputDebugString("Couldn't QI DDraw2\r\n");
  207.     return;
  208.     }
  209.     /*
  210.      * IDirectDraw2 exists. We must be at least DX2
  211.      */
  212.     pDDraw2->Release();
  213.     *pdwDXVersion = 0x200;
  214.  
  215.     /*
  216.      *  See if we can create the DirectInput object.
  217.      */
  218.     DIHinst = LoadLibrary("DINPUT.DLL");
  219.     if (DIHinst == 0) 
  220.     {
  221.         /*
  222.          * No DInput... must be DX2
  223.          */
  224.         OutputDebugString("Couldn't LoadLibrary DInput\r\n");
  225.     pDDraw->Release();
  226.     FreeLibrary(DDHinst);
  227.     return;
  228.     }
  229.  
  230.     DirectInputCreate = (DIRECTINPUTCREATE)
  231.                             GetProcAddress(DIHinst, "DirectInputCreateA");
  232.     FreeLibrary(DIHinst);
  233.  
  234.     if (DirectInputCreate == 0) 
  235.     {
  236.         /*
  237.          * No DInput... must be DX2
  238.          */
  239.     FreeLibrary(DDHinst);
  240.     pDDraw->Release();
  241.         OutputDebugString("Couldn't GetProcAddress DInputCreate\r\n");
  242.     return;
  243.     }
  244.  
  245.     /*
  246.      * DirectInputCreate exists. That's enough to tell us that we are at least DX3
  247.      */
  248.     *pdwDXVersion = 0x300;
  249.  
  250.     /*
  251.      * Checks for 3a vs 3b?
  252.      */
  253.  
  254.     /*
  255.      * We can tell if DX5 is present by checking for the existence of IDirectDrawSurface3.
  256.      * First we need a surface to QI off of.
  257.      */
  258.     DDSURFACEDESC desc;
  259.  
  260.     ZeroMemory(&desc, sizeof(desc));
  261.     desc.dwSize = sizeof(desc);
  262.     desc.dwFlags = DDSD_CAPS;
  263.     desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
  264.  
  265.     hr = pDDraw->SetCooperativeLevel(NULL,DDSCL_NORMAL);
  266.     if (FAILED(hr)) 
  267.     {
  268.     /*
  269.      * Failure. This means DDraw isn't properly installed.
  270.      */
  271.     pDDraw->Release();
  272.     FreeLibrary(DDHinst);
  273.     *pdwDXVersion = 0;
  274.         OutputDebugString("Couldn't Set coop level\r\n");
  275.     return;
  276.     }
  277.  
  278.     hr = pDDraw->CreateSurface(&desc, &pSurf, NULL);
  279.     if (FAILED(hr)) 
  280.     {
  281.     /*
  282.      * Failure. This means DDraw isn't properly installed.
  283.      */
  284.     pDDraw->Release();
  285.     FreeLibrary(DDHinst);
  286.     *pdwDXVersion = 0;
  287.         OutputDebugString("Couldn't CreateSurface\r\n");
  288.     return;
  289.     }
  290.  
  291.     /*
  292.      * Try for the IDirectDrawSurface3 interface. If it works, we're on DX5 at least
  293.      */
  294.     if ( FAILED(pSurf->QueryInterface(IID_IDirectDrawSurface3,(LPVOID*)&pSurf3)) )
  295.     {
  296.         pDDraw->Release();
  297.         FreeLibrary(DDHinst);
  298.  
  299.         return;
  300.     }
  301.  
  302.     /*
  303.      * QI for IDirectDrawSurface3 succeeded. We must be at least DX5
  304.      */
  305.     *pdwDXVersion = 0x500;
  306.  
  307.     pSurf->Release();
  308.     pDDraw->Release();
  309.     FreeLibrary(DDHinst);
  310.  
  311.     return;
  312. }
  313.  
  314.