/* ______ ___ ___ * /\ _ \ /\_ \ /\_ \ * \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___ * \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\ * \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \ * \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/ * \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/ * /\____/ * \_/__/ * * Get version of installed DirectX. * * By Stefan Schimanski. * * Modified get_dx_ver() from DirectX 7 SDK. * * See readme.txt for copyright information. */ /* Set DIRECTX_SDK_VERSION according to the installed SDK version. * Note that this file requires at least the SDK version 5 to compile, * so that DIRECTX_SDK_VERSION must be >= 0x500. */ #define DIRECTX_SDK_VERSION 0x500 #include "allegro.h" #include "allegro/internal/aintern.h" #include "allegro/platform/aintwin.h" /* needed by the SDK version 8 with MSVC 5 (SP3) */ #define DIRECTINPUT_VERSION 0x300 #ifndef SCAN_DEPEND #include #include #endif #ifndef ALLEGRO_WINDOWS #error something is wrong with the makefile #endif typedef HRESULT(WINAPI *DIRECTDRAWCREATE) (GUID *, LPDIRECTDRAW *, IUnknown *); typedef HRESULT(WINAPI *DIRECTINPUTCREATE) (HINSTANCE, DWORD, LPDIRECTINPUT *, IUnknown *); typedef HRESULT(WINAPI *DSETUPCREATE)(DWORD*,DWORD*); /* get_dx_ver: * returns the DirectX dx_version number: * * 0 no DirectX installed * 0x100 DirectX 1 installed * 0x200 DirectX 2 installed * 0x300 DirectX 3 installed * 0x500 at least DirectX 5 installed * 0x600 at least DirectX 6 installed * 0x700 at least DirectX 7 installed */ int get_dx_ver(void) { HRESULT hr; HINSTANCE ddraw_hinst = NULL; HINSTANCE dinput_hinst = NULL; HINSTANCE dsetup_hinst = NULL; LPDIRECTDRAW directdraw = NULL; LPDIRECTDRAW2 directdraw2 = NULL; DIRECTDRAWCREATE DirectDrawCreate = NULL; DIRECTINPUTCREATE DirectInputCreate = NULL; DSETUPCREATE DSetupCreate = NULL; OSVERSIONINFO os_version; LPDIRECTDRAWSURFACE ddraw_surf = NULL; LPDIRECTDRAWSURFACE3 ddraw_surf3 = NULL; DWORD dsetup_revision; DWORD dsetup_version; INT dsetup_result; #if DIRECTX_SDK_VERSION >= 0x600 LPDIRECTDRAWSURFACE4 ddraw_surf4 = NULL; #if DIRECTX_SDK_VERSION >= 0x700 LPDIRECTDRAWSURFACE7 ddraw_surf7 = NULL; #endif #endif DDSURFACEDESC ddraw_surf_desc; LPVOID temp; int dx_version = 0; /* first get the Windows platform */ os_version.dwOSVersionInfoSize = sizeof(os_version); if (!GetVersionEx(&os_version)) return dx_version; if (os_version.dwPlatformId == VER_PLATFORM_WIN32_NT) { /* NT is easy... NT 4.0 is DX2, 4.0 SP3 is DX3, 5.0 is DX5 at least * and no DX on earlier versions */ if (os_version.dwMajorVersion < 4) { /* No DX on NT 3.51 or earlier */ return dx_version; } /* First check for DX 8 and 9 */ dsetup_hinst = LoadLibrary( "DSETUP.DLL" ); if ( dsetup_hinst ) { DSetupCreate = (DSETUPCREATE)GetProcAddress(dsetup_hinst, "DirectXSetupGetVersion"); if ( DSetupCreate ) { dsetup_result = DSetupCreate( &dsetup_version, &dsetup_revision ); // returns 0 on failure if ( dsetup_result ) { switch (dsetup_version) { case 0x00040005: dx_version = 0x500; break; case 0x00040006: dx_version = 0x600; break; case 0x00040007: dx_version = 0x700; break; case 0x00040008: /* v8.x */ dx_version = 0x800; switch (dsetup_revision) { case 0x0001032A: case 0x00010371: dx_version = 0x810; /* 8.1 */ dx_version = 0x810; /* 8.1 */ break; case 0x00010385: dx_version = 0x81a; /* 8.1a or b (stupid MS...) */ break; case 0x00020386: dx_version = 0x820; /* 8.2 */ break; default: dx_version = 0x800; /* 8.0 */ } /* switch (dsetup_revision) */ case 0x00040009: switch (dsetup_revision) { case 0x00000384: dx_version = 0x900; /* 9.0 */ break; case 0x00000385: dx_version = 0x90a; /* 9.0a */ break; case 0x00000386: dx_version = 0x90b; /* 9.0b */ break; case 0x00000387: dx_version = 0x90b; /* 9.0(b or c) */ break; case 0x00000388: dx_version = 0x90c; /* 9.0c */ break; default: dx_version = 0x900; } /* switch (dsetup_revision) */ } /* switch (dsetup_version) */ } } FreeLibrary( dsetup_hinst ); if ( dx_version ) return dx_version; } if (os_version.dwMajorVersion == 4) { /* NT4 up to SP2 is DX2, and SP3 onwards is DX3, so we are at least DX2 */ dx_version = 0x200; /* we are not supposed to be able to tell which SP we are on, so check for DInput */ dinput_hinst = LoadLibrary("DINPUT.DLL"); if (!dinput_hinst) { /* no DInput... must be DX2 on NT 4 pre-SP3 */ OutputDebugString("Couldn't LoadLibrary DInput\r\n"); return dx_version; } DirectInputCreate = (DIRECTINPUTCREATE) GetProcAddress(dinput_hinst, "DirectInputCreateA"); FreeLibrary(dinput_hinst); if (!DirectInputCreate) { /* no DInput... must DX2 on NT 4 pre-SP3 */ return dx_version; } /* DX3 on NT4 SP3 or higher */ dx_version = 0x300; return dx_version; } /* it's at least NT 5 and it's DX5a or higher: * drop through to Win9x tests for a test of DDraw */ } /* now we know we are in Windows 9x (or maybe 3.1), so anything's possible; * first see if DDRAW.DLL even exists. */ ddraw_hinst = LoadLibrary("DDRAW.DLL"); if (!ddraw_hinst) { dx_version = 0; goto End; } /* see if we can create the DirectDraw object */ DirectDrawCreate = (DIRECTDRAWCREATE) GetProcAddress(ddraw_hinst, "DirectDrawCreate"); if (!DirectDrawCreate) { dx_version = 0; goto End; } hr = DirectDrawCreate(NULL, &directdraw, NULL); if (FAILED(hr)) { dx_version = 0; goto End; } /* so DirectDraw exists, we are at least DX1 */ dx_version = 0x100; /* let's see if IDirectDraw2 exists */ hr = IDirectDraw_QueryInterface(directdraw, &IID_IDirectDraw2, &temp); if (FAILED(hr)) { /* no IDirectDraw2 exists... must be DX1 */ goto End; } directdraw2 = temp; /* IDirectDraw2 exists... must be at least DX2 */ IDirectDraw2_Release(directdraw2); dx_version = 0x200; /* see if we can create the DirectInput object */ dinput_hinst = LoadLibrary("DINPUT.DLL"); if (!dinput_hinst) { /* no DInput... must be DX2 */ goto End; } DirectInputCreate = (DIRECTINPUTCREATE) GetProcAddress(dinput_hinst, "DirectInputCreateA"); FreeLibrary(dinput_hinst); if (!DirectInputCreate) { /* no DInput... must be DX2 */ goto End; } /* DirectInputCreate exists; that's enough to tell us that we are at least DX3 */ dx_version = 0x300; /* we can tell if DX5 is present by checking for the existence of IDirectDrawSurface3; * first we need a surface to QI off of */ memset(&ddraw_surf_desc, 0, sizeof(ddraw_surf_desc)); ddraw_surf_desc.dwSize = sizeof(ddraw_surf_desc); ddraw_surf_desc.dwFlags = DDSD_CAPS; ddraw_surf_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; hr = IDirectDraw_SetCooperativeLevel(directdraw, NULL, DDSCL_NORMAL); if (FAILED(hr)) { /* failure: this means DDraw isn't properly installed */ dx_version = 0; goto End; } hr = IDirectDraw_CreateSurface(directdraw, &ddraw_surf_desc, &ddraw_surf, NULL); if (FAILED(hr)) { /* failure: this means DDraw isn't properly installed */ dx_version = 0; goto End; } /* try for the IDirectDrawSurface3 interface; if it works, we're on DX5 at least */ hr = IDirectDrawSurface_QueryInterface(ddraw_surf, &IID_IDirectDrawSurface3, &temp); if (FAILED(hr)) goto End; ddraw_surf3 = temp; /* QI for IDirectDrawSurface3 succeeded; we must be at least DX5 */ dx_version = 0x500; #if DIRECTX_SDK_VERSION >= 0x600 /* try for the IDirectDrawSurface4 interface; if it works, we're on DX6 at least */ hr = IDirectDrawSurface_QueryInterface(ddraw_surf, &IID_IDirectDrawSurface4, (LPVOID *) &ddraw_surf4); if (FAILED(hr)) goto End; /* QI for IDirectDrawSurface4 succeeded; we must be at least DX6 */ dx_version = 0x600; #if DIRECTX_SDK_VERSION >= 0x700 /* try for the IDirectDrawSurface7 interface; if it works, we're on DX7 at least */ hr = IDirectDrawSurface_QueryInterface(ddraw_surf, &IID_IDirectDrawSurface7, (LPVOID *) &ddraw_surf7); if (FAILED(hr)) goto End; /* QI for IDirectDrawSurface7 succeeded; we must be at least DX7 */ dx_version = 0x700; #endif #endif End: if (directdraw) IDirectDraw_Release(directdraw); if (ddraw_hinst) FreeLibrary(ddraw_hinst); return dx_version; }