checkdx.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. //-----------------------------------------------------------------------------
  2. // File: GetDXVer.cpp
  3. //
  4. // Desc: Demonstrates how applications can detect what version of DirectX
  5. // is installed.
  6. //
  7. // (C) Copyright 1995-1997 Microsoft Corp. All rights reserved.
  8. //-----------------------------------------------------------------------------
  9. #include <windows.h>
  10. #include <windowsx.h>
  11. #include <ddraw.h>
  12. #include <dinput.h>
  13. #include <dmusici.h>
  14. typedef HRESULT(WINAPI * DIRECTDRAWCREATE)( GUID*, LPDIRECTDRAW*, IUnknown* );
  15. typedef HRESULT(WINAPI * DIRECTDRAWCREATEEX)( GUID*, VOID**, REFIID, IUnknown* );
  16. typedef HRESULT(WINAPI * DIRECTINPUTCREATE)( HINSTANCE, DWORD, LPDIRECTINPUT*,
  17. IUnknown* );
  18. //-----------------------------------------------------------------------------
  19. // Name: GetDXVersion()
  20. // Desc: This function returns two arguments:
  21. // dwDXVersion:
  22. // 0x0000 = No DirectX installed
  23. // 0x0100 = DirectX version 1 installed
  24. // 0x0200 = DirectX 2 installed
  25. // 0x0300 = DirectX 3 installed
  26. // 0x0500 = At least DirectX 5 installed.
  27. // 0x0600 = At least DirectX 6 installed.
  28. // 0x0601 = At least DirectX 6.1 installed.
  29. // 0x0700 = At least DirectX 7 installed.
  30. // dwDXPlatform:
  31. // 0 = Unknown (This is a failure case)
  32. // VER_PLATFORM_WIN32_WINDOWS = Windows 9X platform
  33. // VER_PLATFORM_WIN32_NT = Windows NT platform
  34. //
  35. // Please note that this code is intended as a general guideline. Your
  36. // app will probably be able to simply query for functionality (via
  37. // QueryInterface) for one or two components.
  38. //
  39. // Please also note:
  40. // "if (dxVer != 0x500) return FALSE;" is BAD.
  41. // "if (dxVer < 0x500) return FALSE;" is MUCH BETTER.
  42. // to ensure your app will run on future releases of DirectX.
  43. //-----------------------------------------------------------------------------
  44. VOID GetDXVersion( DWORD* pdwDXVersion, DWORD* pdwDXPlatform )
  45. {
  46. HRESULT hr;
  47. HINSTANCE DDHinst = 0;
  48. HINSTANCE DIHinst = 0;
  49. LPDIRECTDRAW pDDraw = 0;
  50. LPDIRECTDRAW2 pDDraw2 = 0;
  51. DIRECTDRAWCREATE DirectDrawCreate = 0;
  52. DIRECTDRAWCREATEEX DirectDrawCreateEx = 0;
  53. DIRECTINPUTCREATE DirectInputCreate = 0;
  54. OSVERSIONINFO osVer;
  55. LPDIRECTDRAWSURFACE pSurf = 0;
  56. LPDIRECTDRAWSURFACE3 pSurf3 = 0;
  57. LPDIRECTDRAWSURFACE4 pSurf4 = 0;
  58. // First get the windows platform
  59. osVer.dwOSVersionInfoSize = sizeof(osVer);
  60. if( !GetVersionEx( &osVer ) )
  61. {
  62. (*pdwDXPlatform) = 0;
  63. (*pdwDXVersion) = 0;
  64. return;
  65. }
  66. if( osVer.dwPlatformId == VER_PLATFORM_WIN32_NT )
  67. {
  68. (*pdwDXPlatform) = VER_PLATFORM_WIN32_NT;
  69. // NT is easy... NT 4.0 is DX2, 4.0 SP3 is DX3, 5.0 is DX5
  70. // and no DX on earlier versions.
  71. if( osVer.dwMajorVersion < 4 )
  72. {
  73. (*pdwDXVersion) = 0; // No DX on NT3.51 or earlier
  74. return;
  75. }
  76. if( osVer.dwMajorVersion == 4 )
  77. {
  78. // NT4 up to SP2 is DX2, and SP3 onwards is DX3, so we are at least DX2
  79. (*pdwDXVersion) = 0x200;
  80. // We're not supposed to be able to tell which SP we're on, so check for dinput
  81. DIHinst = LoadLibrary( "DINPUT.DLL" );
  82. if( DIHinst == 0 )
  83. {
  84. // No DInput... must be DX2 on NT 4 pre-SP3
  85. OutputDebugString( "Couldn't LoadLibrary DInput\r\n" );
  86. return;
  87. }
  88. DirectInputCreate = (DIRECTINPUTCREATE)GetProcAddress( DIHinst,
  89. "DirectInputCreateA" );
  90. FreeLibrary( DIHinst );
  91. if( DirectInputCreate == 0 )
  92. {
  93. // No DInput... must be pre-SP3 DX2
  94. OutputDebugString( "Couldn't GetProcAddress DInputCreate\r\n" );
  95. return;
  96. }
  97. // It must be NT4, DX2
  98. (*pdwDXVersion) = 0x300; // DX3 on NT4 SP3 or higher
  99. return;
  100. }
  101. // Else it's NT5 or higher, and it's DX5a or higher: Drop through to
  102. // Win9x tests for a test of DDraw (DX6 or higher)
  103. }
  104. else
  105. {
  106. // Not NT... must be Win9x
  107. (*pdwDXPlatform) = VER_PLATFORM_WIN32_WINDOWS;
  108. }
  109. // Now we know we are in Windows 9x (or maybe 3.1), so anything's possible.
  110. // First see if DDRAW.DLL even exists.
  111. DDHinst = LoadLibrary( "DDRAW.DLL" );
  112. if( DDHinst == 0 )
  113. {
  114. (*pdwDXVersion) = 0;
  115. (*pdwDXPlatform) = 0;
  116. FreeLibrary( DDHinst );
  117. return;
  118. }
  119. // See if we can create the DirectDraw object.
  120. DirectDrawCreate = (DIRECTDRAWCREATE)GetProcAddress( DDHinst, "DirectDrawCreate" );
  121. if( DirectDrawCreate == 0 )
  122. {
  123. (*pdwDXVersion) = 0;
  124. (*pdwDXPlatform) = 0;
  125. FreeLibrary( DDHinst );
  126. OutputDebugString( "Couldn't LoadLibrary DDraw\r\n" );
  127. return;
  128. }
  129. hr = DirectDrawCreate( NULL, &pDDraw, NULL );
  130. if( FAILED(hr) )
  131. {
  132. (*pdwDXVersion) = 0;
  133. (*pdwDXPlatform) = 0;
  134. FreeLibrary( DDHinst );
  135. OutputDebugString( "Couldn't create DDraw\r\n" );
  136. return;
  137. }
  138. // So DirectDraw exists. We are at least DX1.
  139. (*pdwDXVersion) = 0x100;
  140. // Let's see if IID_IDirectDraw2 exists.
  141. hr = pDDraw->QueryInterface( IID_IDirectDraw2, (VOID**)&pDDraw2 );
  142. if( FAILED(hr) )
  143. {
  144. // No IDirectDraw2 exists... must be DX1
  145. pDDraw->Release();
  146. FreeLibrary( DDHinst );
  147. OutputDebugString( "Couldn't QI DDraw2\r\n" );
  148. return;
  149. }
  150. // IDirectDraw2 exists. We must be at least DX2
  151. pDDraw2->Release();
  152. (*pdwDXVersion) = 0x200;
  153. ///////////////////////////////////////////////////////////////////////////
  154. // DirectX 3.0 Checks
  155. ///////////////////////////////////////////////////////////////////////////
  156. // DirectInput was added for DX3
  157. DIHinst = LoadLibrary( "DINPUT.DLL" );
  158. if( DIHinst == 0 )
  159. {
  160. // No DInput... must not be DX3
  161. OutputDebugString( "Couldn't LoadLibrary DInput\r\n" );
  162. pDDraw->Release();
  163. FreeLibrary( DDHinst );
  164. return;
  165. }
  166. DirectInputCreate = (DIRECTINPUTCREATE)GetProcAddress( DIHinst,
  167. "DirectInputCreateA" );
  168. if( DirectInputCreate == 0 )
  169. {
  170. // No DInput... must be DX2
  171. FreeLibrary( DIHinst );
  172. FreeLibrary( DDHinst );
  173. pDDraw->Release();
  174. OutputDebugString( "Couldn't GetProcAddress DInputCreate\r\n" );
  175. return;
  176. }
  177. // DirectInputCreate exists. We are at least DX3
  178. (*pdwDXVersion) = 0x300;
  179. FreeLibrary( DIHinst );
  180. // Can do checks for 3a vs 3b here
  181. ///////////////////////////////////////////////////////////////////////////
  182. // DirectX 5.0 Checks
  183. ///////////////////////////////////////////////////////////////////////////
  184. // We can tell if DX5 is present by checking for the existence of
  185. // IDirectDrawSurface3. First, we need a surface to QI off of.
  186. DDSURFACEDESC ddsd;
  187. ZeroMemory( &ddsd, sizeof(ddsd) );
  188. ddsd.dwSize = sizeof(ddsd);
  189. ddsd.dwFlags = DDSD_CAPS;
  190. ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
  191. hr = pDDraw->SetCooperativeLevel( NULL, DDSCL_NORMAL );
  192. if( FAILED(hr) )
  193. {
  194. // Failure. This means DDraw isn't properly installed.
  195. pDDraw->Release();
  196. FreeLibrary( DDHinst );
  197. (*pdwDXVersion) = 0;
  198. OutputDebugString( "Couldn't Set coop level\r\n" );
  199. return;
  200. }
  201. hr = pDDraw->CreateSurface( &ddsd, &pSurf, NULL );
  202. if( FAILED(hr) )
  203. {
  204. // Failure. This means DDraw isn't properly installed.
  205. pDDraw->Release();
  206. FreeLibrary( DDHinst );
  207. *pdwDXVersion = 0;
  208. OutputDebugString( "Couldn't CreateSurface\r\n" );
  209. return;
  210. }
  211. // Query for the IDirectDrawSurface3 interface
  212. if( FAILED( pSurf->QueryInterface( IID_IDirectDrawSurface3,
  213. (VOID**)&pSurf3 ) ) )
  214. {
  215. pDDraw->Release();
  216. FreeLibrary( DDHinst );
  217. return;
  218. }
  219. // QI for IDirectDrawSurface3 succeeded. We must be at least DX5
  220. (*pdwDXVersion) = 0x500;
  221. ///////////////////////////////////////////////////////////////////////////
  222. // DirectX 6.0 Checks
  223. ///////////////////////////////////////////////////////////////////////////
  224. // The IDirectDrawSurface4 interface was introduced with DX 6.0
  225. if( FAILED( pSurf->QueryInterface( IID_IDirectDrawSurface4,
  226. (VOID**)&pSurf4 ) ) )
  227. {
  228. pDDraw->Release();
  229. FreeLibrary( DDHinst );
  230. return;
  231. }
  232. // IDirectDrawSurface4 was create successfully. We must be at least DX6
  233. (*pdwDXVersion) = 0x600;
  234. pSurf->Release();
  235. pDDraw->Release();
  236. ///////////////////////////////////////////////////////////////////////////
  237. // DirectX 6.1 Checks
  238. ///////////////////////////////////////////////////////////////////////////
  239. // Check for DMusic, which was introduced with DX6.1
  240. LPDIRECTMUSIC pDMusic = NULL;
  241. CoInitialize( NULL );
  242. hr = CoCreateInstance( CLSID_DirectMusic, NULL, CLSCTX_INPROC_SERVER,
  243. IID_IDirectMusic, (VOID**)&pDMusic );
  244. if( FAILED(hr) )
  245. {
  246. OutputDebugString( "Couldn't create CLSID_DirectMusic\r\n" );
  247. FreeLibrary( DDHinst );
  248. return;
  249. }
  250. // DirectMusic was created successfully. We must be at least DX6.1
  251. (*pdwDXVersion) = 0x601;
  252. pDMusic->Release();
  253. CoUninitialize();
  254. ///////////////////////////////////////////////////////////////////////////
  255. // DirectX 7.0 Checks
  256. ///////////////////////////////////////////////////////////////////////////
  257. // Check for DirectX 7 by creating a DDraw7 object
  258. LPDIRECTDRAW7 pDD7;
  259. DirectDrawCreateEx = (DIRECTDRAWCREATEEX)GetProcAddress( DDHinst,
  260. "DirectDrawCreateEx" );
  261. if( NULL == DirectDrawCreateEx )
  262. {
  263. FreeLibrary( DDHinst );
  264. return;
  265. }
  266. if( FAILED( DirectDrawCreateEx( NULL, (VOID**)&pDD7, IID_IDirectDraw7,
  267. NULL ) ) )
  268. {
  269. FreeLibrary( DDHinst );
  270. return;
  271. }
  272. // DDraw7 was created successfully. We must be at least DX7.0
  273. (*pdwDXVersion) = 0x700;
  274. pDD7->Release();
  275. ///////////////////////////////////////////////////////////////////////////
  276. // End of checks
  277. ///////////////////////////////////////////////////////////////////////////
  278. // Close open libraries and return
  279. FreeLibrary( DDHinst );
  280. return;
  281. }
  282. int getDXVersion(){
  283. DWORD version,platform;
  284. GetDXVersion( &version,&platform );
  285. return (version>>8)&0xff;
  286. }