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.

2722 lines
77 KiB

  1. /******************************Module*Header*******************************\
  2. * Module Name:
  3. *
  4. * icmapi.cxx
  5. *
  6. * Abstract
  7. *
  8. * This module implements Integrated Color match API support
  9. *
  10. * Author:
  11. *
  12. * Mark Enstrom (marke) 9-27-93
  13. *
  14. * Copyright (c) 1993-1999 Microsoft Corporation
  15. \**************************************************************************/
  16. #include "precomp.hxx"
  17. extern "C" {
  18. ULONG GreGetBitmapBitsSize(CONST BITMAPINFO *pbmi); // in ntgdi.c
  19. BOOL bInitICM();
  20. }
  21. #pragma alloc_text(INIT, bInitICM)
  22. PCOLORSPACE gpStockColorSpace;
  23. HCOLORSPACE ghStockColorSpace;
  24. UINT giIcmGammaRange;
  25. #if DBG_ICM
  26. ULONG IcmDebugLevel = 0;
  27. #endif
  28. #define sRGB_PROFILENAME L"sRGB Color Space Profile.icm"
  29. LOGCOLORSPACEW gcsStockColorSpace = {
  30. LCS_SIGNATURE,
  31. 0x400,
  32. sizeof(LOGCOLORSPACEW),
  33. LCS_CALIBRATED_RGB,
  34. LCS_GM_IMAGES,
  35. {
  36. {0x000006b91,0x000003db8,0x00000070e},
  37. {0x000005793,0x00000a9ba,0x000001bf4},
  38. {0x0000038aa,0x00000188e,0x000012888}
  39. },
  40. 0x23333, // 2.2
  41. 0x23333, // 2.2
  42. 0x23333, // 2.2
  43. 0};
  44. #define MAX_COLORTABLE 256
  45. //
  46. // iIcmControlFlags
  47. //
  48. #define ICM_CONTROL_WIN95_COLORSPACE 0x00010000 // Win95 compatible colorspace
  49. //
  50. // Misc. macros
  51. //
  52. #define ALIGN_DWORD(nBytes) (((nBytes) + 3) & ~3)
  53. //
  54. // ICM supports output color mode (originally come from ICM.H)
  55. //
  56. #define BM_RGBTRIPLETS 0x0002
  57. #define BM_xRGBQUADS 0x0008
  58. #define BM_xBGRQUADS 0x0010
  59. #define BM_CMYKQUADS 0x0020
  60. #define BM_KYMCQUADS 0x0305
  61. //
  62. // ICM modes list
  63. //
  64. // if (IS_HOST_ICM(pdca->lIcmMode))
  65. // {
  66. // if (pdca->hcmXform)
  67. // {
  68. // if (IS_CMYK_COLOR(pdca->lIcmMode))
  69. // {
  70. // Host ICM ON, CMYK color mode.
  71. // With CMYK color mode, we should have valid color transform.
  72. // }
  73. // else
  74. // {
  75. // Host ICM ON, RGB color mode.
  76. // }
  77. // }
  78. // else
  79. // {
  80. // Host ICM ON, RGB color mode,
  81. // But no color translation because src == dst color space.
  82. // }
  83. // }
  84. // else if (IS_DEVICE_ICM(pdca->lIcmMode))
  85. // {
  86. // Device ICM ON.
  87. // }
  88. // else if (IS_OUTSIDEDC_ICM(pdca->lIcmMode))
  89. // {
  90. // Application ICM ON.
  91. // }
  92. //
  93. /******************************Public*Routine******************************\
  94. * GreCreateColorSpace
  95. *
  96. * Arguments:
  97. *
  98. * Return Value:
  99. *
  100. * History:
  101. *
  102. * 9/25/1996 Mark Enstrom [marke]
  103. *
  104. \**************************************************************************/
  105. HCOLORSPACE
  106. GreCreateColorSpace(
  107. PLOGCOLORSPACEEXW pLogColorSpaceEx
  108. )
  109. {
  110. ICMAPI(("GreCreateColorSpace\n"));
  111. HCOLORSPACE hRet = NULL;
  112. PCOLORSPACE pColorSpace;
  113. //
  114. // Check the validation of this color space.
  115. //
  116. if ((pLogColorSpaceEx->lcsColorSpace.lcsSignature != LCS_SIGNATURE) ||
  117. (pLogColorSpaceEx->lcsColorSpace.lcsVersion != 0x400) ||
  118. (pLogColorSpaceEx->lcsColorSpace.lcsSize != sizeof(LOGCOLORSPACEW)))
  119. {
  120. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  121. return (NULL);
  122. }
  123. //
  124. // Allocate COLORSPACE object.
  125. //
  126. pColorSpace = (PCOLORSPACE) ALLOCOBJ(sizeof(COLORSPACE), ICMLCS_TYPE, FALSE);
  127. if (pColorSpace == (PCOLORSPACE)NULL)
  128. {
  129. WARNING("bCreateColorSpace failed memory allocation\n");
  130. }
  131. else
  132. {
  133. //
  134. // Register LOGCOLORSPACE handle.
  135. //
  136. hRet = (HCOLORSPACE)HmgInsertObject(
  137. pColorSpace,
  138. HMGR_ALLOC_ALT_LOCK,
  139. ICMLCS_TYPE);
  140. if (hRet)
  141. {
  142. //
  143. // Copy LOGCOLORSPACE into COLORSPACE object.
  144. //
  145. pColorSpace->lcsSignature(pLogColorSpaceEx->lcsColorSpace.lcsSignature);
  146. pColorSpace->lcsVersion(pLogColorSpaceEx->lcsColorSpace.lcsVersion);
  147. pColorSpace->lcsSize(pLogColorSpaceEx->lcsColorSpace.lcsSize);
  148. pColorSpace->lcsCSType(pLogColorSpaceEx->lcsColorSpace.lcsCSType);
  149. pColorSpace->lcsIntent(pLogColorSpaceEx->lcsColorSpace.lcsIntent);
  150. pColorSpace->vSETlcsEndpoints(&(pLogColorSpaceEx->lcsColorSpace.lcsEndpoints));
  151. pColorSpace->lcsGammaRed(pLogColorSpaceEx->lcsColorSpace.lcsGammaRed);
  152. pColorSpace->lcsGammaGreen(pLogColorSpaceEx->lcsColorSpace.lcsGammaGreen);
  153. pColorSpace->lcsGammaBlue(pLogColorSpaceEx->lcsColorSpace.lcsGammaBlue);
  154. pColorSpace->vSETlcsFilename((PWCHAR)&(pLogColorSpaceEx->lcsColorSpace.lcsFilename[0]),MAX_PATH);
  155. pColorSpace->lcsExFlags(pLogColorSpaceEx->dwFlags);
  156. //
  157. // Decrement color space handle which increment at creation time.
  158. //
  159. DEC_SHARE_REF_CNT(pColorSpace);
  160. ICMMSG(("GreCreateColorSpace():Object %x: ref. count = %d\n",
  161. hRet,HmgQueryAltLock((HOBJ)hRet)));
  162. }
  163. else
  164. {
  165. FREEOBJ(pColorSpace,ICMLCS_TYPE);
  166. }
  167. }
  168. return(hRet);
  169. }
  170. /******************************Public*Routine******************************\
  171. *
  172. * Routine Name
  173. *
  174. * NtGdiCreateColorSpace
  175. *
  176. * Routine Description:
  177. *
  178. * Create a color space object - stub
  179. *
  180. * Arguments:
  181. *
  182. * pLogColorSpace - Logical Color space passed in. This will be used as the
  183. * user-mode visible protion of this object
  184. *
  185. * Return Value:
  186. *
  187. * Handle to ColorSpace object or NULL on failure
  188. *
  189. \**************************************************************************/
  190. HANDLE
  191. APIENTRY
  192. NtGdiCreateColorSpace(
  193. PLOGCOLORSPACEEXW pLogColorSpaceEx
  194. )
  195. {
  196. ICMAPI(("NtGdiCreateColorSpace\n"));
  197. HANDLE hRet = NULL;
  198. BOOL bStatus = TRUE;
  199. LOGCOLORSPACEEXW tmpLcsEx;
  200. __try
  201. {
  202. ProbeForRead(pLogColorSpaceEx,sizeof(LOGCOLORSPACEEXW),sizeof(ULONG));
  203. RtlCopyMemory(&tmpLcsEx,pLogColorSpaceEx,sizeof(LOGCOLORSPACEEXW));
  204. }
  205. __except(EXCEPTION_EXECUTE_HANDLER)
  206. {
  207. bStatus = FALSE;
  208. }
  209. if (bStatus)
  210. {
  211. hRet = (HANDLE)GreCreateColorSpace(&tmpLcsEx);
  212. }
  213. return(hRet);
  214. }
  215. /******************************Public*Routine******************************\
  216. * bDeleteColorSpace
  217. *
  218. * Arguments:
  219. *
  220. * Return Value:
  221. *
  222. * History:
  223. *
  224. * 9/20/1996 Mark Enstrom [marke]
  225. *
  226. \**************************************************************************/
  227. BOOL
  228. bDeleteColorSpace(
  229. HCOLORSPACE hColorSpace
  230. )
  231. {
  232. ICMAPI(("bDeleteColorSpace\n"));
  233. BOOL bRet = FALSE;
  234. PCOLORSPACE pColorSpace;
  235. if (DIFFHANDLE(hColorSpace,ghStockColorSpace))
  236. {
  237. ICMMSG(("bDeleteColorSpace():Object %x: ref. count = %d\n",
  238. hColorSpace,HmgQueryAltLock((HOBJ)hColorSpace)));
  239. //
  240. // Try to remove handle from hmgr. This will fail if the color space
  241. // is locked down on any threads or if it has been marked global or
  242. // un-deleteable.
  243. //
  244. pColorSpace = (PCOLORSPACE)HmgRemoveObject(
  245. (HOBJ)hColorSpace,
  246. 0,
  247. 0,
  248. TRUE,
  249. ICMLCS_TYPE);
  250. if (pColorSpace != (PCOLORSPACE)NULL)
  251. {
  252. FREEOBJ(pColorSpace,ICMLCS_TYPE);
  253. bRet = TRUE;
  254. }
  255. else
  256. {
  257. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  258. WARNING("Couldn't remove COLORSPACE object");
  259. }
  260. }
  261. else
  262. {
  263. //
  264. // Under Win31 deleting stock objects returns True.
  265. //
  266. bRet = TRUE;
  267. }
  268. return(bRet);
  269. }
  270. /******************************Public*Routine******************************\
  271. * NtGdiDeleteColorSpace
  272. *
  273. * Routine Description:
  274. *
  275. * Delete a color space object
  276. *
  277. * Arguments:
  278. *
  279. * hColorSpace - Handle of Logical Color Space to delete
  280. *
  281. * Return Value:
  282. *
  283. * BOOL status
  284. *
  285. \**************************************************************************/
  286. BOOL
  287. APIENTRY
  288. NtGdiDeleteColorSpace(
  289. HANDLE hColorSpace
  290. )
  291. {
  292. ICMAPI(("NtGdiDeleteColorSpace\n"));
  293. //
  294. // Delete ColorSpace
  295. //
  296. return(bDeleteColorSpace((HCOLORSPACE)hColorSpace));
  297. }
  298. /******************************Public*Routine******************************\
  299. *
  300. * Routine Name
  301. *
  302. * NtGdiSetColorSpace
  303. *
  304. * Routine Description:
  305. *
  306. * Set Color Space for DC
  307. *
  308. * Arguments:
  309. *
  310. * hdc - handle of dc
  311. * hColorSpace - handle of color space
  312. *
  313. * Return Value:
  314. *
  315. * BOOL Status
  316. *
  317. \**************************************************************************/
  318. BOOL
  319. APIENTRY
  320. NtGdiSetColorSpace(
  321. HDC hdc,
  322. HCOLORSPACE hColorSpace
  323. )
  324. {
  325. BOOL bReturn = FALSE;
  326. ICMAPI(("NtGdiSetColorSpace\n"));
  327. //
  328. // validate the DC
  329. //
  330. XDCOBJ dco(hdc);
  331. if (dco.bValid())
  332. {
  333. //
  334. // is it a different colorspace
  335. //
  336. if (DIFFHANDLE(hColorSpace,dco.pdc->hColorSpace()))
  337. {
  338. //
  339. // now validate HColorSpace
  340. //
  341. COLORSPACEREF ColorSpaceSel(hColorSpace);
  342. if (ColorSpaceSel.bValid())
  343. {
  344. //
  345. // dec ref count of old color space.
  346. //
  347. DEC_SHARE_REF_CNT((PCOLORSPACE)dco.pdc->pColorSpace());
  348. ICMMSG(("NtGdiSetColorSpace():Old Object %x: ref. count = %d\n",
  349. dco.pdc->hColorSpace(),HmgQueryAltLock((HOBJ)dco.pdc->hColorSpace())));
  350. //
  351. // set color space handle in dc
  352. //
  353. dco.pdc->hColorSpace(hColorSpace);
  354. dco.pdc->pColorSpace(ColorSpaceSel.pColorSpace());
  355. //
  356. // up the ref count of the selected color space.
  357. //
  358. INC_SHARE_REF_CNT(ColorSpaceSel.pColorSpace());
  359. ICMMSG(("NtGdiSetColorSpace():New Object %x: ref. count = %d\n",
  360. dco.pdc->hColorSpace(),HmgQueryAltLock((HOBJ)dco.pdc->hColorSpace())-1));
  361. /* -1: because of COLORSPACEREF locks this, then actuall number is N-1 */
  362. //
  363. // We are succeed to select.
  364. //
  365. bReturn = TRUE;
  366. }
  367. else
  368. {
  369. //
  370. // keep color space as same as current.
  371. //
  372. }
  373. }
  374. else
  375. {
  376. //
  377. // Same handle has been selected.
  378. //
  379. bReturn = TRUE;
  380. }
  381. dco.vUnlockFast();
  382. }
  383. return(bReturn);
  384. }
  385. #ifdef _IA64_
  386. //
  387. // There is a compiler bug that shows up in this function.
  388. // Disable optimization until it is fixed.
  389. //
  390. #pragma optimize( "", off )
  391. #endif
  392. /******************************Public*Routine******************************\
  393. * GreSetICMMode()
  394. *
  395. * History:
  396. *
  397. * Write it:
  398. * 27-Jan-1997 -by- Hideyuki Nagase [hideyukn]
  399. \**************************************************************************/
  400. BOOL
  401. GreSetICMMode(
  402. HDC hdc,
  403. ULONG nCommand,
  404. ULONG iReqData
  405. )
  406. {
  407. ICMMSG(("GreSetICMMode\n"));
  408. BOOL bRet = TRUE;
  409. XDCOBJ dco(hdc);
  410. if(!dco.bValid())
  411. {
  412. WARNING("GreSetICMMode(): Invalid DC\n");
  413. return (FALSE);
  414. }
  415. DEVLOCKOBJ dlo;
  416. if (dlo.bLock(dco))
  417. {
  418. ULONG NewReqMode, OldReqMode;
  419. ULONG NewMode,OldMode;
  420. ULONG NewColorType, OldColorType;
  421. PDEVOBJ po(dco.hdev());
  422. //
  423. // Check target surface
  424. //
  425. SURFACE *pSurface = dco.pSurface();
  426. //
  427. // Get current ICM destination color type
  428. //
  429. NewColorType = OldColorType = GET_COLORTYPE(dco.pdc->lIcmMode());
  430. //
  431. // Get current ICM mode.
  432. //
  433. NewMode = OldMode = ICM_MODE(dco.pdc->lIcmMode());
  434. //
  435. // Get previous requested mode.
  436. //
  437. NewReqMode = OldReqMode = REQ_ICM_MODE(dco.pdc->lIcmMode());
  438. switch (nCommand)
  439. {
  440. case ICM_SET_MODE:
  441. ICMMSG(("GreSetICMMode():Update ICM mode -> %x\n",iReqData));
  442. //
  443. // iReqData should be one of these.
  444. //
  445. switch (iReqData)
  446. {
  447. case REQ_ICM_OFF:
  448. //
  449. // Turn off ICM.
  450. //
  451. // (should preserve alt mode)
  452. //
  453. NewReqMode = REQ_ICM_OFF;
  454. NewMode = (ICM_ALT_MODE(dco.pdc->lIcmMode()) | DC_ICM_OFF);
  455. break;
  456. case REQ_ICM_HOST:
  457. case REQ_ICM_DEVICE:
  458. case REQ_ICM_OUTSIDEDC:
  459. //
  460. // Update new requested mode.
  461. //
  462. NewReqMode = iReqData;
  463. //
  464. // Figure out ICM mode from requested mode.
  465. //
  466. NewMode = ICM_REQ_TO_MODE(NewReqMode);
  467. //
  468. // We don't allow "ICM on Device" with non-DDB surface.
  469. //
  470. if (IS_ICM_DEVICE_REQUESTED(NewReqMode))
  471. {
  472. if (po.bValid())
  473. {
  474. //
  475. // ICM on Device is requested, check driver's capacity.
  476. //
  477. if (po.flGraphicsCaps() & GCAPS_ICM)
  478. {
  479. //
  480. // DC is device DC. (not, info or memory)
  481. //
  482. if (dco.dctp() != DCTYPE_MEMORY)
  483. {
  484. //
  485. // OK, we can enable device ICM.
  486. //
  487. }
  488. else
  489. {
  490. ICMMSG(("NtGdiSetIcmMode():DC is memory DC, but device icm requested\n"));
  491. //
  492. // Enable host ICM instead.
  493. //
  494. NewMode = DC_ICM_HOST;
  495. }
  496. }
  497. else
  498. {
  499. WARNING("GreSetICMMode(): ICM on Device is requested, but driver could not.\n");
  500. //
  501. // Oh!, device driver does *not* support ICM on device or driver.
  502. // Turn on ICM on HOST.
  503. //
  504. NewMode = DC_ICM_HOST;
  505. }
  506. }
  507. else
  508. {
  509. //
  510. // we will keep current mode. and return false.
  511. //
  512. bRet = FALSE;
  513. }
  514. }
  515. if (bRet)
  516. {
  517. //
  518. // Should preserve alt mode through ICM mode change.
  519. //
  520. NewMode |= ICM_ALT_MODE(dco.pdc->lIcmMode());
  521. }
  522. break;
  523. default:
  524. //
  525. // Unknown request mode.
  526. //
  527. bRet = FALSE;
  528. }
  529. break;
  530. case ICM_SET_CALIBRATE_MODE:
  531. ICMMSG(("GreSetICMMode():Update ICM device calibrate -> %x\n",iReqData));
  532. if (iReqData)
  533. {
  534. NewMode |= DC_ICM_DEVICE_CALIBRATE;
  535. }
  536. else
  537. {
  538. NewMode &= ~DC_ICM_DEVICE_CALIBRATE;
  539. }
  540. break;
  541. case ICM_SET_COLOR_MODE:
  542. case ICM_CHECK_COLOR_MODE:
  543. ICMMSG(("GreSetICMMode():Update ICM colortype -> %x\n",iReqData));
  544. //
  545. // iReqData should be one of these.
  546. //
  547. switch (iReqData)
  548. {
  549. case BM_xRGBQUADS:
  550. case BM_xBGRQUADS:
  551. // Clear lazy color correction.
  552. //
  553. // NewMode &= ~DC_ICM_LAZY_CORRECTION;
  554. //
  555. // Note: bitmap might have color which expected to corrected later.
  556. //
  557. // Set color type as RGB.
  558. //
  559. NewColorType = DC_ICM_RGB_COLOR;
  560. break;
  561. case BM_CMYKQUADS:
  562. case BM_KYMCQUADS:
  563. if (po.bValid())
  564. {
  565. //
  566. // Set color type as CMYK.
  567. //
  568. NewColorType = DC_ICM_CMYK_COLOR;
  569. //
  570. // Check device driver could handle CMYK color or not
  571. //
  572. if (po.flGraphicsCaps() & GCAPS_CMYKCOLOR)
  573. {
  574. //
  575. // We don't allow "CMYK color" with non-DDB surface.
  576. //
  577. if (dco.dctp() != DCTYPE_MEMORY)
  578. {
  579. //
  580. // We can go with CMYK color.
  581. //
  582. }
  583. else
  584. {
  585. ICMMSG(("NtGdiSetIcmMode():Enable lazy color correction\n"));
  586. //
  587. // Memory DC can only hold RGB based color,
  588. // so RGB to CMYK color translation will happen when
  589. // apps does BitBlt onto real device surface from this
  590. // compatible surface.
  591. //
  592. NewMode |= DC_ICM_LAZY_CORRECTION;
  593. NewColorType = DC_ICM_RGB_COLOR;
  594. }
  595. }
  596. else
  597. {
  598. //
  599. // Driver could not handle, ICM could not turn on.
  600. //
  601. WARNING("GreSetICMMode(): Device driver could not handle CMYK color\n");
  602. //
  603. // we will keep current code. and return false.
  604. //
  605. bRet = FALSE;
  606. }
  607. }
  608. else
  609. {
  610. bRet = FALSE;
  611. }
  612. break;
  613. default:
  614. ICMMSG(("GreSetICMMode():Unknown color type\n"));
  615. //
  616. // Unknown color mode.
  617. //
  618. bRet = FALSE;
  619. }
  620. break;
  621. default :
  622. ICMMSG(("GreSetICMMode():Unknown command\n"));
  623. bRet = FALSE;
  624. break;
  625. }
  626. if (bRet && (nCommand != ICM_CHECK_COLOR_MODE))
  627. {
  628. if ((OldMode != NewMode) || (OldReqMode != NewReqMode) || (OldColorType != NewColorType))
  629. {
  630. //
  631. // Update ICM mode. (we will keep original request mode and colortype).
  632. //
  633. // kernel side.
  634. //
  635. dco.pdc->lIcmMode(NewColorType|NewReqMode|NewMode);
  636. // and, client side (need to preserve usermode only flags).
  637. //
  638. ULONG UserModeFlag = (dco.pdc->lIcmModeClient() & DC_ICM_USERMODE_FLAG);
  639. dco.pdc->lIcmModeClient(NewColorType|NewReqMode|NewMode|UserModeFlag);
  640. if (OldMode != NewMode)
  641. {
  642. SURFACE *pSurfDest = dco.pSurface();
  643. XEPALOBJ palDestDC(dco.ppal());
  644. if (palDestDC.bValid())
  645. {
  646. //
  647. // update all drawing state
  648. //
  649. palDestDC.vUpdateTime();
  650. if (pSurfDest != NULL)
  651. {
  652. XEPALOBJ palDestSurf(pSurfDest->ppal());
  653. if (palDestSurf.bValid())
  654. {
  655. //
  656. // update palette.
  657. //
  658. palDestSurf.vUpdateTime();
  659. }
  660. }
  661. }
  662. }
  663. ICMMSG(("NtGdiSetIcmMode():ICM mode were changed to %x\n",dco.pdc->lIcmMode()));
  664. }
  665. else
  666. {
  667. ICMMSG(("NtGdiSetIcmMode():ICM mode were NOT changed!\n"));
  668. }
  669. }
  670. }
  671. else
  672. {
  673. //
  674. // Fail to enable ICM for fullscreen DC.
  675. //
  676. }
  677. dco.vUnlockFast();
  678. return(bRet);
  679. }
  680. #ifdef _IA64_
  681. #pragma optimize( "", on )
  682. #endif
  683. /******************************Public*Routine******************************\
  684. * NtGdiSetIcmMode
  685. *
  686. * ICM mode changed, update all times
  687. *
  688. * History:
  689. *
  690. * Write it:
  691. * 27-Jan-1997 -by- Hideyuki Nagase [hideyukn]
  692. \**************************************************************************/
  693. BOOL WINAPI
  694. NtGdiSetIcmMode(
  695. HDC hdc,
  696. ULONG nCommand,
  697. ULONG ulMode
  698. )
  699. {
  700. ICMMSG(("NtGdiSetIcmMode\n"));
  701. return(GreSetICMMode(hdc,nCommand,ulMode));
  702. }
  703. /******************************Public*Routine******************************\
  704. * GreCreateColorTransform
  705. *
  706. * Arguments:
  707. *
  708. * Return Value:
  709. *
  710. * History:
  711. *
  712. * Write it:
  713. * 27-Jan-1997 -by- Hideyuki Nagase [hideyukn]
  714. \**************************************************************************/
  715. HANDLE
  716. GreCreateColorTransform(
  717. HDC hdc,
  718. LPLOGCOLORSPACEW pLogColorSpaceW,
  719. PVOID pvSrcProfile,
  720. ULONG cjSrcProfile,
  721. PVOID pvDstProfile,
  722. ULONG cjDstProfile,
  723. PVOID pvTrgProfile,
  724. ULONG cjTrgProfile
  725. )
  726. {
  727. HANDLE hRet = NULL;
  728. ICMAPI(("GreCreateColorTransform\n"));
  729. //
  730. // Check the validation of this color space.
  731. //
  732. if ((pLogColorSpaceW->lcsSignature != LCS_SIGNATURE) ||
  733. (pLogColorSpaceW->lcsVersion != 0x400) ||
  734. (pLogColorSpaceW->lcsSize != sizeof(LOGCOLORSPACEW)))
  735. {
  736. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  737. return (NULL);
  738. }
  739. XDCOBJ dcoDst(hdc);
  740. if (dcoDst.bValid())
  741. {
  742. if (!dcoDst.pdc->bInFullScreen())
  743. {
  744. COLORTRANSFORMOBJ CXFormObj;
  745. //
  746. // Create new color transform object.
  747. //
  748. hRet = CXFormObj.hCreate(dcoDst,
  749. pLogColorSpaceW,
  750. pvSrcProfile,
  751. cjSrcProfile,
  752. pvDstProfile,
  753. cjDstProfile,
  754. pvTrgProfile,
  755. cjTrgProfile);
  756. if (!hRet)
  757. {
  758. WARNING("GreCreateColorTransform fail to allocate object\n");
  759. SAVE_ERROR_CODE(ERROR_NOT_ENOUGH_MEMORY);
  760. }
  761. }
  762. else
  763. {
  764. WARNING("GreCreateColorTransform(): hdc is full screen\n");
  765. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  766. }
  767. dcoDst.vUnlockFast();
  768. }
  769. else
  770. {
  771. WARNING("GreCreateColorTransform(): hdc is invalid\n");
  772. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  773. }
  774. return (hRet);
  775. }
  776. /******************************Public*Routine******************************\
  777. * NtGdiCreateColorTransform
  778. *
  779. * Arguments:
  780. *
  781. * Return Value:
  782. *
  783. * History:
  784. *
  785. * Write it:
  786. * 27-Jan-1997 -by- Hideyuki Nagase [hideyukn]
  787. \**************************************************************************/
  788. HANDLE WINAPI
  789. NtGdiCreateColorTransform(
  790. HDC hdc,
  791. LPLOGCOLORSPACEW pLogColorSpaceW,
  792. PVOID pvSrcProfile,
  793. ULONG cjSrcProfile,
  794. PVOID pvDestProfile,
  795. ULONG cjDestProfile,
  796. PVOID pvTargetProfile,
  797. ULONG cjTargetProfile
  798. )
  799. {
  800. HANDLE hColorTransform = NULL;
  801. LOGCOLORSPACEW KmLogColorSpaceW;
  802. HANDLE hSecureSource = NULL;
  803. HANDLE hSecureDestination = NULL;
  804. HANDLE hSecureTarget = NULL;
  805. PVOID pKmSrcProfile = NULL;
  806. PVOID pKmDstProfile = NULL;
  807. PVOID pKmTrgProfile = NULL;
  808. BOOL bError = FALSE;
  809. ICMAPI(("NtGdiCreateColorTransform\n"));
  810. __try
  811. {
  812. if (pLogColorSpaceW)
  813. {
  814. //
  815. // Copy LOGCOLORSPACE
  816. //
  817. ProbeForRead(pLogColorSpaceW,sizeof(LOGCOLORSPACEW),sizeof(ULONG));
  818. RtlCopyMemory(&KmLogColorSpaceW,pLogColorSpaceW,sizeof(LOGCOLORSPACEW));
  819. }
  820. else
  821. {
  822. //
  823. // We need LOGCOLORSPACE, at least.
  824. //
  825. return (NULL);
  826. }
  827. //
  828. // Lock down client side mapped files.
  829. //
  830. if (pvSrcProfile && cjSrcProfile)
  831. {
  832. ProbeForRead(pvSrcProfile,cjSrcProfile,sizeof(BYTE));
  833. hSecureSource = MmSecureVirtualMemory(pvSrcProfile,cjSrcProfile,PAGE_READONLY);
  834. if (hSecureSource)
  835. {
  836. pKmSrcProfile = pvSrcProfile;
  837. }
  838. else
  839. {
  840. WARNING("NtGdiCreateColorTransform():Fail to lock source profile\n");
  841. bError = TRUE;
  842. }
  843. }
  844. if (pvDestProfile && cjDestProfile)
  845. {
  846. ProbeForRead(pvDestProfile,cjDestProfile,sizeof(BYTE));
  847. hSecureDestination = MmSecureVirtualMemory(pvDestProfile,cjDestProfile,PAGE_READONLY);
  848. if (hSecureDestination)
  849. {
  850. pKmDstProfile = pvDestProfile;
  851. }
  852. else
  853. {
  854. WARNING("NtGdiCreateColorTransform():Fail to lock destination profile\n");
  855. bError = TRUE;
  856. }
  857. }
  858. if (pvTargetProfile && cjTargetProfile)
  859. {
  860. ProbeForRead(pvTargetProfile,cjTargetProfile,sizeof(BYTE));
  861. hSecureTarget = MmSecureVirtualMemory(pvTargetProfile,cjTargetProfile,PAGE_READONLY);
  862. if (hSecureTarget)
  863. {
  864. pKmTrgProfile = pvTargetProfile;
  865. }
  866. else
  867. {
  868. WARNING("NtGdiCreateColorTransform():Fail to lock target profile\n");
  869. bError = TRUE;
  870. }
  871. }
  872. }
  873. __except(EXCEPTION_EXECUTE_HANDLER)
  874. {
  875. WARNING("NtGdiCreateColorTransform(): Fail to lock usermode parameters\n");
  876. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  877. bError = TRUE;
  878. }
  879. if (!bError)
  880. {
  881. //
  882. // Create Color Transform.
  883. //
  884. hColorTransform = GreCreateColorTransform(hdc,
  885. &KmLogColorSpaceW,
  886. pKmSrcProfile,
  887. cjSrcProfile,
  888. pKmDstProfile,
  889. cjDestProfile,
  890. pKmTrgProfile,
  891. cjTargetProfile);
  892. if (!hColorTransform)
  893. {
  894. WARNING("GreCreateColorTransform() failed\n");
  895. }
  896. }
  897. if (hSecureSource)
  898. {
  899. MmUnsecureVirtualMemory(hSecureSource);
  900. }
  901. if (hSecureDestination)
  902. {
  903. MmUnsecureVirtualMemory(hSecureDestination);
  904. }
  905. if (hSecureTarget)
  906. {
  907. MmUnsecureVirtualMemory(hSecureTarget);
  908. }
  909. return (hColorTransform);
  910. }
  911. /******************************Public*Routine******************************\
  912. * GreDeleteColorTransform
  913. *
  914. * Arguments:
  915. *
  916. * Return Value:
  917. *
  918. * History:
  919. *
  920. * Feb.21.1997 -by- Hideyuki Nagase [hideyukn]
  921. \**************************************************************************/
  922. BOOL
  923. GreDeleteColorTransform(
  924. HDC hdc,
  925. HANDLE hColorTransform
  926. )
  927. {
  928. ICMAPI(("GreDeleteColorTransform\n"));
  929. BOOL bRet = FALSE;
  930. //
  931. // Lock DC, call driver to delete color transform.
  932. // if the driver doesn't support this call, this is an
  933. // error
  934. //
  935. XDCOBJ dcoDst(hdc);
  936. //
  937. // Validate the destination DC.
  938. //
  939. if (dcoDst.bValid())
  940. {
  941. if (dcoDst.pdc->bInFullScreen())
  942. {
  943. WARNING("GreCreateColorTransform(): hdc is full screen\n");
  944. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  945. }
  946. else
  947. {
  948. COLORTRANSFORMOBJ CXFormObj(hColorTransform);
  949. if (CXFormObj.bValid())
  950. {
  951. //
  952. // Delete it
  953. //
  954. bRet = CXFormObj.bDelete(dcoDst);
  955. }
  956. }
  957. dcoDst.vUnlock();
  958. }
  959. else
  960. {
  961. WARNING1("ERORR GreGdiDeleteColorTransform called on invalid DC\n");
  962. }
  963. return(bRet);
  964. }
  965. /******************************Public*Routine******************************\
  966. * NtGdiDeleteColorTransform
  967. *
  968. * Arguments:
  969. *
  970. * Return Value:
  971. *
  972. * History:
  973. *
  974. * 5-Aug-1996 -by- Mark Enstrom [marke]
  975. *
  976. \**************************************************************************/
  977. BOOL
  978. NtGdiDeleteColorTransform(
  979. HDC hdc,
  980. HANDLE hColorTransform
  981. )
  982. {
  983. ICMAPI(("NtGdiDeleteColorTransform\n"));
  984. return (GreDeleteColorTransform(hdc,hColorTransform));
  985. }
  986. /******************************Public*Routine******************************\
  987. * GreCheckBitmapBits
  988. *
  989. * Arguments:
  990. *
  991. * Return Value:
  992. *
  993. * History:
  994. *
  995. * Write it:
  996. * 27-Jan-1997 -by- Hideyuki Nagase [hideyukn]
  997. \**************************************************************************/
  998. BOOL
  999. GreCheckBitmapBits(
  1000. HDC hdc,
  1001. HANDLE hColorTransform,
  1002. DEVBITMAPINFO *pdbmi,
  1003. PVOID pvBits,
  1004. PBYTE paResults)
  1005. {
  1006. ICMAPI(("GreCheckBitmapBits\n"));
  1007. BOOL bRet = FALSE;
  1008. XDCOBJ dco(hdc);
  1009. if (dco.bValid())
  1010. {
  1011. DEVLOCKOBJ dlo;
  1012. if (dlo.bLock(dco))
  1013. {
  1014. PDEVOBJ po(dco.hdev());
  1015. if (po.bValid())
  1016. {
  1017. if (PPFNVALID(po, IcmCheckBitmapBits))
  1018. {
  1019. //
  1020. // We need to pass driver's transform handle to driver.
  1021. //
  1022. COLORTRANSFORMOBJ CXFormObj(hColorTransform);
  1023. if (CXFormObj.bValid())
  1024. {
  1025. SURFMEM SurfDimoTemp;
  1026. SurfDimoTemp.bCreateDIB(pdbmi,pvBits);
  1027. if (SurfDimoTemp.bValid())
  1028. {
  1029. //
  1030. // Call device driver.
  1031. //
  1032. bRet = (*PPFNDRV(po, IcmCheckBitmapBits))(
  1033. po.dhpdev(),
  1034. CXFormObj.hGetDeviceColorTransform(),
  1035. SurfDimoTemp.pSurfobj(),
  1036. paResults);
  1037. }
  1038. }
  1039. }
  1040. else
  1041. {
  1042. WARNING("GreCheckBitmapBits called on device that does not support call\n");
  1043. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  1044. }
  1045. }
  1046. }
  1047. dco.vUnlockFast();
  1048. }
  1049. return (bRet);
  1050. }
  1051. /******************************Public*Routine******************************\
  1052. * NtGdiCheckBitmapBits
  1053. *
  1054. * Arguments:
  1055. *
  1056. * Return Value:
  1057. *
  1058. * History:
  1059. *
  1060. * Write it:
  1061. * 27-Jan-1997 -by- Hideyuki Nagase [hideyukn]
  1062. \**************************************************************************/
  1063. BOOL WINAPI
  1064. NtGdiCheckBitmapBits(
  1065. HDC hdc,
  1066. HANDLE hColorTransform,
  1067. PVOID pvBits,
  1068. ULONG bmFormat,
  1069. DWORD dwWidth,
  1070. DWORD dwHeight,
  1071. DWORD dwStride,
  1072. PBYTE paResults)
  1073. {
  1074. ICMAPI(("NtGdiCheckBitmapBits\n"));
  1075. ULONG ulBytesPerPixel;
  1076. ULONG ulSizeInByte;
  1077. ULONG ulSizeForResult;
  1078. HANDLE hSecureBits = NULL;
  1079. HANDLE hSecureRets = NULL;
  1080. DEVBITMAPINFO dbmi;
  1081. BOOL bRet = TRUE;
  1082. //
  1083. // limitted support.
  1084. //
  1085. if (
  1086. (bmFormat != BM_RGBTRIPLETS) || (dwHeight != 1)
  1087. )
  1088. {
  1089. WARNING("NtGdiCheckBitmapBits(): Format is not supported, yet\n");
  1090. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  1091. return (FALSE);
  1092. }
  1093. //
  1094. // So, far, we only support RGBTRIPLE format, and n x 1 bitmap.
  1095. //
  1096. ulBytesPerPixel = sizeof(RGBTRIPLE);
  1097. ulSizeInByte = ALIGN_DWORD(dwWidth * ulBytesPerPixel);
  1098. ulSizeForResult = dwWidth;
  1099. //
  1100. // dwStride should be equal to ulSizeInByte,
  1101. // because we should only has 1 height bitmap.
  1102. //
  1103. if (dwStride != ulSizeInByte)
  1104. {
  1105. WARNING("NtGdiCheckBitmapBits(): Format is not supported, yet\n");
  1106. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  1107. return (FALSE);
  1108. }
  1109. //
  1110. // Fill up DEVBITMAPINFO
  1111. //
  1112. dbmi.iFormat = BMF_24BPP;
  1113. dbmi.cxBitmap = dwWidth;
  1114. dbmi.cyBitmap = dwHeight;
  1115. dbmi.cjBits = ulSizeInByte;
  1116. dbmi.hpal = NULL;
  1117. dbmi.fl = 0;
  1118. //
  1119. // Lock down user mode memory for bitmap and result buffer
  1120. //
  1121. __try
  1122. {
  1123. ProbeForRead(pvBits,ulSizeInByte,sizeof(DWORD));
  1124. ProbeForRead(paResults,ulSizeForResult,sizeof(BYTE));
  1125. hSecureBits = MmSecureVirtualMemory(pvBits, ulSizeInByte, PAGE_READONLY);
  1126. hSecureRets = MmSecureVirtualMemory(paResults, ulSizeForResult, PAGE_READWRITE);
  1127. }
  1128. __except(EXCEPTION_EXECUTE_HANDLER)
  1129. {
  1130. WARNING("NtGdiCheckBitmapBits():Error in capture usermode memory\n");
  1131. bRet = FALSE;
  1132. }
  1133. if (bRet && hSecureBits && hSecureRets)
  1134. {
  1135. bRet = GreCheckBitmapBits(hdc,hColorTransform,
  1136. &dbmi,pvBits,
  1137. (PBYTE)paResults);
  1138. }
  1139. if (hSecureBits)
  1140. {
  1141. MmUnsecureVirtualMemory(hSecureBits);
  1142. }
  1143. if (hSecureRets)
  1144. {
  1145. MmUnsecureVirtualMemory(hSecureRets);
  1146. }
  1147. return (bRet);
  1148. }
  1149. /******************************Public*Routine******************************\
  1150. * NtGdiColorCorrectPalette
  1151. *
  1152. * If this is a query operation then:
  1153. * If the DC has ICM enabled NON_DEVICE and
  1154. * the palette is not already color corrected then
  1155. * Get the logical palette entries and return to app in array provided
  1156. *
  1157. *
  1158. * If this is a set operation and the DC has ICM_NON_DEVICE and the palette
  1159. * is ok then set the palette entries.
  1160. *
  1161. * If this is a set operation and the DC is DEVICE then do nothing
  1162. * --Maybe call device driver if it exports ICM calls
  1163. *
  1164. *
  1165. * NOTE: if hpalette is moved to dcattr, then this routine can be
  1166. * eliminated and done byt get/set palette entries from user mode
  1167. *
  1168. * Arguments:
  1169. *
  1170. * Return Value:
  1171. *
  1172. * History:
  1173. *
  1174. * 15-Aug-1996 -by- Mark Enstrom [marke]
  1175. *
  1176. \**************************************************************************/
  1177. ULONG
  1178. APIENTRY
  1179. NtGdiColorCorrectPalette(
  1180. HDC hdc,
  1181. HPALETTE hpal,
  1182. ULONG FirstEntry,
  1183. ULONG NumberOfEntries,
  1184. PALETTEENTRY *ppalEntry,
  1185. ULONG Command)
  1186. {
  1187. ICMAPI(("NtGdiColorCorrectPalette\n"));
  1188. DCOBJ dcoDst(hdc);
  1189. EPALOBJ pal((HPALETTE) hpal);
  1190. ULONG ulRet = 0;
  1191. if (dcoDst.bValid() && pal.bValid())
  1192. {
  1193. if ((NumberOfEntries == 0) ||
  1194. (NumberOfEntries > pal.cEntries()) ||
  1195. (FirstEntry > pal.cEntries()) ||
  1196. ((FirstEntry + NumberOfEntries) > pal.cEntries()))
  1197. {
  1198. WARNING("NtGdiColorCorrectPalette(): Invalid parameter\n");
  1199. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  1200. return(ulRet);
  1201. }
  1202. if (IS_ICM_HOST(dcoDst.pdc->lIcmMode()))
  1203. {
  1204. if (Command == ColorPaletteQuery)
  1205. {
  1206. //
  1207. // check palette for already colorcorrected flag
  1208. //
  1209. __try
  1210. {
  1211. ProbeForWrite(ppalEntry,sizeof(PALETTEENTRY) * NumberOfEntries,sizeof(PALETTEENTRY));
  1212. //
  1213. // Get palette entries.
  1214. //
  1215. ulRet = pal.ulGetEntries(FirstEntry, NumberOfEntries, ppalEntry, FALSE);
  1216. }
  1217. __except(EXCEPTION_EXECUTE_HANDLER)
  1218. {
  1219. WARNING("NtGdiColorCorrectPalette():Error in GetEntries\n");
  1220. ulRet = 0;
  1221. }
  1222. }
  1223. else if (Command == ColorPaletteSet)
  1224. {
  1225. __try
  1226. {
  1227. ProbeForRead(ppalEntry,sizeof(PALETTEENTRY) * NumberOfEntries,sizeof(PALETTEENTRY));
  1228. //
  1229. // Set palette entries.
  1230. //
  1231. ulRet = pal.ulSetEntries(FirstEntry, NumberOfEntries, ppalEntry);
  1232. }
  1233. __except(EXCEPTION_EXECUTE_HANDLER)
  1234. {
  1235. WARNING("NtGdiColorCorrectPalette():Error in SetEntries\n");
  1236. ulRet = 0;
  1237. }
  1238. }
  1239. }
  1240. else
  1241. {
  1242. WARNING("NtGdiColorCorrectPalette(): Invalid ICM mode\n");
  1243. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  1244. }
  1245. }
  1246. else
  1247. {
  1248. WARNING("NtGdiColorCorrectPalette(): Invalid hdc or hpal\n");
  1249. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  1250. }
  1251. return(ulRet);
  1252. }
  1253. /******************************Public*Routine******************************\
  1254. * GreGetDeviceGammaRampInternal
  1255. *
  1256. * History:
  1257. *
  1258. * Wrote it:
  1259. * 28.Jun.2000 -by- Hideyuki Nagase [hideyukn]
  1260. \**************************************************************************/
  1261. BOOL
  1262. GreGetDeviceGammaRampInternal(
  1263. HDEV hdev,
  1264. LPVOID lpGammaRamp
  1265. )
  1266. {
  1267. BOOL bRet = FALSE;
  1268. PDEVOBJ po(hdev);
  1269. //
  1270. // GetDeviceGammaRamp is only for display device.
  1271. //
  1272. if (po.bValid() && po.bDisplayPDEV())
  1273. {
  1274. //
  1275. // Check color depth is not less than 8 bpp (need 256 color at least)
  1276. //
  1277. if ((po.iDitherFormat() == BMF_8BPP) ||
  1278. (po.iDitherFormat() == BMF_16BPP) ||
  1279. (po.iDitherFormat() == BMF_24BPP) ||
  1280. (po.iDitherFormat() == BMF_32BPP))
  1281. {
  1282. //
  1283. // Check this PDEV has thier own GammaTable or not.
  1284. //
  1285. if (po.bHasGammaRampTable())
  1286. {
  1287. ICMMSG(("GreGetDeviceGammaRamp(): Use PDEV's GammaRamp Table\n"));
  1288. //
  1289. // Copy from PDEV's GammaRamp buffer.
  1290. //
  1291. RtlCopyMemory(lpGammaRamp,po.pvGammaRampTable(),MAX_COLORTABLE * sizeof(WORD) * 3);
  1292. }
  1293. else
  1294. {
  1295. ICMMSG(("GreGetDeviceGammaRamp(): Use default GammaRamp Table\n"));
  1296. //
  1297. // Fill up with ident. GammaRamp
  1298. //
  1299. LPWORD lpRed = (LPWORD)lpGammaRamp;
  1300. LPWORD lpGreen = (LPWORD)lpGammaRamp + MAX_COLORTABLE;
  1301. LPWORD lpBlue = (LPWORD)lpGammaRamp + MAX_COLORTABLE + MAX_COLORTABLE;
  1302. //
  1303. // Indent. GammaRamp is 0x0000 -> 0xFF00 for each R,G and B.
  1304. // And LOBYTE is 0, only HIBYTE has value from 0 to 0xFF.
  1305. //
  1306. for (UINT i = 0; i < MAX_COLORTABLE; i++)
  1307. {
  1308. lpRed[i] = lpGreen[i] = lpBlue[i] = (WORD)(i << 8);
  1309. }
  1310. }
  1311. //
  1312. // Filled up the buffer, return TRUE.
  1313. //
  1314. bRet = TRUE;
  1315. }
  1316. else
  1317. {
  1318. ICMMSG(("GreGetDeviceGammaRamp(): Surface is less than 8 bpp\n"));
  1319. }
  1320. }
  1321. else
  1322. {
  1323. ICMMSG(("GreGetDeviceGammaRamp(): DC might not be display\n"));
  1324. }
  1325. return (bRet);
  1326. }
  1327. /******************************Public*Routine******************************\
  1328. * GreGetDeviceGammaRamp
  1329. *
  1330. * History:
  1331. *
  1332. * Wrote it:
  1333. * 1.Apr.1997 -by- Hideyuki Nagase [hideyukn]
  1334. \**************************************************************************/
  1335. BOOL
  1336. GreGetDeviceGammaRamp(
  1337. HDC hdc,
  1338. LPVOID lpGammaRamp
  1339. )
  1340. {
  1341. ICMAPI(("GreGetDeviceGammaRamp\n"));
  1342. BOOL bRet = FALSE;
  1343. XDCOBJ dco(hdc);
  1344. if (dco.bValid())
  1345. {
  1346. //
  1347. // DC should not be info or meta DC.
  1348. //
  1349. if (dco.dctp() == DCTYPE_DIRECT)
  1350. {
  1351. DEVLOCKOBJ dlo;
  1352. if (dlo.bLock(dco))
  1353. {
  1354. bRet = GreGetDeviceGammaRampInternal(dco.hdev(),lpGammaRamp);
  1355. }
  1356. }
  1357. dco.vUnlockFast();
  1358. }
  1359. if (!bRet)
  1360. {
  1361. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  1362. }
  1363. return (bRet);
  1364. }
  1365. /******************************Public*Routine******************************\
  1366. * NtGdiGetDeviceGammaRamp
  1367. *
  1368. * History:
  1369. *
  1370. * Wrote it:
  1371. * 1.Apr.1997 -by- Hideyuki Nagase [hideyukn]
  1372. \**************************************************************************/
  1373. BOOL
  1374. NtGdiGetDeviceGammaRamp(
  1375. HDC hdc,
  1376. LPVOID lpGammaRamp
  1377. )
  1378. {
  1379. ICMAPI(("NtGdiGetDeviceGammaRamp\n"));
  1380. BOOL bRet = FALSE;
  1381. if (lpGammaRamp)
  1382. {
  1383. HANDLE hSecure = NULL;
  1384. BOOL bError = FALSE;
  1385. __try
  1386. {
  1387. ProbeForWrite(lpGammaRamp, MAX_COLORTABLE * sizeof(WORD) * 3, sizeof(WORD));
  1388. hSecure = MmSecureVirtualMemory(lpGammaRamp, MAX_COLORTABLE * sizeof(WORD) * 3, PAGE_READWRITE);
  1389. }
  1390. __except(EXCEPTION_EXECUTE_HANDLER)
  1391. {
  1392. WARNING("NtGdiGetDeviceGammaRamp: Fail to capture usermode buffer\n");
  1393. bError = TRUE;
  1394. }
  1395. if ((bError == FALSE) && hSecure)
  1396. {
  1397. bRet = GreGetDeviceGammaRamp(hdc,lpGammaRamp);
  1398. }
  1399. if (hSecure)
  1400. {
  1401. MmUnsecureVirtualMemory(hSecure);
  1402. }
  1403. }
  1404. else
  1405. {
  1406. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  1407. }
  1408. return(bRet);
  1409. }
  1410. /******************************Public*Routine******************************\
  1411. * GreSetDeviceGammaRampInternal
  1412. *
  1413. * History:
  1414. *
  1415. * Wrote it:
  1416. * 1.Apr.1997 -by- Hideyuki Nagase [hideyukn]
  1417. * 2.Nov.1998 -by- Scott MacDonald [smac] Split it into two functions
  1418. \**************************************************************************/
  1419. BOOL
  1420. GreSetDeviceGammaRampInternal(
  1421. HDEV hdev,
  1422. LPVOID lpGammaRamp,
  1423. BOOL bDoRangeCheck
  1424. )
  1425. {
  1426. ICMAPI(("GreSetDeviceGammaRampInternal\n"));
  1427. BOOL bRet = FALSE;
  1428. PDEVOBJ po(hdev);
  1429. //
  1430. // GetDeviceGammaRamp is only for display device.
  1431. //
  1432. if (po.bValid() && po.bDisplayPDEV())
  1433. {
  1434. BOOL bUsePalette = FALSE;
  1435. BOOL bValidBPP = FALSE;
  1436. //
  1437. // Check color depth is not less than 8 bpp (need 256 color at least)
  1438. //
  1439. if ((po.iDitherFormat() == BMF_8BPP) ||
  1440. (po.iDitherFormat() == BMF_16BPP) ||
  1441. (po.iDitherFormat() == BMF_24BPP) ||
  1442. (po.iDitherFormat() == BMF_32BPP))
  1443. {
  1444. if ((PPFNVALID(po, IcmSetDeviceGammaRamp)) &&
  1445. (po.flGraphicsCaps2() & GCAPS2_CHANGEGAMMARAMP))
  1446. {
  1447. //
  1448. // Driver supports DrvSetDeviceGammaRamp()
  1449. //
  1450. bValidBPP = TRUE;
  1451. }
  1452. else
  1453. {
  1454. //
  1455. // Driver does not suppprt it, but we can sinulate it
  1456. // with palette only for 8 bpp case.
  1457. //
  1458. if ((po.iDitherFormat() == BMF_8BPP) && po.bIsPalManaged())
  1459. {
  1460. //
  1461. // For 8 bpp surface, we can adjust color via
  1462. // palette on device if palettalized device.
  1463. //
  1464. bUsePalette = TRUE;
  1465. bValidBPP = TRUE;
  1466. }
  1467. }
  1468. }
  1469. else
  1470. {
  1471. //
  1472. // Can not set GammaRamp for 1/4 bpp surface
  1473. //
  1474. }
  1475. //
  1476. // PDEV's bpp is suite for set GammaRamp ?
  1477. //
  1478. if (bValidBPP)
  1479. {
  1480. BOOL bNeedCallDriver = TRUE;
  1481. BOOL bDefaultGammaRamp = !bDoRangeCheck;
  1482. BOOL bSameGammaRamp = FALSE;
  1483. if (po.bHasGammaRampTable())
  1484. {
  1485. //
  1486. // If this PDEV is already has GammaRamp table, we will check
  1487. // this is same as the table what we are going to set.
  1488. //
  1489. if (RtlCompareMemory(po.pvGammaRampTable(),
  1490. lpGammaRamp,
  1491. MAX_COLORTABLE * sizeof(WORD) * 3)
  1492. == (MAX_COLORTABLE * sizeof(WORD) * 3))
  1493. {
  1494. //
  1495. // Same
  1496. //
  1497. bSameGammaRamp = TRUE;
  1498. }
  1499. }
  1500. if (bSameGammaRamp)
  1501. {
  1502. ICMMSG(("GreSetDeviceGammaRamp(): Same GammaRamp is already selected\n"));
  1503. //
  1504. // Same GammaRamp is already selected, nothing need to do.
  1505. //
  1506. bRet = TRUE;
  1507. }
  1508. else
  1509. {
  1510. //
  1511. // Scan the input GammaRamp to check within the range.
  1512. //
  1513. LPWORD lpRed = (LPWORD)lpGammaRamp;
  1514. LPWORD lpGreen = (LPWORD)lpGammaRamp + MAX_COLORTABLE;
  1515. LPWORD lpBlue = (LPWORD)lpGammaRamp + MAX_COLORTABLE + MAX_COLORTABLE;
  1516. INT iRange = (INT)(giIcmGammaRange);
  1517. //
  1518. // if we encounter any Gamma outside range, break!
  1519. //
  1520. for (UINT i = 0; ((i < MAX_COLORTABLE) && (bNeedCallDriver == TRUE)); i++)
  1521. {
  1522. UINT iAveGamma = i;
  1523. UINT iRed = (UINT)(lpRed[i] >> 8);
  1524. UINT iGreen = (UINT)(lpGreen[i] >> 8);
  1525. UINT iBlue = (UINT)(lpBlue[i] >> 8);
  1526. INT iRangeMax = (INT)(iAveGamma + iRange);
  1527. INT iRangeMin = (INT)(iAveGamma - iRange);
  1528. ICMMSG(("iRangeMax = %x:iRangeMix = %x:iRed = %x:iGreen = %x:iBlue = %x\n",
  1529. iRangeMax, iRangeMin,(INT)iRed,(INT)iGreen,(INT)iBlue));
  1530. if ((((INT)iRed < iRangeMin) || ((INT)iRed > iRangeMax) ||
  1531. ((INT)iGreen < iRangeMin) || ((INT)iGreen > iRangeMax) ||
  1532. ((INT)iBlue < iRangeMin) || ((INT)iBlue > iRangeMax)) &&
  1533. bDoRangeCheck)
  1534. {
  1535. //
  1536. // The Gamma is out of range, don't need call driver
  1537. //
  1538. bNeedCallDriver = FALSE;
  1539. }
  1540. //
  1541. // Check if the GammaRamp is ident. or not.
  1542. //
  1543. if (bDefaultGammaRamp &&
  1544. ((lpRed[i] != (iAveGamma << 8)) ||
  1545. (lpGreen[i] != (iAveGamma << 8)) ||
  1546. (lpBlue[i] != (iAveGamma << 8))))
  1547. {
  1548. ICMMSG(("GreSetDeviceGammaRamp():Not ident. GammaRamp\n"));
  1549. bDefaultGammaRamp = FALSE;
  1550. }
  1551. }
  1552. if (bNeedCallDriver)
  1553. {
  1554. if (bUsePalette && bDefaultGammaRamp)
  1555. {
  1556. //
  1557. // If we will use palette, and GammaRamp are going to changed to
  1558. // default, we don't need to have GammaRamp table.
  1559. //
  1560. if (po.bHasGammaRampTable())
  1561. {
  1562. ICMMSG(("GreSetDeviceGammaRamp():Default GammaRamp (need update palette)\n"));
  1563. //
  1564. // The specified GammaRamp is ident., don't need to keep it.
  1565. //
  1566. po.bHasGammaRampTable(FALSE);
  1567. VFREEMEM(po.pvGammaRampTable());
  1568. po.pvGammaRampTable(NULL);
  1569. }
  1570. else
  1571. {
  1572. ICMMSG(("GreSetDeviceGammaRamp():Default GammaRamp (no palette call)\n"));
  1573. //
  1574. // If we don't have GammaRamp table in PDEV, it means
  1575. // we are in defult already. So don't need to call driver
  1576. // (= don't need to update palette.)
  1577. //
  1578. bNeedCallDriver = FALSE;
  1579. }
  1580. }
  1581. else
  1582. {
  1583. //
  1584. // Check this PDEV has thier own GammaTable or not.
  1585. //
  1586. if (!po.bHasGammaRampTable())
  1587. {
  1588. ICMMSG(("GreSetDeviceGammaRamp(): Allocate GammaRamp Table\n"));
  1589. //
  1590. // Allocate GammaRamp table for this PDEV
  1591. //
  1592. LPVOID pv = (LPVOID) PALLOCNOZ(MAX_COLORTABLE * sizeof(WORD) * 3,'mciG');
  1593. if (pv)
  1594. {
  1595. //
  1596. // Mark this PDEV has GammaTable.
  1597. //
  1598. po.pvGammaRampTable(pv);
  1599. po.bHasGammaRampTable(TRUE);
  1600. }
  1601. else
  1602. {
  1603. WARNING("GreSetDeviceGammaRamp():Fail to allocate GammaRamp table\n");
  1604. //
  1605. // Error, we don't need to call driver.
  1606. //
  1607. bNeedCallDriver = FALSE;
  1608. }
  1609. }
  1610. }
  1611. if (bNeedCallDriver)
  1612. {
  1613. if (po.bHasGammaRampTable())
  1614. {
  1615. ICMMSG(("GreSetDeviceGammaRamp():Updating GammaRamp Table in PDEV...\n"));
  1616. //
  1617. // Save new GammaRamp into PDEV.
  1618. //
  1619. RtlCopyMemory(po.pvGammaRampTable(),lpGammaRamp,
  1620. MAX_COLORTABLE * sizeof(WORD) * 3);
  1621. }
  1622. //
  1623. // Update GammaRamp on device using PDEV's GammaRamp Table.
  1624. //
  1625. bRet = UpdateGammaRampOnDevice(po.hdev(),TRUE);
  1626. if (bDefaultGammaRamp && po.bHasGammaRampTable())
  1627. {
  1628. ICMMSG(("GreSetDeviceGammaRamp():Default GammaRamp is setted (non-palette)\n"));
  1629. //
  1630. // The specified GammaRamp is ident., don't need to keep it.
  1631. //
  1632. po.bHasGammaRampTable(FALSE);
  1633. VFREEMEM(po.pvGammaRampTable());
  1634. po.pvGammaRampTable(NULL);
  1635. }
  1636. }
  1637. else
  1638. {
  1639. //
  1640. // Fail... couldn't call driver and return false.
  1641. //
  1642. bRet = FALSE;
  1643. }
  1644. }
  1645. else
  1646. {
  1647. ICMMSG(("GreSetDeviceGammaRamp(): GammaRamp is out of range\n"));
  1648. }
  1649. }
  1650. }
  1651. else
  1652. {
  1653. ICMMSG(("GreSetDeviceGammaRamp(): Surface/Driver does not support loadable GammaRamp\n"));
  1654. }
  1655. }
  1656. return (bRet);
  1657. }
  1658. /******************************Public*Routine******************************\
  1659. * GreSetDeviceGammaRamp
  1660. *
  1661. * History:
  1662. *
  1663. * Wrote it:
  1664. * 1.Apr.1997 -by- Hideyuki Nagase [hideyukn]
  1665. \**************************************************************************/
  1666. BOOL
  1667. GreSetDeviceGammaRamp(
  1668. HDC hdc,
  1669. LPVOID lpGammaRamp,
  1670. BOOL bDoRangeCheck
  1671. )
  1672. {
  1673. ICMAPI(("GreSetDeviceGammaRamp\n"));
  1674. BOOL bRet = FALSE;
  1675. XDCOBJ dco(hdc);
  1676. if (dco.bValid())
  1677. {
  1678. //
  1679. // DC should not be info or meta DC.
  1680. //
  1681. if (dco.dctp() == DCTYPE_DIRECT)
  1682. {
  1683. DEVLOCKOBJ dlo;
  1684. if (dlo.bLock(dco))
  1685. {
  1686. bRet = GreSetDeviceGammaRampInternal(dco.hdev(),
  1687. lpGammaRamp,
  1688. bDoRangeCheck);
  1689. }
  1690. }
  1691. dco.vUnlockFast();
  1692. }
  1693. if (!bRet)
  1694. {
  1695. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  1696. }
  1697. return (bRet);
  1698. }
  1699. /******************************Public*Routine******************************\
  1700. * NtGdiSetDeviceGammaRamp
  1701. *
  1702. * History:
  1703. *
  1704. * Wrote it:
  1705. * 1.Apr.1997 -by- Hideyuki Nagase [hideyukn]
  1706. \**************************************************************************/
  1707. BOOL
  1708. NtGdiSetDeviceGammaRamp(
  1709. HDC hdc,
  1710. LPVOID lpGammaRamp
  1711. )
  1712. {
  1713. ICMAPI(("NtGdiSetDeviceGammaRamp\n"));
  1714. BOOL bRet = FALSE;
  1715. if (lpGammaRamp)
  1716. {
  1717. HANDLE hSecure = NULL;
  1718. BOOL bError = FALSE;
  1719. __try
  1720. {
  1721. ProbeForRead(lpGammaRamp, MAX_COLORTABLE * sizeof(WORD) * 3, sizeof(WORD));
  1722. hSecure = MmSecureVirtualMemory(lpGammaRamp, MAX_COLORTABLE * sizeof(WORD) * 3, PAGE_READONLY);
  1723. }
  1724. __except(EXCEPTION_EXECUTE_HANDLER)
  1725. {
  1726. WARNING("NtGdiSetDeviceGammaRamp: Fail to capture usermode buffer\n");
  1727. bError = TRUE;
  1728. }
  1729. if ((bError == FALSE) && hSecure)
  1730. {
  1731. bRet = GreSetDeviceGammaRamp(hdc,lpGammaRamp,TRUE);
  1732. }
  1733. if (hSecure)
  1734. {
  1735. MmUnsecureVirtualMemory(hSecure);
  1736. }
  1737. }
  1738. else
  1739. {
  1740. SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
  1741. }
  1742. return(bRet);
  1743. }
  1744. /******************************Public*Routine******************************\
  1745. * cjGetLogicalColorSpace
  1746. *
  1747. * Arguments:
  1748. *
  1749. * Return Value:
  1750. *
  1751. * History:
  1752. *
  1753. * 9/20/1996 Mark Enstrom [marke]
  1754. *
  1755. \**************************************************************************/
  1756. INT
  1757. cjGetLogicalColorSpace(
  1758. HANDLE hColorSpace,
  1759. INT cjBuffer,
  1760. LPVOID lpvBuffer
  1761. )
  1762. {
  1763. ICMAPI(("cjGetLogicalColorSpace\n"));
  1764. INT cRet = 0;
  1765. if (cjBuffer >= sizeof(LOGCOLORSPACEW) && (lpvBuffer != NULL))
  1766. {
  1767. COLORSPACEREF ColorSpace((HCOLORSPACE)hColorSpace);
  1768. if (ColorSpace.bValid())
  1769. {
  1770. LPLOGCOLORSPACEW lpLogColorSpace = (LPLOGCOLORSPACEW)lpvBuffer;
  1771. lpLogColorSpace->lcsSignature = ColorSpace.pColorSpace()->lcsSignature();
  1772. lpLogColorSpace->lcsVersion = ColorSpace.pColorSpace()->lcsVersion();
  1773. lpLogColorSpace->lcsSize = ColorSpace.pColorSpace()->lcsSize();
  1774. lpLogColorSpace->lcsCSType = ColorSpace.pColorSpace()->lcsCSType();
  1775. lpLogColorSpace->lcsIntent = ColorSpace.pColorSpace()->lcsIntent();
  1776. ColorSpace.pColorSpace()->vGETlcsEndpoints(&lpLogColorSpace->lcsEndpoints);
  1777. lpLogColorSpace->lcsGammaRed = ColorSpace.pColorSpace()->lcsGammaRed();
  1778. lpLogColorSpace->lcsGammaGreen= ColorSpace.pColorSpace()->lcsGammaGreen();
  1779. lpLogColorSpace->lcsGammaBlue = ColorSpace.pColorSpace()->lcsGammaBlue();
  1780. ColorSpace.pColorSpace()->vGETlcsFilename((PWCHAR)&lpLogColorSpace->lcsFilename[0],MAX_PATH);
  1781. if (cjBuffer >= sizeof(LOGCOLORSPACEEXW))
  1782. {
  1783. PLOGCOLORSPACEEXW lpLogColorSpaceEx = (PLOGCOLORSPACEEXW)lpvBuffer;
  1784. lpLogColorSpaceEx->dwFlags = ColorSpace.pColorSpace()->lcsExFlags();
  1785. cRet = sizeof(LOGCOLORSPACEEXW);
  1786. }
  1787. else
  1788. {
  1789. cRet = sizeof(LOGCOLORSPACEW);
  1790. }
  1791. }
  1792. }
  1793. return cRet;
  1794. }
  1795. /******************************Public*Routine******************************\
  1796. * GreIcmQueryBrushBitmap
  1797. *
  1798. * Arguments:
  1799. *
  1800. * Return Value:
  1801. *
  1802. * History:
  1803. *
  1804. * Rewrite it:
  1805. * 27-Jan-1997 -by- Hideyuki Nagase [hideyukn]
  1806. \**************************************************************************/
  1807. BOOL
  1808. GreIcmQueryBrushBitmap(
  1809. HDC hdc,
  1810. HBRUSH hbrush,
  1811. PBITMAPINFO pbmiDIB,
  1812. PVOID pvBits,
  1813. ULONG *pulBits,
  1814. DWORD *piUsage,
  1815. BOOL *pbAlreadyTran
  1816. )
  1817. {
  1818. BOOL bRet = FALSE;
  1819. DWORD iUsage = DIB_RGB_COLORS;
  1820. BOOL bAlreadyTran = FALSE;
  1821. PBYTE pDIBits = NULL;
  1822. ULONG ulSizeInfo = sizeof(BITMAPINFO) + ((MAX_COLORTABLE - 1) * sizeof(RGBQUAD));
  1823. ICMAPI(("GreIcmQueryBrushBitmap\n"));
  1824. if ((pbmiDIB == NULL) || (piUsage == NULL) || (pbAlreadyTran == NULL) || (pulBits == NULL))
  1825. {
  1826. return FALSE;
  1827. }
  1828. XDCOBJ dcoDst(hdc);
  1829. if (dcoDst.bValid())
  1830. {
  1831. //
  1832. // ICM must be on, non-device mode only
  1833. //
  1834. if (dcoDst.pdc->bIsHostICM())
  1835. {
  1836. BRUSHSELOBJ bro((HBRUSH) hbrush);
  1837. if (bro.bValid())
  1838. {
  1839. //
  1840. // must be a DIB brush
  1841. //
  1842. if (bro.flAttrs() & BR_IS_DIB)
  1843. {
  1844. //
  1845. // if brush was created with DIB_PAL_COLORS then
  1846. // ICM translation is not needed.
  1847. //
  1848. if ((iUsage = bro.iUsage()) == DIB_RGB_COLORS)
  1849. {
  1850. //
  1851. // see if translated DIB already exists
  1852. //
  1853. PBRUSH pbr = bro.pbrush();
  1854. if (pbr->hFindIcmDIB(dcoDst.pdc->hcmXform()) != NULL)
  1855. {
  1856. ICMMSG(("GreIcmQueryBrushBitmap() Find !\n"));
  1857. bAlreadyTran = TRUE;
  1858. }
  1859. else
  1860. {
  1861. ICMMSG(("GreIcmQueryBrushBitmap() Not Find, then create it!\n"));
  1862. bAlreadyTran = FALSE;
  1863. //
  1864. // Initialize BITMAPINFO header.
  1865. //
  1866. RtlZeroMemory(pbmiDIB,ulSizeInfo);
  1867. pbmiDIB->bmiHeader.biSize = sizeof(BITMAPINFO);
  1868. //
  1869. // get bits per pixel, could use this to determine if color table is needed
  1870. //
  1871. bRet = GreGetDIBitsInternal(hdc,
  1872. bro.hbmPattern(),
  1873. 0,0,NULL,
  1874. pbmiDIB,
  1875. DIB_RGB_COLORS,
  1876. 0,ulSizeInfo);
  1877. if (bRet)
  1878. {
  1879. ULONG cjBits = GreGetBitmapBitsSize(pbmiDIB);
  1880. if (cjBits == 0)
  1881. {
  1882. //
  1883. // Empty or overflow..
  1884. //
  1885. bRet = FALSE;
  1886. }
  1887. else if (pvBits == NULL)
  1888. {
  1889. //
  1890. // Caller want to know the size of bitmap.
  1891. //
  1892. *pulBits = cjBits;
  1893. bRet = TRUE;
  1894. }
  1895. else if (cjBits <= *pulBits)
  1896. {
  1897. //
  1898. // We have enough memory to get bitmap bits.
  1899. //
  1900. bRet = GreGetDIBitsInternal(hdc,
  1901. bro.hbmPattern(),
  1902. 0,
  1903. ABS(pbmiDIB->bmiHeader.biHeight),
  1904. (LPBYTE) pvBits,
  1905. pbmiDIB,
  1906. DIB_RGB_COLORS,
  1907. cjBits,
  1908. ulSizeInfo);
  1909. //
  1910. // Put used size.
  1911. //
  1912. *pulBits = cjBits;
  1913. }
  1914. else
  1915. {
  1916. WARNING("GreIcmQueryBrushBitmap: the buffer is not enough\n");
  1917. }
  1918. }
  1919. else
  1920. {
  1921. WARNING("GreIcmQueryBrushBitmap: failed to GetDIBits\n");
  1922. }
  1923. }
  1924. }
  1925. else
  1926. {
  1927. ICMMSG(("GreIcmQueryBrushBitmap: brush is not DIB_RGB_COLORS\n"));
  1928. }
  1929. }
  1930. else
  1931. {
  1932. ICMMSG(("GreIcmQueryBrushBitmap: brush is not DIBPATTERN\n"));
  1933. }
  1934. }
  1935. else
  1936. {
  1937. WARNING("GreIcmQueryBrushBitmap: invalid brush\n");
  1938. }
  1939. }
  1940. dcoDst.vUnlockFast();
  1941. }
  1942. else
  1943. {
  1944. WARNING("GreIcmQueryBrushBitmap: invalid DC\n");
  1945. }
  1946. *piUsage = iUsage;
  1947. *pbAlreadyTran = bAlreadyTran;
  1948. return (bRet);
  1949. }
  1950. /******************************Public*Routine******************************\
  1951. * GreIcmSetBrushBitmap
  1952. *
  1953. * Arguments:
  1954. *
  1955. * Return Value:
  1956. *
  1957. * History:
  1958. *
  1959. * Rewrite it:
  1960. * 27-Jan-1997 -by- Hideyuki Nagase [hideyukn]
  1961. \**************************************************************************/
  1962. BOOL
  1963. GreIcmSetBrushBitmap(
  1964. HDC hdc,
  1965. HBRUSH hbrush,
  1966. PBITMAPINFO pbmiDIB,
  1967. PVOID pvBits
  1968. )
  1969. {
  1970. BOOL bRet = FALSE;
  1971. ULONG ulSizeInfo = sizeof(BITMAPINFO) + ((MAX_COLORTABLE - 1) * sizeof(RGBQUAD));
  1972. ICMAPI(("GreIcmSetBrushBitmap\n"));
  1973. XDCOBJ dcoDst(hdc);
  1974. if (dcoDst.bValid())
  1975. {
  1976. //
  1977. // ICM must be on, non-device mode only
  1978. //
  1979. if (dcoDst.pdc->bIsHostICM())
  1980. {
  1981. BRUSHSELOBJ bro((HBRUSH) hbrush);
  1982. if (bro.bValid())
  1983. {
  1984. //
  1985. // must be a DIB brush
  1986. //
  1987. if (bro.flAttrs() & BR_IS_DIB)
  1988. {
  1989. //
  1990. // Create a new DIB for this brush based on
  1991. // the DC's hcmXform. The client must already
  1992. // have translated this DIB
  1993. //
  1994. PBRUSH pbr = bro.pbrush();
  1995. //
  1996. // try to create a new DIB
  1997. //
  1998. HBITMAP hDIB = GreCreateDIBitmapReal(
  1999. hdc,
  2000. CBM_INIT | CBM_CREATEDIB,
  2001. (PBYTE)pvBits,
  2002. pbmiDIB,
  2003. DIB_RGB_COLORS,
  2004. ulSizeInfo,
  2005. 0x007fffff,
  2006. NULL,
  2007. 0,
  2008. NULL,
  2009. CDBI_INTERNAL,
  2010. 0,
  2011. NULL);
  2012. if (hDIB)
  2013. {
  2014. //
  2015. // Keep translate DIB in cache.
  2016. //
  2017. bRet = pbr->bAddIcmDIB(dcoDst.pdc->hcmXform(),hDIB);
  2018. }
  2019. }
  2020. else
  2021. {
  2022. ICMMSG(("GreIcmSetBrushBitmap: brush is not DIBPATTERN\n"));
  2023. }
  2024. }
  2025. else
  2026. {
  2027. WARNING("GreIcmSetBrushBitmap: invalid brush\n");
  2028. }
  2029. }
  2030. dcoDst.vUnlockFast();
  2031. }
  2032. else
  2033. {
  2034. WARNING("GreIcmSetBrushBitmap: invalid DC\n");
  2035. }
  2036. return(bRet);
  2037. }
  2038. /******************************Public*Routine******************************\
  2039. * NtGdiIcmBrushInfo
  2040. *
  2041. * Arguments:
  2042. *
  2043. * Return Value:
  2044. *
  2045. * History:
  2046. *
  2047. * Rewrite it:
  2048. * 27-Jan-1997 -by- Hideyuki Nagase [hideyukn]
  2049. \**************************************************************************/
  2050. BOOL
  2051. NtGdiIcmBrushInfo(
  2052. HDC hdc,
  2053. HBRUSH hbrush,
  2054. PBITMAPINFO pbmiDIB,
  2055. PVOID pvBits,
  2056. ULONG *pulBits,
  2057. DWORD *piUsage,
  2058. BOOL *pbAlreadyTran,
  2059. ULONG Command
  2060. )
  2061. {
  2062. BOOL bRet = TRUE;
  2063. HANDLE hSecureHeader = NULL;
  2064. HANDLE hSecureBits = NULL;
  2065. ULONG cjHeader = (sizeof(BITMAPINFO) + ((MAX_COLORTABLE - 1) * sizeof(RGBQUAD)));
  2066. ULONG cjBits = 0;
  2067. switch (Command)
  2068. {
  2069. case IcmQueryBrush:
  2070. {
  2071. BOOL bAlreadyTran = FALSE;
  2072. DWORD iUsage = DIB_RGB_COLORS;
  2073. __try
  2074. {
  2075. //
  2076. // Capture user mode memories.
  2077. //
  2078. ProbeForWrite(pbmiDIB,cjHeader,sizeof(DWORD));
  2079. hSecureHeader = MmSecureVirtualMemory(pbmiDIB,cjHeader,PAGE_READWRITE);
  2080. if ((pvBits != NULL) && hSecureHeader)
  2081. {
  2082. //
  2083. // Caller needs bitmap bits
  2084. //
  2085. ProbeForRead(pulBits,sizeof(ULONG),sizeof(ULONG));
  2086. cjBits = *pulBits;
  2087. ProbeForWrite(pvBits,cjBits,sizeof(DWORD));
  2088. hSecureBits = MmSecureVirtualMemory(pvBits,cjBits,PAGE_READWRITE);
  2089. }
  2090. }
  2091. __except(EXCEPTION_EXECUTE_HANDLER)
  2092. {
  2093. WARNING("NtGdiIcmBrushInfo - IcmQueryBrush failed copy usermode parameter\n");
  2094. bRet = FALSE;
  2095. }
  2096. if (bRet && hSecureHeader && ((pvBits == NULL) || hSecureBits))
  2097. {
  2098. //
  2099. // Get DIB brush bits.
  2100. //
  2101. bRet = GreIcmQueryBrushBitmap(hdc,
  2102. hbrush,
  2103. pbmiDIB,
  2104. pvBits,
  2105. &cjBits,
  2106. &iUsage,
  2107. &bAlreadyTran);
  2108. }
  2109. if (bRet)
  2110. {
  2111. __try
  2112. {
  2113. ProbeForWrite(pulBits,sizeof(ULONG),sizeof(ULONG));
  2114. *pulBits = cjBits;
  2115. if (pbAlreadyTran)
  2116. {
  2117. ProbeForWrite(pbAlreadyTran,sizeof(BOOL), sizeof(BOOL));
  2118. *pbAlreadyTran = bAlreadyTran;
  2119. }
  2120. if (piUsage)
  2121. {
  2122. ProbeForWrite(piUsage,sizeof(DWORD), sizeof(DWORD));
  2123. *piUsage = iUsage;
  2124. }
  2125. }
  2126. __except(EXCEPTION_EXECUTE_HANDLER)
  2127. {
  2128. WARNING("NtGdiIcmBrushInfo failed copy usermode parameter\n");
  2129. bRet = FALSE;
  2130. }
  2131. }
  2132. break;
  2133. }
  2134. case IcmSetBrush:
  2135. {
  2136. __try
  2137. {
  2138. //
  2139. // Lock down header memory.
  2140. //
  2141. ProbeForRead(pbmiDIB,cjHeader,sizeof(DWORD));
  2142. hSecureHeader = MmSecureVirtualMemory(pbmiDIB,cjHeader,PAGE_READWRITE);
  2143. ProbeForRead(pulBits,sizeof(ULONG),sizeof(ULONG));
  2144. cjBits = *pulBits;
  2145. }
  2146. __except(EXCEPTION_EXECUTE_HANDLER)
  2147. {
  2148. WARNING("NtGdiIcmBrushInfo - IcmSetBrush failed copy usermode parameter\n");
  2149. bRet = FALSE;
  2150. }
  2151. if (bRet && hSecureHeader)
  2152. {
  2153. //
  2154. // Compute bitmap size.
  2155. //
  2156. ULONG cjBitsNeeded = GreGetBitmapBitsSize(pbmiDIB);
  2157. if ((cjBitsNeeded == 0) || (cjBitsNeeded > cjBits))
  2158. {
  2159. WARNING1("NtGdiIcmBrushInfo - IcmSetBrush bitmap size is wrong\n");
  2160. bRet = FALSE;
  2161. }
  2162. else
  2163. {
  2164. __try
  2165. {
  2166. //
  2167. // Lock Bits.
  2168. //
  2169. ProbeForRead(pvBits,cjBitsNeeded,sizeof(DWORD));
  2170. hSecureBits = MmSecureVirtualMemory(pvBits,cjBitsNeeded,PAGE_READWRITE);
  2171. }
  2172. __except(EXCEPTION_EXECUTE_HANDLER)
  2173. {
  2174. WARNING("NtGdiIcmBrushInfo - IcmSetBrush failed lock pvBits\n");
  2175. bRet = FALSE;
  2176. }
  2177. if (bRet && hSecureBits)
  2178. {
  2179. //
  2180. // Set brush DIB bits.
  2181. //
  2182. bRet = GreIcmSetBrushBitmap(hdc,
  2183. hbrush,
  2184. pbmiDIB,
  2185. pvBits);
  2186. }
  2187. }
  2188. }
  2189. break;
  2190. }
  2191. default:
  2192. WARNING("NtGdiIcmBrushInfo(): unknown command\n");
  2193. SAVE_ERROR_CODE(ERROR_INVALID_PARAMETER);
  2194. bRet = FALSE;
  2195. }
  2196. //
  2197. // Unlock user mode memory if locked.
  2198. //
  2199. if (hSecureHeader)
  2200. {
  2201. MmUnsecureVirtualMemory(hSecureHeader);
  2202. }
  2203. if (hSecureBits)
  2204. {
  2205. MmUnsecureVirtualMemory(hSecureBits);
  2206. }
  2207. return (bRet);
  2208. }
  2209. /******************************Public*Routine******************************\
  2210. * bInitIcm
  2211. *
  2212. * Init ICM information
  2213. *
  2214. * Arguments:
  2215. *
  2216. * None
  2217. *
  2218. * Return Value:
  2219. *
  2220. * Status
  2221. *
  2222. * History:
  2223. *
  2224. * 9/25/1996 Mark Enstrom [marke]
  2225. *
  2226. \**************************************************************************/
  2227. extern "C" BOOL bInitICM()
  2228. {
  2229. ICMAPI(("bInitIcm\n"));
  2230. BOOL bRet = TRUE;
  2231. //
  2232. // Read ICM configuration.
  2233. //
  2234. RTL_QUERY_REGISTRY_TABLE QueryTable[2];
  2235. NTSTATUS NtStatus;
  2236. ULONG iIcmControlFlag = 0;
  2237. //
  2238. // read icm global configuration.
  2239. //
  2240. QueryTable[0].QueryRoutine = NULL;
  2241. QueryTable[0].Flags = (RTL_QUERY_REGISTRY_DIRECT |
  2242. RTL_QUERY_REGISTRY_REQUIRED);
  2243. QueryTable[0].Name = (PWSTR)L"GdiIcmControl";
  2244. QueryTable[0].EntryContext = (PVOID) &iIcmControlFlag;
  2245. QueryTable[0].DefaultType = REG_NONE;
  2246. QueryTable[0].DefaultData = 0;
  2247. QueryTable[0].DefaultLength = 0;
  2248. QueryTable[1].QueryRoutine = NULL;
  2249. QueryTable[1].Flags = 0;
  2250. QueryTable[1].Name = (PWSTR)NULL;
  2251. NtStatus = RtlQueryRegistryValues(RTL_REGISTRY_WINDOWS_NT,
  2252. L"ICM",
  2253. QueryTable,
  2254. NULL,
  2255. NULL);
  2256. if(!NT_SUCCESS(NtStatus))
  2257. {
  2258. WARNING1("Error reading GdiIcmControl (Optional, Not Error)\n");
  2259. iIcmControlFlag = 0L;
  2260. }
  2261. //
  2262. // NOTE: After sRGB.icm become really default.
  2263. //
  2264. if (!(iIcmControlFlag & ICM_CONTROL_WIN95_COLORSPACE))
  2265. {
  2266. //
  2267. // Configure default colorspace to sRGB.
  2268. //
  2269. gcsStockColorSpace.lcsCSType = LCS_sRGB;
  2270. //
  2271. // Set sRGB color profile name.
  2272. //
  2273. wcscpy(gcsStockColorSpace.lcsFilename,sRGB_PROFILENAME);
  2274. }
  2275. //
  2276. // Next, try to read GammaRange
  2277. //
  2278. //
  2279. // Initialize with default value.
  2280. //
  2281. giIcmGammaRange = 0x80; // Plus/Minus 128 is allowable by default.
  2282. QueryTable[0].Name = (PWSTR)L"GdiIcmGammaRange";
  2283. QueryTable[0].EntryContext = (PVOID) &giIcmGammaRange;
  2284. NtStatus = RtlQueryRegistryValues(RTL_REGISTRY_WINDOWS_NT,
  2285. L"ICM",
  2286. QueryTable,
  2287. NULL,
  2288. NULL);
  2289. if(!NT_SUCCESS(NtStatus))
  2290. {
  2291. WARNING1("Error reading GdiIcmGammaRange (Optional, Not Error)\n");
  2292. giIcmGammaRange = 0x80; // Plus/Minus 128 is allowable by default.
  2293. }
  2294. //
  2295. // Validate the value
  2296. //
  2297. if (giIcmGammaRange > 256)
  2298. {
  2299. giIcmGammaRange = 256;
  2300. }
  2301. #if HIDEYUKN_DBG
  2302. DbgPrint("GDI:IcmControlFlag = %x\n",iIcmControlFlag);
  2303. DbgPrint("GDI:IcmGammaRange = %x\n",giIcmGammaRange);
  2304. #endif
  2305. //
  2306. // Create Logical Color Space StockObject.
  2307. //
  2308. LOGCOLORSPACEEXW LogColorSpaceExW;
  2309. LogColorSpaceExW.lcsColorSpace = gcsStockColorSpace;
  2310. LogColorSpaceExW.dwFlags = 0;
  2311. HCOLORSPACE hColorSpace = GreCreateColorSpace(&LogColorSpaceExW);
  2312. if (hColorSpace)
  2313. {
  2314. //
  2315. // Set Owner of color space.
  2316. //
  2317. HmgSetOwner((HOBJ)hColorSpace, OBJECT_OWNER_PUBLIC, ICMLCS_TYPE);
  2318. //
  2319. // Mark the object is undeletable
  2320. //
  2321. HmgMarkUndeletable((HOBJ)hColorSpace,ICMLCS_TYPE);
  2322. //
  2323. // Set this colorspace to stock object.
  2324. //
  2325. bSetStockObject(hColorSpace,PRIV_STOCK_COLORSPACE);
  2326. //
  2327. // Keep stcok object to global
  2328. //
  2329. ghStockColorSpace = (HCOLORSPACE)GreGetStockObject(PRIV_STOCK_COLORSPACE);
  2330. //
  2331. // Lock color space to increment ref. count. (never become zero !)
  2332. //
  2333. gpStockColorSpace = (PCOLORSPACE)HmgShareLock((HOBJ)ghStockColorSpace,ICMLCS_TYPE);
  2334. //
  2335. // Initialize default DC_ATTR and DCLEVEL.
  2336. //
  2337. DcAttrDefault.hColorSpace = ghStockColorSpace;
  2338. dclevelDefault.pColorSpace = gpStockColorSpace;
  2339. if (gpStockColorSpace == NULL)
  2340. {
  2341. bRet = FALSE;
  2342. }
  2343. }
  2344. else
  2345. {
  2346. bRet = FALSE;
  2347. }
  2348. return(bRet);
  2349. }