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.

3672 lines
100 KiB

  1. /****************************Module*Header******************************\
  2. * Module Name: PROFILE.C
  3. *
  4. * Module Descripton: Profile data manipulation functions
  5. *
  6. * Warnings:
  7. *
  8. * Issues:
  9. *
  10. * Public Routines:
  11. *
  12. * Created: 11 January 1996
  13. * Author: Srinivasan Chandrasekar [srinivac]
  14. *
  15. * Copyright (c) 1996, 1997 Microsoft Corporation
  16. \***********************************************************************/
  17. #include "mscms.h"
  18. #define PROFILE_GROWTHCUSHION 16*1024
  19. //
  20. // Local functions
  21. //
  22. HPROFILE InternalOpenColorProfile(PPROFILE, DWORD, DWORD, DWORD);
  23. BOOL InternalCreateProfileFromLCS(LPLOGCOLORSPACE, PBYTE*, BOOL);
  24. BOOL FreeProfileObject(HPROFILE);
  25. BOOL AddTagTableEntry(PPROFOBJ, TAGTYPE, DWORD, DWORD, BOOL);
  26. BOOL AddTaggedElement(PPROFOBJ, TAGTYPE, DWORD);
  27. BOOL DeleteTaggedElement(PPROFOBJ, PTAGDATA);
  28. BOOL ChangeTaggedElementSize(PPROFOBJ, PTAGDATA, DWORD);
  29. BOOL GrowProfile(PPROFOBJ, DWORD);
  30. void MoveProfileData(PPROFOBJ, PBYTE, PBYTE, LONG, BOOL);
  31. BOOL IsReferenceTag(PPROFOBJ, PTAGDATA);
  32. /******************************************************************************
  33. *
  34. * OpenColorProfile
  35. *
  36. * Function:
  37. * These are the ANSI & Unicode wrappers for InternalOpenColorProfile.
  38. * Please see InternalOpenColorProfile for more details on this function.
  39. *
  40. * Returns:
  41. * Handle to open profile on success, zero on failure.
  42. *
  43. ******************************************************************************/
  44. #ifdef UNICODE // Windows NT versions
  45. HPROFILE WINAPI OpenColorProfileA(
  46. PPROFILE pProfile,
  47. DWORD dwDesiredAccess,
  48. DWORD dwShareMode,
  49. DWORD dwCreationMode
  50. )
  51. {
  52. PROFILE wProfile; // Unicode version
  53. HPROFILE rc = NULL;
  54. //
  55. // Validate parameters before touching them
  56. //
  57. if (!pProfile ||
  58. IsBadReadPtr(pProfile, sizeof(PROFILE)) ||
  59. (pProfile->pProfileData &&
  60. IsBadReadPtr(pProfile->pProfileData, pProfile->cbDataSize)) ||
  61. (!pProfile->pProfileData &&
  62. (pProfile->cbDataSize != 0)) ||
  63. (pProfile->dwType != PROFILE_FILENAME &&
  64. pProfile->dwType != PROFILE_MEMBUFFER
  65. )
  66. )
  67. {
  68. WARNING((__TEXT("Invalid parameter to OpenColorProfile\n")));
  69. SetLastError(ERROR_INVALID_PARAMETER);
  70. return NULL;
  71. }
  72. if (pProfile->dwType == PROFILE_FILENAME)
  73. {
  74. //
  75. // Convert the profile name to Unicode and call the Unicode version
  76. //
  77. wProfile.dwType = pProfile->dwType;
  78. if (!pProfile->pProfileData || pProfile->cbDataSize == 0)
  79. {
  80. WARNING((__TEXT("Invalid parameter to OpenColorProfile\n")));
  81. SetLastError(ERROR_INVALID_PARAMETER);
  82. return NULL;
  83. }
  84. wProfile.pProfileData = (WCHAR*)MemAlloc(pProfile->cbDataSize * sizeof(WCHAR));
  85. if (!wProfile.pProfileData)
  86. {
  87. WARNING((__TEXT("Error allocating memory for Unicode profile structure\n")));
  88. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  89. return NULL;
  90. }
  91. if (! MultiByteToWideChar(CP_ACP, 0, pProfile->pProfileData, pProfile->cbDataSize,
  92. wProfile.pProfileData, pProfile->cbDataSize))
  93. {
  94. WARNING((__TEXT("Error converting profile structure to Unicode\n")));
  95. goto EndOpenColorProfileA;
  96. }
  97. wProfile.cbDataSize = pProfile->cbDataSize * sizeof(WCHAR);
  98. }
  99. else
  100. {
  101. //
  102. // It is a memory based profile, so no ANSI/Unicode conversion
  103. //
  104. wProfile = *pProfile;
  105. }
  106. rc = InternalOpenColorProfile(&wProfile, dwDesiredAccess,
  107. dwShareMode, dwCreationMode);
  108. EndOpenColorProfileA:
  109. if (pProfile->dwType == PROFILE_FILENAME)
  110. {
  111. MemFree(wProfile.pProfileData);
  112. }
  113. return rc;
  114. }
  115. HPROFILE WINAPI OpenColorProfileW(
  116. PPROFILE pProfile,
  117. DWORD dwDesiredAccess,
  118. DWORD dwShareMode,
  119. DWORD dwCreationMode
  120. )
  121. {
  122. //
  123. // Internal function is Unicode in Windows NT, call it directly.
  124. //
  125. return InternalOpenColorProfile(pProfile, dwDesiredAccess,
  126. dwShareMode, dwCreationMode);
  127. }
  128. #else // Windows 95 versions
  129. HPROFILE WINAPI OpenColorProfileA(
  130. PPROFILE pProfile,
  131. DWORD dwDesiredAccess,
  132. DWORD dwShareMode,
  133. DWORD dwCreationMode
  134. )
  135. {
  136. //
  137. // Internal function is ANSI in Windows 95, call it directly.
  138. //
  139. return InternalOpenColorProfile(pProfile, dwDesiredAccess,
  140. dwShareMode, dwCreationMode);
  141. }
  142. HPROFILE WINAPI OpenColorProfileW(
  143. PPROFILE pProfile,
  144. DWORD dwDesiredAccess,
  145. DWORD dwShareMode,
  146. DWORD dwCreationMode
  147. )
  148. {
  149. PROFILE aProfile; // ANSI version
  150. HPROFILE rc = NULL;
  151. BOOL bUsedDefaultChar;
  152. //
  153. // Validate parameters before touching them
  154. //
  155. if (!pProfile ||
  156. IsBadReadPtr(pProfile, sizeof(PROFILE)) ||
  157. (pProfile->pProfileData &&
  158. IsBadReadPtr(pProfile->pProfileData, pProfile->cbDataSize)) ||
  159. (!pProfile->pProfileData &&
  160. (pProfile->cbDataSize != 0)) ||
  161. (pProfile->dwType != PROFILE_FILENAME &&
  162. pProfile->dwType != PROFILE_MEMBUFFER
  163. )
  164. )
  165. {
  166. WARNING((__TEXT("Invalid parameter to OpenColorProfile\n")));
  167. SetLastError(ERROR_INVALID_PARAMETER);
  168. return NULL;
  169. }
  170. if (pProfile->dwType == PROFILE_FILENAME)
  171. {
  172. //
  173. // Convert the profile name to ANSI and call the ANSI version
  174. //
  175. aProfile.dwType = pProfile->dwType;
  176. if (!pProfile->pProfileData || pProfile->cbDataSize == 0)
  177. {
  178. WARNING((__TEXT("Invalid parameter to OpenColorProfile\n")));
  179. SetLastError(ERROR_INVALID_PARAMETER);
  180. return NULL;
  181. }
  182. aProfile.pProfileData = (char*)MemAlloc(pProfile->cbDataSize * sizeof(char));
  183. if (!aProfile.pProfileData)
  184. {
  185. WARNING((__TEXT("Error allocating memory for ANSI profile structure\n")));
  186. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  187. return NULL;
  188. }
  189. if (! WideCharToMultiByte(CP_ACP, 0, pProfile->pProfileData, pProfile->cbDataSize/sizeof(WCHAR),
  190. aProfile.pProfileData, pProfile->cbDataSize,
  191. NULL, &bUsedDefaultChar) || bUsedDefaultChar)
  192. {
  193. WARNING((__TEXT("Error converting profile structure to ANSI\n")));
  194. goto EndOpenColorProfileW;
  195. }
  196. aProfile.cbDataSize = pProfile->cbDataSize * sizeof(char);
  197. }
  198. else
  199. {
  200. //
  201. // It is a memory based profile, so no ANSI/Unicode conversion
  202. //
  203. aProfile = *pProfile;
  204. }
  205. rc = InternalOpenColorProfile(&aProfile, dwDesiredAccess,
  206. dwShareMode, dwCreationMode);
  207. EndOpenColorProfileW:
  208. if (pProfile->dwType == PROFILE_FILENAME)
  209. {
  210. MemFree(aProfile.pProfileData);
  211. }
  212. return rc;
  213. }
  214. #endif // ! UNICODE
  215. /******************************************************************************
  216. *
  217. * CloseColorProfile
  218. *
  219. * Function:
  220. * This functions closes a color profile object, and frees all memory
  221. * associated with it.
  222. *
  223. * Arguments:
  224. * hProfile - handle identifing the profile object
  225. *
  226. * Returns:
  227. * TRUE if successful, FALSE otherwise
  228. *
  229. ******************************************************************************/
  230. BOOL WINAPI CloseColorProfile(
  231. HPROFILE hProfile
  232. )
  233. {
  234. TRACEAPI((__TEXT("CloseColorProfile\n")));
  235. //
  236. // Validate parameters
  237. //
  238. if (!ValidHandle(hProfile, OBJ_PROFILE))
  239. {
  240. WARNING((__TEXT("Invalid parameter to CloseColorProfile\n")));
  241. SetLastError(ERROR_INVALID_PARAMETER);
  242. return FALSE;
  243. }
  244. return FreeProfileObject(hProfile);
  245. }
  246. /******************************************************************************
  247. *
  248. * GetColorProfileFromHandle
  249. *
  250. * Function:
  251. * This functions returns a buffer filled with the profile contents.
  252. *
  253. * Arguments:
  254. * hProfile - handle identifing the profile object
  255. * pProfileData - pointer to buffer to receive the data. Can be NULL.
  256. * pcbData - pointer to size of buffer. On return it is size
  257. * filled/needed.
  258. *
  259. * Returns:
  260. * TRUE if successful, FALSE otherwise
  261. *
  262. ******************************************************************************/
  263. BOOL WINAPI GetColorProfileFromHandle(
  264. HPROFILE hProfile,
  265. PBYTE pProfileData,
  266. PDWORD pcbSize
  267. )
  268. {
  269. PPROFOBJ pProfObj;
  270. DWORD dwFileSize;
  271. BOOL rc = FALSE;
  272. //
  273. // ValidatePrameters
  274. //
  275. if (!ValidHandle(hProfile, OBJ_PROFILE) ||
  276. !pcbSize ||
  277. IsBadWritePtr(pcbSize, sizeof(DWORD)) ||
  278. (pProfileData &&
  279. IsBadWritePtr(pProfileData, *pcbSize)))
  280. {
  281. WARNING((__TEXT("Invalid parameter to CloseColorProfile\n")));
  282. SetLastError(ERROR_INVALID_PARAMETER);
  283. return FALSE;
  284. }
  285. pProfObj = (PPROFOBJ)HDLTOPTR(hProfile);
  286. ASSERT(pProfObj != NULL);
  287. dwFileSize = FIX_ENDIAN(HEADER(pProfObj)->phSize);
  288. if (pProfileData && *pcbSize >= dwFileSize)
  289. {
  290. CopyMemory(pProfileData, pProfObj->pView, dwFileSize);
  291. rc = TRUE;
  292. }
  293. else
  294. {
  295. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  296. }
  297. *pcbSize = dwFileSize;
  298. return rc;
  299. }
  300. /******************************************************************************
  301. *
  302. * IsColorProfileValid
  303. *
  304. * Function:
  305. * This functions checks if a given profile is a valid ICC profile
  306. * that can be used for color matching
  307. *
  308. * Arguments:
  309. * hProfile - handle identifing the profile object
  310. * pbValid - Pointer to variable that receives TRUE if it is a
  311. * valid profile, FALSE otherwise
  312. *
  313. * Returns:
  314. * TRUE if successful, FALSE otherwise
  315. *
  316. ******************************************************************************/
  317. BOOL WINAPI IsColorProfileValid(
  318. HPROFILE hProfile,
  319. PBOOL pbValid
  320. )
  321. {
  322. PPROFOBJ pProfObj;
  323. PCMMOBJ pCMMObj;
  324. DWORD cmmID;
  325. BOOL rc = FALSE;
  326. TRACEAPI((__TEXT("IsColorProfileValid\n")));
  327. //
  328. // Validate parameters
  329. //
  330. if (!ValidHandle(hProfile, OBJ_PROFILE) ||
  331. !pbValid ||
  332. IsBadWritePtr(pbValid, sizeof(BOOL)))
  333. {
  334. WARNING((__TEXT("Invalid parameter to IsColorProfileValid\n")));
  335. SetLastError(ERROR_INVALID_PARAMETER);
  336. return FALSE;
  337. }
  338. pProfObj = (PPROFOBJ)HDLTOPTR(hProfile);
  339. ASSERT(pProfObj != NULL);
  340. //
  341. // Quick check on the integrity of the profile before calling the CMM
  342. //
  343. if (!ValidProfile(pProfObj))
  344. {
  345. *pbValid = FALSE;
  346. return TRUE;
  347. }
  348. //
  349. // Get CMM associated with profile. If it does not exist or does not
  350. // support the CMValidate function, get default CMM.
  351. //
  352. cmmID = HEADER(pProfObj)->phCMMType;
  353. cmmID = FIX_ENDIAN(cmmID);
  354. pCMMObj = GetColorMatchingModule(cmmID);
  355. if (!pCMMObj || !pCMMObj->fns.pCMIsProfileValid)
  356. {
  357. TERSE((__TEXT("CMM associated with profile could not be used")));
  358. if (pCMMObj)
  359. {
  360. ReleaseColorMatchingModule(pCMMObj);
  361. }
  362. pCMMObj = GetColorMatchingModule(CMM_WINDOWS_DEFAULT);
  363. if (!pCMMObj || !pCMMObj->fns.pCMIsProfileValid)
  364. {
  365. RIP((__TEXT("Default CMM doesn't support CMValidateProfile")));
  366. SetLastError(ERROR_INVALID_CMM);
  367. goto EndIsColorProfileValid;
  368. }
  369. }
  370. ASSERT(pProfObj->pView != NULL);
  371. rc = pCMMObj->fns.pCMIsProfileValid(hProfile, pbValid);
  372. EndIsColorProfileValid:
  373. if (pCMMObj)
  374. {
  375. ReleaseColorMatchingModule(pCMMObj);
  376. }
  377. return rc;
  378. }
  379. /******************************************************************************
  380. *
  381. * CreateProfileFromLogColorSpace
  382. *
  383. * Function:
  384. * These are the ANSI & Unicode wrappers for InternalCreateProfileFromLCS.
  385. * Please see InternalCreateProfileFromLCS for more details on this
  386. * function.
  387. *
  388. * Returns:
  389. * TRUE if successful, FALSE otherwise
  390. *
  391. ******************************************************************************/
  392. #ifdef UNICODE // Windows NT versions
  393. BOOL WINAPI CreateProfileFromLogColorSpaceA(
  394. LPLOGCOLORSPACEA pLogColorSpace,
  395. PBYTE *pBuffer
  396. )
  397. {
  398. LOGCOLORSPACEW lcs;
  399. //
  400. // Validate Parameters
  401. //
  402. if (! pLogColorSpace ||
  403. IsBadReadPtr(pLogColorSpace, sizeof(LOGCOLORSPACEA)) ||
  404. pLogColorSpace->lcsFilename[0] != '\0')
  405. {
  406. WARNING((__TEXT("Invalid parameter to CreateProfileFromLogColorSpace\n")));
  407. SetLastError(ERROR_INVALID_PARAMETER);
  408. return FALSE;
  409. }
  410. *((LPLOGCOLORSPACEA)&lcs) = *pLogColorSpace;
  411. lcs.lcsFilename[0] = '\0';
  412. return InternalCreateProfileFromLCS(&lcs, pBuffer, FALSE);
  413. }
  414. BOOL WINAPI CreateProfileFromLogColorSpaceW(
  415. LPLOGCOLORSPACEW pLogColorSpace,
  416. PBYTE *pBuffer
  417. )
  418. {
  419. //
  420. // Internal function is Unicode in Windows NT, call it directly.
  421. //
  422. return InternalCreateProfileFromLCS(pLogColorSpace, pBuffer, TRUE);
  423. }
  424. #else // Windows 95 versions
  425. BOOL WINAPI CreateProfileFromLogColorSpaceA(
  426. LPLOGCOLORSPACEA pLogColorSpace,
  427. PBYTE *pBuffer
  428. )
  429. {
  430. //
  431. // Internal function is ANSI in Windows 95, call it directly.
  432. //
  433. return InternalCreateProfileFromLCS(pLogColorSpace, pBuffer, TRUE);
  434. }
  435. BOOL WINAPI CreateProfileFromLogColorSpaceW(
  436. LPLOGCOLORSPACEW pLogColorSpace,
  437. PBYTE *pBuffer
  438. )
  439. {
  440. LOGCOLORSPACEA lcs;
  441. //
  442. // Validate Parameters
  443. //
  444. if (! pLogColorSpace ||
  445. IsBadReadPtr(pLogColorSpace, sizeof(LOGCOLORSPACEW)) ||
  446. pLogColorSpace->lcsFilename[0] != '\0')
  447. {
  448. WARNING((__TEXT("Invalid parameter to CreateProfileFromLogColorSpace\n")));
  449. SetLastError(ERROR_INVALID_PARAMETER);
  450. return FALSE;
  451. }
  452. lcs = *((LPLOGCOLORSPACEA)pLogColorSpace);
  453. lcs.lcsFilename[0] = '\0';
  454. return InternalCreateProfileFromLCS(&lcs, pBuffer, FALSE);
  455. }
  456. #endif // ! UNICODE
  457. /******************************************************************************
  458. *
  459. * IsColorProfileTagPresent
  460. *
  461. * Function:
  462. * This functions checks if a given tag is present in the profile
  463. *
  464. * Arguments:
  465. * hProfile - handle identifing the profile object
  466. * tagType - the tag to check for
  467. * pbPrent - pointer to variable that receives TRUE if it the tag is
  468. * present, FALSE otherwise
  469. *
  470. * Returns:
  471. * TRUE if successful, FALSE otherwise
  472. *
  473. ******************************************************************************/
  474. BOOL WINAPI IsColorProfileTagPresent(
  475. HPROFILE hProfile,
  476. TAGTYPE tagType,
  477. PBOOL pbPresent
  478. )
  479. {
  480. PPROFOBJ pProfObj;
  481. PTAGDATA pTagData;
  482. DWORD nCount, i;
  483. TRACEAPI((__TEXT("IsColorProfileTagPresent\n")));
  484. //
  485. // Validate parameters
  486. //
  487. if (!ValidHandle(hProfile, OBJ_PROFILE) ||
  488. !pbPresent ||
  489. IsBadWritePtr(pbPresent, sizeof(BOOL)))
  490. {
  491. WARNING((__TEXT("Invalid parameter to IsColorProfileTagPresent\n")));
  492. SetLastError(ERROR_INVALID_PARAMETER);
  493. return FALSE;
  494. }
  495. pProfObj = (PPROFOBJ)HDLTOPTR(hProfile);
  496. ASSERT(pProfObj != NULL);
  497. //
  498. // Check the integrity of the profile
  499. //
  500. if (!ValidProfile(pProfObj))
  501. {
  502. WARNING((__TEXT("Invalid profile passed to IsColorProfileTagPresent\n")));
  503. SetLastError(ERROR_INVALID_PROFILE);
  504. return FALSE;
  505. }
  506. //
  507. // Get count of tag items - it is right after the profile header
  508. //
  509. nCount = TAG_COUNT(pProfObj);
  510. nCount = FIX_ENDIAN(nCount);
  511. VERBOSE((__TEXT("Profile 0x%x has 0x%x(%d) tags\n"), hProfile, nCount, nCount));
  512. //
  513. // Tag data records follow the count.
  514. //
  515. pTagData = TAG_DATA(pProfObj);
  516. //
  517. // Check if any of these records match the tag passed in.
  518. //
  519. *pbPresent = FALSE;
  520. tagType = FIX_ENDIAN(tagType); // to match tags in profile
  521. for (i=0; i<nCount; i++)
  522. {
  523. if (pTagData->tagType == tagType)
  524. {
  525. *pbPresent = TRUE;
  526. break;
  527. }
  528. pTagData++; // Next record
  529. }
  530. return TRUE;
  531. }
  532. /******************************************************************************
  533. *
  534. * GetCountColorProfileElements
  535. *
  536. * Function:
  537. * This functions returns the number of tagged elements in the profile
  538. *
  539. * Arguments:
  540. * hProfile - handle identifing the profile object
  541. * pnCount - pointer to variable to receive number of tagged elements
  542. * Returns:
  543. * TRUE if successful, FALSE otherwise
  544. *
  545. ******************************************************************************/
  546. BOOL WINAPI GetCountColorProfileElements(
  547. HPROFILE hProfile,
  548. PDWORD pnCount
  549. )
  550. {
  551. PPROFOBJ pProfObj;
  552. TRACEAPI((__TEXT("GetCountColorProfileElements\n")));
  553. //
  554. // Validate parameters
  555. //
  556. if (!ValidHandle(hProfile, OBJ_PROFILE) ||
  557. !pnCount ||
  558. IsBadWritePtr(pnCount, sizeof(DWORD)))
  559. {
  560. WARNING((__TEXT("Invalid parameter to GetCountColorProfileElements\n")));
  561. SetLastError(ERROR_INVALID_PARAMETER);
  562. return FALSE;
  563. }
  564. pProfObj = (PPROFOBJ)HDLTOPTR(hProfile);
  565. ASSERT(pProfObj != NULL);
  566. //
  567. // Check the integrity of the profile
  568. //
  569. if (!ValidProfile(pProfObj))
  570. {
  571. WARNING((__TEXT("Invalid profile passed to GetCountColorProfileElements\n")));
  572. SetLastError(ERROR_INVALID_PROFILE);
  573. return FALSE;
  574. }
  575. //
  576. // Get count of tag items - it is right after the profile header
  577. //
  578. *pnCount = TAG_COUNT(pProfObj);
  579. *pnCount = FIX_ENDIAN(*pnCount);
  580. return TRUE;
  581. }
  582. /******************************************************************************
  583. *
  584. * GetColorProfileElementTag
  585. *
  586. * Function:
  587. * This functions retrieves the tag name of the dwIndex'th element
  588. * in the profile
  589. *
  590. * Arguments:
  591. * hProfile - handle identifing the profile object
  592. * dwIndex - one-based index of the tag whose name is required
  593. * pTagType - gets the name of the tag on return
  594. *
  595. * Returns:
  596. * TRUE if successful, FALSE otherwise
  597. *
  598. ******************************************************************************/
  599. BOOL WINAPI GetColorProfileElementTag(
  600. HPROFILE hProfile,
  601. DWORD dwIndex,
  602. PTAGTYPE pTagType
  603. )
  604. {
  605. PPROFOBJ pProfObj;
  606. PTAGDATA pTagData;
  607. DWORD nCount;
  608. BOOL rc = FALSE;
  609. TRACEAPI((__TEXT("GetColorProfileElementTag\n")));
  610. //
  611. // Validate parameters
  612. //
  613. if (!ValidHandle(hProfile, OBJ_PROFILE) ||
  614. IsBadWritePtr(pTagType, sizeof(TAGTYPE)) ||
  615. dwIndex <= 0)
  616. {
  617. WARNING((__TEXT("Invalid parameter to GetColorProfileElementTag\n")));
  618. SetLastError(ERROR_INVALID_PARAMETER);
  619. return FALSE;
  620. }
  621. pProfObj = (PPROFOBJ)HDLTOPTR(hProfile);
  622. ASSERT(pProfObj != NULL);
  623. //
  624. // Check the integrity of the profile
  625. //
  626. if (!ValidProfile(pProfObj))
  627. {
  628. WARNING((__TEXT("Invalid profile passed to GetColorProfileElementTag\n")));
  629. SetLastError(ERROR_INVALID_PROFILE);
  630. return FALSE;
  631. }
  632. //
  633. // Get count of tag items - it is right after the profile header
  634. //
  635. nCount = TAG_COUNT(pProfObj);
  636. nCount = FIX_ENDIAN(nCount);
  637. if (dwIndex > nCount)
  638. {
  639. WARNING((__TEXT("GetColorProfileElementTag:index (%d) invalid\n"), dwIndex));
  640. SetLastError(ERROR_INVALID_PARAMETER);
  641. return FALSE;
  642. }
  643. //
  644. // Tag data records follow the count.
  645. //
  646. pTagData = TAG_DATA(pProfObj);
  647. *pTagType = FIX_ENDIAN(pTagData[dwIndex-1].tagType); // 1-based index
  648. return TRUE;
  649. }
  650. /******************************************************************************
  651. *
  652. * GetColorProfileElement
  653. *
  654. * Function:
  655. * This functions retrieves the data that a tagged element refers to
  656. * starting from the given offset.
  657. *
  658. * Arguments:
  659. * hProfile - handle identifing the profile object
  660. * tagType - the tag name of the element whose data is required
  661. * dwOffset - offset within the element data from which to retrieve
  662. * pcbSize - number of bytes to get. On return it is the number of
  663. * bytes retrieved
  664. * pBuffer - pointer to buffer to recieve data
  665. *
  666. * Returns:
  667. * TRUE if successful, FALSE otherwise
  668. *
  669. * Comments:
  670. * If pBuffer is NULL, it returns size of data in *pcbSize and ignores
  671. * dwOffset.
  672. *
  673. ******************************************************************************/
  674. BOOL WINAPI GetColorProfileElement(
  675. HPROFILE hProfile,
  676. TAGTYPE tagType,
  677. DWORD dwOffset,
  678. PDWORD pcbSize,
  679. PVOID pBuffer,
  680. PBOOL pbReference
  681. )
  682. {
  683. PPROFOBJ pProfObj;
  684. PTAGDATA pTagData;
  685. DWORD nCount, nBytes, i;
  686. BOOL found;
  687. BOOL rc = FALSE; // Assume failure
  688. TRACEAPI((__TEXT("GetColorProfileElement\n")));
  689. //
  690. // Validate parameters
  691. //
  692. if (!ValidHandle(hProfile, OBJ_PROFILE) ||
  693. !pcbSize ||
  694. IsBadWritePtr(pcbSize, sizeof(DWORD)) ||
  695. !pbReference ||
  696. IsBadWritePtr(pbReference, sizeof(BOOL))
  697. )
  698. {
  699. WARNING((__TEXT("Invalid parameter to GetColorProfileElement\n")));
  700. SetLastError(ERROR_INVALID_PARAMETER);
  701. return FALSE;
  702. }
  703. pProfObj = (PPROFOBJ)HDLTOPTR(hProfile);
  704. ASSERT(pProfObj != NULL);
  705. //
  706. // Check the integrity of the profile
  707. //
  708. if (!ValidProfile(pProfObj))
  709. {
  710. WARNING((__TEXT("Invalid profile passed to GetColorProfileElement\n")));
  711. SetLastError(ERROR_INVALID_PROFILE);
  712. return FALSE;
  713. }
  714. //
  715. // Get count of tag items - it is right after the profile header
  716. //
  717. nCount = TAG_COUNT(pProfObj);
  718. nCount = FIX_ENDIAN(nCount);
  719. //
  720. // Tag data records follow the count.
  721. //
  722. pTagData = TAG_DATA(pProfObj);
  723. //
  724. // Check if any of these records match the tag passed in.
  725. //
  726. found = FALSE;
  727. tagType = FIX_ENDIAN(tagType); // to match tags in profile
  728. for (i=0; i<nCount; i++)
  729. {
  730. if (pTagData->tagType == tagType)
  731. {
  732. found = TRUE;
  733. break;
  734. }
  735. pTagData++; // next record
  736. }
  737. if (found)
  738. {
  739. //
  740. // If pBuffer is NULL, copy size of data
  741. //
  742. if (!pBuffer)
  743. {
  744. *pcbSize = FIX_ENDIAN(pTagData->cbSize);
  745. SetLastError(ERROR_INSUFFICIENT_BUFFER);
  746. }
  747. else
  748. {
  749. //
  750. // pBuffer is not NULL, get number of bytes to copy
  751. //
  752. if (dwOffset >= FIX_ENDIAN(pTagData->cbSize))
  753. {
  754. WARNING((__TEXT("dwOffset too large for GetColorProfileElement\n")));
  755. SetLastError(ERROR_INVALID_PARAMETER);
  756. return FALSE;
  757. }
  758. else if (dwOffset + *pcbSize > FIX_ENDIAN(pTagData->cbSize))
  759. {
  760. nBytes = FIX_ENDIAN(pTagData->cbSize) - dwOffset;
  761. }
  762. else
  763. {
  764. nBytes = *pcbSize;
  765. }
  766. //
  767. // Check if output buffer is large enough
  768. //
  769. if (IsBadWritePtr(pBuffer, nBytes))
  770. {
  771. WARNING((__TEXT("Bad buffer passed to GetColorProfileElement\n")));
  772. SetLastError(ERROR_INVALID_PARAMETER);
  773. return FALSE;
  774. }
  775. //
  776. // Copy the data into user supplied buffer
  777. //
  778. CopyMemory((PVOID)pBuffer,
  779. (PVOID)(pProfObj->pView + FIX_ENDIAN(pTagData->dwOffset)
  780. + dwOffset), nBytes);
  781. *pcbSize = nBytes;
  782. rc = TRUE; // Success!
  783. }
  784. //
  785. // Check if multiple tags reference this tag's data
  786. //
  787. *pbReference = IsReferenceTag(pProfObj, pTagData);
  788. }
  789. else
  790. {
  791. SetLastError(ERROR_TAG_NOT_FOUND);
  792. }
  793. return rc;
  794. }
  795. /******************************************************************************
  796. *
  797. * SetColorProfileElementSize
  798. *
  799. * Function:
  800. * This functions sets the data size of a tagged element. If the element
  801. * is already present in the profile it's size is changed, and the data
  802. * is truncated or extended as the case may be. If the element is not
  803. * present, it is created and the data is filled with zeroes.
  804. *
  805. * Arguments:
  806. * hProfile - handle identifing the profile object
  807. * tagType - the tag name of the element
  808. * cbSize - new size for the element data
  809. *
  810. * Returns:
  811. * TRUE if successful, FALSE otherwise
  812. *
  813. * Comments:
  814. * If cbSize is 0, and the element is present, it is deleted.
  815. *
  816. ******************************************************************************/
  817. BOOL WINAPI SetColorProfileElementSize(
  818. HPROFILE hProfile,
  819. TAGTYPE tagType,
  820. DWORD cbSize
  821. )
  822. {
  823. PTAGDATA pTagData;
  824. PPROFOBJ pProfObj;
  825. DWORD i, nCount, newSize;
  826. TAGTYPE rawTag;
  827. BOOL found, rc = FALSE;
  828. TRACEAPI((__TEXT("SetColorProfileElementSize\n")));
  829. //
  830. // Validate parameters
  831. //
  832. if (!ValidHandle(hProfile, OBJ_PROFILE))
  833. {
  834. WARNING((__TEXT("Invalid parameter to SetColorProfileElementSize\n")));
  835. SetLastError(ERROR_INVALID_PARAMETER);
  836. return FALSE;
  837. }
  838. pProfObj = (PPROFOBJ)HDLTOPTR(hProfile);
  839. ASSERT(pProfObj != NULL);
  840. //
  841. // Check the integrity of the profile
  842. //
  843. if (!ValidProfile(pProfObj))
  844. {
  845. WARNING((__TEXT("Invalid profile passed to SetColorProfileElementSize\n")));
  846. SetLastError(ERROR_INVALID_PROFILE);
  847. return FALSE;
  848. }
  849. //
  850. // Check if profile has write access
  851. //
  852. if (!(pProfObj->dwFlags & READWRITE_ACCESS))
  853. {
  854. WARNING((__TEXT("Writing to a profile without read/write access\n")));
  855. SetLastError(ERROR_ACCESS_DENIED);
  856. return FALSE;
  857. }
  858. //
  859. // Get count of tag items - it is right after the profile header
  860. //
  861. nCount = TAG_COUNT(pProfObj);
  862. nCount = FIX_ENDIAN(nCount);
  863. //
  864. // Tag data records follow the count.
  865. //
  866. pTagData = TAG_DATA(pProfObj);
  867. //
  868. // Check if any of these records match the tag passed in.
  869. //
  870. found = FALSE;
  871. rawTag = FIX_ENDIAN(tagType);
  872. for (i=0; i<nCount; i++)
  873. {
  874. if (pTagData->tagType == rawTag)
  875. {
  876. found = TRUE;
  877. break;
  878. }
  879. pTagData++; // Next record
  880. }
  881. if (found)
  882. {
  883. //
  884. // If it is a reference tag, create data area for it
  885. //
  886. if (IsReferenceTag(pProfObj, pTagData))
  887. {
  888. if (cbSize == 0)
  889. {
  890. PTAGDATA pTemp;
  891. //
  892. // Move everything after the tag table entry up
  893. // by size of one tag table entry.
  894. //
  895. MoveProfileData(pProfObj, (PBYTE)(pTagData+1), (PBYTE)pTagData,
  896. PROFILE_SIZE(pProfObj) - (LONG)((PBYTE)(pTagData+1) - VIEW(pProfObj)), TRUE);
  897. //
  898. // Go through the tag table and update the pointers
  899. //
  900. pTemp = TAG_DATA(pProfObj);
  901. //
  902. // Get count of tag items - it is right after the profile header
  903. //
  904. nCount = TAG_COUNT(pProfObj);
  905. nCount = FIX_ENDIAN(nCount) - 1;
  906. TAG_COUNT(pProfObj) = FIX_ENDIAN(nCount);
  907. for (i=0; i<nCount; i++)
  908. {
  909. DWORD dwTemp = FIX_ENDIAN(pTemp->dwOffset);
  910. dwTemp -= sizeof(TAGDATA);
  911. pTemp->dwOffset = FIX_ENDIAN(dwTemp);
  912. pTemp++; // Next record
  913. }
  914. //
  915. // Use nCount as a placeholder to calculate file size
  916. //
  917. nCount = FIX_ENDIAN(HEADER(pProfObj)->phSize) - sizeof(TAGDATA);
  918. HEADER(pProfObj)->phSize = FIX_ENDIAN(nCount);
  919. }
  920. else
  921. {
  922. DWORD dwOffset;
  923. //
  924. // Resize the profile if needed. For memory buffers, we have to realloc,
  925. // and for mapped objects, we have to close and reopen the view.
  926. //
  927. newSize = FIX_ENDIAN(HEADER(pProfObj)->phSize);
  928. newSize = DWORD_ALIGN(newSize) + cbSize;
  929. //
  930. // Check for overflow
  931. //
  932. if (newSize < FIX_ENDIAN(HEADER(pProfObj)->phSize) ||
  933. newSize < cbSize)
  934. {
  935. WARNING((__TEXT("Overflow in setting reference element size\n")));
  936. SetLastError(ERROR_ARITHMETIC_OVERFLOW);
  937. return FALSE;
  938. }
  939. if (newSize > pProfObj->dwMapSize)
  940. {
  941. //Sundown: dwOffset should not be over 4gb
  942. DWORD dwOffset = (ULONG)(ULONG_PTR)(pTagData - TAG_DATA(pProfObj));
  943. if (! GrowProfile(pProfObj, newSize))
  944. {
  945. return FALSE;
  946. }
  947. //
  948. // Recalculate pointers as mapping or memory pointer
  949. // could have changed when growing profile
  950. //
  951. pTagData = TAG_DATA(pProfObj) + dwOffset;
  952. }
  953. //
  954. // Calculate location of new data - should be DWORD aligned
  955. //
  956. dwOffset = DWORD_ALIGN(FIX_ENDIAN(HEADER(pProfObj)->phSize));
  957. pTagData->dwOffset = FIX_ENDIAN(dwOffset);
  958. //
  959. // Set final file size
  960. //
  961. HEADER(pProfObj)->phSize = FIX_ENDIAN(dwOffset+cbSize);
  962. }
  963. rc = TRUE;
  964. }
  965. else
  966. {
  967. if (cbSize == 0)
  968. {
  969. rc = DeleteTaggedElement(pProfObj, pTagData);
  970. }
  971. else
  972. {
  973. DWORD cbOldSize;
  974. //
  975. // Get current size of element
  976. //
  977. cbOldSize = FIX_ENDIAN(pTagData->cbSize);
  978. //
  979. // Compress or expand the file as the case may be.
  980. //
  981. if (cbSize > cbOldSize)
  982. {
  983. //Sundown: dwOffset should be safe to truncate
  984. DWORD dwOffset = (ULONG)(ULONG_PTR)(pTagData - TAG_DATA(pProfObj));
  985. //
  986. // Check for overflow
  987. //
  988. newSize = PROFILE_SIZE(pProfObj) + DWORD_ALIGN(cbSize) -
  989. DWORD_ALIGN(cbOldSize);
  990. if (newSize < PROFILE_SIZE(pProfObj))
  991. {
  992. WARNING((__TEXT("Overflow in increasing element size\n")));
  993. SetLastError(ERROR_ARITHMETIC_OVERFLOW);
  994. return FALSE;
  995. }
  996. if (!GrowProfile(pProfObj, newSize))
  997. {
  998. return FALSE;
  999. }
  1000. //
  1001. // Recompute pointers
  1002. //
  1003. pTagData = TAG_DATA(pProfObj) + dwOffset;
  1004. }
  1005. rc = ChangeTaggedElementSize(pProfObj, pTagData, cbSize);
  1006. }
  1007. }
  1008. }
  1009. else
  1010. {
  1011. if (cbSize == 0)
  1012. {
  1013. WARNING((__TEXT("SetColorProfileElementSize (deleting): Tag not found\n")));
  1014. SetLastError(ERROR_TAG_NOT_FOUND);
  1015. }
  1016. else
  1017. {
  1018. rc = AddTaggedElement(pProfObj, tagType, cbSize);
  1019. }
  1020. }
  1021. return rc;
  1022. }
  1023. /******************************************************************************
  1024. *
  1025. * SetColorProfileElement
  1026. *
  1027. * Function:
  1028. * This functions sets the data for a tagged element. It does not
  1029. * change the size of the element, and only writes as much data as
  1030. * would fit within the current size, overwriting any existing data.
  1031. *
  1032. * Arguments:
  1033. * hProfile - handle identifing the profile object
  1034. * tagType - the tag name of the element
  1035. * dwOffset - offset within the element data from which to write
  1036. * pcbSize - number of bytes to write. On return it is the number of
  1037. * bytes written.
  1038. * pBuffer - pointer to buffer having data to write
  1039. *
  1040. * Returns:
  1041. * TRUE if successful, FALSE otherwise
  1042. *
  1043. ******************************************************************************/
  1044. BOOL WINAPI SetColorProfileElement(
  1045. HPROFILE hProfile,
  1046. TAGTYPE tagType,
  1047. DWORD dwOffset,
  1048. PDWORD pcbSize,
  1049. PVOID pBuffer
  1050. )
  1051. {
  1052. PPROFOBJ pProfObj;
  1053. PTAGDATA pTagData;
  1054. DWORD nCount, nBytes, i;
  1055. BOOL found;
  1056. BOOL rc = FALSE; // Assume failure
  1057. TRACEAPI((__TEXT("SetColorProfileElement\n")));
  1058. //
  1059. // Validate parameters
  1060. //
  1061. if (!ValidHandle(hProfile, OBJ_PROFILE) ||
  1062. !pcbSize ||
  1063. IsBadWritePtr(pcbSize, sizeof(DWORD)) ||
  1064. !pBuffer ||
  1065. IsBadReadPtr(pBuffer, *pcbSize)
  1066. )
  1067. {
  1068. WARNING((__TEXT("Invalid parameter to SetColorProfileElement\n")));
  1069. SetLastError(ERROR_INVALID_PARAMETER);
  1070. return FALSE;
  1071. }
  1072. pProfObj = (PPROFOBJ)HDLTOPTR(hProfile);
  1073. ASSERT(pProfObj != NULL);
  1074. //
  1075. // Check the integrity of the profile
  1076. //
  1077. if (!ValidProfile(pProfObj))
  1078. {
  1079. WARNING((__TEXT("Invalid profile passed to SetColorProfileElement\n")));
  1080. SetLastError(ERROR_INVALID_PROFILE);
  1081. return FALSE;
  1082. }
  1083. //
  1084. // Check if profile has write access
  1085. //
  1086. if (!(pProfObj->dwFlags & READWRITE_ACCESS))
  1087. {
  1088. WARNING((__TEXT("Writing to a profile without read/write access\n")));
  1089. SetLastError(ERROR_ACCESS_DENIED);
  1090. return FALSE;
  1091. }
  1092. //
  1093. // Get count of tag items - it is right after the profile header
  1094. //
  1095. nCount = TAG_COUNT(pProfObj);
  1096. nCount = FIX_ENDIAN(nCount);
  1097. //
  1098. // Tag data records follow the count.
  1099. //
  1100. pTagData = TAG_DATA(pProfObj);
  1101. //
  1102. // Check if any of these records match the tag passed in
  1103. //
  1104. found = FALSE;
  1105. tagType = FIX_ENDIAN(tagType);
  1106. for (i=0; i<nCount; i++)
  1107. {
  1108. if (pTagData->tagType == tagType)
  1109. {
  1110. found = TRUE;
  1111. break;
  1112. }
  1113. pTagData++; // Next record
  1114. }
  1115. if (found)
  1116. {
  1117. //
  1118. // If it is a reference tag, create new space for it
  1119. //
  1120. if (IsReferenceTag(pProfObj, pTagData))
  1121. {
  1122. SetColorProfileElementSize(hProfile, tagType, FIX_ENDIAN(pTagData->cbSize));
  1123. }
  1124. //
  1125. // Get number of bytes to set
  1126. //
  1127. if (dwOffset >= FIX_ENDIAN(pTagData->cbSize))
  1128. {
  1129. WARNING((__TEXT("dwOffset too large for SetColorProfileElement\n")));
  1130. SetLastError(ERROR_INVALID_PARAMETER);
  1131. return FALSE;
  1132. }
  1133. else if (dwOffset + *pcbSize > FIX_ENDIAN(pTagData->cbSize))
  1134. {
  1135. nBytes = FIX_ENDIAN(pTagData->cbSize) - dwOffset;
  1136. }
  1137. else
  1138. {
  1139. nBytes = *pcbSize;
  1140. }
  1141. //
  1142. // Copy the data into the profile
  1143. //
  1144. CopyMemory((PVOID)(pProfObj->pView + FIX_ENDIAN(pTagData->dwOffset)
  1145. + dwOffset), (PVOID)pBuffer, nBytes);
  1146. *pcbSize = nBytes;
  1147. rc = TRUE;
  1148. }
  1149. else
  1150. {
  1151. WARNING((__TEXT("SetColorProfileElement: Tag not found\n")));
  1152. SetLastError(ERROR_TAG_NOT_FOUND);
  1153. }
  1154. return rc;
  1155. }
  1156. /******************************************************************************
  1157. *
  1158. * SetColorProfileElementReference
  1159. *
  1160. * Function:
  1161. * This functions creates a new tag and makes it refer to the same
  1162. * data as an existing tag.
  1163. *
  1164. * Arguments:
  1165. * hProfile - handle identifing the profile object
  1166. * newTag - new tag to create
  1167. * refTag - reference tag whose data newTag should refer to
  1168. *
  1169. * Returns:
  1170. * TRUE if successful, FALSE otherwise
  1171. *
  1172. ******************************************************************************/
  1173. BOOL WINAPI SetColorProfileElementReference(
  1174. HPROFILE hProfile,
  1175. TAGTYPE newTag,
  1176. TAGTYPE refTag
  1177. )
  1178. {
  1179. PPROFOBJ pProfObj;
  1180. PTAGDATA pTagData, pOrigTag;
  1181. DWORD nCount, i;
  1182. BOOL found;
  1183. BOOL rc = FALSE; // Assume failure
  1184. TRACEAPI((__TEXT("SetColorProfileElementReference\n")));
  1185. //
  1186. // Validate parameters
  1187. //
  1188. if (!ValidHandle(hProfile, OBJ_PROFILE))
  1189. {
  1190. WARNING((__TEXT("Invalid parameter to SetColorProfileElementReference\n")));
  1191. SetLastError(ERROR_INVALID_PARAMETER);
  1192. return FALSE;
  1193. }
  1194. pProfObj = (PPROFOBJ)HDLTOPTR(hProfile);
  1195. ASSERT(pProfObj != NULL);
  1196. //
  1197. // Check the integrity of the profile
  1198. //
  1199. if (!ValidProfile(pProfObj))
  1200. {
  1201. WARNING((__TEXT("Invalid profile passed to SetColorProfileElementReference\n")));
  1202. SetLastError(ERROR_INVALID_PROFILE);
  1203. return FALSE;
  1204. }
  1205. //
  1206. // Check if profile has write access
  1207. //
  1208. if (!(pProfObj->dwFlags & READWRITE_ACCESS))
  1209. {
  1210. WARNING((__TEXT("Writing to a profile without read/write access\n")));
  1211. SetLastError(ERROR_ACCESS_DENIED);
  1212. return FALSE;
  1213. }
  1214. //
  1215. // Get count of tag items - it is right after the profile header
  1216. //
  1217. nCount = TAG_COUNT(pProfObj);
  1218. nCount = FIX_ENDIAN(nCount);
  1219. //
  1220. // Tag data records follow the count.
  1221. //
  1222. pTagData = TAG_DATA(pProfObj);
  1223. //
  1224. // Check if any of these records match the tag passed in
  1225. //
  1226. found = FALSE;
  1227. refTag = FIX_ENDIAN(refTag);
  1228. for (i=0; i<nCount; i++)
  1229. {
  1230. if (pTagData->tagType == refTag)
  1231. {
  1232. pOrigTag = pTagData;
  1233. found = TRUE;
  1234. }
  1235. if (pTagData->tagType == FIX_ENDIAN(newTag))
  1236. {
  1237. WARNING((__TEXT("Duplicate tag present in SetColorProfileElementReference %x\n"), newTag));
  1238. SetLastError(ERROR_DUPLICATE_TAG);
  1239. return FALSE;
  1240. }
  1241. pTagData++; // Next record
  1242. }
  1243. if (found)
  1244. {
  1245. DWORD newSize;
  1246. //
  1247. // Grow profile if needed
  1248. //
  1249. newSize = FIX_ENDIAN(HEADER(pProfObj)->phSize);
  1250. newSize = DWORD_ALIGN(newSize) + sizeof(TAGDATA);
  1251. //
  1252. // Check for overflow
  1253. //
  1254. if (newSize < FIX_ENDIAN(HEADER(pProfObj)->phSize))
  1255. {
  1256. WARNING((__TEXT("Overflow in adding element\n")));
  1257. SetLastError(ERROR_ARITHMETIC_OVERFLOW);
  1258. return FALSE;
  1259. }
  1260. if (newSize > pProfObj->dwMapSize)
  1261. {
  1262. //Sundown: safe truncation
  1263. DWORD dwOffset = (ULONG)(ULONG_PTR)(pOrigTag - TAG_DATA(pProfObj));
  1264. if (! GrowProfile(pProfObj, newSize))
  1265. {
  1266. return FALSE;
  1267. }
  1268. //
  1269. // Recalculate pointers as mapping or memory pointer
  1270. // could have changed when growing profile
  1271. //
  1272. pOrigTag = TAG_DATA(pProfObj) + dwOffset;
  1273. }
  1274. rc = AddTagTableEntry(pProfObj, newTag, FIX_ENDIAN(pOrigTag->dwOffset),
  1275. FIX_ENDIAN(pOrigTag->cbSize), FALSE);
  1276. }
  1277. else
  1278. {
  1279. WARNING((__TEXT("SetColorProfileElementReference: Tag 0x%x not found\n"),
  1280. FIX_ENDIAN(refTag))); // Re-fix it to reflect data passed in
  1281. SetLastError(ERROR_TAG_NOT_FOUND);
  1282. }
  1283. return rc;
  1284. }
  1285. /******************************************************************************
  1286. *
  1287. * GetColorProfileHeader
  1288. *
  1289. * Function:
  1290. * This functions retrieves the header of a profile
  1291. *
  1292. * Arguments:
  1293. * hProfile - handle identifing the profile object
  1294. * pHeader - pointer to buffer to recieve the header
  1295. *
  1296. * Returns:
  1297. * TRUE if successful, FALSE otherwise
  1298. *
  1299. ******************************************************************************/
  1300. BOOL WINAPI GetColorProfileHeader(
  1301. HPROFILE hProfile,
  1302. PPROFILEHEADER pHeader
  1303. )
  1304. {
  1305. PPROFOBJ pProfObj;
  1306. DWORD nCount, i, temp;
  1307. TRACEAPI((__TEXT("GetColorProfileHeader\n")));
  1308. //
  1309. // Validate parameters
  1310. //
  1311. if (!ValidHandle(hProfile, OBJ_PROFILE) ||
  1312. IsBadWritePtr(pHeader, sizeof(PROFILEHEADER)))
  1313. {
  1314. WARNING((__TEXT("Invalid parameter to GetColorProfileHeader\n")));
  1315. SetLastError(ERROR_INVALID_PARAMETER);
  1316. return FALSE;
  1317. }
  1318. pProfObj = (PPROFOBJ)HDLTOPTR(hProfile);
  1319. ASSERT(pProfObj != NULL);
  1320. //
  1321. // Check the integrity of the profile.
  1322. //
  1323. if (!ValidProfile(pProfObj))
  1324. {
  1325. WARNING((__TEXT("Invalid profile passed to GetColorProfileHeader\n")));
  1326. SetLastError(ERROR_INVALID_PROFILE);
  1327. return FALSE;
  1328. }
  1329. CopyMemory((PVOID)pHeader, (PVOID)pProfObj->pView,
  1330. sizeof(PROFILEHEADER));
  1331. //
  1332. // Fix up all fields to platform specific values.
  1333. // The following code assumes that the profile header is a
  1334. // multiple of DWORDs which it is!
  1335. //
  1336. ASSERT(sizeof(PROFILEHEADER) % sizeof(DWORD) == 0);
  1337. nCount = sizeof(PROFILEHEADER)/sizeof(DWORD);
  1338. for (i=0; i<nCount;i++)
  1339. {
  1340. temp = (DWORD)((PDWORD)pHeader)[i];
  1341. ((PDWORD)pHeader)[i] = FIX_ENDIAN(temp);
  1342. }
  1343. return TRUE;
  1344. }
  1345. /******************************************************************************
  1346. *
  1347. * SetColorProfileHeader
  1348. *
  1349. * Function:
  1350. * This functions sets the header of a profile
  1351. *
  1352. * Arguments:
  1353. * hProfile - handle identifing the profile object
  1354. * pHeader - pointer to buffer identifing the header
  1355. *
  1356. * Returns:
  1357. * TRUE if successful, FALSE otherwise
  1358. *
  1359. ******************************************************************************/
  1360. BOOL WINAPI SetColorProfileHeader(
  1361. HPROFILE hProfile,
  1362. PPROFILEHEADER pHeader
  1363. )
  1364. {
  1365. PPROFOBJ pProfObj;
  1366. DWORD nCount, i, temp;
  1367. TRACEAPI((__TEXT("SetColorProfileHeader\n")));
  1368. //
  1369. // Validate parameters
  1370. //
  1371. if (!ValidHandle(hProfile, OBJ_PROFILE) ||
  1372. IsBadReadPtr(pHeader, sizeof(PROFILEHEADER)))
  1373. {
  1374. WARNING((__TEXT("Invalid parameter to SetColorProfileHeader\n")));
  1375. SetLastError(ERROR_INVALID_PARAMETER);
  1376. return FALSE;
  1377. }
  1378. pProfObj = (PPROFOBJ)HDLTOPTR(hProfile);
  1379. ASSERT(pProfObj != NULL);
  1380. //
  1381. // Check if profile has write access
  1382. //
  1383. if (!(pProfObj->dwFlags & READWRITE_ACCESS))
  1384. {
  1385. WARNING((__TEXT("Writing to a profile without read/write access\n")));
  1386. SetLastError(ERROR_ACCESS_DENIED);
  1387. return FALSE;
  1388. }
  1389. //
  1390. // Fix up all fields to BIG-ENDIAN.
  1391. // The following code assumes that the profile header is a
  1392. // multiple of DWORDs which it is!
  1393. //
  1394. ASSERT(sizeof(PROFILEHEADER) % sizeof(DWORD) == 0);
  1395. nCount = sizeof(PROFILEHEADER)/sizeof(DWORD);
  1396. for (i=0; i<nCount;i++)
  1397. {
  1398. temp = (DWORD)((PDWORD)pHeader)[i];
  1399. ((PDWORD)pHeader)[i] = FIX_ENDIAN(temp);
  1400. }
  1401. CopyMemory((PVOID)pProfObj->pView, (PVOID)pHeader,
  1402. sizeof(PROFILEHEADER));
  1403. //
  1404. // Put back app supplied buffer the way it came in
  1405. //
  1406. for (i=0; i<nCount;i++)
  1407. {
  1408. temp = (DWORD)((PDWORD)pHeader)[i];
  1409. ((PDWORD)pHeader)[i] = FIX_ENDIAN(temp);
  1410. }
  1411. return TRUE;
  1412. }
  1413. /******************************************************************************
  1414. *
  1415. * GetPS2ColorSpaceArray
  1416. *
  1417. * Function:
  1418. * This functions retrieves the PostScript Level 2 CSA from the profile
  1419. *
  1420. * Arguments:
  1421. * hProfile - handle identifing the profile object
  1422. * dwIntent - rendering intent of CSA
  1423. * dwCSAType - type of CSA
  1424. * pbuffer - pointer to receive the CSA
  1425. * pcbSize - pointer to size of buffer. If function fails because
  1426. * buffer is not big enough, it is filled with required size.
  1427. * pcbBinary - TRUE if binary data is requested. On return it is set to
  1428. * reflect the data returned
  1429. *
  1430. * Returns:
  1431. * TRUE if successful, FALSE otherwise
  1432. *
  1433. ******************************************************************************/
  1434. BOOL WINAPI
  1435. GetPS2ColorSpaceArray (
  1436. HPROFILE hProfile,
  1437. DWORD dwIntent,
  1438. DWORD dwCSAType,
  1439. PBYTE pBuffer,
  1440. PDWORD pcbSize,
  1441. LPBOOL pbBinary
  1442. )
  1443. {
  1444. PPROFOBJ pProfObj;
  1445. PCMMOBJ pCMMObj;
  1446. DWORD cmmID;
  1447. BOOL rc;
  1448. TRACEAPI((__TEXT("GetPS2ColorSpaceArray\n")));
  1449. //
  1450. // Validate parameters
  1451. //
  1452. if (!ValidHandle(hProfile, OBJ_PROFILE) ||
  1453. IsBadWritePtr(pcbSize, sizeof(DWORD)) ||
  1454. (pBuffer &&
  1455. IsBadWritePtr(pBuffer, *pcbSize)
  1456. ) ||
  1457. IsBadWritePtr(pbBinary, sizeof(BOOL))
  1458. )
  1459. {
  1460. WARNING((__TEXT("Invalid parameter to GetPS2ColorSpaceArray\n")));
  1461. SetLastError(ERROR_INVALID_PARAMETER);
  1462. return FALSE;
  1463. }
  1464. pProfObj = (PPROFOBJ)HDLTOPTR(hProfile);
  1465. ASSERT(pProfObj != NULL);
  1466. //
  1467. // Check the integrity of the profile
  1468. //
  1469. if (!ValidProfile(pProfObj))
  1470. {
  1471. WARNING((__TEXT("Invalid profile passed to GetPS2ColorSpaceArray\n")));
  1472. SetLastError(ERROR_INVALID_PROFILE);
  1473. return FALSE;
  1474. }
  1475. //
  1476. // Check if application specified CMM is present
  1477. //
  1478. pCMMObj = GetPreferredCMM();
  1479. if (!pCMMObj || (pCMMObj->dwFlags & CMM_DONT_USE_PS2_FNS) ||
  1480. !pCMMObj->fns.pCMGetPS2ColorSpaceArray)
  1481. {
  1482. if (pCMMObj)
  1483. {
  1484. pCMMObj->dwFlags |= CMM_DONT_USE_PS2_FNS;
  1485. ReleaseColorMatchingModule(pCMMObj);
  1486. }
  1487. //
  1488. // Get CMM associated with profile. If it does not exist or does not
  1489. // support the CMGetPS2ColorSpaceArray function, get default CMM.
  1490. //
  1491. cmmID = HEADER(pProfObj)->phCMMType;
  1492. cmmID = FIX_ENDIAN(cmmID);
  1493. pCMMObj = GetColorMatchingModule(cmmID);
  1494. if (!pCMMObj || (pCMMObj->dwFlags & CMM_DONT_USE_PS2_FNS) ||
  1495. !pCMMObj->fns.pCMGetPS2ColorSpaceArray)
  1496. {
  1497. TERSE((__TEXT("CMM associated with profile could not be used")));
  1498. if (pCMMObj)
  1499. {
  1500. pCMMObj->dwFlags |= CMM_DONT_USE_PS2_FNS;
  1501. ReleaseColorMatchingModule(pCMMObj);
  1502. }
  1503. pCMMObj = GetColorMatchingModule(CMM_WINDOWS_DEFAULT);
  1504. if (!pCMMObj || !pCMMObj->fns.pCMGetPS2ColorSpaceArray)
  1505. {
  1506. WARNING((__TEXT("Default CMM doesn't support CMGetPS2ColorSpaceArray\n")));
  1507. if (pCMMObj)
  1508. {
  1509. ReleaseColorMatchingModule(pCMMObj);
  1510. pCMMObj = NULL;
  1511. }
  1512. }
  1513. }
  1514. }
  1515. ASSERT(pProfObj->pView != NULL);
  1516. if (pCMMObj)
  1517. {
  1518. rc = pCMMObj->fns.pCMGetPS2ColorSpaceArray(hProfile, dwIntent, dwCSAType,
  1519. pBuffer, pcbSize, pbBinary);
  1520. }
  1521. else
  1522. {
  1523. rc = InternalGetPS2ColorSpaceArray(pProfObj->pView, dwIntent,
  1524. dwCSAType, pBuffer, pcbSize, pbBinary);
  1525. }
  1526. if (pCMMObj)
  1527. {
  1528. ReleaseColorMatchingModule(pCMMObj);
  1529. }
  1530. VERBOSE((__TEXT("GetPS2ColorSpaceArray returning %s\n"),
  1531. rc ? "TRUE" : "FALSE"));
  1532. return rc;
  1533. }
  1534. /******************************************************************************
  1535. *
  1536. * GetPS2ColorRenderingIntent
  1537. *
  1538. * Function:
  1539. * This functions retrieves the PostScript Level 2 color rendering intent
  1540. * from the profile
  1541. *
  1542. * Arguments:
  1543. * hProfile - handle identifing the profile object
  1544. * pbuffer - pointer to receive the color rendering intent
  1545. * pcbSize - pointer to size of buffer. If function fails because
  1546. * buffer is not big enough, it is filled with required size.
  1547. * pcbBinary - TRUE if binary data is requested. On return it is set to
  1548. * reflect the data returned
  1549. *
  1550. * Returns:
  1551. * TRUE if successful, FALSE otherwise
  1552. *
  1553. ******************************************************************************/
  1554. BOOL WINAPI GetPS2ColorRenderingIntent(
  1555. HPROFILE hProfile,
  1556. DWORD dwIntent,
  1557. PBYTE pBuffer,
  1558. PDWORD pcbSize
  1559. )
  1560. {
  1561. PPROFOBJ pProfObj;
  1562. PCMMOBJ pCMMObj;
  1563. DWORD cmmID;
  1564. BOOL rc;
  1565. TRACEAPI((__TEXT("GetPS2ColorRenderingIntent\n")));
  1566. //
  1567. // Validate parameters
  1568. //
  1569. if (!ValidHandle(hProfile, OBJ_PROFILE) ||
  1570. IsBadWritePtr(pcbSize, sizeof(DWORD)) ||
  1571. (pBuffer &&
  1572. IsBadWritePtr(pBuffer, *pcbSize)
  1573. )
  1574. )
  1575. {
  1576. WARNING((__TEXT("Invalid parameter to GetPS2ColorRenderingIntent\n")));
  1577. SetLastError(ERROR_INVALID_PARAMETER);
  1578. return FALSE;
  1579. }
  1580. pProfObj = (PPROFOBJ)HDLTOPTR(hProfile);
  1581. ASSERT(pProfObj != NULL);
  1582. //
  1583. // Check the integrity of the profile
  1584. //
  1585. if (!ValidProfile(pProfObj))
  1586. {
  1587. WARNING((__TEXT("Invalid profile passed to GetPS2ColorRenderingIntent\n")));
  1588. SetLastError(ERROR_INVALID_PROFILE);
  1589. return FALSE;
  1590. }
  1591. //
  1592. // Check if application specified CMM is present
  1593. //
  1594. pCMMObj = GetPreferredCMM();
  1595. if (!pCMMObj || (pCMMObj->dwFlags & CMM_DONT_USE_PS2_FNS) ||
  1596. !pCMMObj->fns.pCMGetPS2ColorRenderingIntent)
  1597. {
  1598. if (pCMMObj)
  1599. {
  1600. pCMMObj->dwFlags |= CMM_DONT_USE_PS2_FNS;
  1601. ReleaseColorMatchingModule(pCMMObj);
  1602. }
  1603. //
  1604. // Get CMM associated with profile. If it does not exist or does not
  1605. // support the CMGetPS2ColorSpaceArray function, get default CMM.
  1606. //
  1607. cmmID = HEADER(pProfObj)->phCMMType;
  1608. cmmID = FIX_ENDIAN(cmmID);
  1609. pCMMObj = GetColorMatchingModule(cmmID);
  1610. if (!pCMMObj || (pCMMObj->dwFlags & CMM_DONT_USE_PS2_FNS) ||
  1611. !pCMMObj->fns.pCMGetPS2ColorRenderingIntent)
  1612. {
  1613. TERSE((__TEXT("CMM associated with profile could not be used")));
  1614. if (pCMMObj)
  1615. {
  1616. pCMMObj->dwFlags |= CMM_DONT_USE_PS2_FNS;
  1617. ReleaseColorMatchingModule(pCMMObj);
  1618. }
  1619. pCMMObj = GetColorMatchingModule(CMM_WINDOWS_DEFAULT);
  1620. if (!pCMMObj || !pCMMObj->fns.pCMGetPS2ColorRenderingIntent)
  1621. {
  1622. WARNING((__TEXT("Default CMM doesn't support CMGetPS2ColorRenderingIntent\n")));
  1623. if (pCMMObj)
  1624. {
  1625. ReleaseColorMatchingModule(pCMMObj);
  1626. pCMMObj = NULL;
  1627. }
  1628. }
  1629. }
  1630. }
  1631. ASSERT(pProfObj->pView != NULL);
  1632. if (pCMMObj)
  1633. {
  1634. rc = pCMMObj->fns.pCMGetPS2ColorRenderingIntent(hProfile,
  1635. dwIntent, pBuffer, pcbSize);
  1636. }
  1637. else
  1638. {
  1639. rc = InternalGetPS2ColorRenderingIntent(pProfObj->pView, dwIntent,
  1640. pBuffer, pcbSize);
  1641. }
  1642. if (pCMMObj)
  1643. {
  1644. ReleaseColorMatchingModule(pCMMObj);
  1645. }
  1646. VERBOSE((__TEXT("GetPS2ColorRenderingIntent returning %s\n"),
  1647. rc ? "TRUE" : "FALSE"));
  1648. return rc;
  1649. }
  1650. /******************************************************************************
  1651. *
  1652. * GetPS2ColorRenderingDictionary
  1653. *
  1654. * Function:
  1655. * This functions retrieves the PostScript Level 2 CRD from the profile
  1656. *
  1657. * Arguments:
  1658. * hProfile - handle identifing the profile object
  1659. * dwIntent - intent whose CRD is required
  1660. * pbuffer - pointer to receive the CSA
  1661. * pcbSize - pointer to size of buffer. If function fails because
  1662. * buffer is not big enough, it is filled with required size.
  1663. * pcbBinary - TRUE if binary data is requested. On return it is set to
  1664. * reflect the data returned
  1665. *
  1666. * Returns:
  1667. * TRUE if successful, FALSE otherwise
  1668. *
  1669. ******************************************************************************/
  1670. BOOL WINAPI GetPS2ColorRenderingDictionary(
  1671. HPROFILE hProfile,
  1672. DWORD dwIntent,
  1673. PBYTE pBuffer,
  1674. PDWORD pcbSize,
  1675. PBOOL pbBinary
  1676. )
  1677. {
  1678. PPROFOBJ pProfObj;
  1679. PCMMOBJ pCMMObj;
  1680. DWORD cmmID;
  1681. BOOL rc;
  1682. TRACEAPI((__TEXT("GetPS2ColorRenderingDictionary\n")));
  1683. //
  1684. // Validate parameters
  1685. //
  1686. if (!ValidHandle(hProfile, OBJ_PROFILE) ||
  1687. IsBadWritePtr(pcbSize, sizeof(DWORD)) ||
  1688. (pBuffer &&
  1689. IsBadWritePtr(pBuffer, *pcbSize)
  1690. ) ||
  1691. IsBadWritePtr(pbBinary, sizeof(BOOL))
  1692. )
  1693. {
  1694. WARNING((__TEXT("Invalid parameter to GetPS2ColorRenderingDictionary\n")));
  1695. SetLastError(ERROR_INVALID_PARAMETER);
  1696. return FALSE;
  1697. }
  1698. pProfObj = (PPROFOBJ)HDLTOPTR(hProfile);
  1699. ASSERT(pProfObj != NULL);
  1700. //
  1701. // Check the integrity of the profile
  1702. //
  1703. if (!ValidProfile(pProfObj))
  1704. {
  1705. WARNING((__TEXT("Invalid profile passed to GetPS2ColorRenderingDictionary\n")));
  1706. SetLastError(ERROR_INVALID_PROFILE);
  1707. return FALSE;
  1708. }
  1709. //
  1710. // Check if application specified CMM is present
  1711. //
  1712. pCMMObj = GetPreferredCMM();
  1713. if (!pCMMObj || (pCMMObj->dwFlags & CMM_DONT_USE_PS2_FNS) ||
  1714. !pCMMObj->fns.pCMGetPS2ColorRenderingDictionary)
  1715. {
  1716. if (pCMMObj)
  1717. {
  1718. pCMMObj->dwFlags |= CMM_DONT_USE_PS2_FNS;
  1719. ReleaseColorMatchingModule(pCMMObj);
  1720. }
  1721. //
  1722. // Get CMM associated with profile. If it does not exist or does not
  1723. // support the CMGetPS2ColorSpaceArray function, get default CMM.
  1724. //
  1725. cmmID = HEADER(pProfObj)->phCMMType;
  1726. cmmID = FIX_ENDIAN(cmmID);
  1727. pCMMObj = GetColorMatchingModule(cmmID);
  1728. if (!pCMMObj || (pCMMObj->dwFlags & CMM_DONT_USE_PS2_FNS) ||
  1729. !pCMMObj->fns.pCMGetPS2ColorRenderingDictionary)
  1730. {
  1731. TERSE((__TEXT("CMM associated with profile could not be used")));
  1732. if (pCMMObj)
  1733. {
  1734. pCMMObj->dwFlags |= CMM_DONT_USE_PS2_FNS;
  1735. ReleaseColorMatchingModule(pCMMObj);
  1736. }
  1737. pCMMObj = GetColorMatchingModule(CMM_WINDOWS_DEFAULT);
  1738. if (!pCMMObj || !pCMMObj->fns.pCMGetPS2ColorRenderingDictionary)
  1739. {
  1740. WARNING((__TEXT("Default CMM doesn't support CMGetPS2ColorRenderingDictionary\n")));
  1741. if (pCMMObj)
  1742. {
  1743. ReleaseColorMatchingModule(pCMMObj);
  1744. pCMMObj = NULL;
  1745. }
  1746. }
  1747. }
  1748. }
  1749. ASSERT(pProfObj->pView != NULL);
  1750. if (pCMMObj)
  1751. {
  1752. rc = pCMMObj->fns.pCMGetPS2ColorRenderingDictionary(hProfile, dwIntent,
  1753. pBuffer, pcbSize, pbBinary);
  1754. }
  1755. else
  1756. {
  1757. rc = InternalGetPS2ColorRenderingDictionary(pProfObj->pView, dwIntent,
  1758. pBuffer, pcbSize, pbBinary);
  1759. }
  1760. if (pCMMObj)
  1761. {
  1762. ReleaseColorMatchingModule(pCMMObj);
  1763. }
  1764. VERBOSE((__TEXT("GetPS2ColorRenderingDictionary returning %s\n"),
  1765. rc ? "TRUE" : "FALSE"));
  1766. return rc;
  1767. }
  1768. /******************************************************************************
  1769. *
  1770. * GetNamedProfileInfo
  1771. *
  1772. * Function:
  1773. * This functions returns information about the given named color space
  1774. * profile. If fails if the given profile is not a named color space profile.
  1775. *
  1776. * Arguments:
  1777. * hProfile - handle identifying the named color space profile object
  1778. * pNamedProfileInfo - pointer to NAMED_PROFILE_INFO structure that is
  1779. * filled on retun if successful.
  1780. *
  1781. * Returns:
  1782. * TRUE if successful, FALSE otherwise
  1783. *
  1784. ******************************************************************************/
  1785. BOOL WINAPI GetNamedProfileInfo(
  1786. HPROFILE hProfile,
  1787. PNAMED_PROFILE_INFO pNamedProfileInfo
  1788. )
  1789. {
  1790. PPROFOBJ pProfObj;
  1791. PCMMOBJ pCMMObj;
  1792. DWORD cmmID;
  1793. BOOL rc;
  1794. TRACEAPI((__TEXT("GetNamedProfileInfo\n")));
  1795. //
  1796. // Validate parameters
  1797. //
  1798. if (!ValidHandle(hProfile, OBJ_PROFILE) ||
  1799. !pNamedProfileInfo ||
  1800. IsBadWritePtr(pNamedProfileInfo, sizeof(NAMED_PROFILE_INFO)))
  1801. {
  1802. WARNING((__TEXT("Invalid parameter to GetNamedProfileInfo\n")));
  1803. SetLastError(ERROR_INVALID_PARAMETER);
  1804. return FALSE;
  1805. }
  1806. pProfObj = (PPROFOBJ)HDLTOPTR(hProfile);
  1807. ASSERT(pProfObj != NULL);
  1808. //
  1809. // Check the integrity of the profile
  1810. //
  1811. if (!ValidProfile(pProfObj))
  1812. {
  1813. WARNING((__TEXT("Invalid profile passed to GetNamedProfileInfo\n")));
  1814. SetLastError(ERROR_INVALID_PROFILE);
  1815. return FALSE;
  1816. }
  1817. //
  1818. // Check if application specified CMM is present
  1819. //
  1820. pCMMObj = GetPreferredCMM();
  1821. if (!pCMMObj ||
  1822. !pCMMObj->fns.pCMGetNamedProfileInfo)
  1823. {
  1824. if (pCMMObj)
  1825. {
  1826. ReleaseColorMatchingModule(pCMMObj);
  1827. }
  1828. //
  1829. // Get CMM associated with profile. If it does not exist or does not
  1830. // support the CMGetNamedProfileInfo function, get default CMM.
  1831. //
  1832. cmmID = HEADER(pProfObj)->phCMMType;
  1833. cmmID = FIX_ENDIAN(cmmID);
  1834. pCMMObj = GetColorMatchingModule(cmmID);
  1835. if (!pCMMObj ||
  1836. !pCMMObj->fns.pCMGetNamedProfileInfo)
  1837. {
  1838. TERSE((__TEXT("CMM associated with profile could not be used")));
  1839. if (pCMMObj)
  1840. {
  1841. ReleaseColorMatchingModule(pCMMObj);
  1842. }
  1843. pCMMObj = GetColorMatchingModule(CMM_WINDOWS_DEFAULT);
  1844. if (!pCMMObj || !pCMMObj->fns.pCMGetNamedProfileInfo)
  1845. {
  1846. RIP((__TEXT("Default CMM doesn't support CMValidateProfile")));
  1847. SetLastError(ERROR_INVALID_CMM);
  1848. if (pCMMObj)
  1849. {
  1850. ReleaseColorMatchingModule(pCMMObj);
  1851. }
  1852. return FALSE;
  1853. }
  1854. }
  1855. }
  1856. ASSERT(pProfObj->pView != NULL);
  1857. rc = pCMMObj->fns.pCMGetNamedProfileInfo(hProfile, pNamedProfileInfo);
  1858. ReleaseColorMatchingModule(pCMMObj);
  1859. return rc;
  1860. }
  1861. /******************************************************************************
  1862. *
  1863. * ConvertColorNameToIndex
  1864. *
  1865. * Function:
  1866. * This functions converts a given array of color names to color indices
  1867. * using the specified named color space profile
  1868. *
  1869. * Arguments:
  1870. * hProfile - handle identifing the named color space profile object
  1871. * paColorName - pointer to array of COLOR_NAME structures
  1872. * paIndex - pointer to array of DWORDs to receive the indices
  1873. * dwCount - number of color names to convert
  1874. *
  1875. * Returns:
  1876. * TRUE if successful, FALSE otherwise
  1877. *
  1878. ******************************************************************************/
  1879. BOOL WINAPI ConvertColorNameToIndex(
  1880. HPROFILE hProfile,
  1881. PCOLOR_NAME paColorName,
  1882. PDWORD paIndex,
  1883. DWORD dwCount
  1884. )
  1885. {
  1886. PPROFOBJ pProfObj;
  1887. PCMMOBJ pCMMObj;
  1888. DWORD cmmID;
  1889. BOOL rc;
  1890. TRACEAPI((__TEXT("ConvertColorNameToIndex\n")));
  1891. //
  1892. // Validate parameters
  1893. //
  1894. if (!ValidHandle(hProfile, OBJ_PROFILE) ||
  1895. !paColorName ||
  1896. dwCount == 0 ||
  1897. IsBadReadPtr(paColorName, dwCount*sizeof(COLOR_NAME)) ||
  1898. !paIndex ||
  1899. IsBadWritePtr(paIndex, dwCount*sizeof(DWORD)))
  1900. {
  1901. WARNING((__TEXT("Invalid parameter to ConvertColorNameToIndex\n")));
  1902. SetLastError(ERROR_INVALID_PARAMETER);
  1903. return FALSE;
  1904. }
  1905. pProfObj = (PPROFOBJ)HDLTOPTR(hProfile);
  1906. ASSERT(pProfObj != NULL);
  1907. //
  1908. // Check the integrity of the profile
  1909. //
  1910. if (!ValidProfile(pProfObj))
  1911. {
  1912. WARNING((__TEXT("Invalid profile passed to ConvertColorNameToIndex\n")));
  1913. SetLastError(ERROR_INVALID_PROFILE);
  1914. return FALSE;
  1915. }
  1916. //
  1917. // Check if application specified CMM is present
  1918. //
  1919. pCMMObj = GetPreferredCMM();
  1920. if (!pCMMObj ||
  1921. !pCMMObj->fns.pCMConvertColorNameToIndex)
  1922. {
  1923. if (pCMMObj)
  1924. {
  1925. ReleaseColorMatchingModule(pCMMObj);
  1926. }
  1927. //
  1928. // Get CMM associated with profile. If it does not exist or does not
  1929. // support the CMConvertColorNameToIndex function, get default CMM.
  1930. //
  1931. cmmID = HEADER(pProfObj)->phCMMType;
  1932. cmmID = FIX_ENDIAN(cmmID);
  1933. pCMMObj = GetColorMatchingModule(cmmID);
  1934. if (!pCMMObj ||
  1935. !pCMMObj->fns.pCMConvertColorNameToIndex)
  1936. {
  1937. TERSE((__TEXT("CMM associated with profile could not be used")));
  1938. if (pCMMObj)
  1939. {
  1940. ReleaseColorMatchingModule(pCMMObj);
  1941. }
  1942. pCMMObj = GetColorMatchingModule(CMM_WINDOWS_DEFAULT);
  1943. if (!pCMMObj || !pCMMObj->fns.pCMConvertColorNameToIndex)
  1944. {
  1945. RIP((__TEXT("Default CMM doesn't support CMConvertColorNameToIndex")));
  1946. SetLastError(ERROR_INVALID_CMM);
  1947. if (pCMMObj)
  1948. {
  1949. ReleaseColorMatchingModule(pCMMObj);
  1950. }
  1951. return FALSE;
  1952. }
  1953. }
  1954. }
  1955. ASSERT(pProfObj->pView != NULL);
  1956. rc = pCMMObj->fns.pCMConvertColorNameToIndex(
  1957. hProfile,
  1958. paColorName,
  1959. paIndex,
  1960. dwCount);
  1961. ReleaseColorMatchingModule(pCMMObj);
  1962. return rc;
  1963. }
  1964. /******************************************************************************
  1965. *
  1966. * ConvertIndexToColorName
  1967. *
  1968. * Function:
  1969. * This functions converts a given array of color indices to color names
  1970. * using the specified named color space profile
  1971. *
  1972. * Arguments:
  1973. * hProfile - handle identifing the named color space profile object
  1974. * paIndex - pointer to array of color indices
  1975. * paColorName - pointer to array of COLOR_NAME structures
  1976. * dwCount - number of color indices to convert
  1977. *
  1978. * Returns:
  1979. * TRUE if successful, FALSE otherwise
  1980. *
  1981. ******************************************************************************/
  1982. BOOL WINAPI ConvertIndexToColorName(
  1983. HPROFILE hProfile,
  1984. PDWORD paIndex,
  1985. PCOLOR_NAME paColorName,
  1986. DWORD dwCount
  1987. )
  1988. {
  1989. PPROFOBJ pProfObj;
  1990. PCMMOBJ pCMMObj;
  1991. DWORD cmmID;
  1992. BOOL rc;
  1993. TRACEAPI((__TEXT("ConvertIndexToColorName\n")));
  1994. //
  1995. // Validate parameters
  1996. //
  1997. if (!ValidHandle(hProfile, OBJ_PROFILE) ||
  1998. !paIndex ||
  1999. dwCount == 0 ||
  2000. IsBadWritePtr(paIndex, dwCount*sizeof(DWORD)) ||
  2001. !paColorName ||
  2002. IsBadReadPtr(paColorName, dwCount*sizeof(COLOR_NAME)))
  2003. {
  2004. WARNING((__TEXT("Invalid parameter to ConvertIndexToColorName\n")));
  2005. SetLastError(ERROR_INVALID_PARAMETER);
  2006. return FALSE;
  2007. }
  2008. pProfObj = (PPROFOBJ)HDLTOPTR(hProfile);
  2009. ASSERT(pProfObj != NULL);
  2010. //
  2011. // Check the integrity of the profile
  2012. //
  2013. if (!ValidProfile(pProfObj))
  2014. {
  2015. WARNING((__TEXT("Invalid profile passed to ConvertIndexToColorName\n")));
  2016. SetLastError(ERROR_INVALID_PROFILE);
  2017. return FALSE;
  2018. }
  2019. //
  2020. // Check if application specified CMM is present
  2021. //
  2022. pCMMObj = GetPreferredCMM();
  2023. if (!pCMMObj ||
  2024. !pCMMObj->fns.pCMConvertIndexToColorName)
  2025. {
  2026. if (pCMMObj)
  2027. {
  2028. ReleaseColorMatchingModule(pCMMObj);
  2029. }
  2030. //
  2031. // Get CMM associated with profile. If it does not exist or does not
  2032. // support the CMConvertIndexToColorName function, get default CMM.
  2033. //
  2034. cmmID = HEADER(pProfObj)->phCMMType;
  2035. cmmID = FIX_ENDIAN(cmmID);
  2036. pCMMObj = GetColorMatchingModule(cmmID);
  2037. if (!pCMMObj ||
  2038. !pCMMObj->fns.pCMConvertIndexToColorName)
  2039. {
  2040. TERSE((__TEXT("CMM associated with profile could not be used")));
  2041. if (pCMMObj)
  2042. {
  2043. ReleaseColorMatchingModule(pCMMObj);
  2044. }
  2045. pCMMObj = GetColorMatchingModule(CMM_WINDOWS_DEFAULT);
  2046. if (!pCMMObj || !pCMMObj->fns.pCMConvertIndexToColorName)
  2047. {
  2048. RIP((__TEXT("Default CMM doesn't support CMConvertIndexToColorName")));
  2049. SetLastError(ERROR_INVALID_CMM);
  2050. if (pCMMObj)
  2051. {
  2052. ReleaseColorMatchingModule(pCMMObj);
  2053. }
  2054. return FALSE;
  2055. }
  2056. }
  2057. }
  2058. ASSERT(pProfObj->pView != NULL);
  2059. rc = pCMMObj->fns.pCMConvertIndexToColorName(
  2060. hProfile,
  2061. paIndex,
  2062. paColorName,
  2063. dwCount);
  2064. ReleaseColorMatchingModule(pCMMObj);
  2065. return rc;
  2066. }
  2067. /******************************************************************************
  2068. *
  2069. * CreateDeviceLinkProfile
  2070. *
  2071. * Function:
  2072. * This functions creates a device link profile from the given set
  2073. * of profiles, using specified intents.
  2074. *
  2075. * Arguments:
  2076. * pahProfiles - pointer to array of handles of profiles
  2077. * nProfiles - number of profiles in array
  2078. * padwIntent - array of intents to use
  2079. * nIntents - size of array - can be 1 or nProfiles
  2080. * dwFlags - optimization flags
  2081. * pProfileData - pointer to pointer to buffer to receive data which
  2082. * this function allocates; caller needs to free.
  2083. * indexPreferredCMM - zero based index of profile which specifies
  2084. * preferred CMM to use.
  2085. *
  2086. * Returns:
  2087. * TRUE if successful, FALSE otherwise
  2088. *
  2089. ******************************************************************************/
  2090. BOOL WINAPI CreateDeviceLinkProfile(
  2091. PHPROFILE pahProfiles,
  2092. DWORD nProfiles,
  2093. PDWORD padwIntent,
  2094. DWORD nIntents,
  2095. DWORD dwFlags,
  2096. PBYTE *pProfileData,
  2097. DWORD indexPreferredCMM
  2098. )
  2099. {
  2100. PPROFOBJ pProfObj;
  2101. PCMMOBJ pCMMObj;
  2102. DWORD cmmID, i;
  2103. BOOL rc;
  2104. TRACEAPI((__TEXT("CreateDeviceLinkProfile\n")));
  2105. //
  2106. // Validate parameters
  2107. //
  2108. if (nProfiles <= 1 ||
  2109. indexPreferredCMM >= nProfiles ||
  2110. pahProfiles == NULL ||
  2111. IsBadReadPtr(pahProfiles, sizeof(HPROFILE) * nProfiles) ||
  2112. padwIntent == NULL ||
  2113. ((nIntents != nProfiles) && (nIntents != 1)) ||
  2114. IsBadReadPtr(padwIntent, nIntents * sizeof(DWORD)))
  2115. {
  2116. WARNING((__TEXT("Invalid parameter to CreateDeviceLinkProfile\n")));
  2117. SetLastError(ERROR_INVALID_PARAMETER);
  2118. return FALSE;
  2119. }
  2120. for (i=0; i<nProfiles; i++)
  2121. {
  2122. if ((pahProfiles[i] == NULL) ||
  2123. ! ValidHandle(pahProfiles[i], OBJ_PROFILE))
  2124. {
  2125. WARNING((__TEXT("Invalid profile passed to CreateDeviceLinkProfile\n")));
  2126. SetLastError(ERROR_INVALID_PARAMETER);
  2127. return FALSE;
  2128. }
  2129. pProfObj = (PPROFOBJ)HDLTOPTR(pahProfiles[i]);
  2130. ASSERT(pProfObj != NULL);
  2131. ASSERT(pProfObj->pView != NULL);
  2132. //
  2133. // Quick check on the integrity of the profile
  2134. //
  2135. if (!ValidProfile(pProfObj))
  2136. {
  2137. WARNING((__TEXT("Invalid profile passed to CreateDeviceLinkProfile\n")));
  2138. SetLastError(ERROR_INVALID_PROFILE);
  2139. return FALSE;
  2140. }
  2141. if (i == indexPreferredCMM)
  2142. {
  2143. //
  2144. // Get ID of preferred CMM
  2145. //
  2146. cmmID = HEADER(pProfObj)->phCMMType;
  2147. cmmID = FIX_ENDIAN(cmmID);
  2148. }
  2149. }
  2150. //
  2151. // Get CMM associated with preferred profile. If it does not exist,
  2152. // get default CMM.
  2153. //
  2154. pCMMObj = GetColorMatchingModule(cmmID);
  2155. if (!pCMMObj || !pCMMObj->fns.pCMCreateDeviceLinkProfile)
  2156. {
  2157. TERSE((__TEXT("CMM associated with profile could not be used")));
  2158. if (pCMMObj)
  2159. {
  2160. ReleaseColorMatchingModule(pCMMObj);
  2161. }
  2162. pCMMObj = GetColorMatchingModule(CMM_WINDOWS_DEFAULT);
  2163. if (!pCMMObj)
  2164. {
  2165. RIP((__TEXT("Default CMM not found\n")));
  2166. SetLastError(ERROR_INVALID_CMM);
  2167. return FALSE;
  2168. }
  2169. }
  2170. ASSERT(pCMMObj->fns.pCMCreateDeviceLinkProfile != NULL);
  2171. rc = pCMMObj->fns.pCMCreateDeviceLinkProfile(
  2172. pahProfiles,
  2173. nProfiles,
  2174. padwIntent,
  2175. nIntents,
  2176. dwFlags,
  2177. pProfileData);
  2178. ReleaseColorMatchingModule(pCMMObj);
  2179. return rc;
  2180. }
  2181. /*****************************************************************************/
  2182. /***************************** Internal Functions ****************************/
  2183. /*****************************************************************************/
  2184. /******************************************************************************
  2185. *
  2186. * InternalOpenColorProfile
  2187. *
  2188. * Function:
  2189. * This functions opens a color profile specified by the pProfile
  2190. * parameter, creates an internal profile object, and returns a handle
  2191. * to it.
  2192. *
  2193. * Arguments:
  2194. * pProfile - ptr to a profile structure that specifies the profile
  2195. * to open
  2196. * dwDesiredAccess - specifies the mode in which to open the profile.
  2197. * Any combination of these values can be used:
  2198. * PROFILE_READ: Allows the app to read the profile.
  2199. * PROFILE_READWRITE: Allows the app to read and write to the profile.
  2200. * dwShareMode - specifies the mode to share the profile with other
  2201. * processes if it is a file. Any combination of these
  2202. * values can be used.
  2203. * 0 : Prevents the file from being shared.
  2204. * FILE_SHARE_READ: Allows opening for read only by other processes.
  2205. * FILE_SHARE_WRITE: Allows opening for write by other processes.
  2206. * dwCreationMode - specifies which actions to take on the profile while
  2207. * opening it (if it is a file). Any one of the following
  2208. * values can be used.
  2209. * CREATE_NEW: Creates a new file. Fails if one exists already.
  2210. * CREATE_ALWAYS: Always create a new file. Overwriting existing.
  2211. * OPEN_EXISTING: Open exisiting file. Fail if not found.
  2212. * OPEN_ALWAYS: Open existing. If not found, create a new one.
  2213. * TRUNCATE_EXISTING: Open existing and truncate to zero bytes. Fail
  2214. * if not found.
  2215. *
  2216. * Returns:
  2217. * Handle to open profile on success, zero on failure.
  2218. *
  2219. ******************************************************************************/
  2220. HPROFILE InternalOpenColorProfile(
  2221. PPROFILE pProfile,
  2222. DWORD dwDesiredAccess,
  2223. DWORD dwShareMode,
  2224. DWORD dwCreationMode
  2225. )
  2226. {
  2227. SECURITY_ATTRIBUTES sa;
  2228. PPROFOBJ pProfObj;
  2229. HPROFILE hProfile;
  2230. DWORD dwMapSize;
  2231. BOOL bNewFile = FALSE;
  2232. BOOL bError = TRUE; // Assume failure
  2233. TRACEAPI((__TEXT("OpenColorProfile\n")));
  2234. //
  2235. // Validate parameters
  2236. //
  2237. if (!pProfile ||
  2238. IsBadReadPtr(pProfile, sizeof(PROFILE)) ||
  2239. (pProfile->pProfileData &&
  2240. IsBadReadPtr(pProfile->pProfileData, pProfile->cbDataSize)) ||
  2241. (!pProfile->pProfileData &&
  2242. (pProfile->cbDataSize != 0)) ||
  2243. (pProfile->dwType != PROFILE_FILENAME &&
  2244. pProfile->dwType != PROFILE_MEMBUFFER
  2245. ) ||
  2246. (dwDesiredAccess != PROFILE_READ &&
  2247. dwDesiredAccess != PROFILE_READWRITE
  2248. )
  2249. )
  2250. {
  2251. WARNING((__TEXT("Invalid parameter to OpenColorProfile\n")));
  2252. SetLastError(ERROR_INVALID_PARAMETER);
  2253. return NULL;
  2254. }
  2255. //
  2256. // Allocate an object on the heap for the profile
  2257. //
  2258. hProfile = AllocateHeapObject(OBJ_PROFILE);
  2259. if (!hProfile)
  2260. {
  2261. WARNING((__TEXT("Could not allocate profile object\n")));
  2262. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  2263. return NULL;
  2264. }
  2265. pProfObj = (PPROFOBJ)HDLTOPTR(hProfile);
  2266. ASSERT(pProfObj != NULL);
  2267. //
  2268. // Copy profile information to our object
  2269. //
  2270. pProfObj->objHdr.dwUseCount = 1;
  2271. pProfObj->dwType = pProfile->dwType;
  2272. pProfObj->cbDataSize = pProfile->cbDataSize;
  2273. pProfObj->pProfileData = (PBYTE)MemAlloc(pProfile->cbDataSize + sizeof(TCHAR));
  2274. if (!pProfObj->pProfileData)
  2275. {
  2276. WARNING((__TEXT("Could not allocate memory for profile data\n")));
  2277. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  2278. goto EndOpenColorProfile;
  2279. }
  2280. CopyMemory((PVOID)pProfObj->pProfileData,
  2281. (PVOID)pProfile->pProfileData,
  2282. pProfile->cbDataSize);
  2283. if (pProfObj->dwType == PROFILE_FILENAME)
  2284. {
  2285. LPTSTR lpFilename;
  2286. if (!pProfile->pProfileData ||
  2287. pProfile->cbDataSize == 0 ||
  2288. lstrlen((LPCTSTR)pProfile->pProfileData) > MAX_PATH ||
  2289. pProfile->cbDataSize > (MAX_PATH * sizeof(TCHAR)))
  2290. {
  2291. WARNING((__TEXT("Invalid parameter to OpenColorProfile\n")));
  2292. SetLastError(ERROR_INVALID_PARAMETER);
  2293. goto EndOpenColorProfile;
  2294. }
  2295. //
  2296. // If only filename is given, it is wrt color directory
  2297. //
  2298. lpFilename = GetFilenameFromPath((LPTSTR)pProfObj->pProfileData);
  2299. if (lpFilename == pProfObj->pProfileData)
  2300. {
  2301. DWORD dwLen = MAX_PATH;
  2302. lpFilename = MemAlloc(dwLen);
  2303. if (!lpFilename)
  2304. {
  2305. WARNING((__TEXT("Could not allocate memory for file name\n")));
  2306. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  2307. goto EndOpenColorProfile;
  2308. }
  2309. (VOID)GetColorDirectory(NULL, lpFilename, &dwLen);
  2310. lstrcat(lpFilename, gszBackslash);
  2311. lstrcat(lpFilename, (LPTSTR)pProfObj->pProfileData);
  2312. MemFree(pProfObj->pProfileData);
  2313. pProfObj->pProfileData = (PVOID)lpFilename;
  2314. pProfObj->cbDataSize = MAX_PATH;
  2315. }
  2316. //
  2317. // File name already null terminates as we used GHND flag which
  2318. // zero initializes the allocated memory
  2319. //
  2320. // Create file mapping
  2321. //
  2322. pProfObj->dwFlags |= MEMORY_MAPPED;
  2323. if (dwCreationMode == OPEN_ALWAYS)
  2324. {
  2325. //
  2326. // If we find a zero length profile, we should error out
  2327. // saying it is a bad profile. If we create a zero length
  2328. // profile, it is fine. To distinguish these two cases, we
  2329. // check for file's existence and if present, change the
  2330. // creation mode to OPEN_EXISTING
  2331. //
  2332. if (GetFileAttributes(pProfObj->pProfileData) != (DWORD)-1)
  2333. {
  2334. dwCreationMode = OPEN_EXISTING;
  2335. }
  2336. }
  2337. //
  2338. // Set security attribute structure
  2339. //
  2340. sa.nLength = sizeof(SECURITY_ATTRIBUTES);
  2341. sa.lpSecurityDescriptor = NULL; // default security
  2342. sa.bInheritHandle = FALSE;
  2343. pProfObj->hFile = CreateFile(pProfObj->pProfileData,
  2344. (dwDesiredAccess == PROFILE_READWRITE) ? GENERIC_READ | GENERIC_WRITE : GENERIC_READ,
  2345. dwShareMode, &sa, dwCreationMode, FILE_FLAG_RANDOM_ACCESS, 0);
  2346. if (pProfObj->hFile == INVALID_HANDLE_VALUE)
  2347. {
  2348. WARNING((__TEXT("Err %ld, could not open profile %s\n"),
  2349. GetLastError(), pProfObj->pProfileData));
  2350. goto EndOpenColorProfile;
  2351. }
  2352. //
  2353. // Get size of file mapping. Add a cushion so that profile can
  2354. // be grown. When closing the profile, the file size is truncated
  2355. // to the size of the actual data. If the profile size grows beyond
  2356. // the cushion, it is continually grown in chunks.
  2357. //
  2358. dwMapSize = GetFileSize(pProfObj->hFile, NULL);
  2359. if (dwMapSize == 0)
  2360. {
  2361. if (dwCreationMode == OPEN_EXISTING)
  2362. {
  2363. WARNING((__TEXT("Invalid profile - zero length\n")));
  2364. SetLastError(ERROR_INVALID_PROFILE);
  2365. goto EndOpenColorProfile;
  2366. }
  2367. else
  2368. {
  2369. dwMapSize = PROFILE_GROWTHCUSHION;
  2370. bNewFile = TRUE;
  2371. }
  2372. }
  2373. pProfObj->hMap = CreateFileMapping(pProfObj->hFile, 0,
  2374. (dwDesiredAccess == PROFILE_READWRITE) ? PAGE_READWRITE : PAGE_READONLY,
  2375. 0, dwMapSize, 0);
  2376. if (!pProfObj->hMap)
  2377. {
  2378. WARNING((__TEXT("Err %ld, could not create map of profile %s\n"),
  2379. GetLastError(), pProfObj->pProfileData));
  2380. goto EndOpenColorProfile;
  2381. }
  2382. pProfObj->dwMapSize = dwMapSize;
  2383. pProfObj->pView = (PBYTE)MapViewOfFile(pProfObj->hMap,
  2384. (dwDesiredAccess == PROFILE_READWRITE) ? FILE_MAP_ALL_ACCESS : FILE_MAP_READ,
  2385. 0, 0, 0);
  2386. if (!pProfObj->pView)
  2387. {
  2388. WARNING((__TEXT("Err %ld, could not create view of profile %s\n"),
  2389. GetLastError(), pProfObj->pProfileData));
  2390. goto EndOpenColorProfile;
  2391. }
  2392. //
  2393. // If a new profile has been created, initialize size
  2394. // and tag table count
  2395. //
  2396. if (bNewFile && dwDesiredAccess == PROFILE_READWRITE)
  2397. {
  2398. HEADER(pProfObj)->phSize = FIX_ENDIAN(sizeof(PROFILEHEADER) +
  2399. sizeof(DWORD));
  2400. HEADER(pProfObj)->phVersion = 0x02000000;
  2401. HEADER(pProfObj)->phSignature = PROFILE_SIGNATURE;
  2402. TAG_COUNT(pProfObj) = 0;
  2403. }
  2404. }
  2405. else
  2406. {
  2407. if (pProfile->cbDataSize == 0)
  2408. {
  2409. //
  2410. // Allocate a small buffer and create a new profile in it
  2411. //
  2412. pProfObj->cbDataSize = PROFILE_GROWTHCUSHION;
  2413. MemFree(pProfObj->pProfileData);
  2414. pProfObj->pView = pProfObj->pProfileData = MemAlloc(pProfObj->cbDataSize);
  2415. if (!pProfObj->pView)
  2416. {
  2417. WARNING((__TEXT("Could not allocate memory for profile data\n")));
  2418. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  2419. goto EndOpenColorProfile;
  2420. }
  2421. HEADER(pProfObj)->phSize = FIX_ENDIAN(sizeof(PROFILEHEADER) +
  2422. sizeof(DWORD));
  2423. HEADER(pProfObj)->phVersion = 0x02000000;
  2424. HEADER(pProfObj)->phSignature = PROFILE_SIGNATURE;
  2425. TAG_COUNT(pProfObj) = 0;
  2426. pProfObj->dwMapSize = pProfObj->cbDataSize;
  2427. }
  2428. else
  2429. {
  2430. //
  2431. // Treat buffer as view of file
  2432. //
  2433. pProfObj->pView = pProfObj->pProfileData;
  2434. pProfObj->dwMapSize = pProfObj->cbDataSize;
  2435. //
  2436. // Do a sanity check on the profile
  2437. //
  2438. if (!ValidProfile(pProfObj))
  2439. {
  2440. WARNING((__TEXT("Invalid profile passed to OpenColorProfile\n")));
  2441. SetLastError(ERROR_INVALID_PROFILE);
  2442. goto EndOpenColorProfile;
  2443. }
  2444. }
  2445. }
  2446. if (dwDesiredAccess == PROFILE_READWRITE)
  2447. pProfObj->dwFlags |= READWRITE_ACCESS;
  2448. bError = FALSE; // Success!
  2449. EndOpenColorProfile:
  2450. if (bError)
  2451. {
  2452. if (hProfile)
  2453. FreeProfileObject(hProfile);
  2454. hProfile = NULL;
  2455. }
  2456. return hProfile;
  2457. }
  2458. /******************************************************************************
  2459. *
  2460. * InternalCreateProfileFromLCS
  2461. *
  2462. * Function:
  2463. * This functions takes a logical color space and creates an ICC profile
  2464. *
  2465. * Arguments:
  2466. * pLogColorSpace - Pointer to LogColorSpace structure
  2467. * pBuffer - Pointer to pointer to buffer. This function allocates and
  2468. * fills this buffer with the profile on success.
  2469. *
  2470. * Returns:
  2471. * TRUE if successful, FALSE otherwise
  2472. *
  2473. ******************************************************************************/
  2474. BOOL InternalCreateProfileFromLCS(
  2475. LPLOGCOLORSPACE pLogColorSpace,
  2476. PBYTE *pBuffer,
  2477. BOOL bValidateParams
  2478. )
  2479. {
  2480. PCMMOBJ pCMMObj = NULL;
  2481. BOOL rc;
  2482. //
  2483. // Validate parameters
  2484. //
  2485. if (bValidateParams &&
  2486. (! pLogColorSpace ||
  2487. IsBadReadPtr(pLogColorSpace, sizeof(LOGCOLORSPACE)) ||
  2488. pLogColorSpace->lcsFilename[0] != '\0'))
  2489. {
  2490. WARNING((__TEXT("Invalid parameter to CreateProfileFromLogColorSpace\n")));
  2491. SetLastError(ERROR_INVALID_PARAMETER);
  2492. return FALSE;
  2493. }
  2494. //
  2495. // We use the default CMM for this
  2496. //
  2497. pCMMObj = GetColorMatchingModule(CMM_WINDOWS_DEFAULT);
  2498. if (!pCMMObj)
  2499. {
  2500. RIP((__TEXT("Default CMM not found\n")));
  2501. SetLastError(ERROR_INVALID_CMM);
  2502. return FALSE;
  2503. }
  2504. ASSERT(pCMMObj->fns.pCMCreateProfile != NULL);
  2505. rc = pCMMObj->fns.pCMCreateProfile(pLogColorSpace, pBuffer);
  2506. ReleaseColorMatchingModule(pCMMObj);
  2507. return rc;
  2508. }
  2509. /******************************************************************************
  2510. *
  2511. * FreeProfileObject
  2512. *
  2513. * Function:
  2514. * This functions frees a profile object and associated memory
  2515. *
  2516. * Arguments:
  2517. * hProfile - handle identifing the profile object to free
  2518. *
  2519. * Returns:
  2520. * TRUE if successful, FALSE otherwise
  2521. *
  2522. ******************************************************************************/
  2523. BOOL FreeProfileObject(
  2524. HANDLE hProfile
  2525. )
  2526. {
  2527. PPROFOBJ pProfObj;
  2528. DWORD dwFileSize = 0;
  2529. DWORD dwErr;
  2530. ASSERT(hProfile != NULL);
  2531. pProfObj = (PPROFOBJ)HDLTOPTR(hProfile);
  2532. ASSERT(pProfObj != NULL);
  2533. dwErr = GetLastError(); // remember any errors we may have set
  2534. //
  2535. // Free memory associated with profile data
  2536. //
  2537. if (pProfObj->pProfileData)
  2538. MemFree((PVOID)pProfObj->pProfileData);
  2539. //
  2540. // If it a memory mapped profile, unmap it
  2541. //
  2542. if (pProfObj->dwFlags & MEMORY_MAPPED)
  2543. {
  2544. if (pProfObj->pView)
  2545. {
  2546. dwFileSize = FIX_ENDIAN(HEADER(pProfObj)->phSize);
  2547. UnmapViewOfFile(pProfObj->pView);
  2548. }
  2549. if (pProfObj->hMap)
  2550. CloseHandle(pProfObj->hMap);
  2551. if (pProfObj->hFile)
  2552. {
  2553. //
  2554. // Set the size of the file correctly
  2555. //
  2556. SetFilePointer(pProfObj->hFile, dwFileSize, NULL, FILE_BEGIN);
  2557. SetEndOfFile(pProfObj->hFile);
  2558. CloseHandle(pProfObj->hFile);
  2559. }
  2560. }
  2561. //
  2562. // Free heap object
  2563. //
  2564. pProfObj->objHdr.dwUseCount--; // decrement before freeing
  2565. FreeHeapObject(hProfile);
  2566. if (dwErr)
  2567. {
  2568. SetLastError(dwErr); // reset our error
  2569. }
  2570. return TRUE;
  2571. }
  2572. /******************************************************************************
  2573. *
  2574. * GrowProfile
  2575. *
  2576. * Function:
  2577. * This functions grows a profile to the new size
  2578. *
  2579. * Arguments:
  2580. * pProfObj - pointer to profile object
  2581. * dwNewSize - new size for the profile
  2582. *
  2583. * Returns:
  2584. * TRUE if successful, FALSE otherwise
  2585. *
  2586. ******************************************************************************/
  2587. BOOL GrowProfile(
  2588. PPROFOBJ pProfObj,
  2589. DWORD dwNewSize
  2590. )
  2591. {
  2592. if (pProfObj->dwMapSize >= dwNewSize)
  2593. return TRUE;
  2594. //
  2595. // Add cushion for future growth
  2596. //
  2597. dwNewSize += PROFILE_GROWTHCUSHION;
  2598. if (pProfObj->dwFlags & MEMORY_MAPPED)
  2599. {
  2600. //
  2601. // Profile is a memory mapped file
  2602. //
  2603. //
  2604. // Close previous view and map
  2605. //
  2606. UnmapViewOfFile(pProfObj->pView);
  2607. CloseHandle(pProfObj->hMap);
  2608. pProfObj->hMap = CreateFileMapping(pProfObj->hFile, 0,
  2609. PAGE_READWRITE, 0, dwNewSize, 0);
  2610. if (!pProfObj->hMap)
  2611. {
  2612. WARNING((__TEXT("Err %ld, could not recreate map of profile %s\n"),
  2613. GetLastError(), pProfObj->pProfileData));
  2614. return FALSE;
  2615. }
  2616. pProfObj->pView = (PBYTE) MapViewOfFile(pProfObj->hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
  2617. if (!pProfObj->pView)
  2618. {
  2619. WARNING((__TEXT("Err %ld, could not recreate view of profile %s\n"),
  2620. GetLastError(), pProfObj->pProfileData));
  2621. return FALSE;
  2622. }
  2623. //
  2624. // Set new size
  2625. //
  2626. pProfObj->dwMapSize = dwNewSize;
  2627. }
  2628. else
  2629. {
  2630. //
  2631. // Profile is an in-memory buffer
  2632. //
  2633. PVOID pTemp = MemReAlloc(pProfObj->pView, dwNewSize);
  2634. if (!pTemp)
  2635. {
  2636. WARNING((__TEXT("Error reallocating memory\n")));
  2637. return FALSE;
  2638. }
  2639. pProfObj->pView = pProfObj->pProfileData = pTemp;
  2640. pProfObj->cbDataSize = pProfObj->dwMapSize = dwNewSize;
  2641. }
  2642. return TRUE;
  2643. }
  2644. /******************************************************************************
  2645. *
  2646. * AddTagTableEntry
  2647. *
  2648. * Function:
  2649. * This functions adds a tag to the tag table
  2650. *
  2651. * Arguments:
  2652. * pProfObj - pointer to profile object
  2653. * tagType - tag to add
  2654. * dwOffset - offset of tag data from start of file
  2655. * cbSize - size of tag data
  2656. * bNewData - TRUE if new tag is not a reference to existing data
  2657. *
  2658. * Returns:
  2659. * TRUE if successful, FALSE otherwise
  2660. *
  2661. ******************************************************************************/
  2662. BOOL AddTagTableEntry(
  2663. PPROFOBJ pProfObj,
  2664. TAGTYPE tagType,
  2665. DWORD dwOffset,
  2666. DWORD cbSize,
  2667. BOOL bNewData
  2668. )
  2669. {
  2670. PTAGDATA pTagData;
  2671. PBYTE src, dest;
  2672. DWORD nCount;
  2673. DWORD cnt, i;
  2674. //
  2675. // Get count of tag items - it is right after the profile header
  2676. //
  2677. nCount = TAG_COUNT(pProfObj);
  2678. nCount = FIX_ENDIAN(nCount);
  2679. //
  2680. // Increase count of tag elements by 1, and add new tag to end of
  2681. // tag table. Move all data below tag table downwards by the size
  2682. // of one tag table entry.
  2683. //
  2684. nCount++;
  2685. dest = (PBYTE)TAG_DATA(pProfObj) + nCount * sizeof(TAGDATA);
  2686. src = (PBYTE)TAG_DATA(pProfObj) + (nCount - 1) * sizeof(TAGDATA);
  2687. //
  2688. // # bytes to move = file size - header - tag count - tag table
  2689. //
  2690. cnt = FIX_ENDIAN(HEADER(pProfObj)->phSize) - sizeof(PROFILEHEADER) -
  2691. sizeof(DWORD) - (nCount - 1) * sizeof(TAGDATA);
  2692. if (cnt > 0)
  2693. {
  2694. //
  2695. // NOTE: CopyMemory() doesn't work for overlapped memory.
  2696. // Use internal function instead.
  2697. //
  2698. MyCopyMemory((PVOID)dest, (PVOID)src, cnt);
  2699. }
  2700. TAG_COUNT(pProfObj) = FIX_ENDIAN(nCount);
  2701. pTagData = (PTAGDATA)src;
  2702. pTagData->tagType = FIX_ENDIAN(tagType);
  2703. pTagData->cbSize = FIX_ENDIAN(cbSize);
  2704. pTagData->dwOffset = FIX_ENDIAN(dwOffset);
  2705. //
  2706. // Go through the tag table and update the offsets of all elements
  2707. // by the size of one tag table entry that we inserted.
  2708. //
  2709. pTagData = TAG_DATA(pProfObj);
  2710. for (i=0; i<nCount; i++)
  2711. {
  2712. cnt = FIX_ENDIAN(pTagData->dwOffset);
  2713. cnt += sizeof(TAGDATA);
  2714. pTagData->dwOffset = FIX_ENDIAN(cnt);
  2715. pTagData++; // Next element
  2716. }
  2717. //
  2718. // Set final file size
  2719. //
  2720. cnt = DWORD_ALIGN(FIX_ENDIAN(HEADER(pProfObj)->phSize)) + sizeof(TAGDATA);
  2721. if (bNewData)
  2722. {
  2723. //
  2724. // The new tag is not a reference to an old tag. Increment
  2725. // file size of size of new data also
  2726. //
  2727. cnt += cbSize;
  2728. }
  2729. HEADER(pProfObj)->phSize = FIX_ENDIAN(cnt);
  2730. return TRUE;
  2731. }
  2732. /******************************************************************************
  2733. *
  2734. * AddTaggedElement
  2735. *
  2736. * Function:
  2737. * This functions adds a new tagged element to a profile
  2738. *
  2739. * Arguments:
  2740. * pProfObj - pointer to profile object
  2741. * tagType - tag to add
  2742. * cbSize - size of tag data
  2743. *
  2744. * Returns:
  2745. * TRUE if successful, FALSE otherwise
  2746. *
  2747. ******************************************************************************/
  2748. BOOL AddTaggedElement(
  2749. PPROFOBJ pProfObj,
  2750. TAGTYPE tagType,
  2751. DWORD cbSize
  2752. )
  2753. {
  2754. DWORD dwOffset, newSize;
  2755. ASSERT(pProfObj != NULL);
  2756. ASSERT(cbSize > 0);
  2757. //
  2758. // Resize the profile if needed. For memory buffers, we have to realloc,
  2759. // and for mapped objects, we have to close and reopen the view.
  2760. //
  2761. newSize = FIX_ENDIAN(HEADER(pProfObj)->phSize);
  2762. newSize = DWORD_ALIGN(newSize) + sizeof(TAGDATA) + cbSize;
  2763. //
  2764. // Check for overflow
  2765. //
  2766. if (newSize < FIX_ENDIAN(HEADER(pProfObj)->phSize) ||
  2767. newSize < cbSize)
  2768. {
  2769. WARNING((__TEXT("Overflow in adding element\n")));
  2770. SetLastError(ERROR_ARITHMETIC_OVERFLOW);
  2771. return FALSE;
  2772. }
  2773. if (newSize > pProfObj->dwMapSize)
  2774. {
  2775. if (! GrowProfile(pProfObj, newSize))
  2776. {
  2777. return FALSE;
  2778. }
  2779. }
  2780. //
  2781. // Calculate location of new data - should be DWORD aligned
  2782. //
  2783. dwOffset = FIX_ENDIAN(HEADER(pProfObj)->phSize);
  2784. dwOffset = DWORD_ALIGN(dwOffset);
  2785. return AddTagTableEntry(pProfObj, tagType, dwOffset, cbSize, TRUE);
  2786. }
  2787. /******************************************************************************
  2788. *
  2789. * DeleteTaggedElement
  2790. *
  2791. * Function:
  2792. * This functions deletes a tagged element from the profile
  2793. *
  2794. * Arguments:
  2795. * pProfObj - pointer to profile object
  2796. * pTagData - pointer to tagged element to delete
  2797. *
  2798. * Returns:
  2799. * TRUE if successful, FALSE otherwise
  2800. *
  2801. ******************************************************************************/
  2802. BOOL DeleteTaggedElement(
  2803. PPROFOBJ pProfObj,
  2804. PTAGDATA pTagData
  2805. )
  2806. {
  2807. PBYTE pData;
  2808. PTAGDATA pTemp;
  2809. DWORD cbSize, nCount, dwOffset, i;
  2810. //
  2811. // Remember location of data and move everything upto the data upwards
  2812. // by size of one tag table entry. Then move everything below the tag data
  2813. // upward by size of data plus size of one tage table entry.
  2814. //
  2815. pData = VIEW(pProfObj) + FIX_ENDIAN(pTagData->dwOffset);
  2816. cbSize = FIX_ENDIAN(pTagData->cbSize);
  2817. cbSize = DWORD_ALIGN(cbSize);
  2818. dwOffset = FIX_ENDIAN(pTagData->dwOffset);
  2819. MoveProfileData(pProfObj, (PBYTE)(pTagData+1), (PBYTE)pTagData,
  2820. (LONG)(pData-(PBYTE)(pTagData+1)), FALSE);
  2821. //
  2822. // Do not attempt to move data past the tag if we are deleting the last tag
  2823. //
  2824. if (pData + cbSize < VIEW(pProfObj) + PROFILE_SIZE(pProfObj))
  2825. {
  2826. MoveProfileData(pProfObj, pData+cbSize, pData-sizeof(TAGDATA),
  2827. PROFILE_SIZE(pProfObj)-(LONG)(pData - VIEW(pProfObj)) - cbSize, TRUE);
  2828. }
  2829. //
  2830. // Get count of tag items - it is right after the profile header, and
  2831. // decrement it by one.
  2832. //
  2833. nCount = TAG_COUNT(pProfObj);
  2834. nCount = FIX_ENDIAN(nCount) - 1;
  2835. TAG_COUNT(pProfObj) = FIX_ENDIAN(nCount);
  2836. //
  2837. // Go through the tag table and update the pointers
  2838. //
  2839. pTemp = TAG_DATA(pProfObj);
  2840. for (i=0; i<nCount; i++)
  2841. {
  2842. DWORD dwTemp = FIX_ENDIAN(pTemp->dwOffset);
  2843. if (dwTemp > dwOffset)
  2844. {
  2845. dwTemp -= cbSize; // cbSize already DWORD aligned
  2846. }
  2847. dwTemp -= sizeof(TAGDATA);
  2848. pTemp->dwOffset = FIX_ENDIAN(dwTemp);
  2849. pTemp++; // Next record
  2850. }
  2851. //
  2852. // Use nCount as a placeholder to calculate file size
  2853. //
  2854. nCount = DWORD_ALIGN(FIX_ENDIAN(HEADER(pProfObj)->phSize));
  2855. nCount -= sizeof(TAGDATA) + cbSize;
  2856. HEADER(pProfObj)->phSize = FIX_ENDIAN(nCount);
  2857. return TRUE;
  2858. }
  2859. /******************************************************************************
  2860. *
  2861. * ChangeTaggedElementSize
  2862. *
  2863. * Function:
  2864. * This functions changes the size of a tagged element in the profile
  2865. *
  2866. * Arguments:
  2867. * pProfObj - pointer to profile object
  2868. * pTagData - pointer to tagged element whose size is to be changed
  2869. * cbSize - new size for the element
  2870. *
  2871. * Returns:
  2872. * TRUE if successful, FALSE otherwise
  2873. *
  2874. ******************************************************************************/
  2875. BOOL ChangeTaggedElementSize(
  2876. PPROFOBJ pProfObj,
  2877. PTAGDATA pTagData,
  2878. DWORD cbSize
  2879. )
  2880. {
  2881. PTAGDATA pTemp;
  2882. PBYTE pData;
  2883. DWORD nCount, cbOldSize;
  2884. DWORD dwOffset, cnt, i;
  2885. ASSERT(pProfObj != NULL);
  2886. ASSERT(cbSize > 0);
  2887. //
  2888. // Get current size of element
  2889. //
  2890. cbOldSize = FIX_ENDIAN(pTagData->cbSize);
  2891. if (cbOldSize == cbSize)
  2892. {
  2893. return TRUE; // Sizes are the same - Do nothing
  2894. }
  2895. pData = VIEW(pProfObj) + FIX_ENDIAN(pTagData->dwOffset);
  2896. //
  2897. // Do not attempt to move data beyond end of file. There is no need to move
  2898. // anything if the last data item is being resized.
  2899. //
  2900. if (pData + DWORD_ALIGN(cbOldSize) < VIEW(pProfObj) + PROFILE_SIZE(pProfObj))
  2901. {
  2902. MoveProfileData(pProfObj, pData + DWORD_ALIGN(cbOldSize), pData + DWORD_ALIGN(cbSize),
  2903. PROFILE_SIZE(pProfObj) - (LONG)(pData - VIEW(pProfObj)) - DWORD_ALIGN(cbOldSize), TRUE);
  2904. }
  2905. pTagData->cbSize = FIX_ENDIAN(cbSize); // Set the new size
  2906. //
  2907. // Get count of tag items - it is right after the profile header
  2908. //
  2909. nCount = TAG_COUNT(pProfObj);
  2910. nCount = FIX_ENDIAN(nCount);
  2911. //
  2912. // Go through the tag table and update the pointers
  2913. //
  2914. pTemp = TAG_DATA(pProfObj);
  2915. dwOffset = FIX_ENDIAN(pTagData->dwOffset);
  2916. for (i=0; i<nCount; i++)
  2917. {
  2918. DWORD dwTemp = FIX_ENDIAN(pTemp->dwOffset);
  2919. if (dwTemp > dwOffset)
  2920. {
  2921. dwTemp += DWORD_ALIGN(cbSize) - DWORD_ALIGN(cbOldSize);
  2922. pTemp->dwOffset = FIX_ENDIAN(dwTemp);
  2923. }
  2924. pTemp++; // Next record
  2925. }
  2926. //
  2927. // Use cnt as a placeholder to calculate file size
  2928. //
  2929. cnt = FIX_ENDIAN(HEADER(pProfObj)->phSize);
  2930. cnt += DWORD_ALIGN(cbSize) - DWORD_ALIGN(cbOldSize);
  2931. HEADER(pProfObj)->phSize = FIX_ENDIAN(cnt);
  2932. return TRUE;
  2933. }
  2934. /******************************************************************************
  2935. *
  2936. * MoveProfileData
  2937. *
  2938. * Function:
  2939. * This function moves data in a profile up or down (from src to dest),
  2940. * and then zeroes out the end of the file or the extra space created.
  2941. *
  2942. * Arguments:
  2943. * pProfObj - pointer to profile object
  2944. * src - pointer to source of block to move
  2945. * dest - pointer to destination for block to move to
  2946. * cnt - number of bytes to move
  2947. *
  2948. * Returns:
  2949. * TRUE if successful, FALSE otherwise
  2950. *
  2951. ******************************************************************************/
  2952. void MoveProfileData(
  2953. PPROFOBJ pProfObj,
  2954. PBYTE src,
  2955. PBYTE dest,
  2956. LONG cnt,
  2957. BOOL bZeroMemory
  2958. )
  2959. {
  2960. //
  2961. // NOTE: CopyMemory() doesn't work for overlapped memory.
  2962. // Use internal function instead.
  2963. //
  2964. MyCopyMemory((PVOID)dest, (PVOID)src, cnt);
  2965. if (bZeroMemory)
  2966. {
  2967. cnt = ABS((LONG)(dest - src));
  2968. if (dest < src)
  2969. {
  2970. //
  2971. // Size decreased, so zero out end of file
  2972. //
  2973. dest = VIEW(pProfObj) + FIX_ENDIAN(HEADER(pProfObj)->phSize) -
  2974. (src - dest);
  2975. }
  2976. else
  2977. {
  2978. //
  2979. // Size increased, so zero out the increased tagdata
  2980. //
  2981. dest = src;
  2982. }
  2983. ZeroMemory(dest, cnt);
  2984. }
  2985. return;
  2986. }
  2987. /******************************************************************************
  2988. *
  2989. * IsReferenceTag
  2990. *
  2991. * Function:
  2992. * This function checks if a given tag's data is referred to by another
  2993. * tag in the profile
  2994. *
  2995. * Arguments:
  2996. * pProfObj - pointer to profile object
  2997. * pTagData - pointer to tagdata which should be checked
  2998. *
  2999. * Returns:
  3000. * TRUE if it is a referece, FALSE otherwise
  3001. *
  3002. ******************************************************************************/
  3003. BOOL IsReferenceTag(
  3004. PPROFOBJ pProfObj,
  3005. PTAGDATA pTagData
  3006. )
  3007. {
  3008. PTAGDATA pTemp;
  3009. DWORD nCount, i;
  3010. BOOL bReference = FALSE;
  3011. pTemp = TAG_DATA(pProfObj);
  3012. nCount = TAG_COUNT(pProfObj);
  3013. nCount = FIX_ENDIAN(nCount);
  3014. for (i=0; i<nCount; i++)
  3015. {
  3016. if ((pTagData->dwOffset == pTemp->dwOffset) &&
  3017. (pTagData->tagType != pTemp->tagType))
  3018. {
  3019. bReference = TRUE;
  3020. break;
  3021. }
  3022. pTemp++; // next record
  3023. }
  3024. return bReference;
  3025. }