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.

1809 lines
45 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1995 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: ddclip.c
  6. * Content: DirectDraw clipper functions
  7. *
  8. * NOTE:
  9. * For functions that manipulate the winwatch list,
  10. * we need to take the win16 lock after we take the directdraw
  11. * lock. The reason for this is that we can get an async
  12. * call from the 16-bit side when a window is closed
  13. * to release winwatch object. Since the win16 lock is held
  14. * when the callup occurs, this makes it safe to manipulate
  15. * the structures.
  16. *
  17. * History:
  18. * Date By Reason
  19. * ==== == ======
  20. * 21-jun-95 craige initial implementation
  21. * 23-jun-95 craige connect with winwatch stuff
  22. * 25-jun-95 craige minor bug fix; one ddraw mutex
  23. * 26-jun-95 craige reorganized surface structure
  24. * 28-jun-95 craige ENTER_DDRAW at very start of fns
  25. * 02-jul-95 craige commented out clipper notification stuff
  26. * 03-jul-95 craige YEEHAW: new driver struct; SEH
  27. * 05-jul-95 craige added Initialize
  28. * 11-jul-95 craige fail aggregation calls
  29. * 13-jul-95 craige ENTER_DDRAW is now the win16 lock
  30. * 31-jul-95 craige validate flags
  31. * 05-aug-95 craige bug 260 - clip user defined rgn to screen
  32. * 09-dec-95 colinmc added execute buffer support
  33. * 15-dec-95 colinmc made clippers sharable across surfaces
  34. * 19-dec-95 kylej added NT cliplist support
  35. * 02-jan-96 kylej handle new interface structs.
  36. * 17-jan-96 kylej fixed NT vis region bug
  37. * 22-feb-96 colinmc clippers no longer need to be associated with a
  38. * DirectDraw object - they can be created independently.
  39. * 03-mar-96 colinmc fixed problem with QueryInterface returning local
  40. * object rather than interface
  41. * 13-mar-96 colinmc added IID validation to QueryInterface.
  42. * 14-mar-96 colinmc added class factory support
  43. * 18-mar-96 colinmc Bug 13545: Independent clipper cleanup
  44. * 21-mar-96 colinmc Bug 13316: Unitialized interfaces
  45. * 09-apr-96 colinmc Bug 13991: Parameter validation on IsClipListChanged
  46. * 26-mar-96 jeffno Watched HWNDs under NT
  47. * 20-sep-96 ketand GetClipList optimization
  48. * 21-jan-96 ketand Deleted unused WinWatch code. Fixed clipping for multi-mon.
  49. * 07-feb-96 ketand bug5673: fix clipping when VisRgn is larger than ClientRect
  50. * 24-mar-97 jeffno Optimized Surfaces
  51. * 05-nov-97 jvanaken Support for master sprite list in SetSpriteDisplayList
  52. *
  53. ***************************************************************************/
  54. #include "ddrawpr.h"
  55. #ifdef WINNT
  56. #include "ddrawgdi.h"
  57. #endif
  58. // function in ddsprite.c to remove invalid clipper from master sprite list
  59. extern void RemoveSpriteClipper(LPDDRAWI_DIRECTDRAW_GBL, LPDDRAWI_DDRAWCLIPPER_INT);
  60. /*
  61. * GLOBAL NOTE: You will notice that these functions usually fetch the
  62. * DirectDraw global object pointer from the global clipper object during
  63. * parameter validation. You may wonder why this is given that clippers
  64. * are pretty much completely independent of drivers. Well, this is purely
  65. * for parameter validation purposes. We just want to ensure that we can
  66. * dereference the clipper global object - we could use any parameter.
  67. * So don't remove this code when you notice its not used. It serves
  68. * a purpose.
  69. * Probably should wrap this stuff up in a nice macro.
  70. */
  71. #undef DPF_MODNAME
  72. #define DPF_MODNAME "DirectDraw::DD_UnInitedClipperQueryInterface"
  73. /*
  74. * DD_UnInitedClipperQueryInterface
  75. */
  76. HRESULT DDAPI DD_UnInitedClipperQueryInterface(
  77. LPDIRECTDRAWCLIPPER lpDDClipper,
  78. REFIID riid,
  79. LPVOID FAR * ppvObj )
  80. {
  81. LPDDRAWI_DDRAWCLIPPER_GBL this;
  82. LPDDRAWI_DDRAWCLIPPER_LCL this_lcl;
  83. LPDDRAWI_DDRAWCLIPPER_INT this_int;
  84. ENTER_DDRAW();
  85. DPF(2,A,"ENTERAPI: DD_UnInitedClipperQueryInterface");
  86. /*
  87. * validate parms
  88. */
  89. TRY
  90. {
  91. this_int = (LPDDRAWI_DDRAWCLIPPER_INT) lpDDClipper;
  92. if( !VALID_DIRECTDRAWCLIPPER_PTR( this_int ) )
  93. {
  94. LEAVE_DDRAW();
  95. return DDERR_INVALIDOBJECT;
  96. }
  97. this_lcl = this_int->lpLcl;
  98. if( !VALID_PTR_PTR( ppvObj ) )
  99. {
  100. DPF( 1, "Invalid clipper pointer" );
  101. LEAVE_DDRAW();
  102. return (DWORD) DDERR_INVALIDPARAMS;
  103. }
  104. if( !VALIDEX_IID_PTR( riid ) )
  105. {
  106. DPF_ERR( "Invalid IID pointer" );
  107. LEAVE_DDRAW();
  108. return (DWORD) DDERR_INVALIDPARAMS;
  109. }
  110. *ppvObj = NULL;
  111. this = this_lcl->lpGbl;
  112. }
  113. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  114. {
  115. DPF_ERR( "Exception encountered validating parameters" );
  116. LEAVE_DDRAW();
  117. return DDERR_INVALIDPARAMS;
  118. }
  119. /*
  120. * check guids
  121. */
  122. if( IsEqualIID(riid, &IID_IUnknown) ||
  123. IsEqualIID(riid, &IID_IDirectDrawClipper) )
  124. {
  125. DD_Clipper_AddRef( lpDDClipper );
  126. *ppvObj = (LPVOID) this_int;
  127. LEAVE_DDRAW();
  128. return DD_OK;
  129. }
  130. LEAVE_DDRAW();
  131. return E_NOINTERFACE;
  132. } /* DD_UnInitedClipperQueryInterface */
  133. #undef DPF_MODNAME
  134. #define DPF_MODNAME "Clipper::QueryInterface"
  135. /*
  136. * DD_Clipper_QueryInterface
  137. */
  138. HRESULT DDAPI DD_Clipper_QueryInterface(
  139. LPDIRECTDRAWCLIPPER lpDDClipper,
  140. REFIID riid,
  141. LPVOID FAR * ppvObj )
  142. {
  143. LPDDRAWI_DDRAWCLIPPER_GBL this;
  144. LPDDRAWI_DDRAWCLIPPER_LCL this_lcl;
  145. LPDDRAWI_DDRAWCLIPPER_INT this_int;
  146. ENTER_DDRAW();
  147. DPF(2,A,"ENTERAPI: DD_Clipper_QueryInterface");
  148. /*
  149. * validate parms
  150. */
  151. TRY
  152. {
  153. this_int = (LPDDRAWI_DDRAWCLIPPER_INT) lpDDClipper;
  154. if( !VALID_DIRECTDRAWCLIPPER_PTR( this_int ) )
  155. {
  156. LEAVE_DDRAW();
  157. return DDERR_INVALIDOBJECT;
  158. }
  159. this_lcl = this_int->lpLcl;
  160. if( !VALID_PTR_PTR( ppvObj ) )
  161. {
  162. DPF( 1, "Invalid clipper pointer" );
  163. LEAVE_DDRAW();
  164. return (DWORD) DDERR_INVALIDPARAMS;
  165. }
  166. if( !VALIDEX_IID_PTR( riid ) )
  167. {
  168. DPF_ERR( "Invalid IID pointer" );
  169. LEAVE_DDRAW();
  170. return (DWORD) DDERR_INVALIDPARAMS;
  171. }
  172. *ppvObj = NULL;
  173. this = this_lcl->lpGbl;
  174. }
  175. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  176. {
  177. DPF_ERR( "Exception encountered validating parameters" );
  178. LEAVE_DDRAW();
  179. return DDERR_INVALIDPARAMS;
  180. }
  181. /*
  182. * check guids
  183. */
  184. if( IsEqualIID(riid, &IID_IUnknown) ||
  185. IsEqualIID(riid, &IID_IDirectDrawClipper) )
  186. {
  187. DD_Clipper_AddRef( lpDDClipper );
  188. *ppvObj = (LPVOID) this_int;
  189. LEAVE_DDRAW();
  190. return DD_OK;
  191. }
  192. LEAVE_DDRAW();
  193. return E_NOINTERFACE;
  194. } /* DD_Clipper_QueryInterface */
  195. #undef DPF_MODNAME
  196. #define DPF_MODNAME "Clipper::AddRef"
  197. /*
  198. * DD_Clipper_AddRef
  199. */
  200. DWORD DDAPI DD_Clipper_AddRef( LPDIRECTDRAWCLIPPER lpDDClipper )
  201. {
  202. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  203. LPDDRAWI_DDRAWCLIPPER_GBL this;
  204. LPDDRAWI_DDRAWCLIPPER_LCL this_lcl;
  205. LPDDRAWI_DDRAWCLIPPER_INT this_int;
  206. DWORD rcnt;
  207. ENTER_DDRAW();
  208. DPF(2,A,"ENTERAPI: DD_Clipper_AddRef");
  209. /*
  210. * validate parms
  211. */
  212. TRY
  213. {
  214. this_int = (LPDDRAWI_DDRAWCLIPPER_INT) lpDDClipper;
  215. if( !VALID_DIRECTDRAWCLIPPER_PTR( this_int ) )
  216. {
  217. LEAVE_DDRAW();
  218. return 0;
  219. }
  220. this_lcl = this_int->lpLcl;
  221. this = this_lcl->lpGbl;
  222. pdrv = this->lpDD;
  223. }
  224. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  225. {
  226. DPF_ERR( "Exception encountered validating parameters" );
  227. LEAVE_DDRAW();
  228. return 0;
  229. }
  230. /*
  231. * update clipper reference count
  232. */
  233. this->dwRefCnt++;
  234. this_lcl->dwLocalRefCnt++;
  235. this_int->dwIntRefCnt++;
  236. rcnt = this_lcl->dwLocalRefCnt & ~OBJECT_ISROOT;
  237. DPF( 5, "Clipper %08lx addrefed, refcnt = %ld", this, rcnt );
  238. LEAVE_DDRAW();
  239. return this_int->dwIntRefCnt;
  240. } /* DD_Clipper_AddRef */
  241. #undef DPF_MODNAME
  242. #define DPF_MODNAME "Clipper::Release"
  243. /*
  244. * RemoveClipperFromList
  245. *
  246. * Remove a clipper from its owning clipper list.
  247. *
  248. * The clipper can either be a member of a global clipper list
  249. * (if no DirectDraw object owns it) or the clipper list of its
  250. * owning DirectDraw driver object. If pdrv == NULL then the
  251. * clipper will be removed from the global clipper list. If
  252. * pdrv != NULL the clipper will be removed from the clipper
  253. * list of that driver object. It is an error if the clipper
  254. * is not on the appropriate clipper list.
  255. *
  256. * Returns TRUE if the clipper was succesfully removed
  257. * Returns FALSE if the clipper could not be found on the
  258. * appropriate clipper list
  259. */
  260. static BOOL RemoveClipperFromList( LPDDRAWI_DIRECTDRAW_GBL pdrv,
  261. LPDDRAWI_DDRAWCLIPPER_INT this_int )
  262. {
  263. LPDDRAWI_DDRAWCLIPPER_INT curr_int;
  264. LPDDRAWI_DDRAWCLIPPER_INT last_int;
  265. curr_int = ( ( pdrv != NULL ) ? pdrv->clipperList : lpGlobalClipperList );
  266. last_int = NULL;
  267. while( curr_int != this_int )
  268. {
  269. last_int = curr_int;
  270. curr_int = curr_int->lpLink;
  271. if( curr_int == NULL )
  272. {
  273. return FALSE;
  274. }
  275. }
  276. if( last_int == NULL )
  277. {
  278. if( pdrv != NULL )
  279. pdrv->clipperList = pdrv->clipperList->lpLink;
  280. else
  281. lpGlobalClipperList = lpGlobalClipperList->lpLink;
  282. }
  283. else
  284. {
  285. last_int->lpLink = curr_int->lpLink;
  286. }
  287. return TRUE;
  288. }
  289. /*
  290. * InternalClipperRelease
  291. *
  292. * Done with a clipper. if no one else is using it, then we can free it.
  293. * Also called by ProcessClipperCleanup
  294. *
  295. * Assumes DirectDrawLock is taken
  296. */
  297. ULONG DDAPI InternalClipperRelease( LPDDRAWI_DDRAWCLIPPER_INT this_int )
  298. {
  299. DWORD intrefcnt;
  300. DWORD lclrefcnt;
  301. DWORD gblrefcnt;
  302. LPDDRAWI_DDRAWCLIPPER_LCL this_lcl;
  303. LPDDRAWI_DDRAWCLIPPER_GBL this;
  304. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  305. BOOL root_object_deleted;
  306. BOOL do_free;
  307. IUnknown * pOwner = NULL;
  308. this_lcl = this_int->lpLcl;
  309. this = this_lcl->lpGbl;
  310. pdrv = this->lpDD;
  311. /*
  312. * decrement reference count to this clipper. If it hits zero,
  313. * cleanup
  314. */
  315. this->dwRefCnt--;
  316. this_lcl->dwLocalRefCnt--;
  317. this_int->dwIntRefCnt--;
  318. gblrefcnt = this->dwRefCnt;
  319. lclrefcnt = this_lcl->dwLocalRefCnt & ~OBJECT_ISROOT;
  320. intrefcnt = this_int->dwIntRefCnt;
  321. root_object_deleted = FALSE;
  322. DPF( 5, "Clipper %08lx released, refcnt = %ld", this, lclrefcnt );
  323. /*
  324. * interface object deleted?
  325. */
  326. if( intrefcnt == 0 )
  327. {
  328. RemoveClipperFromList( pdrv, this_int );
  329. #ifdef POSTPONED2
  330. /*
  331. * If clipper interface object is referenced in master sprite
  332. * list, delete those references from the list.
  333. */
  334. if (this->dwFlags & DDRAWICLIP_INMASTERSPRITELIST)
  335. {
  336. RemoveSpriteClipper(pdrv, this_int);
  337. }
  338. #endif //POSTPONED2
  339. /*
  340. * Invalidate the interface and free it
  341. */
  342. this_int->lpVtbl = NULL;
  343. this_int->lpLcl = NULL;
  344. MemFree( this_int );
  345. }
  346. /*
  347. * local object deleted?
  348. */
  349. if( lclrefcnt == 0 )
  350. {
  351. /*
  352. * If the ddraw interface which created this clipper caused the surface to addref the ddraw
  353. * object, then we need to release that addref now.
  354. */
  355. pOwner = this_lcl->pAddrefedThisOwner;
  356. /*
  357. * see if we are deleting the root object
  358. */
  359. if( this_lcl->dwLocalRefCnt & OBJECT_ISROOT )
  360. {
  361. root_object_deleted = TRUE;
  362. }
  363. }
  364. /*
  365. * did the object get globally deleted?
  366. */
  367. do_free = FALSE;
  368. if( gblrefcnt == 0 )
  369. {
  370. do_free = TRUE;
  371. // Need to free the static clip list
  372. MemFree( this->lpStaticClipList );
  373. this->lpStaticClipList = NULL;
  374. /*
  375. * if this was the final delete, but this wasn't the root object,
  376. * then we need to delete the dangling root object
  377. */
  378. if( !root_object_deleted )
  379. {
  380. LPDDRAWI_DDRAWCLIPPER_LCL rootx;
  381. rootx = (LPVOID) (((LPSTR) this) - sizeof( DDRAWI_DDRAWCLIPPER_LCL ) );
  382. MemFree( rootx );
  383. }
  384. }
  385. else if( lclrefcnt == 0 )
  386. {
  387. /*
  388. * only remove the object if it wasn't the root. if it
  389. * was the root, we must leave it dangling until the last
  390. * object referencing it goes away.
  391. */
  392. if( !root_object_deleted )
  393. {
  394. do_free = TRUE;
  395. }
  396. }
  397. /*
  398. * free the object if needed
  399. */
  400. if( do_free )
  401. {
  402. /*
  403. * just in case someone comes back in with this pointer, set
  404. * an invalid vtbl & data ptr.
  405. */
  406. this_lcl->lpGbl = NULL;
  407. MemFree( this_lcl );
  408. }
  409. /*
  410. * If the clipper took a ref count on the ddraw object that created it,
  411. * release that ref now as the very last thing
  412. * We don't want to do this on ddhelp's thread cuz it really mucks up the
  413. * process cleanup stuff.
  414. */
  415. if (pOwner && (dwHelperPid != GetCurrentProcessId()) )
  416. {
  417. pOwner->lpVtbl->Release(pOwner);
  418. }
  419. return intrefcnt;
  420. } /* InternalClipperRelease */
  421. /*
  422. * DD_Clipper_Release
  423. */
  424. ULONG DDAPI DD_Clipper_Release( LPDIRECTDRAWCLIPPER lpDDClipper )
  425. {
  426. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  427. LPDDRAWI_DDRAWCLIPPER_GBL this;
  428. LPDDRAWI_DDRAWCLIPPER_LCL this_lcl;
  429. LPDDRAWI_DDRAWCLIPPER_INT this_int;
  430. ULONG rc;
  431. ENTER_DDRAW();
  432. DPF(2,A,"ENTERAPI: DD_Clipper_Release");
  433. /*
  434. * validate parms
  435. */
  436. TRY
  437. {
  438. this_int = (LPDDRAWI_DDRAWCLIPPER_INT) lpDDClipper;
  439. if( !VALIDEX_DIRECTDRAWCLIPPER_PTR( this_int ) )
  440. {
  441. LEAVE_DDRAW();
  442. return 0;
  443. }
  444. this_lcl = this_int->lpLcl;
  445. this = this_lcl->lpGbl;
  446. pdrv = this->lpDD;
  447. }
  448. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  449. {
  450. DPF_ERR( "Exception encountered validating parameters" );
  451. LEAVE_DDRAW();
  452. return 0;
  453. }
  454. rc = InternalClipperRelease( this_int );
  455. LEAVE_DDRAW();
  456. return rc;
  457. } /* DD_Clipper_Release */
  458. #undef DPF_MODNAME
  459. #define DPF_MODNAME "Clipper::SetHwnd"
  460. /*
  461. * DD_Clipper_SetHWnd
  462. */
  463. HRESULT DDAPI DD_Clipper_SetHWnd(
  464. LPDIRECTDRAWCLIPPER lpDDClipper,
  465. DWORD dwFlags,
  466. HWND hWnd )
  467. {
  468. LPDDRAWI_DDRAWCLIPPER_INT this_int;
  469. LPDDRAWI_DDRAWCLIPPER_LCL this_lcl;
  470. LPDDRAWI_DDRAWCLIPPER_GBL this;
  471. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  472. ENTER_DDRAW();
  473. DPF(2,A,"ENTERAPI: DD_Clipper_SetHWnd");
  474. TRY
  475. {
  476. this_int = (LPDDRAWI_DDRAWCLIPPER_INT) lpDDClipper;
  477. if( !VALID_DIRECTDRAWCLIPPER_PTR( this_int ) )
  478. {
  479. LEAVE_DDRAW();
  480. return DDERR_INVALIDOBJECT;
  481. }
  482. this_lcl = this_int->lpLcl;
  483. if( hWnd != NULL )
  484. {
  485. if( !IsWindow( hWnd ) )
  486. {
  487. DPF_ERR( "Invalid window handle" );
  488. LEAVE_DDRAW();
  489. return DDERR_INVALIDPARAMS;
  490. }
  491. }
  492. if( dwFlags )
  493. {
  494. DPF_ERR( "Invalid flags" );
  495. LEAVE_DDRAW();
  496. return DDERR_INVALIDPARAMS;
  497. }
  498. this = this_lcl->lpGbl;
  499. pdrv = this->lpDD;
  500. }
  501. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  502. {
  503. DPF_ERR( "Exception encountered validating parameters" );
  504. LEAVE_DDRAW();
  505. return DDERR_INVALIDPARAMS;
  506. }
  507. (HWND) this->hWnd = hWnd;
  508. LEAVE_DDRAW();
  509. return DD_OK;
  510. } /* DD_Clipper_SetHWnd */
  511. #undef DPF_MODNAME
  512. #define DPF_MODNAME "Clipper::GetHwnd"
  513. /*
  514. * DD_Clipper_GetHWnd
  515. */
  516. HRESULT DDAPI DD_Clipper_GetHWnd(
  517. LPDIRECTDRAWCLIPPER lpDDClipper,
  518. HWND FAR *lphWnd )
  519. {
  520. LPDDRAWI_DDRAWCLIPPER_INT this_int;
  521. LPDDRAWI_DDRAWCLIPPER_LCL this_lcl;
  522. LPDDRAWI_DDRAWCLIPPER_GBL this;
  523. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  524. /*
  525. * validate parms
  526. */
  527. TRY
  528. {
  529. ENTER_DDRAW();
  530. DPF(2,A,"ENTERAPI: DD_Clipper_GetHWnd");
  531. this_int = (LPDDRAWI_DDRAWCLIPPER_INT) lpDDClipper;
  532. if( !VALID_DIRECTDRAWCLIPPER_PTR( this_int ) )
  533. {
  534. LEAVE_DDRAW();
  535. return DDERR_INVALIDOBJECT;
  536. }
  537. this_lcl = this_int->lpLcl;
  538. if( !VALID_HWND_PTR( lphWnd ) )
  539. {
  540. LEAVE_DDRAW();
  541. return DDERR_INVALIDPARAMS;
  542. }
  543. this = this_lcl->lpGbl;
  544. pdrv = this->lpDD;
  545. *lphWnd = (HWND) this->hWnd;
  546. }
  547. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  548. {
  549. DPF_ERR( "Exception encountered validating parameters" );
  550. LEAVE_DDRAW();
  551. return DDERR_INVALIDPARAMS;
  552. }
  553. LEAVE_DDRAW();
  554. return DD_OK;
  555. } /* DD_Clipper_GetHWnd */
  556. #define SIZE_OF_A_CLIPLIST(lpRgn) \
  557. (sizeof(RGNDATAHEADER)+sizeof(RECTL)*lpRgn->rdh.nCount)
  558. HRESULT InternalGetClipList(
  559. LPDIRECTDRAWCLIPPER lpDDClipper,
  560. LPRECT lpRect,
  561. LPRGNDATA lpClipList,
  562. LPDWORD lpdwSize,
  563. LPDDRAWI_DIRECTDRAW_GBL pdrv )
  564. {
  565. LPDDRAWI_DDRAWCLIPPER_GBL this;
  566. HRESULT ddrval = DD_OK;
  567. DWORD cbRealSize;
  568. HDC hdc;
  569. HRGN hrgn;
  570. RECT rectT;
  571. #ifndef WIN95
  572. DWORD cbSaveSize;
  573. #endif
  574. this = ((LPDDRAWI_DDRAWCLIPPER_INT)(lpDDClipper))->lpLcl->lpGbl;
  575. // if no hwnd specified, then it is just a static cliplist
  576. if( this->hWnd == 0 )
  577. {
  578. if( this->lpStaticClipList == NULL )
  579. {
  580. return DDERR_NOCLIPLIST;
  581. }
  582. cbRealSize = SIZE_OF_A_CLIPLIST( this->lpStaticClipList );
  583. if( lpClipList == NULL )
  584. {
  585. *lpdwSize = cbRealSize;
  586. return DD_OK;
  587. }
  588. if( *lpdwSize < cbRealSize )
  589. {
  590. DPF_ERR( "Region size too small" );
  591. *lpdwSize = cbRealSize;
  592. return DDERR_REGIONTOOSMALL;
  593. }
  594. memcpy( lpClipList, this->lpStaticClipList, cbRealSize );
  595. ClipRgnToRect( lpRect, lpClipList );
  596. return DD_OK;
  597. }
  598. // Use an hwnd for the clipping
  599. #ifdef WIN95
  600. {
  601. hdc = GetDCEx( (HWND)this->hWnd, NULL, DCX_USESTYLE | DCX_CACHE );
  602. if( hdc == NULL )
  603. {
  604. DPF_ERR( "GetDCEx failed" );
  605. return DDERR_GENERIC;
  606. }
  607. hrgn = DD16_InquireVisRgn( hdc );
  608. if( hrgn == NULL )
  609. {
  610. DPF_ERR( "InquireVisRgn failed" );
  611. ReleaseDC( (HWND)this->hWnd, hdc );
  612. return DDERR_GENERIC;
  613. }
  614. }
  615. #else
  616. {
  617. int APIENTRY GetRandomRgn( HDC hdc, HRGN hrgn, int iNum );
  618. int rc;
  619. hdc = GetDC( (HWND) this->hWnd );
  620. if( hdc == NULL )
  621. {
  622. DPF_ERR( "GetDC failed" );
  623. return DDERR_GENERIC;
  624. }
  625. // Create the appropriate Region object
  626. hrgn = CreateRectRgn( 0, 0, 0, 0 );
  627. if( hrgn == NULL )
  628. {
  629. DPF_ERR( "CreateRectRgn failed" );
  630. ReleaseDC( (HWND) this->hWnd, hdc );
  631. return DDERR_GENERIC;
  632. }
  633. // Set the Region to the DC
  634. rc = GetRandomRgn( hdc, hrgn, 4 );
  635. if( rc == -1 )
  636. {
  637. DPF_ERR( "GetRandomRgn failed" );
  638. ReleaseDC( (HWND) this->hWnd, hdc );
  639. DeleteObject( hrgn );
  640. return DDERR_GENERIC;
  641. }
  642. }
  643. #endif
  644. // Client only asking for a size?
  645. if( lpClipList == NULL )
  646. {
  647. // Get the size
  648. *lpdwSize = GetRegionData( hrgn, 0, NULL );
  649. // Release allocations
  650. ReleaseDC( (HWND) this->hWnd, hdc );
  651. DeleteObject( hrgn );
  652. // Check if GetRegionData failed
  653. if( *lpdwSize == 0 )
  654. return DDERR_GENERIC;
  655. return DD_OK;
  656. }
  657. #ifndef WIN95
  658. // Store the size passed in, because GetRegionData may trash it.
  659. cbSaveSize = *lpdwSize;
  660. #endif
  661. // Get the window's region's REGIONDATA
  662. cbRealSize = GetRegionData( hrgn, *lpdwSize, lpClipList );
  663. #ifndef WIN95
  664. if (cbRealSize == 0)
  665. {
  666. cbRealSize = GetRegionData(hrgn, 0, NULL);
  667. if (cbSaveSize < cbRealSize)
  668. {
  669. ReleaseDC( (HWND)this->hWnd, hdc );
  670. DeleteObject( hrgn );
  671. *lpdwSize = cbRealSize;
  672. DPF(4, "size of clip region too small");
  673. return DDERR_REGIONTOOSMALL;
  674. }
  675. }
  676. #endif
  677. ReleaseDC( (HWND)this->hWnd, hdc );
  678. DeleteObject( hrgn );
  679. if( cbRealSize == 0 )
  680. {
  681. DPF_ERR( "GetRegionData failed" );
  682. return DDERR_GENERIC;
  683. }
  684. #ifdef WIN95
  685. // GetRegionData may have failed because the buffer
  686. // was too small
  687. if( *lpdwSize < cbRealSize )
  688. {
  689. DPF( 4, "size of clip region too small" );
  690. *lpdwSize = cbRealSize;
  691. return DDERR_REGIONTOOSMALL;
  692. }
  693. #endif
  694. // Before we do anything more, we need to make sure
  695. // to clip the Rgn to ClientRect of the Window. Normally
  696. // this is not necessary; but InquireVisRgn might
  697. // tell us the vis region of the parent window if the window
  698. // was a dialog or other wnd that used CS_PARENTDC
  699. GetClientRect( (HWND) this->hWnd, &rectT );
  700. ClientToScreen( (HWND) this->hWnd, (LPPOINT)&rectT );
  701. ClientToScreen( (HWND) this->hWnd, ((LPPOINT)&rectT)+1 );
  702. ClipRgnToRect( &rectT, lpClipList );
  703. // lpDD may be NULL if the clipper was created independently
  704. if( pdrv &&
  705. (pdrv->cMonitors > 1) &&
  706. (pdrv->dwFlags & DDRAWI_DISPLAYDRV) )
  707. {
  708. // On multi-mon systems, the Desktop coordinates may be different
  709. // from the device coordinates. On the primary, they are the same however.
  710. // The lpRect passed in is in device coordinates; so we need to convert it
  711. // into desktop coordinates.
  712. UINT i;
  713. LPRECT prectClip;
  714. if( pdrv->rectDevice.top != 0 ||
  715. pdrv->rectDevice.left != 0 )
  716. {
  717. RECT rectT;
  718. if( lpRect != NULL )
  719. {
  720. rectT.left = lpRect->left + pdrv->rectDevice.left;
  721. rectT.right = lpRect->right + pdrv->rectDevice.left;
  722. rectT.top = lpRect->top + pdrv->rectDevice.top;
  723. rectT.bottom = lpRect->bottom + pdrv->rectDevice.top;
  724. }
  725. else
  726. {
  727. rectT = pdrv->rectDevice;
  728. }
  729. // Clip the cliplist to the target rect
  730. ClipRgnToRect( &rectT, lpClipList );
  731. // Clip the cliplist to the device's rect
  732. ClipRgnToRect( &pdrv->rectDevice, lpClipList );
  733. // Iterate over each rect in the region
  734. for ( i = 0, prectClip = (LPRECT)lpClipList->Buffer;
  735. i < lpClipList->rdh.nCount;
  736. i++, prectClip++ )
  737. {
  738. // Convert each Rect into Device coordinates
  739. prectClip->left -= pdrv->rectDevice.left;
  740. prectClip->right -= pdrv->rectDevice.left;
  741. prectClip->top -= pdrv->rectDevice.top;
  742. prectClip->bottom -= pdrv->rectDevice.top;
  743. }
  744. }
  745. else
  746. {
  747. // Clip the cliplist to the target rect
  748. ClipRgnToRect( lpRect, lpClipList );
  749. // Clip the cliplist to the device's rect
  750. ClipRgnToRect( &pdrv->rectDesktop, lpClipList );
  751. }
  752. }
  753. else
  754. {
  755. ClipRgnToRect( lpRect, lpClipList );
  756. }
  757. return DD_OK;
  758. }
  759. /*
  760. * DD_Clipper_GetClipList
  761. */
  762. HRESULT DDAPI DD_Clipper_GetClipList(
  763. LPDIRECTDRAWCLIPPER lpDDClipper,
  764. LPRECT lpRect,
  765. LPRGNDATA lpClipList,
  766. LPDWORD lpdwSize )
  767. {
  768. LPDDRAWI_DDRAWCLIPPER_INT this_int;
  769. LPDDRAWI_DDRAWCLIPPER_LCL this_lcl;
  770. LPDDRAWI_DDRAWCLIPPER_GBL this;
  771. DWORD size;
  772. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  773. ENTER_DDRAW();
  774. DPF(2,A,"ENTERAPI: DD_Clipper_GetClipList");
  775. /*
  776. * validate parms
  777. */
  778. TRY
  779. {
  780. this_int = (LPDDRAWI_DDRAWCLIPPER_INT) lpDDClipper;
  781. if( !VALID_DIRECTDRAWCLIPPER_PTR( this_int ) )
  782. {
  783. LEAVE_DDRAW();
  784. return DDERR_INVALIDOBJECT;
  785. }
  786. this_lcl = this_int->lpLcl;
  787. if( !VALID_DWORD_PTR( lpdwSize ) )
  788. {
  789. DPF_ERR( "Invalid size ptr" );
  790. LEAVE_DDRAW();
  791. return DDERR_INVALIDPARAMS;
  792. }
  793. if( lpRect != NULL )
  794. {
  795. if( !VALID_RECT_PTR( lpRect ) )
  796. {
  797. DPF_ERR( "Invalid rectangle ptr" );
  798. LEAVE_DDRAW();
  799. return DDERR_INVALIDPARAMS;
  800. }
  801. size = lpRect->left;
  802. }
  803. if( lpClipList != NULL )
  804. {
  805. if( !VALID_RGNDATA_PTR( lpClipList, *lpdwSize ) )
  806. {
  807. LEAVE_DDRAW();
  808. return DDERR_INVALIDCLIPLIST;
  809. }
  810. // Touch the last address in the promised block to verify
  811. // the memory is actually there. Note that we are
  812. // standing on our head here to prevent the optimizing
  813. // compiler from helping us by removing this code. This
  814. // is done by the macro above, but we want it in the
  815. // retail build, too.
  816. {
  817. volatile BYTE *foo = ((BYTE*)lpClipList) + *lpdwSize - 1;
  818. BYTE bar = *foo;
  819. }
  820. lpClipList->rdh.nCount = 0;
  821. }
  822. this = this_lcl->lpGbl;
  823. pdrv = this->lpDD;
  824. }
  825. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  826. {
  827. DPF_ERR( "Exception encountered validating parameters" );
  828. LEAVE_DDRAW();
  829. return DDERR_INVALIDPARAMS;
  830. }
  831. /*
  832. * go fetch the clip list
  833. */
  834. {
  835. HRESULT ddrval;
  836. #ifdef WIN16_SEPARATE
  837. ENTER_WIN16LOCK();
  838. #endif
  839. ddrval = InternalGetClipList( lpDDClipper, lpRect, lpClipList, lpdwSize, pdrv );
  840. #ifdef WIN16_SEPARATE
  841. LEAVE_WIN16LOCK();
  842. #endif
  843. LEAVE_DDRAW();
  844. return ddrval;
  845. }
  846. } /* DD_Clipper_GetClipList */
  847. /*
  848. * DD_Clipper_SetClipList
  849. */
  850. HRESULT DDAPI DD_Clipper_SetClipList(
  851. LPDIRECTDRAWCLIPPER lpDDClipper,
  852. LPRGNDATA lpClipList,
  853. DWORD dwFlags )
  854. {
  855. LPDDRAWI_DDRAWCLIPPER_INT this_int;
  856. LPDDRAWI_DDRAWCLIPPER_LCL this_lcl;
  857. LPDDRAWI_DDRAWCLIPPER_GBL this;
  858. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  859. LPRGNDATA prd;
  860. DWORD size;
  861. ENTER_DDRAW();
  862. DPF(2,A,"ENTERAPI: DD_Clipper_SetClipList");
  863. TRY
  864. {
  865. this_int = (LPDDRAWI_DDRAWCLIPPER_INT) lpDDClipper;
  866. if( !VALID_DIRECTDRAWCLIPPER_PTR( this_int ) )
  867. {
  868. LEAVE_DDRAW();
  869. return DDERR_INVALIDOBJECT;
  870. }
  871. this_lcl = this_int->lpLcl;
  872. if( dwFlags )
  873. {
  874. DPF_ERR( "Invalid flags" );
  875. LEAVE_DDRAW();
  876. return DDERR_INVALIDPARAMS;
  877. }
  878. if( lpClipList != NULL )
  879. {
  880. if( !VALID_RGNDATA_PTR( lpClipList, sizeof(RGNDATA) ) )
  881. {
  882. LEAVE_DDRAW();
  883. return DDERR_INVALIDCLIPLIST;
  884. }
  885. if( lpClipList->rdh.nCount <= 0 )
  886. {
  887. LEAVE_DDRAW();
  888. return DDERR_INVALIDCLIPLIST;
  889. }
  890. if( this_lcl->lpDD_int == NULL || this_lcl->lpDD_int->lpVtbl != &ddCallbacks )
  891. {
  892. if( (lpClipList->rdh.dwSize < sizeof(RGNDATAHEADER)) ||
  893. (lpClipList->rdh.iType != RDH_RECTANGLES ) ||
  894. IsBadReadPtr(lpClipList, SIZE_OF_A_CLIPLIST(lpClipList)) )
  895. {
  896. LEAVE_DDRAW();
  897. return DDERR_INVALIDCLIPLIST;
  898. }
  899. }
  900. }
  901. this = this_lcl->lpGbl;
  902. pdrv = this->lpDD;
  903. }
  904. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  905. {
  906. DPF_ERR( "Exception encountered validating parameters" );
  907. LEAVE_DDRAW();
  908. return DDERR_INVALIDPARAMS;
  909. }
  910. /*
  911. * can't set a clip list if there is an hwnd
  912. */
  913. if( this->hWnd != 0 )
  914. {
  915. DPF_ERR( "Can't set a clip list: hwnd set" );
  916. LEAVE_DDRAW();
  917. return DDERR_CLIPPERISUSINGHWND;
  918. }
  919. /*
  920. * if NULL, just delete old cliplist
  921. */
  922. if( lpClipList == NULL )
  923. {
  924. MemFree( this->lpStaticClipList );
  925. this->lpStaticClipList = NULL;
  926. LEAVE_DDRAW();
  927. return DD_OK;
  928. }
  929. /*
  930. * duplicate the user's region data
  931. */
  932. size = SIZE_OF_A_CLIPLIST(lpClipList);
  933. prd = MemAlloc( size );
  934. if( prd == NULL )
  935. {
  936. LEAVE_DDRAW();
  937. return DDERR_OUTOFMEMORY;
  938. }
  939. memcpy( prd, lpClipList, size );
  940. /*
  941. * save cliplist info
  942. */
  943. MemFree( this->lpStaticClipList );
  944. this->lpStaticClipList = prd;
  945. LEAVE_DDRAW();
  946. return DD_OK;
  947. } /* DD_Clipper_SetClipList */
  948. #undef DPF_MODNAME
  949. #define DPF_MODNAME "Clipper:IsClipListChanged"
  950. /*
  951. * DD_Clipper_IsClipListChanged
  952. */
  953. HRESULT DDAPI DD_Clipper_IsClipListChanged(
  954. LPDIRECTDRAWCLIPPER lpDDClipper,
  955. BOOL FAR *lpbChanged )
  956. {
  957. LPDDRAWI_DDRAWCLIPPER_INT this_int;
  958. LPDDRAWI_DDRAWCLIPPER_LCL this_lcl;
  959. LPDDRAWI_DDRAWCLIPPER_GBL this;
  960. volatile LPDDRAWI_DIRECTDRAW_GBL pdrv;
  961. ENTER_DDRAW();
  962. DPF(2,A,"ENTERAPI: DD_Clipper_IsClipListChanged");
  963. /*
  964. * validate parms
  965. */
  966. TRY
  967. {
  968. this_int = (LPDDRAWI_DDRAWCLIPPER_INT) lpDDClipper;
  969. if( !VALID_DIRECTDRAWCLIPPER_PTR( this_int ) )
  970. {
  971. LEAVE_DDRAW();
  972. return DDERR_INVALIDOBJECT;
  973. }
  974. this_lcl = this_int->lpLcl;
  975. this = this_lcl->lpGbl;
  976. pdrv = this->lpDD;
  977. *lpbChanged = 0;
  978. }
  979. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  980. {
  981. DPF_ERR( "Exception encountered validating parameters" );
  982. LEAVE_DDRAW();
  983. return DDERR_INVALIDPARAMS;
  984. }
  985. #pragma message( REMIND( "Do we want to just fail non-watched IsClipListChanged?" ))
  986. *lpbChanged = TRUE;
  987. LEAVE_DDRAW();
  988. return DD_OK;
  989. } /* DD_Clipper_IsClipListChanged */
  990. #undef DPF_MODNAME
  991. #define DPF_MODNAME "GetClipper"
  992. /*
  993. * DD_Surface_GetClipper
  994. *
  995. * Surface function: get the clipper associated with surface
  996. */
  997. HRESULT DDAPI DD_Surface_GetClipper(
  998. LPDIRECTDRAWSURFACE lpDDSurface,
  999. LPDIRECTDRAWCLIPPER FAR * lplpDDClipper)
  1000. {
  1001. LPDDRAWI_DDRAWSURFACE_INT this_int;
  1002. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  1003. LPDDRAWI_DDRAWSURFACE_GBL this;
  1004. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  1005. ENTER_DDRAW();
  1006. DPF(2,A,"ENTERAPI: DD_Surface_GetClipper");
  1007. /*
  1008. * validate parms
  1009. */
  1010. TRY
  1011. {
  1012. this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
  1013. if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
  1014. {
  1015. LEAVE_DDRAW();
  1016. return DDERR_INVALIDOBJECT;
  1017. }
  1018. this_lcl = this_int->lpLcl;
  1019. this = this_lcl->lpGbl;
  1020. if( !VALID_PTR_PTR( lplpDDClipper ) )
  1021. {
  1022. DPF_ERR( "Invalid clipper pointer" );
  1023. LEAVE_DDRAW();
  1024. return DDERR_INVALIDPARAMS;
  1025. }
  1026. *lplpDDClipper = NULL;
  1027. pdrv = this->lpDD;
  1028. if( this_lcl->lpSurfMore->lpDDIClipper == NULL )
  1029. {
  1030. DPF_ERR( "No clipper associated with surface" );
  1031. LEAVE_DDRAW();
  1032. return DDERR_NOCLIPPERATTACHED;
  1033. }
  1034. //
  1035. // For now, if the current surface is optimized, quit
  1036. //
  1037. if (this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
  1038. {
  1039. DPF_ERR( "It is an optimized surface" );
  1040. LEAVE_DDRAW();
  1041. return DDERR_ISOPTIMIZEDSURFACE;
  1042. }
  1043. }
  1044. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1045. {
  1046. DPF_ERR( "Exception encountered validating parameters" );
  1047. LEAVE_DDRAW();
  1048. return DDERR_INVALIDPARAMS;
  1049. }
  1050. DD_Clipper_AddRef( (LPDIRECTDRAWCLIPPER) this_lcl->lpSurfMore->lpDDIClipper );
  1051. *lplpDDClipper = (LPDIRECTDRAWCLIPPER) this_lcl->lpSurfMore->lpDDIClipper;
  1052. LEAVE_DDRAW();
  1053. return DD_OK;
  1054. } /* DD_Surface_GetClipper */
  1055. #undef DPF_MODNAME
  1056. #define DPF_MODNAME "SetClipper"
  1057. /*
  1058. * DD_Surface_SetClipper
  1059. *
  1060. * Surface function: set the clipper associated with surface
  1061. */
  1062. HRESULT DDAPI DD_Surface_SetClipper(
  1063. LPDIRECTDRAWSURFACE lpDDSurface,
  1064. LPDIRECTDRAWCLIPPER lpDDClipper )
  1065. {
  1066. LPDDRAWI_DDRAWSURFACE_INT this_int;
  1067. LPDDRAWI_DDRAWSURFACE_LCL this_lcl;
  1068. LPDDRAWI_DDRAWSURFACE_GBL this;
  1069. LPDDRAWI_DDRAWCLIPPER_INT this_clipper_int;
  1070. LPDDRAWI_DIRECTDRAW_GBL pdrv;
  1071. BOOL detach;
  1072. ENTER_DDRAW();
  1073. DPF(2,A,"ENTERAPI: DD_Surface_SetClipper");
  1074. /*
  1075. * validate parms
  1076. */
  1077. TRY
  1078. {
  1079. this_int = (LPDDRAWI_DDRAWSURFACE_INT) lpDDSurface;
  1080. if( !VALID_DIRECTDRAWSURFACE_PTR( this_int ) )
  1081. {
  1082. LEAVE_DDRAW();
  1083. return DDERR_INVALIDOBJECT;
  1084. }
  1085. this_lcl = this_int->lpLcl;
  1086. this = this_lcl->lpGbl;
  1087. if( this_lcl->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER ||
  1088. this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
  1089. {
  1090. /*
  1091. * Can't attach a clipper to an execute buffer or an optimized
  1092. * surface.
  1093. */
  1094. DPF_ERR( "Invalid surface type: can't attach clipper" );
  1095. LEAVE_DDRAW();
  1096. return DDERR_INVALIDSURFACETYPE;
  1097. }
  1098. this_clipper_int = (LPDDRAWI_DDRAWCLIPPER_INT) lpDDClipper;
  1099. if( this_clipper_int != NULL )
  1100. {
  1101. if( !VALID_DIRECTDRAWCLIPPER_PTR( this_clipper_int ) )
  1102. {
  1103. LEAVE_DDRAW();
  1104. return DDERR_INVALIDOBJECT;
  1105. }
  1106. }
  1107. pdrv = this->lpDD;
  1108. //
  1109. // For now, if the current surface is optimized, quit
  1110. //
  1111. if (this_lcl->ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
  1112. {
  1113. DPF_ERR( "Cannot set clipper to an optimized surface" );
  1114. LEAVE_DDRAW();
  1115. return DDERR_ISOPTIMIZEDSURFACE;
  1116. }
  1117. }
  1118. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1119. {
  1120. DPF_ERR( "Exception encountered validating parameters" );
  1121. LEAVE_DDRAW();
  1122. return DDERR_INVALIDPARAMS;
  1123. }
  1124. /*
  1125. * NULL clipper, remove clipper from this surface
  1126. */
  1127. detach = FALSE;
  1128. if( this_clipper_int == NULL )
  1129. {
  1130. detach = TRUE;
  1131. this_clipper_int = this_lcl->lpSurfMore->lpDDIClipper;
  1132. if( this_clipper_int == NULL )
  1133. {
  1134. DPF_ERR( "No attached clipper" );
  1135. LEAVE_DDRAW();
  1136. return DDERR_NOCLIPPERATTACHED;
  1137. }
  1138. }
  1139. /*
  1140. * removing the clipper from the surface?
  1141. */
  1142. if( detach )
  1143. {
  1144. this_lcl->lpDDClipper = NULL;
  1145. this_lcl->lpSurfMore->lpDDIClipper = NULL;
  1146. DD_Clipper_Release( (LPDIRECTDRAWCLIPPER) this_clipper_int );
  1147. LEAVE_DDRAW();
  1148. return DD_OK;
  1149. }
  1150. /*
  1151. * Setting the clipper.
  1152. * You can set the same clipper multiple times without bumping
  1153. * the reference count. This is done for orthogonality with
  1154. * palettes.
  1155. */
  1156. if( this_clipper_int != this_lcl->lpSurfMore->lpDDIClipper )
  1157. {
  1158. /*
  1159. * If there was an existing clipper release it now.
  1160. */
  1161. if( this_lcl->lpSurfMore->lpDDIClipper != NULL)
  1162. DD_Clipper_Release( (LPDIRECTDRAWCLIPPER) this_lcl->lpSurfMore->lpDDIClipper );
  1163. this_lcl->lpSurfMore->lpDDIClipper = this_clipper_int;
  1164. this_lcl->lpDDClipper = this_clipper_int->lpLcl;
  1165. DD_Clipper_AddRef( (LPDIRECTDRAWCLIPPER) this_clipper_int );
  1166. }
  1167. LEAVE_DDRAW();
  1168. return DD_OK;
  1169. } /* DD_Surface_SetClipper */
  1170. #undef DPF_MODNAME
  1171. #define DPF_MODNAME "InternalCreateClipper"
  1172. /*
  1173. * InternalCreateClipper
  1174. *
  1175. * Core clipper creation.
  1176. *
  1177. * NOTE: Assumes the caller has already entered the DirectDraw critical
  1178. * section.
  1179. */
  1180. HRESULT InternalCreateClipper(
  1181. LPDDRAWI_DIRECTDRAW_GBL lpDD,
  1182. DWORD dwFlags,
  1183. LPDIRECTDRAWCLIPPER FAR *lplpDDClipper,
  1184. IUnknown FAR *pUnkOuter,
  1185. BOOL fInitialized,
  1186. LPDDRAWI_DIRECTDRAW_LCL lpDD_lcl,
  1187. LPDDRAWI_DIRECTDRAW_INT lpDD_int )
  1188. {
  1189. LPDDRAWI_DDRAWCLIPPER_INT pclipper_int;
  1190. LPDDRAWI_DDRAWCLIPPER_LCL pclipper_lcl;
  1191. LPDDRAWI_DDRAWCLIPPER_GBL pclipper;
  1192. DWORD clipper_size;
  1193. if( pUnkOuter != NULL )
  1194. {
  1195. return CLASS_E_NOAGGREGATION;
  1196. }
  1197. TRY
  1198. {
  1199. /*
  1200. * NOTE: We do not attempt to validate the DirectDraw
  1201. * object passed in. This will be NULL if we are creating
  1202. * a clipper not owned by any DirectDraw object.
  1203. * IDirectDraw_CreateClipper will validate this for us.
  1204. */
  1205. if( !VALID_PTR_PTR( lplpDDClipper ) )
  1206. {
  1207. DPF_ERR( "Invalid pointer to pointer to clipper" );
  1208. return DDERR_INVALIDPARAMS;
  1209. }
  1210. *lplpDDClipper = NULL;
  1211. /*
  1212. * verify flags
  1213. */
  1214. if( dwFlags )
  1215. {
  1216. DPF_ERR( "Invalid flags" );
  1217. return DDERR_INVALIDPARAMS;
  1218. }
  1219. }
  1220. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1221. {
  1222. DPF_ERR( "Exception encountered validating parameters" );
  1223. return DDERR_INVALIDPARAMS;
  1224. }
  1225. /*
  1226. * allocate the clipper object
  1227. */
  1228. clipper_size = sizeof( DDRAWI_DDRAWCLIPPER_GBL ) +
  1229. sizeof( DDRAWI_DDRAWCLIPPER_LCL );
  1230. pclipper_lcl = (LPDDRAWI_DDRAWCLIPPER_LCL) MemAlloc( clipper_size );
  1231. if( pclipper_lcl == NULL )
  1232. {
  1233. DPF_ERR( "Insufficient memory to allocate the clipper" );
  1234. return DDERR_OUTOFMEMORY;
  1235. }
  1236. pclipper_lcl->lpGbl = (LPDDRAWI_DDRAWCLIPPER_GBL) (((LPSTR)pclipper_lcl) +
  1237. sizeof( DDRAWI_DDRAWCLIPPER_LCL ) );
  1238. pclipper = pclipper_lcl->lpGbl;
  1239. pclipper_lcl->lpDD_lcl = lpDD_lcl;
  1240. pclipper_lcl->lpDD_int = lpDD_int;
  1241. pclipper_int = MemAlloc( sizeof( DDRAWI_DDRAWCLIPPER_INT ));
  1242. if( NULL == pclipper_int)
  1243. {
  1244. DPF_ERR( "Insufficient memory to allocate the clipper" );
  1245. MemFree( pclipper_lcl );
  1246. return DDERR_OUTOFMEMORY;
  1247. }
  1248. /*
  1249. * set up data
  1250. */
  1251. pclipper_int->lpLcl = pclipper_lcl;
  1252. pclipper_int->dwIntRefCnt = 0; // will be addrefed later
  1253. /*
  1254. * Link the clipper into the appropriate list (either the
  1255. * given DirectDraw object's list or the global clipper
  1256. * list dependening on whether it is being created off
  1257. * a DirectDraw object or nor.
  1258. */
  1259. if( lpDD != NULL)
  1260. {
  1261. /*
  1262. * The DirectDraw object's list.
  1263. */
  1264. pclipper_int->lpLink = lpDD->clipperList;
  1265. lpDD->clipperList = pclipper_int;
  1266. }
  1267. else
  1268. {
  1269. /*
  1270. * The global clipper list.
  1271. */
  1272. pclipper_int->lpLink = lpGlobalClipperList;
  1273. lpGlobalClipperList = pclipper_int;
  1274. }
  1275. /*
  1276. * fill in misc stuff
  1277. *
  1278. * NOTE: The DirectDraw object pointer will be initialized by
  1279. * IDirectDraw_CreateClipper. DirectDrawClipperCreate will
  1280. * leave it NULL'd out.
  1281. */
  1282. pclipper->lpDD = lpDD;
  1283. pclipper->dwFlags = 0UL;
  1284. /*
  1285. * bump reference count, return object
  1286. */
  1287. pclipper->dwProcessId = GetCurrentProcessId();
  1288. pclipper_lcl->dwLocalRefCnt = OBJECT_ISROOT;
  1289. if( fInitialized )
  1290. {
  1291. /*
  1292. * Initialized by default. Use the real vtable.
  1293. */
  1294. pclipper->dwFlags |= DDRAWICLIP_ISINITIALIZED;
  1295. pclipper_int->lpVtbl = (LPVOID) &ddClipperCallbacks;
  1296. }
  1297. else
  1298. {
  1299. /*
  1300. * Object is not initialized. Use the dummy vtable
  1301. * which only lets the caller call AddRef(), Release()
  1302. * and Initialize().
  1303. */
  1304. pclipper_int->lpVtbl = (LPVOID) &ddUninitClipperCallbacks;
  1305. }
  1306. DD_Clipper_AddRef( (LPDIRECTDRAWCLIPPER) pclipper_int );
  1307. *lplpDDClipper = (LPDIRECTDRAWCLIPPER) pclipper_int;
  1308. /*
  1309. * If this ddraw object generates independent child objects, then this clipper takes
  1310. * a ref count on that ddraw object. First check lpDD_int, as this object may not
  1311. * be owned by a DDraw object.
  1312. */
  1313. if (lpDD_int && CHILD_SHOULD_TAKE_REFCNT(lpDD_int))
  1314. {
  1315. IDirectDraw *pdd = (IDirectDraw*) lpDD_int;
  1316. pdd->lpVtbl->AddRef(pdd);
  1317. pclipper_lcl->pAddrefedThisOwner = (IUnknown *) pdd;
  1318. }
  1319. return DD_OK;
  1320. } /* InternalCreateClipper */
  1321. #undef DPF_MODNAME
  1322. #define DPF_MODNAME "CreateClipper"
  1323. /*
  1324. * DD_CreateClipper
  1325. *
  1326. * Driver function: create a clipper
  1327. */
  1328. HRESULT DDAPI DD_CreateClipper(
  1329. LPDIRECTDRAW lpDD,
  1330. DWORD dwFlags,
  1331. LPDIRECTDRAWCLIPPER FAR *lplpDDClipper,
  1332. IUnknown FAR *pUnkOuter )
  1333. {
  1334. HRESULT hRes;
  1335. LPDDRAWI_DIRECTDRAW_INT this_int;
  1336. LPDDRAWI_DIRECTDRAW_LCL this_lcl;
  1337. LPDDRAWI_DIRECTDRAW_GBL this;
  1338. ENTER_DDRAW();
  1339. DPF(2,A,"ENTERAPI: DD_CreateClipper");
  1340. TRY
  1341. {
  1342. this_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
  1343. if( !VALID_DIRECTDRAW_PTR( this_int ) )
  1344. {
  1345. LEAVE_DDRAW();
  1346. return DDERR_INVALIDOBJECT;
  1347. }
  1348. this_lcl = this_int->lpLcl;
  1349. this = this_lcl->lpGbl;
  1350. }
  1351. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1352. {
  1353. DPF_ERR( "Exception encountered validating parameters" );
  1354. LEAVE_DDRAW();
  1355. return DDERR_INVALIDPARAMS;
  1356. }
  1357. /*
  1358. * Actually create the clipper.
  1359. */
  1360. hRes = InternalCreateClipper( this, dwFlags, lplpDDClipper, pUnkOuter, TRUE, this_lcl, this_int );
  1361. LEAVE_DDRAW();
  1362. return hRes;
  1363. } /* DD_CreateClipper */
  1364. #undef DPF_MODNAME
  1365. #define DPF_MODNAME "DirectDrawCreateClipper"
  1366. /*
  1367. * DirectDrawCreateClipper
  1368. *
  1369. * One of the three end-user API exported from DDRAW.DLL.
  1370. * Creates a DIRECTDRAWCLIPPER object not owned by a
  1371. * particular DirectDraw object.
  1372. */
  1373. HRESULT WINAPI DirectDrawCreateClipper( DWORD dwFlags, LPDIRECTDRAWCLIPPER FAR *lplpDDClipper, IUnknown FAR *pUnkOuter )
  1374. {
  1375. HRESULT hRes;
  1376. ENTER_DDRAW();
  1377. DPF(2,A,"ENTERAPI: DirectDrawCreateClipper");
  1378. hRes = InternalCreateClipper( NULL, dwFlags, lplpDDClipper, pUnkOuter, TRUE, NULL, NULL );
  1379. LEAVE_DDRAW();
  1380. return hRes;
  1381. } /* DirectDrawCreateClipper */
  1382. #undef DPF_MODNAME
  1383. #define DPF_MODNAME "Clipper: Initialize"
  1384. /*
  1385. * DD_Clipper_Initialize
  1386. */
  1387. HRESULT DDAPI DD_Clipper_Initialize(
  1388. LPDIRECTDRAWCLIPPER lpDDClipper,
  1389. LPDIRECTDRAW lpDD,
  1390. DWORD dwFlags )
  1391. {
  1392. LPDDRAWI_DDRAWCLIPPER_INT this_int;
  1393. LPDDRAWI_DDRAWCLIPPER_LCL this_lcl;
  1394. LPDDRAWI_DDRAWCLIPPER_GBL this_gbl;
  1395. LPDDRAWI_DIRECTDRAW_INT pdrv_int;
  1396. LPDDRAWI_DIRECTDRAW_GBL pdrv_gbl;
  1397. ENTER_DDRAW();
  1398. DPF(2,A,"ENTERAPI: DD_Clipper_Initialize");
  1399. TRY
  1400. {
  1401. this_int = (LPDDRAWI_DDRAWCLIPPER_INT) lpDDClipper;
  1402. if( !VALID_DIRECTDRAWCLIPPER_PTR( this_int ) )
  1403. {
  1404. DPF_ERR( "Invalid clipper interface pointer" );
  1405. LEAVE_DDRAW();
  1406. return DDERR_INVALIDPARAMS;
  1407. }
  1408. this_lcl = this_int->lpLcl;
  1409. this_gbl = this_lcl->lpGbl;
  1410. pdrv_int = (LPDDRAWI_DIRECTDRAW_INT) lpDD;
  1411. if( NULL != pdrv_int )
  1412. {
  1413. if( !VALID_DIRECTDRAW_PTR( pdrv_int ) )
  1414. {
  1415. DPF_ERR( "Invalid DirectDraw object" );
  1416. LEAVE_DDRAW();
  1417. return DDERR_INVALIDPARAMS;
  1418. }
  1419. pdrv_gbl = pdrv_int->lpLcl->lpGbl;
  1420. }
  1421. else
  1422. {
  1423. pdrv_gbl = NULL;
  1424. }
  1425. if( this_gbl->dwFlags & DDRAWICLIP_ISINITIALIZED )
  1426. {
  1427. DPF_ERR( "Clipper already initialized" );
  1428. LEAVE_DDRAW();
  1429. return DDERR_ALREADYINITIALIZED;
  1430. }
  1431. /*
  1432. * Validate flags - no flags currently supported
  1433. */
  1434. if( 0UL != dwFlags )
  1435. {
  1436. DPF_ERR( "Invalid flags" );
  1437. LEAVE_DDRAW();
  1438. return DDERR_INVALIDPARAMS;
  1439. }
  1440. }
  1441. EXCEPT( EXCEPTION_EXECUTE_HANDLER )
  1442. {
  1443. DPF_ERR( "Exception encountered validating parameters" );
  1444. LEAVE_DDRAW();
  1445. return DDERR_INVALIDPARAMS;
  1446. }
  1447. /*
  1448. * As we don't support any flags the only function of Initialize() is
  1449. * to move the clipper from the global list to the list of the supplied
  1450. * driver object. If no driver is supplied Initialized is a no-op.
  1451. * CoCreateInstance() does all the initialization necessary.
  1452. */
  1453. if( NULL != pdrv_gbl )
  1454. {
  1455. RemoveClipperFromList( NULL, this_int );
  1456. this_int->lpLink = pdrv_gbl->clipperList;
  1457. pdrv_gbl->clipperList = this_int;
  1458. this_gbl->lpDD = pdrv_gbl;
  1459. this_lcl->lpDD_lcl = pdrv_int->lpLcl;
  1460. this_lcl->lpDD_int = pdrv_int;
  1461. }
  1462. this_gbl->dwFlags |= DDRAWICLIP_ISINITIALIZED;
  1463. /*
  1464. * The real vtable can be used now.
  1465. */
  1466. this_int->lpVtbl = &ddClipperCallbacks;
  1467. LEAVE_DDRAW();
  1468. return DD_OK;
  1469. } /* DD_Clipper_Initialize */
  1470. /*
  1471. * ProcessClipperCleanup
  1472. *
  1473. * A process is done, clean up any clippers it may have created
  1474. *
  1475. * NOTE: we enter with a lock taken on the DIRECTDRAW object.
  1476. */
  1477. void ProcessClipperCleanup( LPDDRAWI_DIRECTDRAW_GBL pdrv, DWORD pid, LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl )
  1478. {
  1479. LPDDRAWI_DDRAWCLIPPER_INT pclipper_int;
  1480. LPDDRAWI_DDRAWCLIPPER_INT ppnext_int;
  1481. DWORD rcnt;
  1482. ULONG rc;
  1483. /*
  1484. * Cleaning up the clippers is now a two stage process. We need to
  1485. * clean up all the clippers create via CreateClipper(), i.e., those
  1486. * attached to a DirectDraw driver object. We also need to clean up
  1487. * those clippers created by thise process with DirectDrawClipperCreate,
  1488. * i.e., those not attached to a driver object.
  1489. */
  1490. /*
  1491. * run through all clippers owned by the driver object, and find ones
  1492. * that have been accessed by this process. If the pdrv_lcl parameter is
  1493. * non-null, only clean them up if they were created by that local object.
  1494. */
  1495. DPF( 4, "ProcessClipperCleanup" );
  1496. if( NULL != pdrv )
  1497. {
  1498. DPF( 5, "Cleaning up clippers owned by driver object 0x%08x", pdrv );
  1499. pclipper_int = pdrv->clipperList;
  1500. }
  1501. else
  1502. {
  1503. pclipper_int = NULL;
  1504. }
  1505. while( pclipper_int != NULL )
  1506. {
  1507. ppnext_int = pclipper_int->lpLink;
  1508. /*
  1509. * All clippers in this list should have a valid back pointer to
  1510. * this driver object.
  1511. */
  1512. DDASSERT( pclipper_int->lpLcl->lpGbl->lpDD == pdrv );
  1513. rc = 1;
  1514. if( (pclipper_int->lpLcl->lpGbl->dwProcessId == pid) &&
  1515. ( (pdrv_lcl == NULL) || (pdrv_lcl == pclipper_int->lpLcl->lpDD_lcl) ))
  1516. {
  1517. /*
  1518. * release the references by this process
  1519. */
  1520. rcnt = pclipper_int->dwIntRefCnt;
  1521. DPF( 5, "Process %08lx had %ld accesses to clipper %08lx", pid, rcnt, pclipper_int );
  1522. while( rcnt > 0 )
  1523. {
  1524. rc = InternalClipperRelease( pclipper_int );
  1525. /* GEE: 0 is now an error code,
  1526. * errors weren't handled before anyway,
  1527. * does this matter.
  1528. */
  1529. if( rc == 0 )
  1530. {
  1531. break;
  1532. }
  1533. rcnt--;
  1534. }
  1535. }
  1536. else
  1537. {
  1538. DPF( 5, "Process %08lx does not have access to clipper" );
  1539. }
  1540. pclipper_int = ppnext_int;
  1541. }
  1542. /*
  1543. * Now clean up the global clipper list.
  1544. * If the pdrv_lcl parameter is not NULL then we are only cleaning up clipper
  1545. * objects created by a particular local driver object. In this case we
  1546. * do not want to free the global clippers.
  1547. *
  1548. * NOTE: The DirectDraw lock is taken so we can safely access this global object.
  1549. */
  1550. if( NULL != pdrv_lcl )
  1551. {
  1552. DPF( 4, "Not cleaning up clippers not owned by a driver object");
  1553. return;
  1554. }
  1555. DPF( 4, "Cleaning up clippers not owned by a driver object" );
  1556. pclipper_int = lpGlobalClipperList;
  1557. while( pclipper_int != NULL )
  1558. {
  1559. ppnext_int = pclipper_int->lpLink;
  1560. /*
  1561. * The clippers in this list should never have a back pointer to a driver
  1562. * object.
  1563. */
  1564. DDASSERT( pclipper_int->lpLcl->lpGbl->lpDD == NULL );
  1565. rc = 1;
  1566. if( pclipper_int->lpLcl->lpGbl->dwProcessId == pid )
  1567. {
  1568. /*
  1569. * release the references by this process
  1570. */
  1571. rcnt = pclipper_int->dwIntRefCnt;
  1572. while( rcnt > 0 )
  1573. {
  1574. rc = InternalClipperRelease( pclipper_int );
  1575. /* GEE: 0 is now an error code,
  1576. * errors weren't handled before anyway,
  1577. * does this matter.
  1578. */
  1579. if( rc == 0 )
  1580. {
  1581. break;
  1582. }
  1583. rcnt--;
  1584. }
  1585. }
  1586. pclipper_int = ppnext_int;
  1587. }
  1588. DPF( 4, "Done ProcessClipperCleanup" );
  1589. } /* ProcessClipperCleanup */