Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

358 lines
9.2 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1997 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: factory.cpp
  6. * Content: DirectDraw Factory support
  7. * History:
  8. * Date By Reason
  9. * ==== == ======
  10. * 24-feb-97 ralphl initial implementation
  11. * 25-feb-97 craige minor tweaks for dx checkin
  12. * 14-mar-97 jeffort version checking changed to support DX3 and above
  13. * 09-apr-97 jeffort version checking added for DX2 and NT
  14. * 30-apr-97 jeffort version >DX5 treated as DX5
  15. * 10-jul-97 jeffort made OSVersion a static variable
  16. * 09-sep-97 mikear QI for IUnknown when aggregating
  17. ***************************************************************************/
  18. #include "ddfactry.h"
  19. //#defines for registry lookup
  20. #define REGSTR_PATH_DDRAW "Software\\Microsoft\\DirectDraw"
  21. #define REGSTR_VAL_DDRAW_OWNDC "OWNDC"
  22. CDDFactory::CDDFactory(IUnknown *pUnkOuter) :
  23. m_cRef(1),
  24. m_pUnkOuter(pUnkOuter != 0 ? pUnkOuter : CAST_TO_IUNKNOWN(this))
  25. {
  26. m_hDDrawDLL = NULL;
  27. DllAddRef();
  28. }
  29. STDAPI DirectDrawFactory_CreateInstance(
  30. IUnknown * pUnkOuter,
  31. REFIID riid,
  32. void ** ppv)
  33. {
  34. HRESULT hr;
  35. CDDFactory *pFactory = new CDDFactory(pUnkOuter);
  36. if( !pFactory )
  37. {
  38. hr = E_OUTOFMEMORY;
  39. }
  40. else
  41. {
  42. hr = pFactory->NonDelegatingQueryInterface(pUnkOuter ? IID_IUnknown : riid, ppv);
  43. pFactory->NonDelegatingRelease();
  44. }
  45. return hr;
  46. }
  47. STDMETHODIMP CDDFactory::NonDelegatingQueryInterface(REFIID riid, void ** ppv)
  48. {
  49. *ppv=NULL;
  50. if (IID_IUnknown==riid)
  51. {
  52. *ppv=(INonDelegatingUnknown *)this;
  53. }
  54. else
  55. {
  56. if (IID_IDirectDrawFactory==riid)
  57. {
  58. *ppv=(IDirectDrawFactory *)this;
  59. }
  60. else
  61. {
  62. return E_NOINTERFACE;
  63. }
  64. }
  65. ((LPUNKNOWN)*ppv)->AddRef();
  66. return NOERROR;
  67. }
  68. STDMETHODIMP_(ULONG) CDDFactory::NonDelegatingAddRef()
  69. {
  70. return InterlockedIncrement(&m_cRef);
  71. }
  72. STDMETHODIMP_(ULONG) CDDFactory::NonDelegatingRelease()
  73. {
  74. LONG lRefCount = InterlockedDecrement(&m_cRef);
  75. if( lRefCount )
  76. {
  77. return lRefCount;
  78. }
  79. delete this;
  80. DllRelease();
  81. return 0;
  82. }
  83. // Standard IUnknown
  84. STDMETHODIMP CDDFactory::QueryInterface(REFIID riid, void ** ppv)
  85. {
  86. return m_pUnkOuter->QueryInterface(riid, ppv);
  87. }
  88. STDMETHODIMP_(ULONG) CDDFactory::AddRef(void)
  89. {
  90. return m_pUnkOuter->AddRef();
  91. }
  92. STDMETHODIMP_(ULONG) CDDFactory::Release(void)
  93. {
  94. return m_pUnkOuter->Release();
  95. }
  96. /*
  97. * CDDFactory::CreateDirectDraw
  98. */
  99. STDMETHODIMP CDDFactory::CreateDirectDraw(
  100. GUID * pGUID,
  101. HWND hWnd,
  102. DWORD dwCoopLevelFlags,
  103. DWORD dwReserved,
  104. IUnknown *pUnkOuter,
  105. IDirectDraw **ppDirectDraw )
  106. {
  107. static OSVERSIONINFO osVer;
  108. CDirectDrawEx *pDirectDrawEx;
  109. HRESULT hr = S_OK;
  110. BOOL fDDrawDllVerFound = FALSE;
  111. *ppDirectDraw = NULL;
  112. /*
  113. * first, see if we can get at DirectDraw or not!
  114. */
  115. if( m_hDDrawDLL == NULL )
  116. {
  117. char path[_MAX_PATH];
  118. char DllName[25];
  119. DWORD dwRet;
  120. // m_hDDrawDLL = LoadLibrary( "ddraw.dll" );
  121. dwRet = GetProfileString("ddrawex","realdll","ddraw.dll",DllName,25);
  122. if( dwRet == 0 )
  123. {
  124. return DDERR_GENERIC;
  125. }
  126. m_hDDrawDLL = LoadLibrary( DllName );
  127. if( m_hDDrawDLL == NULL )
  128. {
  129. return DDERR_LOADFAILED;
  130. }
  131. /*
  132. * get ddraw.dll version number
  133. */
  134. if( GetModuleFileName( (HINSTANCE)m_hDDrawDLL, path, sizeof( path ) ) )
  135. {
  136. int size;
  137. DWORD tmp;
  138. size = (int) GetFileVersionInfoSize( path, (LPDWORD) &tmp );
  139. if( size != 0 )
  140. {
  141. LPVOID vinfo;
  142. vinfo = (LPVOID) LocalAlloc( LPTR, size );
  143. if(vinfo == NULL)
  144. {
  145. hr = DDERR_OUTOFMEMORY;
  146. goto CleanUp;
  147. }
  148. if( GetFileVersionInfo( path, 0, size, vinfo ) )
  149. {
  150. VS_FIXEDFILEINFO *ver=NULL;
  151. UINT cb;
  152. if( VerQueryValue(vinfo, "\\", (LPVOID *)&ver, &cb) )
  153. {
  154. if( ver != NULL )
  155. {
  156. /*
  157. * we only need the most significant dword,
  158. * the LS dword contains the build number only...
  159. * Hack: The '|5' forces recognition of DX6+
  160. */
  161. m_dwDDVerMS = ver->dwFileVersionMS | 5;
  162. fDDrawDllVerFound = TRUE;
  163. }
  164. }
  165. }
  166. LocalFree( vinfo );
  167. }
  168. }
  169. osVer.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
  170. if ( !fDDrawDllVerFound || !GetVersionEx(&osVer) )
  171. {
  172. hr = DDERR_BADVERSIONINFO;
  173. goto CleanUp;
  174. }
  175. //if we are on NT4.0 Gold, the DLL version will be 4.00
  176. if (osVer.dwPlatformId == VER_PLATFORM_WIN32_NT && LOWORD( m_dwDDVerMS) == 0)
  177. {
  178. //boost the LOWORD up so we will not fail the next check below
  179. m_dwDDVerMS += 3;
  180. }
  181. /*
  182. * don't work on anything but DX2 DX 3 or DX 5.
  183. */
  184. if( !((HIWORD( m_dwDDVerMS ) >= 4) && (LOWORD( m_dwDDVerMS) >= 3)) )
  185. {
  186. hr = DDERR_UNSUPPORTED;
  187. goto CleanUp;
  188. }
  189. if( LOWORD( m_dwDDVerMS) > 5)
  190. {
  191. //we will assume that any version >= DX5 will support what we need, so we
  192. //will mark anything greater than 5 as DX5
  193. m_dwDDVerMS = 5;
  194. }
  195. /*
  196. * get the various entry points we need
  197. */
  198. m_pDirectDrawCreate = (LPDIRECTDRAWCREATE) GetProcAddress((HINSTANCE) m_hDDrawDLL, "DirectDrawCreate" );
  199. if( m_pDirectDrawCreate == NULL )
  200. {
  201. hr = DDERR_BADPROCADDRESS;
  202. goto CleanUp;
  203. }
  204. m_pDirectDrawEnumerateW = (LPDIRECTDRAWENUMW) GetProcAddress( (HINSTANCE)m_hDDrawDLL, "DirectDrawEnumerateW" );
  205. if( m_pDirectDrawEnumerateW == NULL )
  206. {
  207. hr = DDERR_BADPROCADDRESS;
  208. goto CleanUp;
  209. }
  210. m_pDirectDrawEnumerateA = (LPDIRECTDRAWENUMA) GetProcAddress((HINSTANCE) m_hDDrawDLL, "DirectDrawEnumerateA" );
  211. if( m_pDirectDrawEnumerateA == NULL )
  212. {
  213. hr = DDERR_BADPROCADDRESS;
  214. goto CleanUp;
  215. }
  216. } // m_hDDrawDLL = NULL
  217. /*
  218. * create and initialize the ddrawex object
  219. */
  220. pDirectDrawEx = new CDirectDrawEx(pUnkOuter);
  221. if( !pDirectDrawEx )
  222. {
  223. hr = DDERR_OUTOFMEMORY;
  224. goto CleanUp;
  225. }
  226. else
  227. {
  228. hr = pDirectDrawEx->Init( pGUID, hWnd, dwCoopLevelFlags, dwReserved, m_pDirectDrawCreate );
  229. if( SUCCEEDED(hr) )
  230. {
  231. hr = pDirectDrawEx->NonDelegatingQueryInterface(IID_IDirectDraw, (void **)ppDirectDraw);
  232. /*
  233. * save the ddraw version number...
  234. */
  235. if (osVer.dwPlatformId == VER_PLATFORM_WIN32_NT)
  236. {
  237. if( LOWORD( m_dwDDVerMS ) == 5 )
  238. {
  239. DWORD type;
  240. DWORD value;
  241. DWORD cb;
  242. HKEY hkey;
  243. //DX5 is busted with OwnDC for StretchBlt
  244. //check a registry key to see if we are
  245. //using dx5 style or dx3 style.
  246. //default is dx3
  247. pDirectDrawEx->m_dwDDVer = WINNT_DX5;
  248. if( ERROR_SUCCESS == RegOpenKey( HKEY_LOCAL_MACHINE, REGSTR_PATH_DDRAW, &hkey ) )
  249. {
  250. cb = sizeof( value );
  251. if( ERROR_SUCCESS == RegQueryValueEx( hkey, REGSTR_VAL_DDRAW_OWNDC, NULL, &type, (CONST LPBYTE)&value, &cb ) )
  252. {
  253. pDirectDrawEx->m_dwDDVer = WINNT_DX5;
  254. }
  255. RegCloseKey(hkey);
  256. }
  257. }
  258. else if (LOWORD (m_dwDDVerMS) == 4 )
  259. {
  260. pDirectDrawEx->m_dwDDVer = WINNT_DX3;
  261. }
  262. else if (LOWORD (m_dwDDVerMS) == 3 )
  263. {
  264. pDirectDrawEx->m_dwDDVer = WINNT_DX2;
  265. }
  266. //should never get here, alread checked above, but be a bit anal
  267. else
  268. {
  269. hr = DDERR_UNSUPPORTED;
  270. goto CleanUp;
  271. }
  272. }
  273. else
  274. {
  275. if( LOWORD( m_dwDDVerMS ) == 5 )
  276. {
  277. pDirectDrawEx->m_dwDDVer = WIN95_DX5;
  278. }
  279. else if (LOWORD (m_dwDDVerMS) == 4 )
  280. {
  281. pDirectDrawEx->m_dwDDVer = WIN95_DX3;
  282. }
  283. else if (LOWORD (m_dwDDVerMS) == 3 )
  284. {
  285. pDirectDrawEx->m_dwDDVer = WIN95_DX2;
  286. }
  287. //should never get here, alread checked above, but be a bit anal
  288. else
  289. {
  290. hr = DDERR_UNSUPPORTED;
  291. goto CleanUp;
  292. }
  293. }
  294. }
  295. pDirectDrawEx->NonDelegatingRelease();
  296. }
  297. CleanUp:
  298. if( hr != S_OK && m_hDDrawDLL != NULL )
  299. {
  300. FreeLibrary((HINSTANCE) m_hDDrawDLL );
  301. m_hDDrawDLL = NULL;
  302. }
  303. return hr;
  304. } /* CDDFactory::CreateDirectDraw */
  305. /*
  306. * CDDFactory::DirectDrawEnumerate
  307. *
  308. * implements ddraw enumerate.
  309. */
  310. STDMETHODIMP CDDFactory::DirectDrawEnumerate(LPDDENUMCALLBACK lpCallback, LPVOID lpContext)
  311. {
  312. #pragma message( REMIND( "DDFactory::DirectDrawEnumerate assumes ANSI" ))
  313. return m_pDirectDrawEnumerateA(lpCallback, lpContext);
  314. } /* CDDFactory::DirectDrawEnumerate */