Leaked source code of windows server 2003
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.

1649 lines
53 KiB

  1. /*==========================================================================
  2. * Copyright (C) 1994-1995 Microsoft Corporation. All Rights Reserved.
  3. *
  4. * File: ddiunk.c
  5. * Content: DirectDraw IUnknown interface
  6. * Implements QueryInterface, AddRef, and Release
  7. * History:
  8. * Date By Reason
  9. * ==== == ======
  10. * 14-mar-95 craige split out of ddraw.c
  11. * 19-mar-95 craige process termination cleanup fixes
  12. * 29-mar-95 craige DC per process to clean up; use GETCURRPID
  13. * 31-mar-95 craige cleanup palettes
  14. * 01-apr-95 craige happy fun joy updated header file
  15. * 07-apr-95 craige bug 14 - check GUID ptr in QI
  16. * don't release NULL hdc
  17. * 12-may-95 craige check for guids
  18. * 15-may-95 craige restore mode, free surfaces & palettes on a
  19. * per-process basis
  20. * 24-may-95 craige release allocated tables
  21. * 02-jun-95 craige extra parm in AddToActiveProcessList
  22. * 06-jun-95 craige call RestoreDisplayMode
  23. * 07-jun-95 craige removed DCLIST
  24. * 12-jun-95 craige new process list stuff
  25. * 21-jun-95 craige clipper stuff
  26. * 25-jun-95 craige one ddraw mutex
  27. * 26-jun-95 craige reorganized surface structure
  28. * 28-jun-95 craige ENTER_DDRAW at very start of fns
  29. * 03-jul-95 craige YEEHAW: new driver struct; SEH
  30. * 13-jul-95 craige removed spurious frees of ddhel dll (obsolete);
  31. * don't restore the mode if not excl mode owner on death
  32. * 20-jul-95 craige internal reorg to prevent thunking during modeset
  33. * 21-nov-95 colinmc made Direct3D a queryable interface off DirectDraw
  34. * 27-nov-95 jeffno ifdef'd out VxD stuff (in DD_Release) for winnt
  35. * 01-dec-95 colinmc new IID for DirectDraw V2
  36. * 22-dec-95 colinmc Direct3D support no longer conditional
  37. * 25-dec-95 craige allow a NULL lpGbl ptr for QI, AddRef, Release
  38. * 31-dec-95 craige validate riid
  39. * 01-jan-96 colinmc Fixed D3D integration bug which lead to
  40. * the Direct3D DLL being released too early.
  41. * 13-jan-96 colinmc Temporary workaround for Direct3D cleanup problem
  42. * 04-jan-96 kylej add interface structures
  43. * 26-jan-96 jeffno Destroy NT kernel-mode objects
  44. * 07-feb-96 jeffno Rearrange DD_Release so that freed objects aren't referenced
  45. * 08-feb-96 colinmc New D3D interface
  46. * 17-feb-96 colinmc Removed final D3D references
  47. * 28-feb-96 colinmc Fixed thread-unsafe problem in DD_Release
  48. * 22-mar-96 colinmc Bug 13316: uninitialized interfaces
  49. * 23-mar-96 colinmc Bug 12252: Direct3D not properly cleaned up on GPF
  50. * 27-mar-96 colinmc Bug 14779: Bad cleanup on Direct3DCreate failure
  51. * 18-apr-96 colinmc Bug 17008: DirectDraw/Direct3D deadlock
  52. * 29-apr-96 colinmc Bug 19954: Must query for Direct3D before texture
  53. * or device
  54. * 03-may-96 kylej Bug 19125: Preserve V1 SetCooperativeLevel behaviour
  55. * 15-sep-96 colinmc Work Item: Removing the restriction on taking Win16
  56. * lock on VRAM surfaces (not including the primary)
  57. * 12-oct-96 colinmc Improvements to Win16 locking code to reduce virtual
  58. * memory usage
  59. * 29-jan-97 smac Fixed video port container bug
  60. * 03-mar-97 smac Added kernel mode interface
  61. * 08-mar-97 colinmc Added support for DMA style AGP parts
  62. * 30-sep-97 jeffno IDirectDraw4
  63. *
  64. ***************************************************************************/
  65. #include "ddrawpr.h"
  66. #ifdef WINNT
  67. #include "ddrawgdi.h"
  68. #endif
  69. #define DPF_MODNAME "DirectDraw::QueryInterface"
  70. /*
  71. * Create the Direct3D interface aggregated by DirectDraw. This involves
  72. * loading the Direct3D DLL, getting the Direct3DCreate entry point and
  73. * invoking it.
  74. *
  75. * NOTE: This function does not call QueryInterface() on the returned
  76. * interface to bump the reference count as this function may be invoked
  77. * by one of the surface QueryInterface() calls to initialized Direct3D
  78. * before the user makes a request for external interface.
  79. *
  80. * Returns:
  81. * DD_OK - success
  82. * E_NOINTERFACE - we could not find valid Direct3D DLLs (we assumed its not
  83. * installed and so the Direct3D interfaces are not understood)
  84. * D3DERR_ - We found a valid Direct3D installation but the object
  85. * creation failed for some reason.
  86. */
  87. HRESULT InitD3DRevision(
  88. LPDDRAWI_DIRECTDRAW_INT this_int,
  89. HINSTANCE * pDLLHinstance,
  90. IUnknown ** ppOwnedIUnknown,
  91. DWORD dwRevisionLevel )
  92. {
  93. D3DCreateProc lpfnD3DCreateProc;
  94. HRESULT rval;
  95. LPDDRAWI_DIRECTDRAW_LCL this_lcl;
  96. this_lcl = this_int->lpLcl;
  97. /*
  98. * This function does no checking to ensure that it
  99. * has not already been invoked for this driver object
  100. * so this must be NULL on entry.
  101. */
  102. DDASSERT( NULL == this_lcl->pD3DIUnknown );
  103. DPF( 4, "Initializing Direct3D" );
  104. /*
  105. * Load the Direct3D DLL.
  106. */
  107. if(*pDLLHinstance == NULL)
  108. {
  109. char* pDLLName;
  110. if (dwRevisionLevel < 0x700)
  111. {
  112. pDLLName = D3D_DLLNAME;
  113. }
  114. else
  115. {
  116. pDLLName = D3DDX7_DLLNAME;
  117. }
  118. *pDLLHinstance = LoadLibrary( pDLLName );
  119. if( *pDLLHinstance == NULL )
  120. {
  121. DPF( 0, "Could not locate the Direct3D DLL (%s)", pDLLName);
  122. return E_NOINTERFACE;
  123. }
  124. }
  125. lpfnD3DCreateProc = (D3DCreateProc)GetProcAddress( *pDLLHinstance, D3DCREATE_PROCNAME );
  126. this_lcl->pPaletteUpdateNotify = (LPPALETTEUPDATENOTIFY)GetProcAddress( *pDLLHinstance, PALETTEUPDATENOTIFY_NAME );
  127. this_lcl->pPaletteAssociateNotify = (LPPALETTEASSOCIATENOTIFY)GetProcAddress( *pDLLHinstance, PALETTEASSOCIATENOTIFY_NAME );
  128. this_lcl->pSurfaceFlipNotify = (LPSURFACEFLIPNOTIFY)GetProcAddress( *pDLLHinstance, SURFACEFLIPNOTIFY_NAME );
  129. this_lcl->pFlushD3DDevices = (FLUSHD3DDEVICES)GetProcAddress( *pDLLHinstance, FLUSHD3DDEVICES_NAME );
  130. this_lcl->pD3DTextureUpdate = (D3DTEXTUREUPDATE)GetProcAddress( *pDLLHinstance, D3DTEXTUREUPDATE_NAME );
  131. if (dwRevisionLevel >= 0x700)
  132. {
  133. this_lcl->pFlushD3DDevices2 = this_lcl->pFlushD3DDevices;
  134. this_lcl->pD3DCreateTexture = (D3DCREATETEXTURE)GetProcAddress( *pDLLHinstance, D3DCREATETEXTURE_NAME );
  135. this_lcl->pD3DDestroyTexture = (D3DDESTROYTEXTURE)GetProcAddress( *pDLLHinstance, D3DDESTROYTEXTURE_NAME );
  136. this_lcl->pD3DSetPriority = (D3DSETPRIORITY)GetProcAddress( *pDLLHinstance, D3DSETPRIORITY_NAME );
  137. this_lcl->pD3DGetPriority = (D3DGETPRIORITY)GetProcAddress( *pDLLHinstance, D3DGETPRIORITY_NAME );
  138. this_lcl->pD3DSetLOD = (D3DSETLOD)GetProcAddress( *pDLLHinstance, D3DSETLOD_NAME );
  139. this_lcl->pD3DGetLOD = (D3DGETLOD)GetProcAddress( *pDLLHinstance, D3DGETLOD_NAME );
  140. this_lcl->pBreakVBLock = (LPBREAKVBLOCK)GetProcAddress( *pDLLHinstance, BREAKVBLOCK_NAME );
  141. this_lcl->pddSurfaceCallbacks = &ddSurfaceCallbacks;
  142. }
  143. else
  144. {
  145. this_lcl->pFlushD3DDevices2 = (FLUSHD3DDEVICES)GetProcAddress( *pDLLHinstance, FLUSHD3DDEVICES2_NAME );
  146. this_lcl->pD3DCreateTexture = NULL;
  147. this_lcl->pD3DDestroyTexture = NULL;
  148. this_lcl->pD3DSetPriority = NULL;
  149. this_lcl->pD3DGetPriority = NULL;
  150. this_lcl->pD3DSetLOD = NULL;
  151. this_lcl->pD3DGetLOD = NULL;
  152. this_lcl->pBreakVBLock = NULL;
  153. this_lcl->pddSurfaceCallbacks = NULL;
  154. }
  155. if( lpfnD3DCreateProc == NULL )
  156. {
  157. DPF( 0, "Could not locate the Direct3DCreate entry point" );
  158. FreeLibrary( *pDLLHinstance );
  159. *pDLLHinstance = NULL;
  160. return E_NOINTERFACE;
  161. }
  162. /*
  163. * ### Tada - an aggregated object creation ###
  164. */
  165. #ifdef USE_D3D_CSECT
  166. rval = (*lpfnD3DCreateProc)( ppOwnedIUnknown, (LPUNKNOWN)this_int );
  167. #else /* USE_D3D_CSECT */
  168. #ifdef WINNT
  169. rval = (*lpfnD3DCreateProc)( 0, ppOwnedIUnknown, (LPUNKNOWN)this_int );
  170. #else
  171. rval = (*lpfnD3DCreateProc)( lpDDCS, ppOwnedIUnknown, (LPUNKNOWN)this_int );
  172. #endif
  173. #endif /* USE_D3D_CSECT */
  174. if( rval == DD_OK )
  175. {
  176. DPF( 4, "Created aggregated Direct3D interface" );
  177. return DD_OK;
  178. }
  179. else
  180. {
  181. /*
  182. * Direct3D did understand the IID but failed to initialize for
  183. * some other reason.
  184. */
  185. DPF( 0, "Could not create aggregated Direct3D interface" );
  186. *ppOwnedIUnknown = NULL;
  187. FreeLibrary( *pDLLHinstance );
  188. *pDLLHinstance = NULL;
  189. return rval;
  190. }
  191. }
  192. HRESULT InitD3D( LPDDRAWI_DIRECTDRAW_INT this_int )
  193. {
  194. LPDDRAWI_DIRECTDRAW_LCL this_lcl;
  195. this_lcl = this_int->lpLcl;
  196. if( DDRAWILCL_DIRECTDRAW7 & this_lcl->dwLocalFlags)
  197. {
  198. return InitD3DRevision( this_int, &this_lcl->hD3DInstance, &this_lcl->pD3DIUnknown, 0x700);
  199. }
  200. else
  201. {
  202. return InitD3DRevision( this_int, &this_lcl->hD3DInstance, &this_lcl->pD3DIUnknown, 0x600);
  203. }
  204. }
  205. #if 0
  206. /*
  207. * This function builds a d3d device context for use by ddraw. DDraw will use this context
  208. * initially to send palette update messages.
  209. */
  210. HRESULT InitDDrawPrivateD3DContext( LPDDRAWI_DIRECTDRAW_INT this_int )
  211. {
  212. IUnknown * pD3DUnknown;
  213. LPDDRAWI_DIRECTDRAW_LCL this_lcl;
  214. HRESULT hr=DD_OK;
  215. HINSTANCE hInstance;
  216. this_lcl = this_int->lpLcl;
  217. DDASSERT( 0 == (this_lcl->dwLocalFlags & DDRAWILCL_ATTEMPTEDD3DCONTEXT) );
  218. /*
  219. * If this is a dx7 ddraw object, then we will piggy back off of the d3d object
  220. * that's created when IDirect3Dx is QIed. This saves creating another d3d object
  221. * since they are quite piggy.
  222. * If this is not a dx7 object, then we have to get our own dx7 d3d, since the dx6
  223. * d3d can't understand our extra calls.
  224. */
  225. if( DDRAWILCL_DIRECTDRAW7 & this_lcl->dwLocalFlags)
  226. {
  227. if( !D3D_INITIALIZED( this_lcl ) )
  228. hr = InitD3D( this_int );
  229. this_lcl->hinstDDrawPrivateD3D = 0;
  230. pD3DUnknown = this_lcl->pD3DIUnknown;
  231. hInstance = this_lcl->hD3DInstance;
  232. //We set this up so d3d doesn't have to struggle trying to figure out which iunknown to use
  233. this_lcl->pPrivateD3DInterface = this_lcl->pD3DIUnknown;
  234. }
  235. else
  236. {
  237. /*
  238. * Have to create a new one and keep it around
  239. */
  240. hr = InitD3DRevision( this_int, &this_lcl->hinstDDrawPrivateD3D, &this_lcl->pPrivateD3DInterface, 0x700 );
  241. pD3DUnknown = this_lcl->pPrivateD3DInterface;
  242. hInstance = this_lcl->hinstDDrawPrivateD3D;
  243. }
  244. if (SUCCEEDED(hr))
  245. {
  246. GETDDRAWCONTEXT pGetContext;
  247. DDASSERT(hInstance);
  248. DDASSERT(pD3DUnknown);
  249. /*
  250. * Go create the d3d device
  251. */
  252. pGetContext = (GETDDRAWCONTEXT)GetProcAddress( hInstance, GETDDRAWCONTEXT_NAME );
  253. if (pGetContext)
  254. {
  255. this_lcl->pDeviceContext = pGetContext(this_lcl);
  256. /*
  257. * Go get the notification entry points.
  258. * If either of these fail, we carry on regardless.
  259. */
  260. this_lcl->pPaletteUpdateNotify = (LPPALETTEUPDATENOTIFY)GetProcAddress( hInstance, PALETTEUPDATENOTIFY_NAME );
  261. this_lcl->pPaletteAssociateNotify = (LPPALETTEASSOCIATENOTIFY)GetProcAddress( hInstance, PALETTEASSOCIATENOTIFY_NAME );
  262. }
  263. }
  264. this_lcl->dwLocalFlags |= DDRAWILCL_ATTEMPTEDD3DCONTEXT;
  265. return hr;
  266. }
  267. #endif
  268. /*
  269. * getDDInterface
  270. */
  271. LPDDRAWI_DIRECTDRAW_INT getDDInterface( LPDDRAWI_DIRECTDRAW_LCL this_lcl, LPVOID lpddcb )
  272. {
  273. LPDDRAWI_DIRECTDRAW_INT curr_int;
  274. ENTER_DRIVERLISTCSECT();
  275. for( curr_int = lpDriverObjectList; curr_int != NULL; curr_int = curr_int->lpLink )
  276. {
  277. if( (curr_int->lpLcl == this_lcl) &&
  278. (curr_int->lpVtbl == lpddcb) )
  279. {
  280. break;
  281. }
  282. }
  283. if( NULL == curr_int )
  284. {
  285. // Couldn't find an existing interface, create one.
  286. curr_int = MemAlloc( sizeof( DDRAWI_DIRECTDRAW_INT ) );
  287. if( NULL == curr_int )
  288. {
  289. LEAVE_DRIVERLISTCSECT();
  290. return NULL;
  291. }
  292. /*
  293. * set up data
  294. */
  295. curr_int->lpVtbl = lpddcb;
  296. curr_int->lpLcl = this_lcl;
  297. curr_int->dwIntRefCnt = 0;
  298. curr_int->lpLink = lpDriverObjectList;
  299. lpDriverObjectList = curr_int;
  300. }
  301. LEAVE_DRIVERLISTCSECT();
  302. DPF( 5, "New driver interface created, %08lx", curr_int );
  303. return curr_int;
  304. }
  305. #ifdef POSTPONED
  306. /*
  307. * Delegating IUnknown for DDraw
  308. */
  309. HRESULT DDAPI DD_DelegatingQueryInterface(
  310. LPDIRECTDRAW lpDD,
  311. REFIID riid,
  312. LPVOID FAR * ppvObj )
  313. {
  314. LPDDRAWI_DIRECTDRAW_INT this_int;
  315. HRESULT hr;
  316. ENTER_DDRAW();
  317. DPF(2,A,"ENTERAPI: DD_DelegatingQueryInterface");
  318. TRY
  319. {
  320. this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
  321. if( !VALID_DIRECTDRAW_PTR( this_int ) )
  322. {
  323. LEAVE_DDRAW();
  324. return DDERR_INVALIDOBJECT;
  325. }
  326. }
  327. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  328. {
  329. DPF_ERR( "Exception encountered validating parameters" );
  330. LEAVE_DDRAW();
  331. return DDERR_INVALIDPARAMS;
  332. }
  333. /*
  334. * We have to check if the owning IUnknown is actually one of our own
  335. * interfaces
  336. */
  337. if ( IS_NATIVE_DDRAW_INTERFACE(this_int->lpLcl->pUnkOuter) )
  338. {
  339. /*
  340. * So we can trust that the int pointer really is a pointer to DDRAW_DIRECTDRAW_INT
  341. */
  342. hr = this_int->lpLcl->pUnkOuter->lpVtbl->QueryInterface((IUnknown*)lpDD, riid, ppvObj);
  343. }
  344. else
  345. {
  346. /*
  347. * So we have no idea whose pointer it is, better pass its this pointer.
  348. */
  349. hr = this_int->lpLcl->pUnkOuter->lpVtbl->QueryInterface(this_int->lpLcl->pUnkOuter, riid, ppvObj);
  350. }
  351. LEAVE_DDRAW();
  352. return hr;
  353. }
  354. DWORD DDAPI DD_DelegatingAddRef( LPDIRECTDRAW lpDD )
  355. {
  356. LPDDRAWI_DIRECTDRAW_INT this_int;
  357. DWORD dw;
  358. ENTER_DDRAW();
  359. DPF(2,A,"ENTERAPI: DD_DelegatingAddRef");
  360. TRY
  361. {
  362. this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
  363. if( !VALID_DIRECTDRAW_PTR( this_int ) )
  364. {
  365. LEAVE_DDRAW();
  366. // what error code can you return from AddRef??
  367. return 0;
  368. }
  369. }
  370. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  371. {
  372. DPF_ERR( "Exception encountered validating parameters" );
  373. LEAVE_DDRAW();
  374. // what error code can you return from AddRef??
  375. return 0;
  376. }
  377. /*
  378. * We have to check if the owning IUnknown is actually one of our own
  379. * interfaces
  380. */
  381. if ( IS_NATIVE_DDRAW_INTERFACE(this_int->lpLcl->pUnkOuter) )
  382. {
  383. /*
  384. * So we can trust that the int pointer really is a pointer to DDRAW_DIRECTDRAW_INT
  385. */
  386. dw = this_int->lpLcl->pUnkOuter->lpVtbl->AddRef((IUnknown*)lpDD);
  387. }
  388. else
  389. {
  390. /*
  391. * So we have no idea whose pointer it is, better pass its this pointer.
  392. */
  393. dw = this_int->lpLcl->pUnkOuter->lpVtbl->AddRef(this_int->lpLcl->pUnkOuter);
  394. }
  395. LEAVE_DDRAW();
  396. return dw;
  397. }
  398. DWORD DDAPI DD_DelegatingRelease( LPDIRECTDRAW lpDD )
  399. {
  400. LPDDRAWI_DIRECTDRAW_INT this_int;
  401. DWORD dw;
  402. ENTER_DDRAW();
  403. DPF(2,A,"ENTERAPI: DD_DeletegatingRelease");
  404. TRY
  405. {
  406. this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
  407. if( !VALID_DIRECTDRAW_PTR( this_int ) )
  408. {
  409. LEAVE_DDRAW();
  410. // what error code can you return from AddRef??
  411. return 0;
  412. }
  413. }
  414. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  415. {
  416. DPF_ERR( "Exception encountered validating parameters" );
  417. LEAVE_DDRAW();
  418. // what error code can you return from Release??
  419. return 0;
  420. }
  421. /*
  422. * We have to check if the owning IUnknown is actually one of our own
  423. * interfaces
  424. */
  425. if ( IS_NATIVE_DDRAW_INTERFACE(this_int->lpLcl->pUnkOuter) )
  426. {
  427. /*
  428. * So we can trust that the int pointer really is a pointer to DDRAW_DIRECTDRAW_INT
  429. */
  430. dw = this_int->lpLcl->pUnkOuter->lpVtbl->Release((IUnknown*)lpDD);
  431. }
  432. else
  433. {
  434. /*
  435. * So we have no idea whose pointer it is, better pass its this pointer.
  436. */
  437. dw = this_int->lpLcl->pUnkOuter->lpVtbl->Release(this_int->lpLcl->pUnkOuter);
  438. }
  439. LEAVE_DDRAW();
  440. return dw;
  441. }
  442. #endif //postponed
  443. /*
  444. * DD_QueryInterface
  445. */
  446. HRESULT DDAPI DD_QueryInterface(
  447. LPDIRECTDRAW lpDD,
  448. REFIID riid,
  449. LPVOID FAR * ppvObj )
  450. {
  451. LPDDRAWI_DIRECTDRAW_INT this_int;
  452. LPDDRAWI_DIRECTDRAW_LCL this_lcl;
  453. HRESULT rval;
  454. ENTER_DDRAW();
  455. DPF(2,A,"ENTERAPI: DD_QueryInterface");
  456. TRY
  457. {
  458. this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
  459. if( !VALID_DIRECTDRAW_PTR( this_int ) )
  460. {
  461. LEAVE_DDRAW();
  462. return DDERR_INVALIDOBJECT;
  463. }
  464. if( !VALID_PTR_PTR( ppvObj ) )
  465. {
  466. DPF( 1, "Invalid object ptr" );
  467. LEAVE_DDRAW();
  468. return DDERR_INVALIDPARAMS;
  469. }
  470. if( !VALIDEX_IID_PTR( riid ) )
  471. {
  472. DPF( 1, "Invalid iid ptr" );
  473. LEAVE_DDRAW();
  474. return DDERR_INVALIDPARAMS;
  475. }
  476. *ppvObj = NULL;
  477. this_lcl = this_int->lpLcl;
  478. }
  479. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  480. {
  481. DPF_ERR( "Exception encountered validating parameters" );
  482. LEAVE_DDRAW();
  483. return DDERR_INVALIDPARAMS;
  484. }
  485. /*
  486. * Is the IID one of DirectDraw's?
  487. */
  488. #ifdef POSTPONED
  489. if( IsEqualIID(riid, &IID_IUnknown) )
  490. {
  491. /*
  492. * If we are being aggregated and the QI is for IUnknown,
  493. * then we must return a non delegating interface. The only way this can
  494. * happen is if the incoming vtable points to our non delegating vtables.
  495. * In this case we can simply addref and return.
  496. * If we are not aggregated, then the QI must have the same pointer value
  497. * as any other QI for IUnknown, so we make that the ddCallbacks.
  498. */
  499. if( ( this_int->lpVtbl == &ddNonDelegatingUnknownCallbacks ) ||
  500. ( this_int->lpVtbl == &ddUninitNonDelegatingUnknownCallbacks ) )
  501. *ppvObj = (LPVOID) this_int;
  502. else
  503. *ppvObj = (LPVOID) getDDInterface( this_int->lpLcl, &ddCallbacks );
  504. }
  505. else
  506. #endif
  507. if (IsEqualIID(riid, &IID_IDirectDraw) || IsEqualIID(riid, &IID_IUnknown) )
  508. {
  509. if( ( this_int->lpVtbl == &ddCallbacks ) ||
  510. ( this_int->lpVtbl == &ddUninitCallbacks ) )
  511. *ppvObj = (LPVOID) this_int;
  512. else
  513. *ppvObj = (LPVOID) getDDInterface( this_int->lpLcl, &ddCallbacks );
  514. }
  515. else if( IsEqualIID(riid, &IID_IDirectDraw2 ) )
  516. {
  517. if( (this_int->lpVtbl == &dd2Callbacks )||
  518. ( this_int->lpVtbl == &dd2UninitCallbacks ) )
  519. *ppvObj = (LPVOID) this_int;
  520. else
  521. *ppvObj = (LPVOID) getDDInterface( this_int->lpLcl, &dd2Callbacks );
  522. }
  523. else if( IsEqualIID(riid, &IID_IDirectDraw4 ) )
  524. {
  525. if( (this_int->lpVtbl == &dd4Callbacks ) ||
  526. ( this_int->lpVtbl == &dd4UninitCallbacks ) )
  527. *ppvObj = (LPVOID) this_int;
  528. else
  529. *ppvObj = (LPVOID) getDDInterface( this_int->lpLcl, &dd4Callbacks );
  530. }
  531. else if( IsEqualIID(riid, &IID_IDirectDraw7 ) )
  532. {
  533. if( (this_int->lpVtbl == &dd7Callbacks ) ||
  534. ( this_int->lpVtbl == &dd7UninitCallbacks ) )
  535. *ppvObj = (LPVOID) this_int;
  536. else
  537. {
  538. *ppvObj = (LPVOID) getDDInterface( this_int->lpLcl, &dd7Callbacks );
  539. #ifdef WIN95
  540. if ( *ppvObj )
  541. {
  542. DDGetMonitorInfo( (LPDDRAWI_DIRECTDRAW_INT) *ppvObj );
  543. }
  544. #endif
  545. }
  546. }
  547. else if( IsEqualIID(riid, &IID_IDDVideoPortContainer ) )
  548. {
  549. if( this_int->lpVtbl == &ddVideoPortContainerCallbacks )
  550. *ppvObj = (LPVOID) this_int;
  551. else
  552. *ppvObj = getDDInterface (this_int->lpLcl, &ddVideoPortContainerCallbacks);
  553. }
  554. else if( IsEqualIID(riid, &IID_IDirectDrawKernel ) )
  555. {
  556. /*
  557. * Don't create the interface if the VDD didn't have a handle
  558. * the kernel mode interface.
  559. */
  560. if( !IsKernelInterfaceSupported( this_lcl ) )
  561. {
  562. DPF( 0, "Kernel Mode interface not supported" );
  563. LEAVE_DDRAW();
  564. return E_NOINTERFACE;
  565. }
  566. if( this_int->lpVtbl == &ddKernelCallbacks )
  567. *ppvObj = (LPVOID) this_int;
  568. else
  569. *ppvObj = getDDInterface (this_int->lpLcl, &ddKernelCallbacks);
  570. }
  571. else if( IsEqualIID(riid, &IID_IDDVideoAcceleratorContainer ) )
  572. {
  573. /*
  574. * Don't create the interface if the hardware doesn't support it
  575. */
  576. if( !IsMotionCompSupported( this_lcl ) )
  577. {
  578. DPF( 0, "Motion comp interface not supported" );
  579. LEAVE_DDRAW();
  580. return E_NOINTERFACE;
  581. }
  582. if( this_int->lpVtbl == &ddMotionCompContainerCallbacks )
  583. *ppvObj = (LPVOID) this_int;
  584. else
  585. *ppvObj = getDDInterface (this_int->lpLcl, &ddMotionCompContainerCallbacks);
  586. if( NULL == *ppvObj )
  587. {
  588. LEAVE_DDRAW();
  589. return E_NOINTERFACE;
  590. }
  591. else
  592. {
  593. DD_AddRef( *ppvObj );
  594. LEAVE_DDRAW();
  595. return DD_OK;
  596. }
  597. }
  598. else
  599. {
  600. #ifndef _IA64_
  601. #if _WIN32_WINNT >= 0x0501
  602. typedef BOOL (WINAPI *PFN_ISWOW64PROC)( HANDLE hProcess,
  603. PBOOL Wow64Process );
  604. HINSTANCE hInst = NULL;
  605. hInst = LoadLibrary( "kernel32.dll" );
  606. if( hInst )
  607. {
  608. PFN_ISWOW64PROC pfnIsWow64 = NULL;
  609. pfnIsWow64 = (PFN_ISWOW64PROC)GetProcAddress( (HMODULE)hInst, "IsWow64Process" );
  610. // We assume that if this function is not available, then it is some OS where
  611. // WOW64 does not exist (this means that pre-Release versions of XP are busted)
  612. if( pfnIsWow64 )
  613. {
  614. BOOL wow64Process;
  615. if (pfnIsWow64(GetCurrentProcess(), &wow64Process) && wow64Process)
  616. {
  617. DPF_ERR("Pre-DX8 D3D interfaces are not supported on WOW64");
  618. LEAVE_DDRAW();
  619. return E_NOINTERFACE;
  620. }
  621. }
  622. FreeLibrary( hInst );
  623. }
  624. else
  625. {
  626. DPF_ERR("LoadLibrary failed. Quitting.");
  627. LEAVE_DDRAW();
  628. return E_NOINTERFACE;
  629. }
  630. #endif // _WIN32_WINNT >= 0x0501
  631. #else // _IA64_
  632. DPF_ERR("Pre-DX8 D3D interfaces are not supported on IA64");
  633. LEAVE_DDRAW();
  634. return E_NOINTERFACE;
  635. #endif // _IA64_
  636. DPF( 4, "IID not understood by DirectDraw QueryInterface - trying Direct3D" );
  637. /*
  638. * It's not one of DirectDraw's so it might be the Direct3D
  639. * interface. So try Direct3D.
  640. */
  641. if( !D3D_INITIALIZED( this_lcl ) )
  642. {
  643. /*
  644. * No Direct3D interface yet so try and create one.
  645. */
  646. rval = InitD3D( this_int );
  647. if( FAILED( rval ) )
  648. {
  649. /*
  650. * Direct3D could not be initialized. No point trying to
  651. * query for the Direct3D interface if we could not
  652. * initialize Direct3D.
  653. *
  654. * NOTE: This assumes that DirectDraw does not aggregate
  655. * any other object type. If it does this code will need
  656. * to be revised.
  657. */
  658. LEAVE_DDRAW();
  659. return rval;
  660. }
  661. }
  662. DDASSERT( D3D_INITIALIZED( this_lcl ) );
  663. /*
  664. * We have a Direct3D interface so try the IID out on it.
  665. */
  666. DPF( 4, "Passing query off to Direct3D interface" );
  667. rval = this_lcl->pD3DIUnknown->lpVtbl->QueryInterface( this_lcl->pD3DIUnknown, riid, ppvObj );
  668. if( rval == DD_OK )
  669. {
  670. DPF( 4, "Sucessfully queried for the Direct3D interface" );
  671. LEAVE_DDRAW();
  672. return DD_OK;
  673. }
  674. }
  675. if( NULL == *ppvObj )
  676. {
  677. DPF_ERR( "IID not understood by DirectDraw" );
  678. LEAVE_DDRAW();
  679. return E_NOINTERFACE;
  680. }
  681. else
  682. {
  683. /*
  684. * Note that this casts the ppvObj to an IUnknown and then calls it.
  685. * This is better than hard-coding to call the DD_AddRef, since we
  686. * may be aggregated and so need to punt addref calls to the owning
  687. * iunknown. This will happen automatically if it's any recognized non-IUnknown
  688. * interface because they all have a delegating unknown
  689. */
  690. ((IUnknown*)( *ppvObj ))->lpVtbl->AddRef(*ppvObj);
  691. LEAVE_DDRAW();
  692. return DD_OK;
  693. }
  694. } /* DD_QueryInterface */
  695. #undef DPF_MODNAME
  696. #define DPF_MODNAME "DirectDraw::UnInitedQueryInterface"
  697. /*
  698. * DD_UnInitedQueryInterface
  699. */
  700. HRESULT DDAPI DD_UnInitedQueryInterface(
  701. LPDIRECTDRAW lpDD,
  702. REFIID riid,
  703. LPVOID FAR * ppvObj )
  704. {
  705. LPDDRAWI_DIRECTDRAW_INT this_int;
  706. ENTER_DDRAW();
  707. DPF(2,A,"ENTERAPI: DD_UnInitedQueryInterface");
  708. TRY
  709. {
  710. this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
  711. if( !VALID_DIRECTDRAW_PTR( this_int ) )
  712. {
  713. LEAVE_DDRAW();
  714. return DDERR_INVALIDOBJECT;
  715. }
  716. if( !VALID_PTR_PTR( ppvObj ) )
  717. {
  718. DPF( 1, "Invalid object ptr" );
  719. LEAVE_DDRAW();
  720. return DDERR_INVALIDPARAMS;
  721. }
  722. if( !VALIDEX_IID_PTR( riid ) )
  723. {
  724. DPF( 1, "Invalid iid ptr" );
  725. LEAVE_DDRAW();
  726. return DDERR_INVALIDPARAMS;
  727. }
  728. *ppvObj = NULL;
  729. }
  730. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  731. {
  732. DPF_ERR( "Exception encountered validating parameters" );
  733. LEAVE_DDRAW();
  734. return DDERR_INVALIDPARAMS;
  735. }
  736. /*
  737. * Is the IID one of DirectDraw's?
  738. */
  739. if( IsEqualIID(riid, &IID_IUnknown) ||
  740. IsEqualIID(riid, &IID_IDirectDraw) )
  741. {
  742. /*
  743. * Our IUnknown interface is the same as our V1
  744. * interface. We must always return the V1 interface
  745. * if IUnknown is requested.
  746. */
  747. if( ( this_int->lpVtbl == &ddCallbacks ) ||
  748. ( this_int->lpVtbl == &ddUninitCallbacks ) )
  749. *ppvObj = (LPVOID) this_int;
  750. else
  751. *ppvObj = (LPVOID) getDDInterface( this_int->lpLcl, &ddUninitCallbacks );
  752. if( NULL == *ppvObj )
  753. {
  754. LEAVE_DDRAW();
  755. return E_NOINTERFACE;
  756. }
  757. else
  758. {
  759. DD_AddRef( *ppvObj );
  760. LEAVE_DDRAW();
  761. return DD_OK;
  762. }
  763. }
  764. else if( IsEqualIID(riid, &IID_IDirectDraw2 ) )
  765. {
  766. if( (this_int->lpVtbl == &dd2Callbacks ) ||
  767. ( this_int->lpVtbl == &dd2UninitCallbacks ) )
  768. *ppvObj = (LPVOID) this_int;
  769. else
  770. *ppvObj = (LPVOID) getDDInterface( this_int->lpLcl, &dd2UninitCallbacks );
  771. if( NULL == *ppvObj )
  772. {
  773. LEAVE_DDRAW();
  774. return E_NOINTERFACE;
  775. }
  776. else
  777. {
  778. DD_AddRef( *ppvObj );
  779. LEAVE_DDRAW();
  780. return DD_OK;
  781. }
  782. }
  783. else if( IsEqualIID(riid, &IID_IDirectDraw4 ) )
  784. {
  785. if( (this_int->lpVtbl == &dd4Callbacks ) ||
  786. ( this_int->lpVtbl == &dd4UninitCallbacks ) )
  787. *ppvObj = (LPVOID) this_int;
  788. else
  789. *ppvObj = (LPVOID) getDDInterface( this_int->lpLcl, &dd4UninitCallbacks );
  790. if( NULL == *ppvObj )
  791. {
  792. LEAVE_DDRAW();
  793. return E_NOINTERFACE;
  794. }
  795. else
  796. {
  797. DD_AddRef( *ppvObj );
  798. LEAVE_DDRAW();
  799. return DD_OK;
  800. }
  801. }
  802. else if( IsEqualIID(riid, &IID_IDirectDraw7 ) )
  803. {
  804. if( (this_int->lpVtbl == &dd7Callbacks ) ||
  805. ( this_int->lpVtbl == &dd7UninitCallbacks ) )
  806. *ppvObj = (LPVOID) this_int;
  807. else
  808. *ppvObj = (LPVOID) getDDInterface( this_int->lpLcl, &dd7UninitCallbacks );
  809. if( NULL == *ppvObj )
  810. {
  811. LEAVE_DDRAW();
  812. return E_NOINTERFACE;
  813. }
  814. else
  815. {
  816. DD_AddRef( *ppvObj );
  817. LEAVE_DDRAW();
  818. return DD_OK;
  819. }
  820. }
  821. DPF( 2, "IID not understood by uninitialized DirectDraw QueryInterface" );
  822. LEAVE_DDRAW();
  823. return E_NOINTERFACE;
  824. } /* DD_UnInitedQueryInterface */
  825. #undef DPF_MODNAME
  826. #define DPF_MODNAME "DirectDraw::AddRef"
  827. /*
  828. * DD_AddRef
  829. */
  830. DWORD DDAPI DD_AddRef( LPDIRECTDRAW lpDD )
  831. {
  832. LPDDRAWI_DIRECTDRAW_INT this_int;
  833. LPDDRAWI_DIRECTDRAW_LCL this_lcl;
  834. LPDDRAWI_DIRECTDRAW_GBL this;
  835. ENTER_DDRAW();
  836. DPF(2,A,"ENTERAPI: DD_AddRef");
  837. /* DPF( 2, "DD_AddRef, pid=%08lx, obj=%08lx", GETCURRPID(), lpDD ); */
  838. TRY
  839. {
  840. this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
  841. if( !VALID_DIRECTDRAW_PTR( this_int ) )
  842. {
  843. LEAVE_DDRAW();
  844. return 0;
  845. }
  846. this_lcl = this_int->lpLcl;
  847. this = this_lcl->lpGbl;
  848. }
  849. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  850. {
  851. DPF_ERR( "Exception encountered validating parameters" );
  852. LEAVE_DDRAW();
  853. return 0;
  854. }
  855. /*
  856. * bump refcnt
  857. */
  858. if( this != NULL )
  859. {
  860. this->dwRefCnt++;
  861. }
  862. this_lcl->dwLocalRefCnt++;
  863. this_int->dwIntRefCnt++;
  864. #ifdef DEBUG
  865. if( this == NULL )
  866. {
  867. DPF( 5, "DD_AddRef, Reference Count: Global Undefined Local = %ld Int = %ld",
  868. this_lcl->dwLocalRefCnt, this_int->dwIntRefCnt );
  869. }
  870. else
  871. {
  872. DPF( 5, "DD_AddRef, Reference Count: Global = %ld Local = %ld Int = %ld",
  873. this->dwRefCnt, this_lcl->dwLocalRefCnt, this_int->dwIntRefCnt );
  874. }
  875. #endif
  876. LEAVE_DDRAW();
  877. return this_int->dwIntRefCnt;
  878. } /* DD_AddRef */
  879. #ifdef WIN95
  880. #define MMDEVLDR_IOCTL_CLOSEVXDHANDLE 6
  881. /*
  882. * closeVxDHandle
  883. */
  884. static void closeVxDHandle( DWORD dwHandle )
  885. {
  886. HANDLE hFile;
  887. hFile = CreateFile(
  888. "\\\\.\\MMDEVLDR.VXD",
  889. GENERIC_WRITE,
  890. FILE_SHARE_WRITE,
  891. NULL,
  892. OPEN_ALWAYS,
  893. FILE_ATTRIBUTE_NORMAL | FILE_FLAG_GLOBAL_HANDLE,
  894. NULL);
  895. if( hFile == INVALID_HANDLE_VALUE )
  896. {
  897. return;
  898. }
  899. DeviceIoControl( hFile,
  900. MMDEVLDR_IOCTL_CLOSEVXDHANDLE,
  901. NULL,
  902. 0,
  903. &dwHandle,
  904. sizeof(dwHandle),
  905. NULL,
  906. NULL);
  907. CloseHandle( hFile );
  908. DPF( 5, "closeVxdHandle( %08lx ) done", dwHandle );
  909. } /* closeVxDHandle */
  910. #endif
  911. #if 0
  912. /*
  913. * This function calls d3dim700.dll to clean up any driver state that may be stored per-ddrawlocal
  914. */
  915. void CleanUpD3DPerLocal(LPDDRAWI_DIRECTDRAW_LCL this_lcl)
  916. {
  917. HINSTANCE hInstance=0;
  918. /*
  919. * Call d3d for per-local cleanup. We only call d3dim7.
  920. * For safety, we'll just load a new copy of the DLL whether or not we're on ddhelp's PID
  921. */
  922. hInstance = LoadLibrary( D3DDX7_DLLNAME );
  923. if (hInstance)
  924. {
  925. FreeLibrary(hInstance);
  926. }
  927. }
  928. #endif
  929. /*
  930. * DD_Release
  931. *
  932. * Once the globalreference count reaches 0, all surfaces are freed and all
  933. * video memory heaps are destroyed.
  934. */
  935. DWORD DDAPI DD_Release( LPDIRECTDRAW lpDD )
  936. {
  937. LPDDRAWI_DIRECTDRAW_INT this_int;
  938. LPDDRAWI_DIRECTDRAW_LCL this_lcl;
  939. LPDDRAWI_DIRECTDRAW_GBL this;
  940. LPDDRAWI_DDRAWSURFACE_INT psurf_int;
  941. LPDDRAWI_DDRAWPALETTE_INT ppal_int;
  942. LPDDRAWI_DDVIDEOPORT_INT pvport_int;
  943. DWORD rc;
  944. DWORD refcnt;
  945. DWORD intrefcnt;
  946. DWORD lclrefcnt;
  947. DWORD gblrefcnt;
  948. int i;
  949. DDHAL_DESTROYDRIVERDATA dddd;
  950. DWORD pid;
  951. HANDLE hinst;
  952. HANDLE hvxd;
  953. #ifdef WIN95
  954. DWORD event16;
  955. DWORD eventDOSBox;
  956. HANDLE hthisvxd;
  957. #endif
  958. #ifdef WINNT
  959. LPATTACHED_PROCESSES lpap;
  960. #endif
  961. ENTER_DDRAW();
  962. pid = GETCURRPID();
  963. DPF(2,A,"ENTERAPI: DD_Release");
  964. /* DPF( 2, "DD_Release, pid=%08lx, obj=%08lx", pid, lpDD ); */
  965. TRY
  966. {
  967. this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
  968. if( !VALID_DIRECTDRAW_PTR( this_int ) )
  969. {
  970. LEAVE_DDRAW();
  971. return 0;
  972. }
  973. if ( this_int->dwIntRefCnt == 0 )
  974. {
  975. DPF_ERR( "DDraw Interface pointer has 0 ref count! Interface has been over-released.");
  976. LEAVE_DDRAW();
  977. return 0;
  978. }
  979. this_lcl = this_int->lpLcl;
  980. this = this_lcl->lpGbl;
  981. }
  982. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  983. {
  984. DPF_ERR( "Exception encountered validating parameters" );
  985. LEAVE_DDRAW();
  986. return 0;
  987. }
  988. /*
  989. * decrement process reference count
  990. */
  991. this_int->dwIntRefCnt--;
  992. intrefcnt = this_int->dwIntRefCnt;
  993. this_lcl->dwLocalRefCnt--;
  994. lclrefcnt = this_lcl->dwLocalRefCnt;
  995. if( this != NULL )
  996. {
  997. this->dwRefCnt--;
  998. gblrefcnt = this->dwRefCnt;
  999. }
  1000. else
  1001. {
  1002. gblrefcnt = (DWORD) -1;
  1003. }
  1004. DPF( 5, "DD_Release, Ref Count: Global = %ld Local = %ld Interface = %ld",
  1005. gblrefcnt, lclrefcnt, intrefcnt );
  1006. /*
  1007. * if the global refcnt is zero, free the driver object
  1008. * note that the local object must not be freed yet because
  1009. * we need to use the HAL callback tables
  1010. */
  1011. hinst = NULL;
  1012. #ifdef WIN95
  1013. event16 = 0;
  1014. eventDOSBox = 0;
  1015. hthisvxd = INVALID_HANDLE_VALUE;
  1016. #endif
  1017. /*
  1018. * if local object is freed, for the owning process we:
  1019. * - cleanup palettes, clippers & surfaces
  1020. * - restore display mode
  1021. * - release exclusive mode
  1022. * - find the DC used by the process
  1023. */
  1024. if( lclrefcnt == 0 )
  1025. {
  1026. #ifdef TIMING
  1027. // Printing timing information
  1028. TimerDump();
  1029. #endif
  1030. /*
  1031. * see if the hwnd was hooked, if so, undo it!
  1032. */
  1033. if( this_lcl->dwLocalFlags & DDRAWILCL_HOOKEDHWND )
  1034. {
  1035. SetAppHWnd( this_lcl, NULL, 0 );
  1036. this_lcl->dwLocalFlags &= ~DDRAWILCL_HOOKEDHWND;
  1037. }
  1038. //
  1039. // Do not call CleanUpD3DPerLocal because it does a LoadLibrary on
  1040. // d3dim700.dll and is currently unnecessary. The LoadLibrary can
  1041. // cause problems when opengl32.dll is detaching from a process
  1042. // because they call DD_Release. Since ddraw.dll is statically linked
  1043. // to opengl32.dll, it may be marked to be unloaded when opengl32.dll
  1044. // is, and the load of d3dim700.dll here can cause ddraw.dll to be
  1045. // reloaded at a different address, in this case, before the first
  1046. // instance of ddraw.dll has been freed.
  1047. //
  1048. //CleanUpD3DPerLocal(this_lcl);
  1049. if( GetCurrentProcessId() == GETCURRPID() )
  1050. {
  1051. /*
  1052. * If we have created the Direct3D IUnknown release it now.
  1053. * NOTE: The life of an aggregated object is the same as that
  1054. * of its owning interface so we can also free the DLL at
  1055. * this point.
  1056. * NOTE: We must free the library AFTER ProcessSurfaceCleanup
  1057. * as it can invoke D3D members to clean up device and texture
  1058. * surfaces.
  1059. */
  1060. if( this_lcl->pD3DIUnknown != NULL )
  1061. {
  1062. DPF(4, "Releasing Direct3D IUnknown");
  1063. this_lcl->pD3DIUnknown->lpVtbl->Release( this_lcl->pD3DIUnknown );
  1064. /*
  1065. * Actually, this FreeLibrary will kill the process if the app
  1066. * did the final release of d3d after the final release of ddraw.
  1067. * The d3d release will punt to the owning IUnknown (us) and we
  1068. * will decrement ref count to zero and free the d3d DLL then
  1069. * return to the caller. The caller was IDirect3D::Release within
  1070. * the d3d DLL, so we would free the code that called us.
  1071. * For DX5 we will take out this FreeLibrary to fix the shutdown
  1072. * problem, but we should probably find something better for DX6 etc.
  1073. */
  1074. //FreeLibrary( this_lcl->hD3DInstance );
  1075. this_lcl->pD3DIUnknown = NULL;
  1076. this_lcl->hD3DInstance = NULL;
  1077. }
  1078. }
  1079. if( this != NULL )
  1080. {
  1081. BOOL excl_exists,has_excl;
  1082. /*
  1083. * punt process from any surfaces and palettes
  1084. */
  1085. FreeD3DSurfaceIUnknowns( this, pid, this_lcl );
  1086. ProcessSurfaceCleanup( this, pid, this_lcl );
  1087. ProcessPaletteCleanup( this, pid, this_lcl );
  1088. ProcessClipperCleanup( this, pid, this_lcl );
  1089. ProcessVideoPortCleanup( this, pid, this_lcl );
  1090. ProcessMotionCompCleanup( this, pid, this_lcl );
  1091. #ifdef WIN95
  1092. if (this_lcl->lpDDCB && this_lcl->lpDDCB->HALDDMiscellaneous2.DestroyDDLocal)
  1093. {
  1094. DWORD dwRet = DDHAL_DRIVER_NOTHANDLED;
  1095. DDHAL_DESTROYDDLOCALDATA destDDLcl;
  1096. destDDLcl.dwFlags = 0;
  1097. destDDLcl.pDDLcl = this_lcl;
  1098. ENTER_WIN16LOCK();
  1099. dwRet = this_lcl->lpDDCB->HALDDMiscellaneous2.DestroyDDLocal(&destDDLcl);
  1100. LEAVE_WIN16LOCK();
  1101. if (dwRet == DDHAL_DRIVER_NOTHANDLED)
  1102. {
  1103. DPF(0, "DD_Release: failed DestroyDDLocal");
  1104. }
  1105. }
  1106. #endif
  1107. /*
  1108. * reset the display mode if needed
  1109. * and only if we are doing the v1 SetCooperativeLevel behaviour
  1110. */
  1111. CheckExclusiveMode(this_lcl, &excl_exists, &has_excl, FALSE, NULL, FALSE);
  1112. if( this_lcl->dwLocalFlags & DDRAWILCL_V1SCLBEHAVIOUR)
  1113. {
  1114. if( (gblrefcnt == 0) ||
  1115. (!excl_exists) ||
  1116. (has_excl ) )
  1117. {
  1118. RestoreDisplayMode( this_lcl, TRUE );
  1119. }
  1120. }
  1121. else
  1122. {
  1123. /*
  1124. * Even in V2 or later, we want to restore the display
  1125. * mode for a non exclusive app. Exclusive mode apps
  1126. * will restore their mode in DoneExclusiveMode
  1127. */
  1128. if(!excl_exists)
  1129. {
  1130. RestoreDisplayMode( this_lcl, TRUE );
  1131. }
  1132. }
  1133. /*
  1134. * exclusive mode held by this process? if so, release it
  1135. */
  1136. if( has_excl )
  1137. {
  1138. DoneExclusiveMode( this_lcl );
  1139. }
  1140. #ifdef WIN95
  1141. /*
  1142. * We don't close the VXD handle just yet as we may need it
  1143. * to release virtual memory aliases if the global object
  1144. * is dying. Just remember that we need to free it for now.
  1145. */
  1146. hthisvxd = (HANDLE) this_lcl->hDDVxd;
  1147. /*
  1148. * Get a VXD handle we can use to communicate with the DirectX vxd.
  1149. * Please note that this code can be executed in the context of
  1150. * the processes which created the local object or DDHELP's if an
  1151. * application is shutting down without cleaning up. Therefore we
  1152. * can't just use the VXD handle stored in the local object as that
  1153. * my belong to a dead process (and hence be an invalid handle in
  1154. * the current process). Therefore, we need to detect whether we
  1155. * are being executed by DDHELP or an application process and
  1156. * choose a vxad handle appropriately. This is the destinction
  1157. * between hthisvxd which is the VXD handle stored in the local
  1158. * object and hvxd which is the VXD handle we can actually use
  1159. * to talk to the VXD.
  1160. */
  1161. hvxd = ( ( GetCurrentProcessId() != GETCURRPID() ) ? hHelperDDVxd : hthisvxd );
  1162. DDASSERT( INVALID_HANDLE_VALUE != hvxd );
  1163. #else /* WIN95 */
  1164. /*
  1165. * Handle is not used on NT. Just pass NULL.
  1166. */
  1167. hvxd = INVALID_HANDLE_VALUE;
  1168. #endif /* WIN95 */
  1169. /*
  1170. * If we created a device window ourselves, destroy it now
  1171. */
  1172. if( ( this_lcl->dwLocalFlags & DDRAWILCL_CREATEDWINDOW ) &&
  1173. IsWindow( (HWND) this_lcl->hWnd ) )
  1174. {
  1175. DestroyWindow( (HWND) this_lcl->hWnd );
  1176. this_lcl->hWnd = 0;
  1177. this_lcl->dwLocalFlags &= ~DDRAWILCL_CREATEDWINDOW;
  1178. }
  1179. /*
  1180. * If we previously loaded a gamma calibrator, unload it now.
  1181. */
  1182. if( this_lcl->hGammaCalibrator != (ULONG_PTR)INVALID_HANDLE_VALUE )
  1183. {
  1184. /*
  1185. * If we are on the helper thread, we don't need to unload the
  1186. * calibrator because it's already gone.
  1187. */
  1188. if( GetCurrentProcessId() == GETCURRPID() )
  1189. {
  1190. FreeLibrary( (HMODULE)this_lcl->hGammaCalibrator );
  1191. }
  1192. this_lcl->hGammaCalibrator = (ULONG_PTR) INVALID_HANDLE_VALUE;
  1193. }
  1194. /*
  1195. * If a mode test was started, but not finished, release the
  1196. * memory now.
  1197. */
  1198. if( this_lcl->lpModeTestContext )
  1199. {
  1200. MemFree( this_lcl->lpModeTestContext->lpModeList );
  1201. MemFree( this_lcl->lpModeTestContext );
  1202. this_lcl->lpModeTestContext = NULL;
  1203. }
  1204. /*
  1205. * The palette handle bitfield
  1206. */
  1207. MemFree(this_lcl->pPaletteHandleUsedBitfield);
  1208. this_lcl->pPaletteHandleUsedBitfield = 0;
  1209. }
  1210. }
  1211. /*
  1212. * Note the local object is freed after the global...
  1213. */
  1214. if( gblrefcnt == 0 )
  1215. {
  1216. DPF( 4, "FREEING DRIVER OBJECT" );
  1217. /*
  1218. * Notify driver.
  1219. */
  1220. dddd.lpDD = this;
  1221. if((this->dwFlags & DDRAWI_EMULATIONINITIALIZED) &&
  1222. (this_lcl->lpDDCB->HELDD.DestroyDriver != NULL))
  1223. {
  1224. /*
  1225. * if the HEL was initialized, make sure we call the HEL
  1226. * DestroyDriver function so it can clean up.
  1227. */
  1228. DPF( 4, "Calling HEL DestroyDriver" );
  1229. dddd.DestroyDriver = NULL;
  1230. /*
  1231. * we don't really care about the return value of this call
  1232. */
  1233. rc = this_lcl->lpDDCB->HELDD.DestroyDriver( &dddd );
  1234. }
  1235. // Note that in a multimon system, a driver that is not attached to the
  1236. // desktop is destroyed by GDI at termination of the process that uses
  1237. // the driver. In this case, Ddhelp cleanup must not try to destroy the
  1238. // driver again or it will cause a GP fault.
  1239. if( (this_lcl->lpDDCB->cbDDCallbacks.DestroyDriver != NULL) &&
  1240. ((this->dwFlags & DDRAWI_ATTACHEDTODESKTOP) ||
  1241. (dwGrimReaperPid != GetCurrentProcessId())))
  1242. {
  1243. dddd.DestroyDriver = this_lcl->lpDDCB->cbDDCallbacks.DestroyDriver;
  1244. DPF( 4, "Calling DestroyDriver" );
  1245. rc = this_lcl->lpDDCB->HALDD.DestroyDriver( &dddd );
  1246. if( rc == DDHAL_DRIVER_HANDLED )
  1247. {
  1248. // Ignore any failure since there's no way to report a failure to
  1249. // the app and exiting now would leave a half initialized interface
  1250. // in the DriverObjectList
  1251. DPF( 5, "DDHAL_DestroyDriver: ddrval = %ld", dddd.ddRVal );
  1252. }
  1253. }
  1254. /*
  1255. * release all surfaces
  1256. */
  1257. psurf_int = this->dsList;
  1258. while( psurf_int != NULL )
  1259. {
  1260. LPDDRAWI_DDRAWSURFACE_INT next_int;
  1261. refcnt = psurf_int->dwIntRefCnt;
  1262. next_int = psurf_int->lpLink;
  1263. while( refcnt > 0 )
  1264. {
  1265. DD_Surface_Release( (LPDIRECTDRAWSURFACE) psurf_int );
  1266. refcnt--;
  1267. }
  1268. psurf_int = next_int;
  1269. }
  1270. /*
  1271. * release all palettes
  1272. */
  1273. ppal_int = this->palList;
  1274. while( ppal_int != NULL )
  1275. {
  1276. LPDDRAWI_DDRAWPALETTE_INT next_int;
  1277. refcnt = ppal_int->dwIntRefCnt;
  1278. next_int = ppal_int->lpLink;
  1279. while( refcnt > 0 )
  1280. {
  1281. DD_Palette_Release( (LPDIRECTDRAWPALETTE) ppal_int );
  1282. refcnt--;
  1283. }
  1284. ppal_int = next_int;
  1285. }
  1286. /*
  1287. * release all videoports
  1288. */
  1289. pvport_int = this->dvpList;
  1290. while( pvport_int != NULL )
  1291. {
  1292. LPDDRAWI_DDVIDEOPORT_INT next_int;
  1293. refcnt = pvport_int->dwIntRefCnt;
  1294. next_int = pvport_int->lpLink;
  1295. while( refcnt > 0 )
  1296. {
  1297. DD_VP_Release( (LPDIRECTDRAWVIDEOPORT) pvport_int );
  1298. refcnt--;
  1299. }
  1300. pvport_int = next_int;
  1301. }
  1302. #ifdef WINNT
  1303. /*
  1304. * The driver needs to know to free its internal state
  1305. */
  1306. // Update DDraw handle in driver GBL object.
  1307. this->hDD = this_lcl->hDD;
  1308. DdDeleteDirectDrawObject(this);
  1309. lpap = lpAttachedProcesses;
  1310. while( lpap != NULL )
  1311. {
  1312. if( lpap->dwPid == pid )
  1313. lpap->dwNTToldYet = 0;
  1314. lpap = lpap->lpLink;
  1315. }
  1316. #endif
  1317. #ifdef USE_ALIAS
  1318. /*
  1319. * If this local object has heap aliases release them now.
  1320. * NOTE: This really should release the heap aliases as by
  1321. * this point all the surfaces should have gone.
  1322. */
  1323. if( NULL != this->phaiHeapAliases )
  1324. {
  1325. DDASSERT( 1UL == this->phaiHeapAliases->dwRefCnt );
  1326. /*
  1327. * Need to decide which VXD handle to use. If we are executing
  1328. * on a DDHELP thread use the helper's VXD handle.
  1329. */
  1330. ReleaseHeapAliases( hvxd, this->phaiHeapAliases );
  1331. }
  1332. #endif /* USE_ALIAS */
  1333. /*
  1334. * Notify the kernel mode interface that we are done using it
  1335. */
  1336. ReleaseKernelInterface( this_lcl );
  1337. #ifndef WINNT
  1338. /*
  1339. * free all video memory heaps
  1340. */
  1341. for( i=0;i<(int)this->vmiData.dwNumHeaps;i++ )
  1342. {
  1343. LPVIDMEM pvm;
  1344. pvm = &this->vmiData.pvmList[i];
  1345. HeapVidMemFini( pvm, hvxd );
  1346. }
  1347. #endif //not WINNT
  1348. /*
  1349. * free extra tables
  1350. */
  1351. MemFree( this->lpdwFourCC );
  1352. MemFree( this->vmiData.pvmList );
  1353. #ifndef WINNT
  1354. //On NT, lpModeInfo points to a contained member of "this"
  1355. MemFree( this->lpModeInfo );
  1356. #endif
  1357. MemFree( this->lpDDVideoPortCaps );
  1358. MemFree( this->lpDDKernelCaps );
  1359. MemFree( (LPVOID) this->lpD3DHALCallbacks2 );
  1360. MemFree( (LPVOID) this->lpD3DHALCallbacks3);
  1361. MemFree( (LPVOID) this->lpD3DExtendedCaps );
  1362. MemFree( this->lpddNLVCaps );
  1363. MemFree( this->lpddNLVHELCaps );
  1364. MemFree( this->lpddNLVBothCaps );
  1365. #ifdef WINNT
  1366. if ( this->lpD3DGlobalDriverData )
  1367. MemFree( this->lpD3DGlobalDriverData->lpTextureFormats );
  1368. // The lpD3DGlobalDriverData, lpD3DHALCallbacks and EXEBUF structs
  1369. // are allocated in one chunk in ddcreate.c
  1370. MemFree( (void *)this->lpD3DHALCallbacks );
  1371. if (NULL != this->SurfaceHandleList.dwList)
  1372. {
  1373. MemFree(this->SurfaceHandleList.dwList);
  1374. }
  1375. #endif
  1376. MemFree(this->lpZPixelFormats);
  1377. MemFree(this->lpddMoreCaps);
  1378. MemFree(this->lpddHELMoreCaps);
  1379. MemFree(this->lpddBothMoreCaps);
  1380. MemFree( this->lpMonitorInfo );
  1381. #ifdef POSTPONED
  1382. MemFree((LPVOID) this->lpDDUmodeDrvInfo);
  1383. MemFree((LPVOID) this->lpDDOptSurfaceInfo);
  1384. #endif
  1385. #ifdef WIN95
  1386. DD16_DoneDriver( this->hInstance );
  1387. event16 = this->dwEvent16;
  1388. eventDOSBox = this->dwDOSBoxEvent;
  1389. #endif
  1390. hinst = (HANDLE) ULongToPtr(this->hInstance);
  1391. /*
  1392. * The DDHAL_CALLBACKS structure tacked onto the end of the
  1393. * global object is also automatically freed here because it
  1394. * was allocated with the global object in a single malloc
  1395. */
  1396. MemFree( this );
  1397. DPF( 4, "Driver is now FREE" );
  1398. }
  1399. if( lclrefcnt == 0 )
  1400. {
  1401. #ifdef WIN95
  1402. /*
  1403. * We are now finished with the local object's VXD handle. However
  1404. * we don't discard it if we are running in DDHELP's context as, in
  1405. * that case, the handle has been freed by the operating system
  1406. * and closing it would be possitively dangerous.
  1407. */
  1408. if( ( GetCurrentProcessId() == GETCURRPID() ) && this )
  1409. {
  1410. DDASSERT( INVALID_HANDLE_VALUE != hthisvxd );
  1411. CloseHandle( hthisvxd );
  1412. }
  1413. #endif /* WIN95 */
  1414. /*
  1415. * only free DC's if we aren't running on DDHELP's context
  1416. */
  1417. if( (GetCurrentProcessId() == GETCURRPID()) && ((HDC)this_lcl->hDC != NULL) )
  1418. {
  1419. LPDDRAWI_DIRECTDRAW_LCL ddlcl;
  1420. // If there are other local objects in this process,
  1421. // wait to delete the hdc until the last object is
  1422. // deleted.
  1423. for( ddlcl=lpDriverLocalList; ddlcl != NULL; ddlcl = ddlcl->lpLink)
  1424. {
  1425. if( (ddlcl != this_lcl) && (ddlcl->hDC == this_lcl->hDC) )
  1426. break;
  1427. }
  1428. if( ddlcl == NULL )
  1429. {
  1430. WORD fPriv;
  1431. #ifdef WIN95
  1432. // We need to unmark it as private now so
  1433. // that the delete will succeed
  1434. fPriv = DD16_MakeObjectPrivate((HDC)this_lcl->hDC, FALSE);
  1435. DDASSERT(fPriv == TRUE);
  1436. /*
  1437. * The following assert will fail occasionally inside
  1438. * GetObjectType. I mean crash. Don't understand. We
  1439. * should put the assert back in for 5a and see if it blows
  1440. * on our machines.
  1441. */
  1442. //DDASSERT(GetObjectType((HDC)this_lcl->hDC) == OBJ_DC);
  1443. #endif
  1444. DeleteDC( (HDC)this_lcl->hDC );
  1445. }
  1446. }
  1447. #ifdef WIN95
  1448. if (NULL != this_lcl->SurfaceHandleList.dwList)
  1449. {
  1450. MemFree(this_lcl->SurfaceHandleList.dwList);
  1451. }
  1452. #endif //WIN95
  1453. /*
  1454. * delete this local object from the master list
  1455. */
  1456. RemoveLocalFromList( this_lcl );
  1457. // Free the local object (finally)!
  1458. MemFree( this_lcl );
  1459. }
  1460. #ifdef WIN95
  1461. if( event16 != 0 )
  1462. {
  1463. closeVxDHandle( event16 );
  1464. }
  1465. if( eventDOSBox != 0 )
  1466. {
  1467. closeVxDHandle( eventDOSBox );
  1468. }
  1469. #endif
  1470. /*
  1471. * if interface is freed, we reset the vtbl and remove it
  1472. * from the list of drivers.
  1473. */
  1474. if( intrefcnt == 0 )
  1475. {
  1476. /*
  1477. * delete this driver object from the master list
  1478. */
  1479. RemoveDriverFromList( this_int, gblrefcnt == 0 );
  1480. /*
  1481. * just in case someone comes back in with this pointer, set
  1482. * an invalid vtbl.
  1483. */
  1484. this_int->lpVtbl = NULL;
  1485. MemFree( this_int );
  1486. }
  1487. LEAVE_DDRAW();
  1488. #ifndef WINNT
  1489. if( hinst != NULL )
  1490. {
  1491. HelperKillModeSetThread( (DWORD) hinst );
  1492. HelperKillDOSBoxThread( (DWORD) hinst );
  1493. }
  1494. #endif //!WINNT
  1495. HIDESHOW_IME(); //Show/hide the IME OUTSIDE of the ddraw critsect.
  1496. return intrefcnt;
  1497. } /* DD_Release */