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.

1774 lines
52 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name: miscgdi.cxx
  3. *
  4. * Misc. GDI routines
  5. *
  6. * Created: 13-Aug-1990 by undead
  7. *
  8. * Copyright (c) 1989-1999 Microsoft Corporation
  9. \**************************************************************************/
  10. #include "precomp.hxx"
  11. //
  12. // GCAPS2_SYNCFLUSH and GCAPS2_SYNCTIMER globals
  13. //
  14. LONG gcSynchronizeFlush = -1;
  15. LONG gcSynchronizeTimer = -1;
  16. UINT_PTR gidSynchronizeTimer;
  17. //
  18. // GCAPS2_SYNCTIMER timer interval, in milliseconds
  19. //
  20. #define SYNCTIMER_FREQUENCY 50
  21. /******************************Public*Routine******************************\
  22. * GreSaveScreenBits (hdev,iMode,iIdent,prcl)
  23. *
  24. * Passes the call to the device driver, or returns doing nothing. This
  25. * call is pretty fast, no locks are done.
  26. *
  27. * Fri 11-Sep-1992 -by- Patrick Haluptzok [patrickh]
  28. * Add cursor exclusion.
  29. *
  30. * Thu 27-Aug-1992 16:40:42 -by- Charles Whitmer [chuckwh]
  31. * Wrote it.
  32. \**************************************************************************/
  33. ULONG_PTR GreSaveScreenBits(HDEV hdev,ULONG iMode,ULONG_PTR iIdent,RECTL *prcl)
  34. {
  35. ULONG_PTR ulReturn = 0;
  36. RECTL rcl = {0,0,0,0};
  37. PDEVOBJ po(hdev);
  38. GreAcquireSemaphoreEx(po.hsemDevLock(), SEMORDER_DEVLOCK, NULL);
  39. GreEnterMonitoredSection(po.ppdev, WD_DEVLOCK);
  40. if (!po.bDisabled())
  41. {
  42. PFN_DrvSaveScreenBits pfn = PPFNDRV(po,SaveScreenBits);
  43. if (pfn != (PFN_DrvSaveScreenBits) NULL)
  44. {
  45. DEVEXCLUDEOBJ dxo;
  46. if (iMode == SS_FREE)
  47. {
  48. // Make if a very small rectangle.
  49. prcl = &rcl;
  50. }
  51. ASSERTGDI(po.bDisplayPDEV(), "ERROR");
  52. ulReturn = (*pfn)(po.pSurface()->pSurfobj(),iMode,iIdent,prcl);
  53. }
  54. }
  55. #if DBG
  56. else
  57. {
  58. if (iMode == SS_FREE)
  59. WARNING("GreSaveScreenBits called to free memory in full screen - memory lost\n");
  60. }
  61. #endif
  62. GreExitMonitoredSection(po.ppdev, WD_DEVLOCK);
  63. GreReleaseSemaphoreEx(po.hsemDevLock());
  64. return(ulReturn);
  65. }
  66. /******************************Public*Routine******************************\
  67. * GreValidateSurfaceHandle
  68. *
  69. * This allows USER to validate handles passed to it by the client side.
  70. *
  71. * Returns: TRUE if handle is valid and of the correct type,
  72. * FALSE otherwise.
  73. *
  74. * History:
  75. * 06-Sep-1991 -by- Patrick Haluptzok patrickh
  76. * Wrote it.
  77. \**************************************************************************/
  78. BOOL GreValidateServerHandle(HANDLE hobj, ULONG ulType)
  79. {
  80. return(HmgValidHandle((HOBJ)hobj, (OBJTYPE) ulType));
  81. }
  82. /******************************Public*Routine******************************\
  83. * GreSetBrushOrg
  84. *
  85. * Set the application defined brush origin into the DC
  86. *
  87. * Returns: Old brush origin
  88. *
  89. * History:
  90. * 30-Oct-1990 -by- Patrick Haluptzok patrickh
  91. * Wrote it.
  92. \**************************************************************************/
  93. BOOL GreSetBrushOrg(
  94. HDC hdc,
  95. int x,
  96. int y,
  97. LPPOINT ptl_)
  98. {
  99. DCOBJ dco(hdc);
  100. PPOINTL ptl = (PPOINTL)ptl_;
  101. if (dco.bValid())
  102. {
  103. if (ptl != NULL)
  104. *ptl = dco.pdc->ptlBrushOrigin();
  105. //
  106. // update DCATTR brush org
  107. //
  108. dco.pdc->pDCAttr->ptlBrushOrigin.x = x;
  109. dco.pdc->pDCAttr->ptlBrushOrigin.y = y;
  110. //
  111. // update km brush prg
  112. //
  113. dco.pdc->ptlBrushOrigin((LONG)x,(LONG)y);
  114. return(TRUE);
  115. }
  116. else
  117. {
  118. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  119. return(FALSE);
  120. }
  121. }
  122. /******************************Public*Routine******************************\
  123. * GreGetBrushOrg
  124. *
  125. * Returns: Old application brush origin
  126. *
  127. * History:
  128. * 30-Oct-1990 -by- Patrick Haluptzok patrickh
  129. * Wrote it.
  130. \**************************************************************************/
  131. BOOL GreGetBrushOrg(HDC hdc,PPOINT ptl_)
  132. {
  133. DCOBJ dco(hdc);
  134. PPOINTL ptl = (PPOINTL)ptl_;
  135. if (dco.bValid())
  136. {
  137. *ptl = dco.pdc->ptlBrushOrigin();
  138. return(TRUE);
  139. }
  140. else
  141. return(FALSE);
  142. }
  143. /******************************Public*Routine******************************\
  144. * vGetDeviceCaps()
  145. *
  146. * Common device capabilities routine.
  147. *
  148. \**************************************************************************/
  149. VOID vGetDeviceCaps(
  150. PDEVOBJ& po,
  151. PDEVCAPS pDevCaps
  152. )
  153. {
  154. GDIINFO* pGdiInfo;
  155. pGdiInfo = po.GdiInfoNotDynamic(); // Use of this local removes pointer
  156. // dereferences
  157. pDevCaps->ulVersion = pGdiInfo->ulVersion;
  158. pDevCaps->ulTechnology = pGdiInfo->ulTechnology;
  159. // Note that ul*Size fields are now in micrometers
  160. pDevCaps->ulHorzSizeM = (pGdiInfo->ulHorzSize+500)/1000;
  161. pDevCaps->ulVertSizeM = (pGdiInfo->ulVertSize+500)/1000;
  162. pDevCaps->ulHorzSize = pGdiInfo->ulHorzSize;
  163. pDevCaps->ulVertSize = pGdiInfo->ulVertSize;
  164. pDevCaps->ulHorzRes = pGdiInfo->ulHorzRes;
  165. pDevCaps->ulVertRes = pGdiInfo->ulVertRes;
  166. pDevCaps->ulBitsPixel = pGdiInfo->cBitsPixel;
  167. if (pDevCaps->ulBitsPixel == 15)
  168. pDevCaps->ulBitsPixel = 16; // Some apps, such as PaintBrush or
  169. // NetScape, break if we return 15bpp
  170. pDevCaps->ulPlanes = pGdiInfo->cPlanes;
  171. pDevCaps->ulNumPens = (pGdiInfo->ulNumColors == (ULONG)-1) ?
  172. (ULONG)-1 : 5 * pGdiInfo->ulNumColors;
  173. pDevCaps->ulNumFonts = po.cFonts();
  174. pDevCaps->ulNumColors = pGdiInfo->ulNumColors;
  175. pDevCaps->ulRasterCaps = pGdiInfo->flRaster;
  176. pDevCaps->ulShadeBlendCaps = pGdiInfo->flShadeBlend;
  177. pDevCaps->ulAspectX = pGdiInfo->ulAspectX;
  178. pDevCaps->ulAspectY = pGdiInfo->ulAspectY;
  179. pDevCaps->ulAspectXY = pGdiInfo->ulAspectXY;
  180. pDevCaps->ulLogPixelsX = pGdiInfo->ulLogPixelsX;
  181. pDevCaps->ulLogPixelsY = pGdiInfo->ulLogPixelsY;
  182. pDevCaps->ulSizePalette = pGdiInfo->ulNumPalReg;
  183. pDevCaps->ulColorRes = pGdiInfo->ulDACRed + pGdiInfo->ulDACGreen + pGdiInfo->ulDACBlue;
  184. pDevCaps->ulPhysicalWidth = pGdiInfo->szlPhysSize.cx;
  185. pDevCaps->ulPhysicalHeight = pGdiInfo->szlPhysSize.cy;
  186. pDevCaps->ulPhysicalOffsetX = pGdiInfo->ptlPhysOffset.x;
  187. pDevCaps->ulPhysicalOffsetY = pGdiInfo->ptlPhysOffset.y;
  188. pDevCaps->ulTextCaps = pGdiInfo->flTextCaps;
  189. pDevCaps->ulTextCaps |= (TC_OP_CHARACTER | TC_OP_STROKE | TC_CP_STROKE |
  190. TC_UA_ABLE | TC_SO_ABLE);
  191. if (pGdiInfo->ulTechnology != DT_PLOTTER)
  192. pDevCaps->ulTextCaps |= TC_VA_ABLE;
  193. pDevCaps->ulVRefresh = pGdiInfo->ulVRefresh;
  194. pDevCaps->ulDesktopHorzRes = pGdiInfo->ulHorzRes;
  195. pDevCaps->ulDesktopVertRes = pGdiInfo->ulVertRes;
  196. pDevCaps->ulBltAlignment = pGdiInfo->ulBltAlignment;
  197. pDevCaps->ulColorManagementCaps
  198. = GetColorManagementCaps(po);
  199. }
  200. /******************************Public*Routine******************************\
  201. * NtGdiGetDeviceCapsAll()
  202. *
  203. * Get all the adjustable device caps for the dc. Allows us to cache this
  204. * information on the client side.
  205. *
  206. * History:
  207. * 09-Jan-1996 -by- Lingyun Wang [lingyunw]
  208. * Made it based on GreGetDeviceCapsAll from the old client\server code.
  209. \**************************************************************************/
  210. BOOL
  211. APIENTRY
  212. NtGdiGetDeviceCapsAll(
  213. HDC hdc,
  214. PDEVCAPS pDevCaps
  215. )
  216. {
  217. BOOL bRet = TRUE;
  218. DEVCAPS devCapsTmp;
  219. // Lock the destination and its transform.
  220. DCOBJ dco(hdc);
  221. // return FALSE if it is a invalid DC
  222. if (!dco.bValid())
  223. {
  224. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  225. return(FALSE);
  226. }
  227. // Lock down the pdev
  228. PDEVOBJ po(dco.hdev());
  229. ASSERTGDI(po.bValid(), "Invalid PDEV");
  230. __try
  231. {
  232. ProbeForWrite(pDevCaps, sizeof(DEVCAPS), sizeof(BYTE));
  233. vGetDeviceCaps(po, pDevCaps);
  234. }
  235. __except(EXCEPTION_EXECUTE_HANDLER)
  236. {
  237. WARNING ("try-except failed IN NtGdiGetDeviceCapsAll\n");
  238. // SetLastError(GetExceptionCode());
  239. bRet = FALSE;
  240. }
  241. return(bRet);
  242. }
  243. /******************************Public*Routine******************************\
  244. * GreUpdateSharedDevCaps()
  245. *
  246. * Update the device caps in the shared memory
  247. *
  248. * History:
  249. * 09-Jan-1996 -by- Lingyun Wang [lingyunw]
  250. * Made it based on GreGetDeviceCapsAll from the old client\server code.
  251. \**************************************************************************/
  252. BOOL
  253. GreUpdateSharedDevCaps(
  254. HDEV hdev
  255. )
  256. {
  257. PDEVOBJ po(hdev);
  258. ASSERTGDI(po.bValid(), "Invalid HDEV");
  259. vGetDeviceCaps(po, gpGdiDevCaps);
  260. return(TRUE);
  261. }
  262. /******************************Public*Routine******************************\
  263. * GreGetDeviceCaps
  264. *
  265. * Returns: device driver specific information
  266. *
  267. * NOTE: This function MUST mirror NtGdiGetDeviceCapsAll and that in
  268. * client\dcquery.c!
  269. *
  270. * History:
  271. * 01-Mar-1992 -by- Donald Sidoroff [donalds]
  272. * Rewritten to corrected GDIINFO structure.
  273. *
  274. * 30-Oct-1990 -by- Patrick Haluptzok patrickh
  275. * Wrote it.
  276. \**************************************************************************/
  277. int GreGetDeviceCaps(HDC hdc, int lIndex)
  278. {
  279. // Init return value
  280. int iRet = 0;
  281. // Lock the destination and its transform.
  282. DCOBJ dco(hdc);
  283. if (dco.bValid())
  284. {
  285. // Lock down the pdev
  286. PDEVOBJ po(dco.hdev());
  287. ASSERTGDI(po.bValid(), "Invalid PDEV");
  288. // Note that dynamic mode changes may cause the GDIINFO data to change
  289. // at any time (but not the actual 'pGdiInfo' pointer):
  290. GDIINFO* pGdiInfo = po.GdiInfoNotDynamic();
  291. switch (lIndex)
  292. {
  293. case DRIVERVERSION: // Version = 0100h for now
  294. iRet = (pGdiInfo->ulVersion);
  295. break;
  296. case TECHNOLOGY: // Device classification
  297. iRet = (pGdiInfo->ulTechnology);
  298. break;
  299. case HORZSIZE: // Horizontal size in millimeters
  300. iRet = (pGdiInfo->ulHorzSize+500)/1000;
  301. break;
  302. case VERTSIZE: // Vertical size in millimeters
  303. iRet = (pGdiInfo->ulVertSize+500)/1000;
  304. break;
  305. case HORZRES: // Horizontal width in pixels
  306. iRet = (pGdiInfo->ulHorzRes);
  307. break;
  308. case VERTRES: // Vertical height in pixels
  309. iRet = (pGdiInfo->ulVertRes);
  310. break;
  311. case BITSPIXEL: // Number of bits per pixel
  312. iRet = (pGdiInfo->cBitsPixel);
  313. if (iRet == 15)
  314. iRet = 16; // Some apps, such as PaintBrush or
  315. // NetScape, break if we return 15bpp
  316. break;
  317. case PLANES: // Number of planes
  318. iRet = (pGdiInfo->cPlanes);
  319. break;
  320. case NUMBRUSHES: // Number of brushes the device has
  321. iRet = (-1);
  322. break;
  323. case NUMPENS: // Number of pens the device has
  324. iRet = (pGdiInfo->ulNumColors == (ULONG)-1) ?
  325. (ULONG)-1 : 5 * pGdiInfo->ulNumColors;
  326. break;
  327. case NUMMARKERS: // Number of markers the device has
  328. iRet = (0);
  329. break;
  330. case NUMFONTS: // Number of fonts the device has
  331. iRet = (po.cFonts());
  332. break;
  333. case NUMCOLORS: // Number of colors in color table
  334. iRet = (pGdiInfo->ulNumColors);
  335. break;
  336. case PDEVICESIZE: // Size required for the device descriptor
  337. iRet = (0);
  338. break;
  339. case CURVECAPS: // Curves capabilities
  340. iRet = (CC_CIRCLES |
  341. CC_PIE |
  342. CC_CHORD |
  343. CC_ELLIPSES |
  344. CC_WIDE |
  345. CC_STYLED |
  346. CC_WIDESTYLED |
  347. CC_INTERIORS |
  348. CC_ROUNDRECT);
  349. break;
  350. case LINECAPS: // Line capabilities
  351. iRet = (LC_POLYLINE |
  352. LC_MARKER |
  353. LC_POLYMARKER |
  354. LC_WIDE |
  355. LC_STYLED |
  356. LC_WIDESTYLED |
  357. LC_INTERIORS);
  358. break;
  359. case POLYGONALCAPS: // Polygonal capabilities
  360. iRet = (PC_POLYGON |
  361. PC_RECTANGLE |
  362. PC_WINDPOLYGON |
  363. PC_TRAPEZOID |
  364. PC_SCANLINE |
  365. PC_WIDE |
  366. PC_STYLED |
  367. PC_WIDESTYLED |
  368. PC_INTERIORS);
  369. break;
  370. case TEXTCAPS: // Text capabilities
  371. {
  372. FLONG fl = pGdiInfo->flTextCaps;
  373. // Engine will simulate vector fonts on raster devices.
  374. if (pGdiInfo->ulTechnology != DT_PLOTTER)
  375. fl |= TC_VA_ABLE;
  376. // Turn underlining, strikeout. Engine will do it for device if needed.
  377. fl |= (TC_UA_ABLE | TC_SO_ABLE);
  378. // Return flag.
  379. iRet = fl;
  380. break;
  381. }
  382. case CLIPCAPS: // Clipping capabilities
  383. iRet = (CP_RECTANGLE);
  384. break;
  385. case RASTERCAPS: // Bitblt capabilities
  386. iRet = (pGdiInfo->flRaster);
  387. break;
  388. case SHADEBLENDCAPS: // Shade and blend capabilities
  389. iRet = (pGdiInfo->flShadeBlend);
  390. break;
  391. case ASPECTX: // Length of X leg
  392. iRet = (pGdiInfo->ulAspectX);
  393. break;
  394. case ASPECTY: // Length of Y leg
  395. iRet = (pGdiInfo->ulAspectY);
  396. break;
  397. case ASPECTXY: // Length of hypotenuse
  398. iRet = (pGdiInfo->ulAspectXY);
  399. break;
  400. case LOGPIXELSX: // Logical pixels/inch in X
  401. iRet = (pGdiInfo->ulLogPixelsX);
  402. break;
  403. case LOGPIXELSY: // Logical pixels/inch in Y
  404. iRet = (pGdiInfo->ulLogPixelsY);
  405. break;
  406. case SIZEPALETTE: // # entries in physical palette
  407. iRet = (pGdiInfo->ulNumPalReg);
  408. break;
  409. case NUMRESERVED: // # reserved entries in palette
  410. iRet = (20);
  411. break;
  412. case COLORRES:
  413. iRet = (pGdiInfo->ulDACRed + pGdiInfo->ulDACGreen + pGdiInfo->ulDACBlue);
  414. break;
  415. case PHYSICALWIDTH: // Physical Width in device units
  416. iRet = (pGdiInfo->szlPhysSize.cx);
  417. break;
  418. case PHYSICALHEIGHT: // Physical Height in device units
  419. iRet = (pGdiInfo->szlPhysSize.cy);
  420. break;
  421. case PHYSICALOFFSETX: // Physical Printable Area x margin
  422. iRet = (pGdiInfo->ptlPhysOffset.x);
  423. break;
  424. case PHYSICALOFFSETY: // Physical Printable Area y margin
  425. iRet = (pGdiInfo->ptlPhysOffset.y);
  426. break;
  427. case VREFRESH: // Vertical refresh rate of the device
  428. iRet = (pGdiInfo->ulVRefresh);
  429. break;
  430. //
  431. // NOTE : temporarily disable this feature for the BETA.
  432. // We will reenable when the engine does it.
  433. //
  434. case DESKTOPHORZRES: // Width of entire virtual desktop
  435. iRet = (pGdiInfo->ulHorzRes);
  436. break;
  437. case DESKTOPVERTRES: // Height of entire virtual desktop
  438. iRet = (pGdiInfo->ulVertRes);
  439. break;
  440. case BLTALIGNMENT: // Preferred blt alignment
  441. iRet = (pGdiInfo->ulBltAlignment);
  442. break;
  443. case HORZSIZEM: // Horizontal size in millimeters/1000
  444. iRet = pGdiInfo->ulHorzSize;
  445. break;
  446. case VERTSIZEM: // Vertical size in millimeters/1000
  447. iRet = pGdiInfo->ulVertSize;
  448. break;
  449. case CAPS1: // InternalCaps
  450. iRet = (po.ppdev->pGraphicsDevice->stateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) ?
  451. C1_MIRROR_DEVICE : 0;
  452. break;
  453. case COLORMGMTCAPS: // Color management capabilities
  454. iRet = GetColorManagementCaps(po);
  455. default:
  456. iRet = 0;
  457. }
  458. }
  459. return(iRet);
  460. }
  461. /******************************Public*Routine******************************\
  462. * BOOL GreDeleteObject(HOBJ)
  463. *
  464. * History:
  465. * Fri 13-Sep-1991 -by- Patrick Haluptzok [patrickh]
  466. * added DC deletion
  467. *
  468. * Tue 27-Nov-1990 -by- Patrick Haluptzok [patrickh]
  469. * added palette deletion, surface deletion, brush deletion.
  470. *
  471. * Wed 22-Aug-1990 Greg Veres [w-gregv]
  472. * Wrote it.
  473. \**************************************************************************/
  474. BOOL APIENTRY GreDeleteObject (HANDLE hobj)
  475. {
  476. int ii;
  477. // don't allow deletion of stock objects, just succeed
  478. if (HmgStockObj(hobj))
  479. {
  480. return(TRUE);
  481. }
  482. switch (HmgObjtype(hobj))
  483. {
  484. case RGN_TYPE:
  485. return(bDeleteRegion((HRGN) hobj));
  486. case SURF_TYPE:
  487. return(bDeleteSurface((HSURF)hobj));
  488. case PAL_TYPE:
  489. return(bDeletePalette((HPAL) hobj));
  490. case LFONT_TYPE:
  491. // see if its in cfont list.
  492. for (ii = 0; ii < MAX_PUBLIC_CFONT; ++ii)
  493. {
  494. if (gpGdiSharedMemory->acfPublic[ii].hf == hobj)
  495. {
  496. // just nuke the hfont as this invalidates the whole entry
  497. gpGdiSharedMemory->acfPublic[ii].hf = 0;
  498. break;
  499. }
  500. }
  501. return(bDeleteFont((HLFONT) hobj, FALSE));
  502. case BRUSH_TYPE:
  503. return(bDeleteBrush((HBRUSH) hobj, FALSE));
  504. case DC_TYPE:
  505. return(bDeleteDCInternal((HDC) hobj,TRUE,FALSE));
  506. default:
  507. return(FALSE);
  508. }
  509. }
  510. /******************************Public*Routine******************************\
  511. * NtGdiDeleteObjectApp()
  512. *
  513. * Same as DeleteObject() but doesn't allow public objects to be deleted.
  514. * This should only be called from server.c coming from the client. User
  515. * and console should call the DeleteObject().
  516. *
  517. * History:
  518. * 01-Nov-1994 -by- Eric Kutter [erick]
  519. * Wrote it.
  520. \**************************************************************************/
  521. BOOL
  522. APIENTRY
  523. NtGdiDeleteObjectApp(
  524. HANDLE hobj
  525. )
  526. {
  527. ULONG objt;
  528. // don't allow deletion of stock objects, just succeed
  529. if (HmgStockObj(hobj))
  530. {
  531. return(TRUE);
  532. }
  533. objt = HmgObjtype(hobj);
  534. // check if it is a public object. If it is, check if it is a public deletable
  535. // surface set by user.
  536. if (GreGetObjectOwner((HOBJ)hobj,objt) == OBJECT_OWNER_PUBLIC)
  537. {
  538. if (objt == SURF_TYPE)
  539. {
  540. WARNING("Trying to delete public surface!");
  541. }
  542. #if 0
  543. BOOL bMsg = TRUE;
  544. if (objt == BRUSH_TYPE)
  545. {
  546. BRUSHSELOBJ bo(hbrush);
  547. if (bo.bValid() || bo.bIsGlobal())
  548. bMsg = FALSE;
  549. }
  550. if (bMsg)
  551. {
  552. DbgPrint("GDI Warning: app trying to delete public object %lx\n",hobj);
  553. }
  554. #endif
  555. //
  556. // return FALSE if hobj == NULL
  557. // otherwise TRUE
  558. //
  559. return(hobj != NULL);
  560. }
  561. switch (objt)
  562. {
  563. case RGN_TYPE:
  564. return(bDeleteRegion((HRGN) hobj));
  565. case SURF_TYPE:
  566. return(bDeleteSurface((HSURF)hobj));
  567. case PAL_TYPE:
  568. return(bDeletePalette((HPAL) hobj));
  569. case LFONT_TYPE:
  570. return(bDeleteFont((HLFONT) hobj, FALSE));
  571. case BRUSH_TYPE:
  572. return(bDeleteBrush((HBRUSH) hobj, FALSE));
  573. case DC_TYPE:
  574. // don't allow deletion of DC's by an app if the undeletable flag is set
  575. return(bDeleteDCInternal((HDC) hobj,FALSE,FALSE));
  576. default:
  577. return(FALSE);
  578. }
  579. }
  580. /******************************Public*Routine******************************\
  581. * cjGetBrushOrPen
  582. *
  583. * Gets brush or pen object data.
  584. *
  585. * For extended pens, some information such as the style array are kept
  586. * only on this, the server side. Most of the brush data is also kept
  587. * on the client side for GetObject.
  588. *
  589. * returns: Number of bytes needed if pvDest == NULL, else bytes copied out.
  590. * For error it returns 0.
  591. *
  592. * History:
  593. * Thu 23-Mar-1992 -by- J. Andrew Goossen [andrewgo]
  594. * Wrote it.
  595. \**************************************************************************/
  596. LONG cjGetBrushOrPen(HANDLE hobj, int iCount, LPVOID pvDest)
  597. {
  598. LONG lRet = 0;
  599. BRUSHSELOBJ bro((HBRUSH) hobj);
  600. // NOTE SIZE: Most of this is bunk, since for NT all brush data is kept on the
  601. // client side, and so some of this code path won't even be
  602. // executed. [andrewgo]
  603. //
  604. // And for DOS, we would return some fields as zero, whereas under
  605. // NT we would always return what we were given. [andrewgo]
  606. if (bro.bValid())
  607. {
  608. if (bro.bIsOldStylePen())
  609. {
  610. // Old style pen...
  611. bSyncBrushObj(bro.pbrush());
  612. if (pvDest == (LPVOID) NULL)
  613. {
  614. lRet = sizeof(LOGPEN);
  615. }
  616. else if (iCount >= sizeof(LOGPEN))
  617. {
  618. if ((iCount == (int) sizeof(EXTLOGPEN)) &&
  619. ((UINT) bro.flStylePen() == PS_NULL))
  620. {
  621. //moved the NULL extended pen handling from client
  622. //side to server side
  623. PEXTLOGPEN pelp = (PEXTLOGPEN) pvDest;
  624. pelp->elpPenStyle = PS_NULL;
  625. pelp->elpWidth = 0;
  626. pelp->elpBrushStyle = 0;
  627. pelp->elpColor = 0;
  628. pelp->elpHatch = 0;
  629. pelp->elpNumEntries = 0;
  630. lRet = sizeof(EXTLOGPEN);
  631. }
  632. else
  633. {
  634. // Fill in the logical pen.
  635. ((LOGPEN *) pvDest)->lopnStyle = (UINT) bro.flStylePen();
  636. ((LOGPEN *) pvDest)->lopnWidth.x = (int) bro.lWidthPen();
  637. ((LOGPEN *) pvDest)->lopnWidth.y = 0;
  638. ((LOGPEN *) pvDest)->lopnColor = bro.clrPen();
  639. lRet = sizeof(LOGPEN);
  640. }
  641. }
  642. }
  643. else if (bro.bIsPen())
  644. {
  645. // Extended pen...
  646. ULONG cstyle = (bro.bIsUserStyled()) ? bro.cstyle() : 0;
  647. int cj = (int) (sizeof(EXTLOGPEN) - sizeof(DWORD) +
  648. sizeof(DWORD) * (SIZE_T) cstyle);
  649. if (pvDest == (LPVOID) NULL)
  650. {
  651. lRet = cj;
  652. }
  653. else if (iCount >= cj)
  654. {
  655. PEXTLOGPEN pelp = (PEXTLOGPEN) pvDest;
  656. pelp->elpPenStyle = (UINT) bro.flStylePen();
  657. pelp->elpWidth = (UINT) bro.lWidthPen();
  658. pelp->elpNumEntries = cstyle;
  659. if (cstyle > 0)
  660. {
  661. // We can't just do a RtlCopyMemory for cosmetics, because
  662. // we don't know how the LONGs are packed in the
  663. // FLOAT_LONG array:
  664. PFLOAT_LONG pelSrc = bro.pstyle();
  665. PLONG plDest = (PLONG) &pelp->elpStyleEntry[0];
  666. for (; cstyle > 0; cstyle--)
  667. {
  668. if (bro.bIsCosmetic())
  669. *plDest = pelSrc->l;
  670. else
  671. {
  672. EFLOATEXT efLength(pelSrc->e);
  673. BOOL b = efLength.bEfToL(*plDest);
  674. ASSERTGDI(b, "Shouldn't have overflowed");
  675. }
  676. plDest++;
  677. pelSrc++;
  678. }
  679. }
  680. // The client side GetObject will fill in the rest of the
  681. // EXTLOGPEN struct. i.e. elpBrushStyle, elpColor, and elpHatch.
  682. // Changed: added these here -30-11-94 -by- Lingyunw
  683. // added lBrushStyle and lHatch to PEN
  684. pelp->elpBrushStyle = bro.lBrushStyle();
  685. pelp->elpColor = bro.crColor();
  686. pelp->elpHatch = bro.lHatch();
  687. lRet = cj;
  688. }
  689. }
  690. else
  691. {
  692. // Brush...
  693. if (pvDest == (LPVOID) NULL)
  694. {
  695. lRet = sizeof(LOGBRUSH);
  696. }
  697. else if (iCount >= sizeof(LOGBRUSH))
  698. {
  699. // make sure the kernel attributes match
  700. bSyncBrushObj(bro.pbrush());
  701. // Fill in logical brush. Figure out what type it is.
  702. // Duplicates of this info is kept on the client side,
  703. // so most calls won't even get here:
  704. if (bro.flAttrs() & BR_IS_SOLID)
  705. {
  706. ((LOGBRUSH *) pvDest)->lbStyle = BS_SOLID;
  707. ((LOGBRUSH *) pvDest)->lbColor = bro.crColor();
  708. ((LOGBRUSH *) pvDest)->lbHatch = 0;
  709. }
  710. else if (bro.flAttrs() & BR_IS_BITMAP)
  711. {
  712. ((LOGBRUSH *) pvDest)->lbStyle = BS_PATTERN;
  713. ((LOGBRUSH *) pvDest)->lbColor = 0;
  714. ((LOGBRUSH *) pvDest)->lbHatch = (ULONG_PTR)bro.hbmClient();
  715. }
  716. else if (bro.flAttrs() & BR_IS_HATCH)
  717. {
  718. ((LOGBRUSH *) pvDest)->lbStyle = BS_HATCHED;
  719. ((LOGBRUSH *) pvDest)->lbColor = bro.crColor();
  720. ((LOGBRUSH *) pvDest)->lbHatch = bro.ulStyle();
  721. }
  722. else if (bro.flAttrs() & BR_IS_NULL)
  723. {
  724. ((LOGBRUSH *) pvDest)->lbStyle = BS_HOLLOW;
  725. ((LOGBRUSH *) pvDest)->lbColor = 0;
  726. ((LOGBRUSH *) pvDest)->lbHatch = 0;
  727. }
  728. else if (bro.flAttrs() & BR_IS_DIB)
  729. {
  730. // Could be BS_DIBPATTERN or BS_DIBPATTERNPT, but we'll just
  731. // return BS_DIBPATTERN.
  732. ((LOGBRUSH *) pvDest)->lbStyle = BS_DIBPATTERN;
  733. ((LOGBRUSH *) pvDest)->lbColor = bro.crColor();
  734. ((LOGBRUSH *) pvDest)->lbHatch = (ULONG_PTR)bro.hbmClient();
  735. }
  736. else
  737. RIP("ERROR GreGetObject invalid brush type");
  738. lRet = sizeof(LOGBRUSH);
  739. }
  740. }
  741. }
  742. else
  743. {
  744. WARNING1("cjGetBrushOrPen():hobj is invalid\n");
  745. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  746. }
  747. return(lRet);
  748. }
  749. /******************************Public*Routine******************************\
  750. * GreGetObject
  751. *
  752. * API function
  753. *
  754. * returns: number of bytes needed if pvDest == NULL, else bytes copied out
  755. * for error it returns 0
  756. *
  757. * in case a log font object is requested, the function will fill the buffer with
  758. * as many bytes of the EXTLOGFONT structure as requested. If a caller
  759. * wants a LOGFONTW structure in the buffer, he should specify
  760. * ulCount == sizeof(LOGFONTW)
  761. * The function will copy the first sizeof(LOGFONTW) bytes of the EXTLOGFONTW
  762. * structure to the buffer, which is precisely the LOGFONTW structure. The rest
  763. * of the EXTLOGFONTW structure will be chopped off.
  764. *
  765. * History:
  766. *
  767. * Thu 12-Dec-1996 -by- Bodin Dresevic [BodinD]
  768. * update: changed EXTLOGFONT to ENUMLOGFONTEXDVW
  769. *
  770. * Thu 30-Jan-1992 -by- J. Andrew Goossen [andrewgo]
  771. * added extended pen support.
  772. *
  773. * Wed 21-Aug-1991 -by- Bodin Dresevic [BodinD]
  774. * update: converted to return EXTLOGFONTW
  775. *
  776. * Fri 24-May-1991 -by- Patrick Haluptzok [patrickh]
  777. * added first pass pen and brush stuff.
  778. *
  779. * Tue 24-Apr-1991 -by- Patrick Haluptzok [patrickh]
  780. * added surface stuff.
  781. *
  782. * 08-Dec-1990 -by- Patrick Haluptzok patrickh
  783. * Wrote it.
  784. \**************************************************************************/
  785. int APIENTRY GreExtGetObjectW(HANDLE hobj, int ulCount, LPVOID pvDest)
  786. {
  787. int cRet = 0;
  788. switch (HmgObjtype(hobj))
  789. {
  790. case PAL_TYPE:
  791. cRet = 2;
  792. if (pvDest != NULL)
  793. {
  794. if (ulCount < 2)
  795. {
  796. cRet = 0;
  797. }
  798. else
  799. {
  800. SEMOBJ semo(ghsemPalette);
  801. {
  802. EPALOBJ pal((HPALETTE) hobj);
  803. if (!(pal.bValid()))
  804. cRet = 0;
  805. else
  806. *((PUSHORT) pvDest) = (USHORT) (pal.cEntries());
  807. }
  808. }
  809. }
  810. break;
  811. case LFONT_TYPE:
  812. // The output object is assumed to be
  813. // an ENUMLOGFONTEXDVW structure.
  814. // client side shall do the translation to LOGFONT if necessary
  815. {
  816. LFONTOBJ lfo((HLFONT) hobj);
  817. if (lfo.bValid())
  818. {
  819. if (pvDest != (LPVOID) NULL)
  820. {
  821. SIZE_T cjCopy = MIN((SIZE_T) ulCount, lfo.cjElfw());
  822. RtlCopyMemory(pvDest, lfo.pelfw(), (UINT) cjCopy);
  823. cRet = (ULONG) cjCopy;
  824. }
  825. else
  826. {
  827. cRet = lfo.cjElfw();
  828. }
  829. }
  830. else
  831. {
  832. WARNING("GreGetObject(): bad handle\n");
  833. }
  834. }
  835. break;
  836. case SURF_TYPE:
  837. if (pvDest != (LPVOID) NULL)
  838. {
  839. cRet = 0;
  840. if (ulCount >= (int)sizeof(BITMAP))
  841. {
  842. SURFREF SurfBm((HSURF) hobj);
  843. if ((SurfBm.bValid()) &&
  844. (SurfBm.ps->bApiBitmap() || SurfBm.ps->bDirectDraw()))
  845. {
  846. BITMAP *pbm = (BITMAP *) pvDest;
  847. pbm->bmType = 0;
  848. pbm->bmWidth = SurfBm.ps->sizl().cx;
  849. pbm->bmHeight = SurfBm.ps->sizl().cy;
  850. pbm->bmBitsPixel = (WORD) gaulConvert[SurfBm.ps->iFormat()];
  851. pbm->bmWidthBytes = ((SurfBm.ps->sizl().cx * pbm->bmBitsPixel + 15) >> 4) << 1;
  852. pbm->bmPlanes = 1;
  853. pbm->bmBits = (LPSTR) NULL;
  854. cRet = sizeof(BITMAP);
  855. // Get the bitmapinfoheader for the dibsection if the buffer
  856. // can hold it.
  857. if (SurfBm.ps->bDIBSection() || SurfBm.ps->bDirectDraw())
  858. {
  859. // Win95 compatability. They fill in the bits even if it
  860. // is not big enough for a full DIBSECTION
  861. pbm->bmBits = IS_USER_ADDRESS((LPSTR) SurfBm.ps->pvBits()) ? (LPSTR) SurfBm.ps->pvBits() : NULL;
  862. // If this is a DIBSection/DirectDraw surface bmWidthBytes must be aligned
  863. // on a DWORD boundary.
  864. pbm->bmWidthBytes = ((SurfBm.ps->sizl().cx * pbm->bmBitsPixel + 31) & ~31) >> 3;
  865. if (ulCount >= sizeof(DIBSECTION))
  866. {
  867. PBITMAPINFOHEADER pbmih = &((DIBSECTION *)pvDest)->dsBmih;
  868. pbmih->biSize = sizeof(BITMAPINFOHEADER);
  869. pbmih->biBitCount = 0;
  870. if (GreGetDIBitsInternal(0,(HBITMAP)hobj,0,0,NULL,
  871. (PBITMAPINFO)pbmih,DIB_RGB_COLORS,0,
  872. sizeof(DIBSECTION)))
  873. {
  874. cRet = sizeof(DIBSECTION);
  875. // More Win9x compatibility: for DDraw surfaces, the
  876. // following field is always zero. GDI+ keys off
  877. // this Win9x feature to do cheap detection of
  878. // DDraw surfaces:
  879. if (SurfBm.ps->bDirectDraw())
  880. {
  881. pbmih->biSizeImage = 0;
  882. }
  883. }
  884. XEPALOBJ pal(SurfBm.ps->ppal());
  885. if (pal.bValid() && pal.bIsBitfields())
  886. {
  887. ((DIBSECTION *)pvDest)->dsBitfields[0] = pal.flRed();
  888. ((DIBSECTION *)pvDest)->dsBitfields[1] = pal.flGre();
  889. ((DIBSECTION *)pvDest)->dsBitfields[2] = pal.flBlu();
  890. }
  891. // to be consistent with win95, Getobject returns BI_RGB for
  892. // 24bpp, and 32bpp when BI_RGB is set at creation time
  893. else
  894. {
  895. if (pal.bValid() && pal.bIsBGR())
  896. {
  897. pbmih->biCompression = BI_RGB;
  898. }
  899. ((DIBSECTION *)pvDest)->dsBitfields[0] = 0;
  900. ((DIBSECTION *)pvDest)->dsBitfields[1] = 0;
  901. ((DIBSECTION *)pvDest)->dsBitfields[2] = 0;
  902. }
  903. ((DIBSECTION *)pvDest)->dshSection = SurfBm.ps->hDIBSection();
  904. ((DIBSECTION *)pvDest)->dsOffset = SurfBm.ps->dwOffset();
  905. }
  906. }
  907. }
  908. }
  909. }
  910. else
  911. {
  912. cRet = sizeof(BITMAP);
  913. }
  914. break;
  915. case BRUSH_TYPE:
  916. cRet = (int) cjGetBrushOrPen(hobj, ulCount, pvDest);
  917. break;
  918. case ICMLCS_TYPE:
  919. cRet = cjGetLogicalColorSpace(hobj,ulCount,pvDest);
  920. break;
  921. default:
  922. break;
  923. }
  924. return(cRet);
  925. }
  926. /******************************Public*Routine******************************\
  927. * GreGetStockObject
  928. *
  929. * API function
  930. *
  931. * returns the handle to the stock object requested.
  932. *
  933. * History:
  934. * 08-Dec-1990 -by- Patrick Haluptzok patrickh
  935. * Wrote it.
  936. \**************************************************************************/
  937. HANDLE gahStockObjects[PRIV_STOCK_LAST+1] = {0};
  938. HANDLE GreGetStockObject(int ulIndex)
  939. {
  940. if (((UINT)ulIndex) <= PRIV_STOCK_LAST)
  941. {
  942. return(gahStockObjects[ulIndex]);
  943. }
  944. else
  945. {
  946. return(0);
  947. }
  948. }
  949. BOOL bSetStockObject(
  950. HANDLE h,
  951. int iObj
  952. )
  953. {
  954. if (h)
  955. {
  956. gahStockObjects[iObj] = (HANDLE)((ULONG_PTR)h | GDISTOCKOBJ);
  957. HmgModifyHandleType((HOBJ) gahStockObjects[iObj]);
  958. }
  959. return(h != NULL);
  960. }
  961. /******************************Public*Routine******************************\
  962. * BOOL GreGetColorAdjustment
  963. *
  964. * Get the color adjustment data of the given DC.
  965. *
  966. * History:
  967. * 25-Aug-1992 -by- Wendy Wu [wendywu]
  968. * Wrote it.
  969. \**************************************************************************/
  970. BOOL APIENTRY GreGetColorAdjustment(HDC hdc, COLORADJUSTMENT *pca)
  971. {
  972. DCOBJ dco(hdc);
  973. BOOL Status;
  974. if (!dco.bValid())
  975. {
  976. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  977. Status = FALSE;
  978. } else {
  979. // Retrieve info from the DC. Mask out the internal flag.
  980. *pca = *dco.pColorAdjustment();
  981. pca->caFlags &= (CA_NEGATIVE | CA_LOG_FILTER);
  982. Status = TRUE;
  983. }
  984. return Status;
  985. }
  986. /******************************Public*Routine******************************\
  987. * BOOL GreSetColorAdjustment
  988. *
  989. * Set the color adjustment data of the given DC.
  990. *
  991. * History:
  992. * 25-Aug-1992 -by- Wendy Wu [wendywu]
  993. * Wrote it.
  994. \**************************************************************************/
  995. BOOL APIENTRY GreSetColorAdjustment(HDC hdc, COLORADJUSTMENT *pcaNew)
  996. {
  997. DCOBJ dco(hdc);
  998. BOOL Status;
  999. if (!dco.bValid())
  1000. {
  1001. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  1002. Status = FALSE;
  1003. } else {
  1004. // Store info into the DC. Turn off any flags that we don't support.
  1005. *dco.pColorAdjustment() = *pcaNew;
  1006. dco.pColorAdjustment()->caFlags &= (CA_NEGATIVE | CA_LOG_FILTER);
  1007. Status = TRUE;
  1008. }
  1009. return Status;
  1010. }
  1011. /******************************Public*Routine******************************\
  1012. * HANDLE GreCreateClientObj()
  1013. *
  1014. * A ClientObj contains no data. It is purly to provide a handle to the
  1015. * client for objects such as metafiles that exist only on the client side.
  1016. *
  1017. * ulType is a client type.
  1018. *
  1019. * History:
  1020. * 17-Jan-1995 -by- Eric Kutter [erick]
  1021. * Wrote it.
  1022. \**************************************************************************/
  1023. HANDLE NtGdiCreateClientObj(
  1024. ULONG ulType)
  1025. {
  1026. HANDLE h = NULL;
  1027. // ClientObj handles should never have any INDEX bits set and have some
  1028. // ALT bits set. Also the type must be a LO_CLIENTOBJ_TYPE
  1029. if((ulType & (INDEX_MASK)) || !(ulType & (ALTTYPE_MASK)) || ((ulType & TYPE_MASK) != LO_CLIENTOBJ_TYPE))
  1030. {
  1031. WARNING("GreCreateClientObj: bad type\n");
  1032. return(h);
  1033. }
  1034. PVOID pv = ALLOCOBJ(sizeof(OBJECT), CLIENTOBJ_TYPE, FALSE);
  1035. if (pv)
  1036. {
  1037. h = HmgInsertObject(pv, 0, CLIENTOBJ_TYPE);
  1038. if (!h)
  1039. {
  1040. WARNING("GreCreateClientObj: HmgInsertObject failed\n");
  1041. FREEOBJ(pv, CLIENTOBJ_TYPE);
  1042. }
  1043. else
  1044. {
  1045. pv = HmgLock((HOBJ) h,CLIENTOBJ_TYPE);
  1046. if (pv != NULL)
  1047. {
  1048. h = MODIFY_HMGR_TYPE(h,ulType);
  1049. HmgModifyHandleType((HOBJ)h);
  1050. DEC_EXCLUSIVE_REF_CNT(pv);
  1051. }
  1052. else
  1053. {
  1054. RIP("GreCreateClientObj failed lock\n");
  1055. }
  1056. }
  1057. }
  1058. else
  1059. {
  1060. WARNING("GreCreateClientObj(): ALLOCOBJ failed\n");
  1061. }
  1062. return(h);
  1063. }
  1064. /******************************Public*Routine******************************\
  1065. *
  1066. *
  1067. * History:
  1068. * 17-Jan-1995 -by- Eric Kutter [erick]
  1069. * Wrote it.
  1070. \**************************************************************************/
  1071. BOOL GreDeleteClientObj(
  1072. HANDLE h)
  1073. {
  1074. PVOID pv = HmgRemoveObject((HOBJ)h, 0, 0, TRUE, CLIENTOBJ_TYPE);
  1075. if (pv != NULL)
  1076. {
  1077. FREEOBJ(pv, CLIENTOBJ_TYPE);
  1078. return(TRUE);
  1079. }
  1080. else
  1081. {
  1082. WARNING("GreDeleteClientObj: HmgRemoveObject failed\n");
  1083. return(FALSE);
  1084. }
  1085. }
  1086. /******************************Public*Routine******************************\
  1087. * NtGdiDeleteClientObj()
  1088. *
  1089. * History:
  1090. * 01-Nov-1994 -by- Eric Kutter [erick]
  1091. * Wrote it.
  1092. \**************************************************************************/
  1093. BOOL
  1094. APIENTRY
  1095. NtGdiDeleteClientObj(
  1096. HANDLE h
  1097. )
  1098. {
  1099. return(GreDeleteClientObj(h));
  1100. }
  1101. /******************************Public*Routine******************************\
  1102. * GreFreePool
  1103. *
  1104. * Private USER call to delete memory allocated by GDI.
  1105. *
  1106. * Only known use is to delete the MDEV structure returned by DrvCreateMDEV
  1107. * and cached by USER.
  1108. *
  1109. * History:
  1110. * 24-Feb-1998 -by- Gilman Wong [gilmanw]
  1111. * Wrote it.
  1112. \**************************************************************************/
  1113. extern "C" VOID GreFreePool(PVOID pv)
  1114. {
  1115. GdiFreePool(pv);
  1116. }
  1117. /******************************Public*Routine******************************\
  1118. * hdevEnumerate
  1119. *
  1120. * Enumerates all display PDEVs without keeping ghsemDriverMgmt, allowing
  1121. * the devlock to be taken on each. This function must be called until it
  1122. * returns NULL or proper cleanup will not occur.
  1123. *
  1124. * History:
  1125. * 02-Jul-1999 -by- John Stephens [johnstep]
  1126. * Wrote it.
  1127. \**************************************************************************/
  1128. HDEV
  1129. hdevEnumerate(
  1130. HDEV hdevPrevious
  1131. )
  1132. {
  1133. PDEV* ppdev;
  1134. GreAcquireSemaphoreEx(ghsemDriverMgmt, SEMORDER_DRIVERMGMT, NULL);
  1135. // If we are called with NULL hdevPrevious then create the PDEVOBJ from
  1136. // gppdevList, else create it from hdevPrevious:
  1137. PDEVOBJ po(hdevPrevious ? hdevPrevious : (HDEV) gppdevList);
  1138. ASSERTGDI(po.bValid(), "Invalid HDEV");
  1139. // Search for the next display PDEV. If hdevPrevious is NULL, then
  1140. // we start with po, else start from the next:
  1141. for (ppdev = hdevPrevious ? po.ppdev->ppdevNext : po.ppdev;
  1142. ppdev;
  1143. ppdev = ppdev->ppdevNext)
  1144. {
  1145. // We're only interested in display PDEVs:
  1146. if (ppdev->fl & PDEV_DISPLAY)
  1147. {
  1148. // We found the next display PDEV, so take a reference count
  1149. // on it before releasing ghsemDriverMgmt and returning. This
  1150. // reference count will be removed next time through:
  1151. ppdev->cPdevRefs++;
  1152. break;
  1153. }
  1154. }
  1155. // If hdevPrevious is not NULL then we need to remove the reference
  1156. // count we took, and we'll also release ghsemDriverMgmt here in the
  1157. // appropriate place:
  1158. if (hdevPrevious)
  1159. {
  1160. // If our reference count is not the last, just decrement, else we
  1161. // need to call vUnreferencePdev so the PDEV will actually be
  1162. // deleted:
  1163. ASSERTGDI(po.cPdevRefs() > 0,
  1164. "PDEV reference count is 0 but should be at least 1");
  1165. if (po.cPdevRefs() > 1)
  1166. {
  1167. po.ppdev->cPdevRefs--;
  1168. GreReleaseSemaphoreEx(ghsemDriverMgmt);
  1169. }
  1170. else
  1171. {
  1172. // Release ghsemDriverMgmt before calling vUnreferencePdev
  1173. // because the call may result in the devlock being taken:
  1174. GreReleaseSemaphoreEx(ghsemDriverMgmt);
  1175. po.vUnreferencePdev();
  1176. }
  1177. }
  1178. else
  1179. {
  1180. GreReleaseSemaphoreEx(ghsemDriverMgmt);
  1181. }
  1182. return (HDEV) ppdev;
  1183. }
  1184. /******************************Public*Routine******************************\
  1185. * vSynchronizeDriver
  1186. *
  1187. * Calls DrvSynchronize if the driver has set either GCAPS2_SYNCFLUSH
  1188. * or GCAPS2_SYNCTIMER, as appropriate.
  1189. *
  1190. * History:
  1191. * 15-Dec-1997 -by- Gilman Wong [gilmanw]
  1192. * Wrote it.
  1193. \**************************************************************************/
  1194. VOID vSynchronizeDriver(FLONG flSynchronizeType)
  1195. {
  1196. HDEV hdev;
  1197. //
  1198. // Note that we check the synchronize counts outside of a lock, which
  1199. // is okay.
  1200. //
  1201. //
  1202. // We just accumlate what needs to be synchronized when we are in the middle
  1203. // of a mode change.
  1204. //
  1205. if (CModeChangeInProgress::lInModeChange)
  1206. {
  1207. if(flSynchronizeType == GCAPS2_SYNCFLUSH && gcSynchronizeFlush != -1)
  1208. InterlockedCompareExchange(&CModeChangeInProgress::lNeedSyncFlush,1,0);
  1209. if(flSynchronizeType == GCAPS2_SYNCTIMER && gcSynchronizeTimer != -1)
  1210. InterlockedCompareExchange(&CModeChangeInProgress::lNeedTimerFlush,1,0);
  1211. return;
  1212. }
  1213. if (((flSynchronizeType == GCAPS2_SYNCFLUSH) && (gcSynchronizeFlush != -1)) ||
  1214. ((flSynchronizeType == GCAPS2_SYNCTIMER) && (gcSynchronizeTimer != -1)))
  1215. {
  1216. for (hdev = hdevEnumerate(NULL); hdev; hdev = hdevEnumerate(hdev))
  1217. {
  1218. PDEVOBJ pdo(hdev);
  1219. ASSERTGDI(pdo.bValid(), "GreFlush: invalid PDEV");
  1220. ASSERTGDI(pdo.bDisplayPDEV(), "GreFlush: not a display PDEV");
  1221. if (pdo.flGraphicsCaps2NotDynamic() & flSynchronizeType)
  1222. {
  1223. GreAcquireSemaphoreEx(pdo.hsemDevLock(), SEMORDER_DEVLOCK, NULL);
  1224. GreEnterMonitoredSection(pdo.ppdev, WD_DEVLOCK);
  1225. if ((pdo.flGraphicsCaps2() & flSynchronizeType) &&
  1226. !(pdo.bDisabled()))
  1227. {
  1228. FLONG fl = 0;
  1229. if ((flSynchronizeType == GCAPS2_SYNCFLUSH) &&
  1230. (gcSynchronizeFlush != -1))
  1231. {
  1232. fl |= DSS_FLUSH_EVENT;
  1233. }
  1234. if ((flSynchronizeType == GCAPS2_SYNCTIMER) &&
  1235. (gcSynchronizeTimer != -1))
  1236. {
  1237. fl |= DSS_TIMER_EVENT;
  1238. }
  1239. pdo.vSync(pdo.pSurface()->pSurfobj(), NULL, fl);
  1240. }
  1241. GreExitMonitoredSection(pdo.ppdev, WD_DEVLOCK);
  1242. GreReleaseSemaphoreEx(pdo.hsemDevLock());
  1243. }
  1244. }
  1245. }
  1246. }
  1247. /******************************Public*Routine******************************\
  1248. * GreFlush
  1249. *
  1250. * Called for GdiFlush.
  1251. *
  1252. * Calls DrvSynchronize if it is hooked and GCAPS2_SYNCFLUSH is set.
  1253. *
  1254. * History:
  1255. * 15-Dec-1997 -by- Gilman Wong [gilmanw]
  1256. * Wrote it.
  1257. \**************************************************************************/
  1258. VOID
  1259. APIENTRY
  1260. GreFlush()
  1261. {
  1262. vSynchronizeDriver(GCAPS2_SYNCFLUSH);
  1263. }
  1264. /******************************Public*Routine******************************\
  1265. * GreSynchronizeTimer
  1266. *
  1267. * When the synchronization timer is enabled, this routine will be called
  1268. * by User's RIT. We, in turn, call any driver that has set GCAPS_SYNCTIMER.
  1269. *
  1270. * History:
  1271. * 2-Jun-1998 -by- J. Andrew Goossen [andrewgo]
  1272. * Wrote it.
  1273. \**************************************************************************/
  1274. VOID APIENTRY GreSynchronizeTimer(PVOID pwnd, UINT msg, UINT_PTR id, LPARAM lParam)
  1275. {
  1276. vSynchronizeDriver(GCAPS2_SYNCTIMER);
  1277. }
  1278. /******************************Public*Routine******************************\
  1279. * vEnableSynchronize
  1280. *
  1281. * This routine enables GCAPS2_SYNCFLUSH and GCAPS2_SYNCTIMER
  1282. * synchronization for the driver.
  1283. *
  1284. * History:
  1285. * 2-Jun-1998 -by- J. Andrew Goossen [andrewgo]
  1286. * Wrote it.
  1287. \**************************************************************************/
  1288. VOID vEnableSynchronize(HDEV hdev)
  1289. {
  1290. GDIFunctionID(vEnableSynchronize);
  1291. PDEVOBJ po(hdev);
  1292. FLONG flCaps = po.flGraphicsCaps2();
  1293. if (flCaps & (GCAPS2_SYNCFLUSH | GCAPS2_SYNCTIMER))
  1294. {
  1295. BOOL AcquireUserCritSec;
  1296. //
  1297. // We will be calling User, which needs to acquire its critical
  1298. // section. The devlock must always be acquired after the User
  1299. // critical section; consequently, we cannot be holding a devlock
  1300. // at this point if we're not already holding the user lock.
  1301. //
  1302. AcquireUserCritSec = !UserIsUserCritSecIn();
  1303. if (AcquireUserCritSec)
  1304. {
  1305. po.vAssertNoDevLock();
  1306. UserEnterUserCritSec();
  1307. }
  1308. if (flCaps & GCAPS2_SYNCTIMER)
  1309. {
  1310. //
  1311. // It's the responsibility of the first thread to increment
  1312. // the count past -1 to create the timer.
  1313. //
  1314. if (++gcSynchronizeTimer == 0)
  1315. {
  1316. ASSERTGDI(gidSynchronizeTimer == 0,
  1317. "Expected no timer to have already been created.");
  1318. //
  1319. // Note that at boot time we actually expect this timer
  1320. // creation to fail, as User hasn't had a chance to
  1321. // create the RIT yet. GreSetTimers handles the actual
  1322. // timer creation for that case. Because of this case,
  1323. // we can't strictly fail here if the timer can't be
  1324. // created; however, it's not the end of the world --
  1325. // this will happen only in a degenerate case, and at
  1326. // worst the video will be very jerky.
  1327. //
  1328. gidSynchronizeTimer = UserSetTimer(SYNCTIMER_FREQUENCY,
  1329. GreSynchronizeTimer);
  1330. }
  1331. }
  1332. if (flCaps & GCAPS2_SYNCFLUSH)
  1333. {
  1334. gcSynchronizeFlush++;
  1335. }
  1336. po.vSynchronizeEnabled(TRUE);
  1337. if (AcquireUserCritSec)
  1338. {
  1339. UserLeaveUserCritSec();
  1340. }
  1341. }
  1342. }
  1343. /******************************Public*Routine******************************\
  1344. * vDisableSynchronize(HDEV hdev)
  1345. *
  1346. * This routine disables GCAPS2_SYNCFLUSH and GCAPS2_SYNCTIMER
  1347. * synchronization for the driver.
  1348. *
  1349. * History:
  1350. * 2-Jun-1998 -by- J. Andrew Goossen [andrewgo]
  1351. * Wrote it.
  1352. \**************************************************************************/
  1353. VOID vDisableSynchronize(HDEV hdev)
  1354. {
  1355. GDIFunctionID(vDisableSynchronize);
  1356. PDEVOBJ po(hdev);
  1357. BOOL AcquireUserCritSec;
  1358. //
  1359. // We will be calling User, which needs to acquire its critical
  1360. // section. The devlock must always be acquired after the User
  1361. // critical section; consequently, we cannot be holding a devlock
  1362. // at this point if we're not already holding the user lock.
  1363. //
  1364. AcquireUserCritSec = !UserIsUserCritSecIn();
  1365. if (AcquireUserCritSec)
  1366. {
  1367. po.vAssertNoDevLock();
  1368. UserEnterUserCritSec();
  1369. }
  1370. if (po.bSynchronizeEnabled())
  1371. {
  1372. FLONG flCaps = po.flGraphicsCaps2();
  1373. if (flCaps & GCAPS2_SYNCFLUSH)
  1374. {
  1375. ASSERTGDI(gcSynchronizeFlush > -1, "Unexpected flush count");
  1376. gcSynchronizeFlush--;
  1377. }
  1378. if (flCaps & GCAPS2_SYNCTIMER)
  1379. {
  1380. //
  1381. // It's the responsibility of the first thread to decrement
  1382. // the count to -1 to kill the timer.
  1383. //
  1384. ASSERTGDI(gcSynchronizeTimer > -1, "Unexpected timer count");
  1385. if (--gcSynchronizeTimer < 0)
  1386. {
  1387. if (gidSynchronizeTimer != 0)
  1388. {
  1389. UserKillTimer(gidSynchronizeTimer);
  1390. gidSynchronizeTimer = 0;
  1391. }
  1392. }
  1393. }
  1394. po.vSynchronizeEnabled(FALSE);
  1395. }
  1396. if (AcquireUserCritSec)
  1397. {
  1398. UserLeaveUserCritSec();
  1399. }
  1400. }
  1401. /******************************Public*Routine******************************\
  1402. * GreStartTimers()
  1403. *
  1404. * Called by User when the RIT thread is finally initialized, and we
  1405. * can set up timers. We need this because driver initialization
  1406. * occurs before the RIT is initialized, which would have been the
  1407. * natural place to put the timer initialization for us.
  1408. *
  1409. * History:
  1410. * 2-Jun-1998 -by- J. Andrew Goossen [andrewgo]
  1411. * Wrote it.
  1412. \**************************************************************************/
  1413. VOID GreStartTimers()
  1414. {
  1415. GDIFunctionID(GreStartTimers);
  1416. BOOL AcquireUserCritSec;
  1417. AcquireUserCritSec = !UserIsUserCritSecIn();
  1418. if (AcquireUserCritSec)
  1419. {
  1420. UserEnterUserCritSec();
  1421. }
  1422. if (gcSynchronizeTimer != -1)
  1423. {
  1424. ASSERTGDI(gidSynchronizeTimer == NULL,
  1425. "Expected no timer to have already been created.");
  1426. gidSynchronizeTimer = UserSetTimer(SYNCTIMER_FREQUENCY,
  1427. GreSynchronizeTimer);
  1428. }
  1429. if (AcquireUserCritSec)
  1430. {
  1431. UserLeaveUserCritSec();
  1432. }
  1433. }
  1434. /**************************************************************************\
  1435. * CmodeChangeInProgress::vDone().
  1436. *
  1437. * Called by DrvChangeDisplaySettings just before it realeases the
  1438. * ghsemShareDevLock so we may flush any pending vSynchronizeDriver calls.
  1439. *
  1440. * History:
  1441. * 18-Oct-2001 -by- Pravin Santiago [pravins]
  1442. * Wrote it.
  1443. \**************************************************************************/
  1444. void CModeChangeInProgress::vDone()
  1445. {
  1446. InterlockedDecrement(&lInModeChange);
  1447. if (lNeedSyncFlush)
  1448. {
  1449. vSynchronizeDriver(GCAPS2_SYNCFLUSH);
  1450. InterlockedDecrement(&lNeedSyncFlush);
  1451. }
  1452. if (lNeedTimerFlush)
  1453. {
  1454. vSynchronizeDriver(GCAPS2_SYNCTIMER);
  1455. InterlockedDecrement(&lNeedTimerFlush);
  1456. }
  1457. }