Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

profile.c

Go to the documentation of this file.
00001 /****************************Module*Header******************************\ 00002 * Module Name: PROFILE.C 00003 * 00004 * Module Descripton: Profile data manipulation functions 00005 * 00006 * Warnings: 00007 * 00008 * Issues: 00009 * 00010 * Public Routines: 00011 * 00012 * Created: 11 January 1996 00013 * Author: Srinivasan Chandrasekar [srinivac] 00014 * 00015 * Copyright (c) 1996, 1997 Microsoft Corporation 00016 \***********************************************************************/ 00017 00018 #include "mscms.h" 00019 00020 #define PROFILE_GROWTHCUSHION 16*1024 00021 00022 // 00023 // Local functions 00024 // 00025 00026 HPROFILE InternalOpenColorProfile(PPROFILE, DWORD, DWORD, DWORD); 00027 BOOL InternalCreateProfileFromLCS(LPLOGCOLORSPACE, PBYTE*, BOOL); 00028 BOOL FreeProfileObject(HPROFILE); 00029 BOOL AddTagTableEntry(PPROFOBJ, TAGTYPE, DWORD, DWORD, BOOL); 00030 BOOL AddTaggedElement(PPROFOBJ, TAGTYPE, DWORD); 00031 BOOL DeleteTaggedElement(PPROFOBJ, PTAGDATA); 00032 BOOL ChangeTaggedElementSize(PPROFOBJ, PTAGDATA, DWORD); 00033 BOOL GrowProfile(PPROFOBJ, DWORD); 00034 void MoveProfileData(PPROFOBJ, PBYTE, PBYTE, LONG, BOOL); 00035 BOOL IsReferenceTag(PPROFOBJ, PTAGDATA); 00036 00037 00038 /****************************************************************************** 00039 * 00040 * OpenColorProfile 00041 * 00042 * Function: 00043 * These are the ANSI & Unicode wrappers for InternalOpenColorProfile. 00044 * Please see InternalOpenColorProfile for more details on this function. 00045 * 00046 * Returns: 00047 * Handle to open profile on success, zero on failure. 00048 * 00049 ******************************************************************************/ 00050 00051 #ifdef UNICODE // Windows NT versions 00052 00053 HPROFILE WINAPI OpenColorProfileA( 00054 PPROFILE pProfile, 00055 DWORD dwDesiredAccess, 00056 DWORD dwShareMode, 00057 DWORD dwCreationMode 00058 ) 00059 { 00060 PROFILE wProfile; // Unicode version 00061 HPROFILE rc = NULL; 00062 00063 // 00064 // Validate parameters before touching them 00065 // 00066 00067 if (!pProfile || 00068 IsBadReadPtr(pProfile, sizeof(PROFILE)) || 00069 (pProfile->pProfileData && 00070 IsBadReadPtr(pProfile->pProfileData, pProfile->cbDataSize)) || 00071 (!pProfile->pProfileData && 00072 (pProfile->cbDataSize != 0)) || 00073 (pProfile->dwType != PROFILE_FILENAME && 00074 pProfile->dwType != PROFILE_MEMBUFFER 00075 ) 00076 ) 00077 { 00078 WARNING((__TEXT("Invalid parameter to OpenColorProfile\n"))); 00079 SetLastError(ERROR_INVALID_PARAMETER); 00080 return NULL; 00081 } 00082 00083 if (pProfile->dwType == PROFILE_FILENAME) 00084 { 00085 // 00086 // Convert the profile name to Unicode and call the Unicode version 00087 // 00088 00089 wProfile.dwType = pProfile->dwType; 00090 00091 if (!pProfile->pProfileData || pProfile->cbDataSize == 0) 00092 { 00093 WARNING((__TEXT("Invalid parameter to OpenColorProfile\n"))); 00094 SetLastError(ERROR_INVALID_PARAMETER); 00095 return NULL; 00096 } 00097 00098 wProfile.pProfileData = (WCHAR*)MemAlloc(pProfile->cbDataSize * sizeof(WCHAR)); 00099 if (!wProfile.pProfileData) 00100 { 00101 WARNING((__TEXT("Error allocating memory for Unicode profile structure\n"))); 00102 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 00103 return NULL; 00104 } 00105 00106 if (! MultiByteToWideChar(CP_ACP, 0, pProfile->pProfileData, pProfile->cbDataSize, 00107 wProfile.pProfileData, pProfile->cbDataSize)) 00108 { 00109 WARNING((__TEXT("Error converting profile structure to Unicode\n"))); 00110 goto EndOpenColorProfileA; 00111 } 00112 00113 wProfile.cbDataSize = pProfile->cbDataSize * sizeof(WCHAR); 00114 } 00115 else 00116 { 00117 // 00118 // It is a memory based profile, so no ANSI/Unicode conversion 00119 // 00120 00121 wProfile = *pProfile; 00122 } 00123 00124 rc = InternalOpenColorProfile(&wProfile, dwDesiredAccess, 00125 dwShareMode, dwCreationMode); 00126 00127 EndOpenColorProfileA: 00128 if (pProfile->dwType == PROFILE_FILENAME) 00129 { 00130 MemFree(wProfile.pProfileData); 00131 } 00132 00133 return rc; 00134 } 00135 00136 HPROFILE WINAPI OpenColorProfileW( 00137 PPROFILE pProfile, 00138 DWORD dwDesiredAccess, 00139 DWORD dwShareMode, 00140 DWORD dwCreationMode 00141 ) 00142 { 00143 // 00144 // Internal function is Unicode in Windows NT, call it directly. 00145 // 00146 00147 return InternalOpenColorProfile(pProfile, dwDesiredAccess, 00148 dwShareMode, dwCreationMode); 00149 } 00150 00151 #else // Windows 95 versions 00152 00153 HPROFILE WINAPI OpenColorProfileA( 00154 PPROFILE pProfile, 00155 DWORD dwDesiredAccess, 00156 DWORD dwShareMode, 00157 DWORD dwCreationMode 00158 ) 00159 { 00160 // 00161 // Internal function is ANSI in Windows 95, call it directly. 00162 // 00163 00164 return InternalOpenColorProfile(pProfile, dwDesiredAccess, 00165 dwShareMode, dwCreationMode); 00166 } 00167 00168 HPROFILE WINAPI OpenColorProfileW( 00169 PPROFILE pProfile, 00170 DWORD dwDesiredAccess, 00171 DWORD dwShareMode, 00172 DWORD dwCreationMode 00173 ) 00174 { 00175 PROFILE aProfile; // ANSI version 00176 HPROFILE rc = NULL; 00177 BOOL bUsedDefaultChar; 00178 00179 // 00180 // Validate parameters before touching them 00181 // 00182 00183 if (!pProfile || 00184 IsBadReadPtr(pProfile, sizeof(PROFILE)) || 00185 (pProfile->pProfileData && 00186 IsBadReadPtr(pProfile->pProfileData, pProfile->cbDataSize)) || 00187 (!pProfile->pProfileData && 00188 (pProfile->cbDataSize != 0)) || 00189 (pProfile->dwType != PROFILE_FILENAME && 00190 pProfile->dwType != PROFILE_MEMBUFFER 00191 ) 00192 ) 00193 { 00194 WARNING((__TEXT("Invalid parameter to OpenColorProfile\n"))); 00195 SetLastError(ERROR_INVALID_PARAMETER); 00196 return NULL; 00197 } 00198 00199 if (pProfile->dwType == PROFILE_FILENAME) 00200 { 00201 // 00202 // Convert the profile name to ANSI and call the ANSI version 00203 // 00204 00205 aProfile.dwType = pProfile->dwType; 00206 00207 if (!pProfile->pProfileData || pProfile->cbDataSize == 0) 00208 { 00209 WARNING((__TEXT("Invalid parameter to OpenColorProfile\n"))); 00210 SetLastError(ERROR_INVALID_PARAMETER); 00211 return NULL; 00212 } 00213 00214 aProfile.pProfileData = (char*)MemAlloc(pProfile->cbDataSize * sizeof(char)); 00215 if (!aProfile.pProfileData) 00216 { 00217 WARNING((__TEXT("Error allocating memory for ANSI profile structure\n"))); 00218 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 00219 return NULL; 00220 } 00221 00222 if (! WideCharToMultiByte(CP_ACP, 0, pProfile->pProfileData, pProfile->cbDataSize/sizeof(WCHAR), 00223 aProfile.pProfileData, pProfile->cbDataSize, 00224 NULL, &bUsedDefaultChar) || bUsedDefaultChar) 00225 { 00226 WARNING((__TEXT("Error converting profile structure to ANSI\n"))); 00227 goto EndOpenColorProfileW; 00228 } 00229 00230 aProfile.cbDataSize = pProfile->cbDataSize * sizeof(char); 00231 } 00232 else 00233 { 00234 // 00235 // It is a memory based profile, so no ANSI/Unicode conversion 00236 // 00237 00238 aProfile = *pProfile; 00239 } 00240 00241 rc = InternalOpenColorProfile(&aProfile, dwDesiredAccess, 00242 dwShareMode, dwCreationMode); 00243 00244 EndOpenColorProfileW: 00245 if (pProfile->dwType == PROFILE_FILENAME) 00246 { 00247 MemFree(aProfile.pProfileData); 00248 } 00249 00250 return rc; 00251 } 00252 00253 #endif // ! UNICODE 00254 00255 /****************************************************************************** 00256 * 00257 * CloseColorProfile 00258 * 00259 * Function: 00260 * This functions closes a color profile object, and frees all memory 00261 * associated with it. 00262 * 00263 * Arguments: 00264 * hProfile - handle identifing the profile object 00265 * 00266 * Returns: 00267 * TRUE if successful, FALSE otherwise 00268 * 00269 ******************************************************************************/ 00270 00271 BOOL WINAPI CloseColorProfile( 00272 HPROFILE hProfile 00273 ) 00274 { 00275 TRACEAPI((__TEXT("CloseColorProfile\n"))); 00276 00277 // 00278 // Validate parameters 00279 // 00280 00281 if (!ValidHandle(hProfile, OBJ_PROFILE)) 00282 { 00283 WARNING((__TEXT("Invalid parameter to CloseColorProfile\n"))); 00284 SetLastError(ERROR_INVALID_PARAMETER); 00285 return FALSE; 00286 } 00287 00288 return FreeProfileObject(hProfile); 00289 } 00290 00291 00292 /****************************************************************************** 00293 * 00294 * GetColorProfileFromHandle 00295 * 00296 * Function: 00297 * This functions returns a buffer filled with the profile contents. 00298 * 00299 * Arguments: 00300 * hProfile - handle identifing the profile object 00301 * pProfileData - pointer to buffer to receive the data. Can be NULL. 00302 * pcbData - pointer to size of buffer. On return it is size 00303 * filled/needed. 00304 * 00305 * Returns: 00306 * TRUE if successful, FALSE otherwise 00307 * 00308 ******************************************************************************/ 00309 00310 BOOL WINAPI GetColorProfileFromHandle( 00311 HPROFILE hProfile, 00312 PBYTE pProfileData, 00313 PDWORD pcbSize 00314 ) 00315 { 00316 PPROFOBJ pProfObj; 00317 DWORD dwFileSize; 00318 BOOL rc = FALSE; 00319 00320 // 00321 // ValidatePrameters 00322 // 00323 00324 if (!ValidHandle(hProfile, OBJ_PROFILE) || 00325 !pcbSize || 00326 IsBadWritePtr(pcbSize, sizeof(DWORD)) || 00327 (pProfileData && 00328 IsBadWritePtr(pProfileData, *pcbSize))) 00329 { 00330 WARNING((__TEXT("Invalid parameter to CloseColorProfile\n"))); 00331 SetLastError(ERROR_INVALID_PARAMETER); 00332 return FALSE; 00333 } 00334 00335 pProfObj = (PPROFOBJ)HDLTOPTR(hProfile); 00336 00337 ASSERT(pProfObj != NULL); 00338 00339 dwFileSize = FIX_ENDIAN(HEADER(pProfObj)->phSize); 00340 00341 if (pProfileData && *pcbSize >= dwFileSize) 00342 { 00343 CopyMemory(pProfileData, pProfObj->pView, dwFileSize); 00344 rc = TRUE; 00345 } 00346 else 00347 { 00348 SetLastError(ERROR_INSUFFICIENT_BUFFER); 00349 } 00350 00351 *pcbSize = dwFileSize; 00352 00353 return rc; 00354 } 00355 00356 00357 /****************************************************************************** 00358 * 00359 * IsColorProfileValid 00360 * 00361 * Function: 00362 * This functions checks if a given profile is a valid ICC profile 00363 * that can be used for color matching 00364 * 00365 * Arguments: 00366 * hProfile - handle identifing the profile object 00367 * pbValid - Pointer to variable that receives TRUE if it is a 00368 * valid profile, FALSE otherwise 00369 * 00370 * Returns: 00371 * TRUE if successful, FALSE otherwise 00372 * 00373 ******************************************************************************/ 00374 00375 BOOL WINAPI IsColorProfileValid( 00376 HPROFILE hProfile, 00377 PBOOL pbValid 00378 ) 00379 { 00380 PPROFOBJ pProfObj; 00381 PCMMOBJ pCMMObj; 00382 DWORD cmmID; 00383 BOOL rc = FALSE; 00384 00385 TRACEAPI((__TEXT("IsColorProfileValid\n"))); 00386 00387 // 00388 // Validate parameters 00389 // 00390 00391 if (!ValidHandle(hProfile, OBJ_PROFILE) || 00392 !pbValid || 00393 IsBadWritePtr(pbValid, sizeof(BOOL))) 00394 { 00395 WARNING((__TEXT("Invalid parameter to IsColorProfileValid\n"))); 00396 SetLastError(ERROR_INVALID_PARAMETER); 00397 return FALSE; 00398 } 00399 00400 pProfObj = (PPROFOBJ)HDLTOPTR(hProfile); 00401 00402 ASSERT(pProfObj != NULL); 00403 00404 // 00405 // Quick check on the integrity of the profile before calling the CMM 00406 // 00407 00408 if (!ValidProfile(pProfObj)) 00409 { 00410 *pbValid = FALSE; 00411 return TRUE; 00412 } 00413 00414 // 00415 // Get CMM associated with profile. If it does not exist or does not 00416 // support the CMValidate function, get default CMM. 00417 // 00418 00419 cmmID = HEADER(pProfObj)->phCMMType; 00420 cmmID = FIX_ENDIAN(cmmID); 00421 00422 pCMMObj = GetColorMatchingModule(cmmID); 00423 if (!pCMMObj || !pCMMObj->fns.pCMIsProfileValid) 00424 { 00425 TERSE((__TEXT("CMM associated with profile could not be used"))); 00426 00427 if (pCMMObj) 00428 { 00429 ReleaseColorMatchingModule(pCMMObj); 00430 } 00431 00432 pCMMObj = GetColorMatchingModule(CMM_WINDOWS_DEFAULT); 00433 if (!pCMMObj || !pCMMObj->fns.pCMIsProfileValid) 00434 { 00435 RIP((__TEXT("Default CMM doesn't support CMValidateProfile"))); 00436 SetLastError(ERROR_INVALID_CMM); 00437 goto EndIsColorProfileValid; 00438 } 00439 } 00440 00441 ASSERT(pProfObj->pView != NULL); 00442 rc = pCMMObj->fns.pCMIsProfileValid(hProfile, pbValid); 00443 00444 EndIsColorProfileValid: 00445 00446 if (pCMMObj) 00447 { 00448 ReleaseColorMatchingModule(pCMMObj); 00449 } 00450 00451 return rc; 00452 } 00453 00454 00455 /****************************************************************************** 00456 * 00457 * CreateProfileFromLogColorSpace 00458 * 00459 * Function: 00460 * These are the ANSI & Unicode wrappers for InternalCreateProfileFromLCS. 00461 * Please see InternalCreateProfileFromLCS for more details on this 00462 * function. 00463 * 00464 * Returns: 00465 * TRUE if successful, FALSE otherwise 00466 * 00467 ******************************************************************************/ 00468 00469 #ifdef UNICODE // Windows NT versions 00470 00471 BOOL WINAPI CreateProfileFromLogColorSpaceA( 00472 LPLOGCOLORSPACEA pLogColorSpace, 00473 PBYTE *pBuffer 00474 ) 00475 { 00476 LOGCOLORSPACEW lcs; 00477 00478 // 00479 // Validate Parameters 00480 // 00481 00482 if (! pLogColorSpace || 00483 IsBadReadPtr(pLogColorSpace, sizeof(LOGCOLORSPACEA)) || 00484 pLogColorSpace->lcsFilename[0] != '\0') 00485 { 00486 WARNING((__TEXT("Invalid parameter to CreateProfileFromLogColorSpace\n"))); 00487 SetLastError(ERROR_INVALID_PARAMETER); 00488 return FALSE; 00489 } 00490 00491 *((LPLOGCOLORSPACEA)&lcs) = *pLogColorSpace; 00492 lcs.lcsFilename[0] = '\0'; 00493 00494 return InternalCreateProfileFromLCS(&lcs, pBuffer, FALSE); 00495 } 00496 00497 BOOL WINAPI CreateProfileFromLogColorSpaceW( 00498 LPLOGCOLORSPACEW pLogColorSpace, 00499 PBYTE *pBuffer 00500 ) 00501 { 00502 // 00503 // Internal function is Unicode in Windows NT, call it directly. 00504 // 00505 00506 return InternalCreateProfileFromLCS(pLogColorSpace, pBuffer, TRUE); 00507 } 00508 00509 #else // Windows 95 versions 00510 00511 BOOL WINAPI CreateProfileFromLogColorSpaceA( 00512 LPLOGCOLORSPACEA pLogColorSpace, 00513 PBYTE *pBuffer 00514 ) 00515 { 00516 // 00517 // Internal function is ANSI in Windows 95, call it directly. 00518 // 00519 00520 return InternalCreateProfileFromLCS(pLogColorSpace, pBuffer, TRUE); 00521 } 00522 00523 BOOL WINAPI CreateProfileFromLogColorSpaceW( 00524 LPLOGCOLORSPACEW pLogColorSpace, 00525 PBYTE *pBuffer 00526 ) 00527 { 00528 LOGCOLORSPACEA lcs; 00529 00530 // 00531 // Validate Parameters 00532 // 00533 00534 if (! pLogColorSpace || 00535 IsBadReadPtr(pLogColorSpace, sizeof(LOGCOLORSPACEW)) || 00536 pLogColorSpace->lcsFilename[0] != '\0') 00537 { 00538 WARNING((__TEXT("Invalid parameter to CreateProfileFromLogColorSpace\n"))); 00539 SetLastError(ERROR_INVALID_PARAMETER); 00540 return FALSE; 00541 } 00542 00543 lcs = *((LPLOGCOLORSPACEA)pLogColorSpace); 00544 lcs.lcsFilename[0] = '\0'; 00545 00546 return InternalCreateProfileFromLCS(&lcs, pBuffer, FALSE); 00547 } 00548 00549 #endif // ! UNICODE 00550 00551 /****************************************************************************** 00552 * 00553 * IsColorProfileTagPresent 00554 * 00555 * Function: 00556 * This functions checks if a given tag is present in the profile 00557 * 00558 * Arguments: 00559 * hProfile - handle identifing the profile object 00560 * tagType - the tag to check for 00561 * pbPrent - pointer to variable that receives TRUE if it the tag is 00562 * present, FALSE otherwise 00563 * 00564 * Returns: 00565 * TRUE if successful, FALSE otherwise 00566 * 00567 ******************************************************************************/ 00568 00569 BOOL WINAPI IsColorProfileTagPresent( 00570 HPROFILE hProfile, 00571 TAGTYPE tagType, 00572 PBOOL pbPresent 00573 ) 00574 { 00575 PPROFOBJ pProfObj; 00576 PTAGDATA pTagData; 00577 DWORD nCount, i; 00578 00579 TRACEAPI((__TEXT("IsColorProfileTagPresent\n"))); 00580 00581 // 00582 // Validate parameters 00583 // 00584 00585 if (!ValidHandle(hProfile, OBJ_PROFILE) || 00586 !pbPresent || 00587 IsBadWritePtr(pbPresent, sizeof(BOOL))) 00588 { 00589 WARNING((__TEXT("Invalid parameter to IsColorProfileTagPresent\n"))); 00590 SetLastError(ERROR_INVALID_PARAMETER); 00591 return FALSE; 00592 } 00593 00594 pProfObj = (PPROFOBJ)HDLTOPTR(hProfile); 00595 00596 ASSERT(pProfObj != NULL); 00597 00598 // 00599 // Check the integrity of the profile 00600 // 00601 00602 if (!ValidProfile(pProfObj)) 00603 { 00604 WARNING((__TEXT("Invalid profile passed to IsColorProfileTagPresent\n"))); 00605 SetLastError(ERROR_INVALID_PROFILE); 00606 return FALSE; 00607 } 00608 00609 // 00610 // Get count of tag items - it is right after the profile header 00611 // 00612 00613 nCount = TAG_COUNT(pProfObj); 00614 nCount = FIX_ENDIAN(nCount); 00615 00616 VERBOSE((__TEXT("Profile 0x%x has 0x%x(%d) tags\n"), hProfile, nCount, nCount)); 00617 00618 // 00619 // Tag data records follow the count. 00620 // 00621 00622 pTagData = TAG_DATA(pProfObj); 00623 00624 // 00625 // Check if any of these records match the tag passed in. 00626 // 00627 00628 *pbPresent = FALSE; 00629 tagType = FIX_ENDIAN(tagType); // to match tags in profile 00630 for (i=0; i<nCount; i++) 00631 { 00632 if (pTagData->tagType == tagType) 00633 { 00634 *pbPresent = TRUE; 00635 break; 00636 } 00637 pTagData++; // Next record 00638 } 00639 00640 return TRUE; 00641 } 00642 00643 00644 /****************************************************************************** 00645 * 00646 * GetCountColorProfileElements 00647 * 00648 * Function: 00649 * This functions returns the number of tagged elements in the profile 00650 * 00651 * Arguments: 00652 * hProfile - handle identifing the profile object 00653 * pnCount - pointer to variable to receive number of tagged elements 00654 * Returns: 00655 * TRUE if successful, FALSE otherwise 00656 * 00657 ******************************************************************************/ 00658 00659 BOOL WINAPI GetCountColorProfileElements( 00660 HPROFILE hProfile, 00661 PDWORD pnCount 00662 ) 00663 { 00664 PPROFOBJ pProfObj; 00665 00666 TRACEAPI((__TEXT("GetCountColorProfileElements\n"))); 00667 00668 // 00669 // Validate parameters 00670 // 00671 00672 if (!ValidHandle(hProfile, OBJ_PROFILE) || 00673 !pnCount || 00674 IsBadWritePtr(pnCount, sizeof(DWORD))) 00675 { 00676 WARNING((__TEXT("Invalid parameter to GetCountColorProfileElements\n"))); 00677 SetLastError(ERROR_INVALID_PARAMETER); 00678 return FALSE; 00679 } 00680 00681 pProfObj = (PPROFOBJ)HDLTOPTR(hProfile); 00682 00683 ASSERT(pProfObj != NULL); 00684 00685 // 00686 // Check the integrity of the profile 00687 // 00688 00689 if (!ValidProfile(pProfObj)) 00690 { 00691 WARNING((__TEXT("Invalid profile passed to GetCountColorProfileElements\n"))); 00692 SetLastError(ERROR_INVALID_PROFILE); 00693 return FALSE; 00694 } 00695 00696 // 00697 // Get count of tag items - it is right after the profile header 00698 // 00699 00700 *pnCount = TAG_COUNT(pProfObj); 00701 *pnCount = FIX_ENDIAN(*pnCount); 00702 00703 return TRUE; 00704 } 00705 00706 00707 /****************************************************************************** 00708 * 00709 * GetColorProfileElementTag 00710 * 00711 * Function: 00712 * This functions retrieves the tag name of the dwIndex'th element 00713 * in the profile 00714 * 00715 * Arguments: 00716 * hProfile - handle identifing the profile object 00717 * dwIndex - one-based index of the tag whose name is required 00718 * pTagType - gets the name of the tag on return 00719 * 00720 * Returns: 00721 * TRUE if successful, FALSE otherwise 00722 * 00723 ******************************************************************************/ 00724 00725 BOOL WINAPI GetColorProfileElementTag( 00726 HPROFILE hProfile, 00727 DWORD dwIndex, 00728 PTAGTYPE pTagType 00729 ) 00730 { 00731 PPROFOBJ pProfObj; 00732 PTAGDATA pTagData; 00733 DWORD nCount; 00734 BOOL rc = FALSE; 00735 00736 TRACEAPI((__TEXT("GetColorProfileElementTag\n"))); 00737 00738 // 00739 // Validate parameters 00740 // 00741 00742 if (!ValidHandle(hProfile, OBJ_PROFILE) || 00743 IsBadWritePtr(pTagType, sizeof(TAGTYPE)) || 00744 dwIndex <= 0) 00745 { 00746 WARNING((__TEXT("Invalid parameter to GetColorProfileElementTag\n"))); 00747 SetLastError(ERROR_INVALID_PARAMETER); 00748 return FALSE; 00749 } 00750 00751 pProfObj = (PPROFOBJ)HDLTOPTR(hProfile); 00752 00753 ASSERT(pProfObj != NULL); 00754 00755 // 00756 // Check the integrity of the profile 00757 // 00758 00759 if (!ValidProfile(pProfObj)) 00760 { 00761 WARNING((__TEXT("Invalid profile passed to GetColorProfileElementTag\n"))); 00762 SetLastError(ERROR_INVALID_PROFILE); 00763 return FALSE; 00764 } 00765 00766 // 00767 // Get count of tag items - it is right after the profile header 00768 // 00769 00770 nCount = TAG_COUNT(pProfObj); 00771 nCount = FIX_ENDIAN(nCount); 00772 00773 if (dwIndex > nCount) 00774 { 00775 WARNING((__TEXT("GetColorProfileElementTag:index (%d) invalid\n"), dwIndex)); 00776 SetLastError(ERROR_INVALID_PARAMETER); 00777 return FALSE; 00778 } 00779 00780 // 00781 // Tag data records follow the count. 00782 // 00783 00784 pTagData = TAG_DATA(pProfObj); 00785 00786 *pTagType = FIX_ENDIAN(pTagData[dwIndex-1].tagType); // 1-based index 00787 00788 return TRUE; 00789 } 00790 00791 00792 /****************************************************************************** 00793 * 00794 * GetColorProfileElement 00795 * 00796 * Function: 00797 * This functions retrieves the data that a tagged element refers to 00798 * starting from the given offset. 00799 * 00800 * Arguments: 00801 * hProfile - handle identifing the profile object 00802 * tagType - the tag name of the element whose data is required 00803 * dwOffset - offset within the element data from which to retrieve 00804 * pcbSize - number of bytes to get. On return it is the number of 00805 * bytes retrieved 00806 * pBuffer - pointer to buffer to recieve data 00807 * 00808 * Returns: 00809 * TRUE if successful, FALSE otherwise 00810 * 00811 * Comments: 00812 * If pBuffer is NULL, it returns size of data in *pcbSize and ignores 00813 * dwOffset. 00814 * 00815 ******************************************************************************/ 00816 00817 BOOL WINAPI GetColorProfileElement( 00818 HPROFILE hProfile, 00819 TAGTYPE tagType, 00820 DWORD dwOffset, 00821 PDWORD pcbSize, 00822 PVOID pBuffer, 00823 PBOOL pbReference 00824 ) 00825 { 00826 PPROFOBJ pProfObj; 00827 PTAGDATA pTagData; 00828 DWORD nCount, nBytes, i; 00829 BOOL found; 00830 BOOL rc = FALSE; // Assume failure 00831 00832 TRACEAPI((__TEXT("GetColorProfileElement\n"))); 00833 00834 // 00835 // Validate parameters 00836 // 00837 00838 if (!ValidHandle(hProfile, OBJ_PROFILE) || 00839 !pcbSize || 00840 IsBadWritePtr(pcbSize, sizeof(DWORD)) || 00841 !pbReference || 00842 IsBadWritePtr(pbReference, sizeof(BOOL)) 00843 ) 00844 { 00845 WARNING((__TEXT("Invalid parameter to GetColorProfileElement\n"))); 00846 SetLastError(ERROR_INVALID_PARAMETER); 00847 return FALSE; 00848 } 00849 00850 pProfObj = (PPROFOBJ)HDLTOPTR(hProfile); 00851 00852 ASSERT(pProfObj != NULL); 00853 00854 // 00855 // Check the integrity of the profile 00856 // 00857 00858 if (!ValidProfile(pProfObj)) 00859 { 00860 WARNING((__TEXT("Invalid profile passed to GetColorProfileElement\n"))); 00861 SetLastError(ERROR_INVALID_PROFILE); 00862 return FALSE; 00863 } 00864 00865 // 00866 // Get count of tag items - it is right after the profile header 00867 // 00868 00869 nCount = TAG_COUNT(pProfObj); 00870 nCount = FIX_ENDIAN(nCount); 00871 00872 // 00873 // Tag data records follow the count. 00874 // 00875 00876 pTagData = TAG_DATA(pProfObj); 00877 00878 // 00879 // Check if any of these records match the tag passed in. 00880 // 00881 00882 found = FALSE; 00883 tagType = FIX_ENDIAN(tagType); // to match tags in profile 00884 for (i=0; i<nCount; i++) 00885 { 00886 if (pTagData->tagType == tagType) 00887 { 00888 found = TRUE; 00889 break; 00890 } 00891 pTagData++; // next record 00892 } 00893 00894 if (found) 00895 { 00896 // 00897 // If pBuffer is NULL, copy size of data 00898 // 00899 00900 if (!pBuffer) 00901 { 00902 *pcbSize = FIX_ENDIAN(pTagData->cbSize); 00903 SetLastError(ERROR_INSUFFICIENT_BUFFER); 00904 } 00905 else 00906 { 00907 // 00908 // pBuffer is not NULL, get number of bytes to copy 00909 // 00910 00911 if (dwOffset >= FIX_ENDIAN(pTagData->cbSize)) 00912 { 00913 WARNING((__TEXT("dwOffset too large for GetColorProfileElement\n"))); 00914 SetLastError(ERROR_INVALID_PARAMETER); 00915 return FALSE; 00916 } 00917 else if (dwOffset + *pcbSize > FIX_ENDIAN(pTagData->cbSize)) 00918 { 00919 nBytes = FIX_ENDIAN(pTagData->cbSize) - dwOffset; 00920 } 00921 else 00922 { 00923 nBytes = *pcbSize; 00924 } 00925 00926 // 00927 // Check if output buffer is large enough 00928 // 00929 00930 if (IsBadWritePtr(pBuffer, nBytes)) 00931 { 00932 WARNING((__TEXT("Bad buffer passed to GetColorProfileElement\n"))); 00933 SetLastError(ERROR_INVALID_PARAMETER); 00934 return FALSE; 00935 } 00936 00937 // 00938 // Copy the data into user supplied buffer 00939 // 00940 00941 CopyMemory((PVOID)pBuffer, 00942 (PVOID)(pProfObj->pView + FIX_ENDIAN(pTagData->dwOffset) 00943 + dwOffset), nBytes); 00944 *pcbSize = nBytes; 00945 rc = TRUE; // Success! 00946 } 00947 00948 // 00949 // Check if multiple tags reference this tag's data 00950 // 00951 00952 *pbReference = IsReferenceTag(pProfObj, pTagData); 00953 } 00954 else 00955 { 00956 SetLastError(ERROR_TAG_NOT_FOUND); 00957 } 00958 00959 return rc; 00960 } 00961 00962 00963 /****************************************************************************** 00964 * 00965 * SetColorProfileElementSize 00966 * 00967 * Function: 00968 * This functions sets the data size of a tagged element. If the element 00969 * is already present in the profile it's size is changed, and the data 00970 * is truncated or extended as the case may be. If the element is not 00971 * present, it is created and the data is filled with zeroes. 00972 * 00973 * Arguments: 00974 * hProfile - handle identifing the profile object 00975 * tagType - the tag name of the element 00976 * cbSize - new size for the element data 00977 * 00978 * Returns: 00979 * TRUE if successful, FALSE otherwise 00980 * 00981 * Comments: 00982 * If cbSize is 0, and the element is present, it is deleted. 00983 * 00984 ******************************************************************************/ 00985 00986 BOOL WINAPI SetColorProfileElementSize( 00987 HPROFILE hProfile, 00988 TAGTYPE tagType, 00989 DWORD cbSize 00990 ) 00991 { 00992 PTAGDATA pTagData; 00993 PPROFOBJ pProfObj; 00994 DWORD i, nCount, newSize; 00995 TAGTYPE rawTag; 00996 BOOL found, rc = FALSE; 00997 00998 TRACEAPI((__TEXT("SetColorProfileElementSize\n"))); 00999 01000 // 01001 // Validate parameters 01002 // 01003 01004 if (!ValidHandle(hProfile, OBJ_PROFILE)) 01005 { 01006 WARNING((__TEXT("Invalid parameter to SetColorProfileElementSize\n"))); 01007 SetLastError(ERROR_INVALID_PARAMETER); 01008 return FALSE; 01009 } 01010 01011 pProfObj = (PPROFOBJ)HDLTOPTR(hProfile); 01012 01013 ASSERT(pProfObj != NULL); 01014 01015 // 01016 // Check the integrity of the profile 01017 // 01018 01019 if (!ValidProfile(pProfObj)) 01020 { 01021 WARNING((__TEXT("Invalid profile passed to SetColorProfileElementSize\n"))); 01022 SetLastError(ERROR_INVALID_PROFILE); 01023 return FALSE; 01024 } 01025 01026 // 01027 // Check if profile has write access 01028 // 01029 01030 if (!(pProfObj->dwFlags & READWRITE_ACCESS)) 01031 { 01032 WARNING((__TEXT("Writing to a profile without read/write access\n"))); 01033 SetLastError(ERROR_ACCESS_DENIED); 01034 return FALSE; 01035 } 01036 01037 // 01038 // Get count of tag items - it is right after the profile header 01039 // 01040 01041 nCount = TAG_COUNT(pProfObj); 01042 nCount = FIX_ENDIAN(nCount); 01043 01044 // 01045 // Tag data records follow the count. 01046 // 01047 01048 pTagData = TAG_DATA(pProfObj); 01049 01050 // 01051 // Check if any of these records match the tag passed in. 01052 // 01053 01054 found = FALSE; 01055 rawTag = FIX_ENDIAN(tagType); 01056 for (i=0; i<nCount; i++) 01057 { 01058 if (pTagData->tagType == rawTag) 01059 { 01060 found = TRUE; 01061 break; 01062 } 01063 pTagData++; // Next record 01064 } 01065 01066 if (found) 01067 { 01068 // 01069 // If it is a reference tag, create data area for it 01070 // 01071 01072 if (IsReferenceTag(pProfObj, pTagData)) 01073 { 01074 if (cbSize == 0) 01075 { 01076 PTAGDATA pTemp; 01077 01078 // 01079 // Move everything after the tag table entry up 01080 // by size of one tag table entry. 01081 // 01082 01083 MoveProfileData(pProfObj, (PBYTE)(pTagData+1), (PBYTE)pTagData, 01084 PROFILE_SIZE(pProfObj) - (LONG)((PBYTE)(pTagData+1) - VIEW(pProfObj)), TRUE); 01085 01086 // 01087 // Go through the tag table and update the pointers 01088 // 01089 01090 pTemp = TAG_DATA(pProfObj); 01091 01092 // 01093 // Get count of tag items - it is right after the profile header 01094 // 01095 01096 nCount = TAG_COUNT(pProfObj); 01097 nCount = FIX_ENDIAN(nCount) - 1; 01098 TAG_COUNT(pProfObj) = FIX_ENDIAN(nCount); 01099 01100 for (i=0; i<nCount; i++) 01101 { 01102 DWORD dwTemp = FIX_ENDIAN(pTemp->dwOffset); 01103 01104 dwTemp -= sizeof(TAGDATA); 01105 pTemp->dwOffset = FIX_ENDIAN(dwTemp); 01106 pTemp++; // Next record 01107 } 01108 01109 // 01110 // Use nCount as a placeholder to calculate file size 01111 // 01112 01113 nCount = FIX_ENDIAN(HEADER(pProfObj)->phSize) - sizeof(TAGDATA); 01114 HEADER(pProfObj)->phSize = FIX_ENDIAN(nCount); 01115 } 01116 else 01117 { 01118 DWORD dwOffset; 01119 01120 // 01121 // Resize the profile if needed. For memory buffers, we have to realloc, 01122 // and for mapped objects, we have to close and reopen the view. 01123 // 01124 01125 newSize = FIX_ENDIAN(HEADER(pProfObj)->phSize); 01126 newSize = DWORD_ALIGN(newSize) + cbSize; 01127 01128 // 01129 // Check for overflow 01130 // 01131 01132 if (newSize < FIX_ENDIAN(HEADER(pProfObj)->phSize) || 01133 newSize < cbSize) 01134 { 01135 WARNING((__TEXT("Overflow in setting reference element size\n"))); 01136 SetLastError(ERROR_ARITHMETIC_OVERFLOW); 01137 return FALSE; 01138 } 01139 01140 if (newSize > pProfObj->dwMapSize) 01141 { 01142 //Sundown: dwOffset should not be over 4gb 01143 DWORD dwOffset = (ULONG)(ULONG_PTR)(pTagData - TAG_DATA(pProfObj)); 01144 01145 if (! GrowProfile(pProfObj, newSize)) 01146 { 01147 return FALSE; 01148 } 01149 // 01150 // Recalculate pointers as mapping or memory pointer 01151 // could have changed when growing profile 01152 // 01153 01154 pTagData = TAG_DATA(pProfObj) + dwOffset; 01155 } 01156 01157 // 01158 // Calculate location of new data - should be DWORD aligned 01159 // 01160 01161 dwOffset = DWORD_ALIGN(FIX_ENDIAN(HEADER(pProfObj)->phSize)); 01162 pTagData->dwOffset = FIX_ENDIAN(dwOffset); 01163 01164 // 01165 // Set final file size 01166 // 01167 01168 HEADER(pProfObj)->phSize = FIX_ENDIAN(dwOffset+cbSize); 01169 } 01170 01171 rc = TRUE; 01172 } 01173 else 01174 { 01175 if (cbSize == 0) 01176 { 01177 rc = DeleteTaggedElement(pProfObj, pTagData); 01178 } 01179 else 01180 { 01181 DWORD cbOldSize; 01182 01183 // 01184 // Get current size of element 01185 // 01186 01187 cbOldSize = FIX_ENDIAN(pTagData->cbSize); 01188 01189 // 01190 // Compress or expand the file as the case may be. 01191 // 01192 01193 if (cbSize > cbOldSize) 01194 { 01195 //Sundown: dwOffset should be safe to truncate 01196 DWORD dwOffset = (ULONG)(ULONG_PTR)(pTagData - TAG_DATA(pProfObj)); 01197 01198 // 01199 // Check for overflow 01200 // 01201 01202 newSize = PROFILE_SIZE(pProfObj) + DWORD_ALIGN(cbSize) - 01203 DWORD_ALIGN(cbOldSize); 01204 01205 if (newSize < PROFILE_SIZE(pProfObj)) 01206 { 01207 WARNING((__TEXT("Overflow in increasing element size\n"))); 01208 SetLastError(ERROR_ARITHMETIC_OVERFLOW); 01209 return FALSE; 01210 } 01211 01212 if (!GrowProfile(pProfObj, newSize)) 01213 { 01214 return FALSE; 01215 } 01216 01217 // 01218 // Recompute pointers 01219 // 01220 01221 pTagData = TAG_DATA(pProfObj) + dwOffset; 01222 } 01223 01224 rc = ChangeTaggedElementSize(pProfObj, pTagData, cbSize); 01225 } 01226 } 01227 } 01228 else 01229 { 01230 if (cbSize == 0) 01231 { 01232 WARNING((__TEXT("SetColorProfileElementSize (deleting): Tag not found\n"))); 01233 SetLastError(ERROR_TAG_NOT_FOUND); 01234 } 01235 else 01236 { 01237 rc = AddTaggedElement(pProfObj, tagType, cbSize); 01238 } 01239 } 01240 01241 return rc; 01242 } 01243 01244 01245 /****************************************************************************** 01246 * 01247 * SetColorProfileElement 01248 * 01249 * Function: 01250 * This functions sets the data for a tagged element. It does not 01251 * change the size of the element, and only writes as much data as 01252 * would fit within the current size, overwriting any existing data. 01253 * 01254 * Arguments: 01255 * hProfile - handle identifing the profile object 01256 * tagType - the tag name of the element 01257 * dwOffset - offset within the element data from which to write 01258 * pcbSize - number of bytes to write. On return it is the number of 01259 * bytes written. 01260 * pBuffer - pointer to buffer having data to write 01261 * 01262 * Returns: 01263 * TRUE if successful, FALSE otherwise 01264 * 01265 ******************************************************************************/ 01266 01267 BOOL WINAPI SetColorProfileElement( 01268 HPROFILE hProfile, 01269 TAGTYPE tagType, 01270 DWORD dwOffset, 01271 PDWORD pcbSize, 01272 PVOID pBuffer 01273 ) 01274 { 01275 PPROFOBJ pProfObj; 01276 PTAGDATA pTagData; 01277 DWORD nCount, nBytes, i; 01278 BOOL found; 01279 BOOL rc = FALSE; // Assume failure 01280 01281 TRACEAPI((__TEXT("SetColorProfileElement\n"))); 01282 01283 // 01284 // Validate parameters 01285 // 01286 01287 if (!ValidHandle(hProfile, OBJ_PROFILE) || 01288 !pcbSize || 01289 IsBadWritePtr(pcbSize, sizeof(DWORD)) || 01290 !pBuffer || 01291 IsBadReadPtr(pBuffer, *pcbSize) 01292 ) 01293 { 01294 WARNING((__TEXT("Invalid parameter to SetColorProfileElement\n"))); 01295 SetLastError(ERROR_INVALID_PARAMETER); 01296 return FALSE; 01297 } 01298 01299 pProfObj = (PPROFOBJ)HDLTOPTR(hProfile); 01300 01301 ASSERT(pProfObj != NULL); 01302 01303 // 01304 // Check the integrity of the profile 01305 // 01306 01307 if (!ValidProfile(pProfObj)) 01308 { 01309 WARNING((__TEXT("Invalid profile passed to SetColorProfileElement\n"))); 01310 SetLastError(ERROR_INVALID_PROFILE); 01311 return FALSE; 01312 } 01313 01314 // 01315 // Check if profile has write access 01316 // 01317 01318 if (!(pProfObj->dwFlags & READWRITE_ACCESS)) 01319 { 01320 WARNING((__TEXT("Writing to a profile without read/write access\n"))); 01321 SetLastError(ERROR_ACCESS_DENIED); 01322 return FALSE; 01323 } 01324 01325 // 01326 // Get count of tag items - it is right after the profile header 01327 // 01328 01329 nCount = TAG_COUNT(pProfObj); 01330 nCount = FIX_ENDIAN(nCount); 01331 01332 // 01333 // Tag data records follow the count. 01334 // 01335 01336 pTagData = TAG_DATA(pProfObj); 01337 01338 // 01339 // Check if any of these records match the tag passed in 01340 // 01341 01342 found = FALSE; 01343 tagType = FIX_ENDIAN(tagType); 01344 for (i=0; i<nCount; i++) 01345 { 01346 if (pTagData->tagType == tagType) 01347 { 01348 found = TRUE; 01349 break; 01350 } 01351 pTagData++; // Next record 01352 } 01353 01354 if (found) 01355 { 01356 // 01357 // If it is a reference tag, create new space for it 01358 // 01359 01360 if (IsReferenceTag(pProfObj, pTagData)) 01361 { 01362 SetColorProfileElementSize(hProfile, tagType, FIX_ENDIAN(pTagData->cbSize)); 01363 } 01364 01365 // 01366 // Get number of bytes to set 01367 // 01368 01369 if (dwOffset >= FIX_ENDIAN(pTagData->cbSize)) 01370 { 01371 WARNING((__TEXT("dwOffset too large for SetColorProfileElement\n"))); 01372 SetLastError(ERROR_INVALID_PARAMETER); 01373 return FALSE; 01374 } 01375 else if (dwOffset + *pcbSize > FIX_ENDIAN(pTagData->cbSize)) 01376 { 01377 nBytes = FIX_ENDIAN(pTagData->cbSize) - dwOffset; 01378 } 01379 else 01380 { 01381 nBytes = *pcbSize; 01382 } 01383 01384 // 01385 // Copy the data into the profile 01386 // 01387 01388 CopyMemory((PVOID)(pProfObj->pView + FIX_ENDIAN(pTagData->dwOffset) 01389 + dwOffset), (PVOID)pBuffer, nBytes); 01390 *pcbSize = nBytes; 01391 01392 rc = TRUE; 01393 } 01394 else 01395 { 01396 WARNING((__TEXT("SetColorProfileElement: Tag not found\n"))); 01397 SetLastError(ERROR_TAG_NOT_FOUND); 01398 } 01399 01400 return rc; 01401 } 01402 01403 01404 /****************************************************************************** 01405 * 01406 * SetColorProfileElementReference 01407 * 01408 * Function: 01409 * This functions creates a new tag and makes it refer to the same 01410 * data as an existing tag. 01411 * 01412 * Arguments: 01413 * hProfile - handle identifing the profile object 01414 * newTag - new tag to create 01415 * refTag - reference tag whose data newTag should refer to 01416 * 01417 * Returns: 01418 * TRUE if successful, FALSE otherwise 01419 * 01420 ******************************************************************************/ 01421 01422 BOOL WINAPI SetColorProfileElementReference( 01423 HPROFILE hProfile, 01424 TAGTYPE newTag, 01425 TAGTYPE refTag 01426 ) 01427 { 01428 PPROFOBJ pProfObj; 01429 PTAGDATA pTagData, pOrigTag; 01430 DWORD nCount, i; 01431 BOOL found; 01432 BOOL rc = FALSE; // Assume failure 01433 01434 TRACEAPI((__TEXT("SetColorProfileElementReference\n"))); 01435 01436 // 01437 // Validate parameters 01438 // 01439 01440 if (!ValidHandle(hProfile, OBJ_PROFILE)) 01441 { 01442 WARNING((__TEXT("Invalid parameter to SetColorProfileElementReference\n"))); 01443 SetLastError(ERROR_INVALID_PARAMETER); 01444 return FALSE; 01445 } 01446 01447 pProfObj = (PPROFOBJ)HDLTOPTR(hProfile); 01448 01449 ASSERT(pProfObj != NULL); 01450 01451 // 01452 // Check the integrity of the profile 01453 // 01454 01455 if (!ValidProfile(pProfObj)) 01456 { 01457 WARNING((__TEXT("Invalid profile passed to SetColorProfileElementReference\n"))); 01458 SetLastError(ERROR_INVALID_PROFILE); 01459 return FALSE; 01460 } 01461 01462 // 01463 // Check if profile has write access 01464 // 01465 01466 if (!(pProfObj->dwFlags & READWRITE_ACCESS)) 01467 { 01468 WARNING((__TEXT("Writing to a profile without read/write access\n"))); 01469 SetLastError(ERROR_ACCESS_DENIED); 01470 return FALSE; 01471 } 01472 01473 // 01474 // Get count of tag items - it is right after the profile header 01475 // 01476 nCount = TAG_COUNT(pProfObj); 01477 nCount = FIX_ENDIAN(nCount); 01478 01479 // 01480 // Tag data records follow the count. 01481 // 01482 01483 pTagData = TAG_DATA(pProfObj); 01484 01485 // 01486 // Check if any of these records match the tag passed in 01487 // 01488 01489 found = FALSE; 01490 refTag = FIX_ENDIAN(refTag); 01491 for (i=0; i<nCount; i++) 01492 { 01493 if (pTagData->tagType == refTag) 01494 { 01495 pOrigTag = pTagData; 01496 found = TRUE; 01497 } 01498 01499 if (pTagData->tagType == FIX_ENDIAN(newTag)) 01500 { 01501 WARNING((__TEXT("Duplicate tag present in SetColorProfileElementReference %x\n"), newTag)); 01502 SetLastError(ERROR_DUPLICATE_TAG); 01503 return FALSE; 01504 } 01505 pTagData++; // Next record 01506 } 01507 01508 if (found) 01509 { 01510 DWORD newSize; 01511 01512 // 01513 // Grow profile if needed 01514 // 01515 01516 newSize = FIX_ENDIAN(HEADER(pProfObj)->phSize); 01517 newSize = DWORD_ALIGN(newSize) + sizeof(TAGDATA); 01518 01519 // 01520 // Check for overflow 01521 // 01522 01523 if (newSize < FIX_ENDIAN(HEADER(pProfObj)->phSize)) 01524 { 01525 WARNING((__TEXT("Overflow in adding element\n"))); 01526 SetLastError(ERROR_ARITHMETIC_OVERFLOW); 01527 return FALSE; 01528 } 01529 01530 if (newSize > pProfObj->dwMapSize) 01531 { 01532 //Sundown: safe truncation 01533 DWORD dwOffset = (ULONG)(ULONG_PTR)(pOrigTag - TAG_DATA(pProfObj)); 01534 01535 if (! GrowProfile(pProfObj, newSize)) 01536 { 01537 return FALSE; 01538 } 01539 // 01540 // Recalculate pointers as mapping or memory pointer 01541 // could have changed when growing profile 01542 // 01543 01544 pOrigTag = TAG_DATA(pProfObj) + dwOffset; 01545 } 01546 01547 rc = AddTagTableEntry(pProfObj, newTag, FIX_ENDIAN(pOrigTag->dwOffset), 01548 FIX_ENDIAN(pOrigTag->cbSize), FALSE); 01549 } 01550 else 01551 { 01552 WARNING((__TEXT("SetColorProfileElementReference: Tag 0x%x not found\n"), 01553 FIX_ENDIAN(refTag))); // Re-fix it to reflect data passed in 01554 SetLastError(ERROR_TAG_NOT_FOUND); 01555 } 01556 01557 return rc; 01558 } 01559 01560 01561 /****************************************************************************** 01562 * 01563 * GetColorProfileHeader 01564 * 01565 * Function: 01566 * This functions retrieves the header of a profile 01567 * 01568 * Arguments: 01569 * hProfile - handle identifing the profile object 01570 * pHeader - pointer to buffer to recieve the header 01571 * 01572 * Returns: 01573 * TRUE if successful, FALSE otherwise 01574 * 01575 ******************************************************************************/ 01576 01577 BOOL WINAPI GetColorProfileHeader( 01578 HPROFILE hProfile, 01579 PPROFILEHEADER pHeader 01580 ) 01581 { 01582 PPROFOBJ pProfObj; 01583 DWORD nCount, i, temp; 01584 01585 TRACEAPI((__TEXT("GetColorProfileHeader\n"))); 01586 01587 // 01588 // Validate parameters 01589 // 01590 01591 if (!ValidHandle(hProfile, OBJ_PROFILE) || 01592 IsBadWritePtr(pHeader, sizeof(PROFILEHEADER))) 01593 { 01594 WARNING((__TEXT("Invalid parameter to GetColorProfileHeader\n"))); 01595 SetLastError(ERROR_INVALID_PARAMETER); 01596 return FALSE; 01597 } 01598 01599 pProfObj = (PPROFOBJ)HDLTOPTR(hProfile); 01600 01601 ASSERT(pProfObj != NULL); 01602 01603 // 01604 // Check the integrity of the profile. 01605 // 01606 01607 if (!ValidProfile(pProfObj)) 01608 { 01609 WARNING((__TEXT("Invalid profile passed to GetColorProfileHeader\n"))); 01610 SetLastError(ERROR_INVALID_PROFILE); 01611 return FALSE; 01612 } 01613 01614 CopyMemory((PVOID)pHeader, (PVOID)pProfObj->pView, 01615 sizeof(PROFILEHEADER)); 01616 01617 // 01618 // Fix up all fields to platform specific values. 01619 // The following code assumes that the profile header is a 01620 // multiple of DWORDs which it is! 01621 // 01622 01623 ASSERT(sizeof(PROFILEHEADER) % sizeof(DWORD) == 0); 01624 01625 nCount = sizeof(PROFILEHEADER)/sizeof(DWORD); 01626 for (i=0; i<nCount;i++) 01627 { 01628 temp = (DWORD)((PDWORD)pHeader)[i]; 01629 ((PDWORD)pHeader)[i] = FIX_ENDIAN(temp); 01630 } 01631 01632 return TRUE; 01633 } 01634 01635 01636 /****************************************************************************** 01637 * 01638 * SetColorProfileHeader 01639 * 01640 * Function: 01641 * This functions sets the header of a profile 01642 * 01643 * Arguments: 01644 * hProfile - handle identifing the profile object 01645 * pHeader - pointer to buffer identifing the header 01646 * 01647 * Returns: 01648 * TRUE if successful, FALSE otherwise 01649 * 01650 ******************************************************************************/ 01651 01652 BOOL WINAPI SetColorProfileHeader( 01653 HPROFILE hProfile, 01654 PPROFILEHEADER pHeader 01655 ) 01656 { 01657 PPROFOBJ pProfObj; 01658 DWORD nCount, i, temp; 01659 01660 TRACEAPI((__TEXT("SetColorProfileHeader\n"))); 01661 01662 // 01663 // Validate parameters 01664 // 01665 01666 if (!ValidHandle(hProfile, OBJ_PROFILE) || 01667 IsBadReadPtr(pHeader, sizeof(PROFILEHEADER))) 01668 { 01669 WARNING((__TEXT("Invalid parameter to SetColorProfileHeader\n"))); 01670 SetLastError(ERROR_INVALID_PARAMETER); 01671 return FALSE; 01672 } 01673 01674 pProfObj = (PPROFOBJ)HDLTOPTR(hProfile); 01675 01676 ASSERT(pProfObj != NULL); 01677 01678 // 01679 // Check if profile has write access 01680 // 01681 01682 if (!(pProfObj->dwFlags & READWRITE_ACCESS)) 01683 { 01684 WARNING((__TEXT("Writing to a profile without read/write access\n"))); 01685 SetLastError(ERROR_ACCESS_DENIED); 01686 return FALSE; 01687 } 01688 01689 // 01690 // Fix up all fields to BIG-ENDIAN. 01691 // The following code assumes that the profile header is a 01692 // multiple of DWORDs which it is! 01693 // 01694 01695 ASSERT(sizeof(PROFILEHEADER) % sizeof(DWORD) == 0); 01696 01697 nCount = sizeof(PROFILEHEADER)/sizeof(DWORD); 01698 for (i=0; i<nCount;i++) 01699 { 01700 temp = (DWORD)((PDWORD)pHeader)[i]; 01701 ((PDWORD)pHeader)[i] = FIX_ENDIAN(temp); 01702 } 01703 01704 CopyMemory((PVOID)pProfObj->pView, (PVOID)pHeader, 01705 sizeof(PROFILEHEADER)); 01706 01707 // 01708 // Put back app supplied buffer the way it came in 01709 // 01710 01711 for (i=0; i<nCount;i++) 01712 { 01713 temp = (DWORD)((PDWORD)pHeader)[i]; 01714 ((PDWORD)pHeader)[i] = FIX_ENDIAN(temp); 01715 } 01716 01717 return TRUE; 01718 } 01719 01720 01721 /****************************************************************************** 01722 * 01723 * GetPS2ColorSpaceArray 01724 * 01725 * Function: 01726 * This functions retrieves the PostScript Level 2 CSA from the profile 01727 * 01728 * Arguments: 01729 * hProfile - handle identifing the profile object 01730 * dwIntent - rendering intent of CSA 01731 * dwCSAType - type of CSA 01732 * pbuffer - pointer to receive the CSA 01733 * pcbSize - pointer to size of buffer. If function fails because 01734 * buffer is not big enough, it is filled with required size. 01735 * pcbBinary - TRUE if binary data is requested. On return it is set to 01736 * reflect the data returned 01737 * 01738 * Returns: 01739 * TRUE if successful, FALSE otherwise 01740 * 01741 ******************************************************************************/ 01742 01743 BOOL WINAPI 01744 GetPS2ColorSpaceArray ( 01745 HPROFILE hProfile, 01746 DWORD dwIntent, 01747 DWORD dwCSAType, 01748 PBYTE pBuffer, 01749 PDWORD pcbSize, 01750 LPBOOL pbBinary 01751 ) 01752 { 01753 PPROFOBJ pProfObj; 01754 PCMMOBJ pCMMObj; 01755 DWORD cmmID; 01756 BOOL rc; 01757 01758 TRACEAPI((__TEXT("GetPS2ColorSpaceArray\n"))); 01759 01760 // 01761 // Validate parameters 01762 // 01763 01764 if (!ValidHandle(hProfile, OBJ_PROFILE) || 01765 IsBadWritePtr(pcbSize, sizeof(DWORD)) || 01766 (pBuffer && 01767 IsBadWritePtr(pBuffer, *pcbSize) 01768 ) || 01769 IsBadWritePtr(pbBinary, sizeof(BOOL)) 01770 ) 01771 { 01772 WARNING((__TEXT("Invalid parameter to GetPS2ColorSpaceArray\n"))); 01773 SetLastError(ERROR_INVALID_PARAMETER); 01774 return FALSE; 01775 } 01776 01777 pProfObj = (PPROFOBJ)HDLTOPTR(hProfile); 01778 01779 ASSERT(pProfObj != NULL); 01780 01781 // 01782 // Check the integrity of the profile 01783 // 01784 01785 if (!ValidProfile(pProfObj)) 01786 { 01787 WARNING((__TEXT("Invalid profile passed to GetPS2ColorSpaceArray\n"))); 01788 SetLastError(ERROR_INVALID_PROFILE); 01789 return FALSE; 01790 } 01791 01792 // 01793 // Check if application specified CMM is present 01794 // 01795 01796 pCMMObj = GetPreferredCMM(); 01797 if (!pCMMObj || (pCMMObj->dwFlags & CMM_DONT_USE_PS2_FNS) || 01798 !pCMMObj->fns.pCMGetPS2ColorSpaceArray) 01799 { 01800 if (pCMMObj) 01801 { 01802 pCMMObj->dwFlags |= CMM_DONT_USE_PS2_FNS; 01803 ReleaseColorMatchingModule(pCMMObj); 01804 } 01805 01806 // 01807 // Get CMM associated with profile. If it does not exist or does not 01808 // support the CMGetPS2ColorSpaceArray function, get default CMM. 01809 // 01810 01811 cmmID = HEADER(pProfObj)->phCMMType; 01812 cmmID = FIX_ENDIAN(cmmID); 01813 01814 pCMMObj = GetColorMatchingModule(cmmID); 01815 01816 if (!pCMMObj || (pCMMObj->dwFlags & CMM_DONT_USE_PS2_FNS) || 01817 !pCMMObj->fns.pCMGetPS2ColorSpaceArray) 01818 { 01819 TERSE((__TEXT("CMM associated with profile could not be used"))); 01820 01821 if (pCMMObj) 01822 { 01823 pCMMObj->dwFlags |= CMM_DONT_USE_PS2_FNS; 01824 ReleaseColorMatchingModule(pCMMObj); 01825 } 01826 01827 pCMMObj = GetColorMatchingModule(CMM_WINDOWS_DEFAULT); 01828 01829 if (!pCMMObj || !pCMMObj->fns.pCMGetPS2ColorSpaceArray) 01830 { 01831 WARNING((__TEXT("Default CMM doesn't support CMGetPS2ColorSpaceArray\n"))); 01832 if (pCMMObj) 01833 { 01834 ReleaseColorMatchingModule(pCMMObj); 01835 pCMMObj = NULL; 01836 } 01837 } 01838 } 01839 } 01840 01841 ASSERT(pProfObj->pView != NULL); 01842 01843 if (pCMMObj) 01844 { 01845 rc = pCMMObj->fns.pCMGetPS2ColorSpaceArray(hProfile, dwIntent, dwCSAType, 01846 pBuffer, pcbSize, pbBinary); 01847 } 01848 else 01849 { 01850 rc = InternalGetPS2ColorSpaceArray(pProfObj->pView, dwIntent, 01851 dwCSAType, pBuffer, pcbSize, pbBinary); 01852 } 01853 01854 if (pCMMObj) 01855 { 01856 ReleaseColorMatchingModule(pCMMObj); 01857 } 01858 01859 VERBOSE((__TEXT("GetPS2ColorSpaceArray returning %s\n"), 01860 rc ? "TRUE" : "FALSE")); 01861 01862 return rc; 01863 } 01864 01865 01866 /****************************************************************************** 01867 * 01868 * GetPS2ColorRenderingIntent 01869 * 01870 * Function: 01871 * This functions retrieves the PostScript Level 2 color rendering intent 01872 * from the profile 01873 * 01874 * Arguments: 01875 * hProfile - handle identifing the profile object 01876 * pbuffer - pointer to receive the color rendering intent 01877 * pcbSize - pointer to size of buffer. If function fails because 01878 * buffer is not big enough, it is filled with required size. 01879 * pcbBinary - TRUE if binary data is requested. On return it is set to 01880 * reflect the data returned 01881 * 01882 * Returns: 01883 * TRUE if successful, FALSE otherwise 01884 * 01885 ******************************************************************************/ 01886 01887 BOOL WINAPI GetPS2ColorRenderingIntent( 01888 HPROFILE hProfile, 01889 DWORD dwIntent, 01890 PBYTE pBuffer, 01891 PDWORD pcbSize 01892 ) 01893 { 01894 PPROFOBJ pProfObj; 01895 PCMMOBJ pCMMObj; 01896 DWORD cmmID; 01897 BOOL rc; 01898 01899 TRACEAPI((__TEXT("GetPS2ColorRenderingIntent\n"))); 01900 01901 // 01902 // Validate parameters 01903 // 01904 01905 if (!ValidHandle(hProfile, OBJ_PROFILE) || 01906 IsBadWritePtr(pcbSize, sizeof(DWORD)) || 01907 (pBuffer && 01908 IsBadWritePtr(pBuffer, *pcbSize) 01909 ) 01910 ) 01911 { 01912 WARNING((__TEXT("Invalid parameter to GetPS2ColorRenderingIntent\n"))); 01913 SetLastError(ERROR_INVALID_PARAMETER); 01914 return FALSE; 01915 } 01916 01917 pProfObj = (PPROFOBJ)HDLTOPTR(hProfile); 01918 01919 ASSERT(pProfObj != NULL); 01920 01921 // 01922 // Check the integrity of the profile 01923 // 01924 01925 if (!ValidProfile(pProfObj)) 01926 { 01927 WARNING((__TEXT("Invalid profile passed to GetPS2ColorRenderingIntent\n"))); 01928 SetLastError(ERROR_INVALID_PROFILE); 01929 return FALSE; 01930 } 01931 01932 // 01933 // Check if application specified CMM is present 01934 // 01935 01936 pCMMObj = GetPreferredCMM(); 01937 if (!pCMMObj || (pCMMObj->dwFlags & CMM_DONT_USE_PS2_FNS) || 01938 !pCMMObj->fns.pCMGetPS2ColorRenderingIntent) 01939 { 01940 if (pCMMObj) 01941 { 01942 pCMMObj->dwFlags |= CMM_DONT_USE_PS2_FNS; 01943 ReleaseColorMatchingModule(pCMMObj); 01944 } 01945 01946 // 01947 // Get CMM associated with profile. If it does not exist or does not 01948 // support the CMGetPS2ColorSpaceArray function, get default CMM. 01949 // 01950 01951 cmmID = HEADER(pProfObj)->phCMMType; 01952 cmmID = FIX_ENDIAN(cmmID); 01953 01954 pCMMObj = GetColorMatchingModule(cmmID); 01955 01956 if (!pCMMObj || (pCMMObj->dwFlags & CMM_DONT_USE_PS2_FNS) || 01957 !pCMMObj->fns.pCMGetPS2ColorRenderingIntent) 01958 { 01959 TERSE((__TEXT("CMM associated with profile could not be used"))); 01960 01961 if (pCMMObj) 01962 { 01963 pCMMObj->dwFlags |= CMM_DONT_USE_PS2_FNS; 01964 ReleaseColorMatchingModule(pCMMObj); 01965 } 01966 01967 pCMMObj = GetColorMatchingModule(CMM_WINDOWS_DEFAULT); 01968 01969 if (!pCMMObj || !pCMMObj->fns.pCMGetPS2ColorRenderingIntent) 01970 { 01971 WARNING((__TEXT("Default CMM doesn't support CMGetPS2ColorRenderingIntent\n"))); 01972 if (pCMMObj) 01973 { 01974 ReleaseColorMatchingModule(pCMMObj); 01975 pCMMObj = NULL; 01976 } 01977 } 01978 } 01979 } 01980 01981 ASSERT(pProfObj->pView != NULL); 01982 01983 if (pCMMObj) 01984 { 01985 rc = pCMMObj->fns.pCMGetPS2ColorRenderingIntent(hProfile, 01986 dwIntent, pBuffer, pcbSize); 01987 } 01988 else 01989 { 01990 rc = InternalGetPS2ColorRenderingIntent(pProfObj->pView, dwIntent, 01991 pBuffer, pcbSize); 01992 } 01993 01994 if (pCMMObj) 01995 { 01996 ReleaseColorMatchingModule(pCMMObj); 01997 } 01998 01999 VERBOSE((__TEXT("GetPS2ColorRenderingIntent returning %s\n"), 02000 rc ? "TRUE" : "FALSE")); 02001 02002 return rc; 02003 } 02004 02005 02006 /****************************************************************************** 02007 * 02008 * GetPS2ColorRenderingDictionary 02009 * 02010 * Function: 02011 * This functions retrieves the PostScript Level 2 CRD from the profile 02012 * 02013 * Arguments: 02014 * hProfile - handle identifing the profile object 02015 * dwIntent - intent whose CRD is required 02016 * pbuffer - pointer to receive the CSA 02017 * pcbSize - pointer to size of buffer. If function fails because 02018 * buffer is not big enough, it is filled with required size. 02019 * pcbBinary - TRUE if binary data is requested. On return it is set to 02020 * reflect the data returned 02021 * 02022 * Returns: 02023 * TRUE if successful, FALSE otherwise 02024 * 02025 ******************************************************************************/ 02026 02027 BOOL WINAPI GetPS2ColorRenderingDictionary( 02028 HPROFILE hProfile, 02029 DWORD dwIntent, 02030 PBYTE pBuffer, 02031 PDWORD pcbSize, 02032 PBOOL pbBinary 02033 ) 02034 { 02035 PPROFOBJ pProfObj; 02036 PCMMOBJ pCMMObj; 02037 DWORD cmmID; 02038 BOOL rc; 02039 02040 TRACEAPI((__TEXT("GetPS2ColorRenderingDictionary\n"))); 02041 02042 // 02043 // Validate parameters 02044 // 02045 02046 if (!ValidHandle(hProfile, OBJ_PROFILE) || 02047 IsBadWritePtr(pcbSize, sizeof(DWORD)) || 02048 (pBuffer && 02049 IsBadWritePtr(pBuffer, *pcbSize) 02050 ) || 02051 IsBadWritePtr(pbBinary, sizeof(BOOL)) 02052 ) 02053 { 02054 WARNING((__TEXT("Invalid parameter to GetPS2ColorRenderingDictionary\n"))); 02055 SetLastError(ERROR_INVALID_PARAMETER); 02056 return FALSE; 02057 } 02058 02059 pProfObj = (PPROFOBJ)HDLTOPTR(hProfile); 02060 02061 ASSERT(pProfObj != NULL); 02062 02063 // 02064 // Check the integrity of the profile 02065 // 02066 02067 if (!ValidProfile(pProfObj)) 02068 { 02069 WARNING((__TEXT("Invalid profile passed to GetPS2ColorRenderingDictionary\n"))); 02070 SetLastError(ERROR_INVALID_PROFILE); 02071 return FALSE; 02072 } 02073 02074 // 02075 // Check if application specified CMM is present 02076 // 02077 02078 pCMMObj = GetPreferredCMM(); 02079 if (!pCMMObj || (pCMMObj->dwFlags & CMM_DONT_USE_PS2_FNS) || 02080 !pCMMObj->fns.pCMGetPS2ColorRenderingDictionary) 02081 { 02082 if (pCMMObj) 02083 { 02084 pCMMObj->dwFlags |= CMM_DONT_USE_PS2_FNS; 02085 ReleaseColorMatchingModule(pCMMObj); 02086 } 02087 02088 // 02089 // Get CMM associated with profile. If it does not exist or does not 02090 // support the CMGetPS2ColorSpaceArray function, get default CMM. 02091 // 02092 02093 cmmID = HEADER(pProfObj)->phCMMType; 02094 cmmID = FIX_ENDIAN(cmmID); 02095 02096 pCMMObj = GetColorMatchingModule(cmmID); 02097 02098 if (!pCMMObj || (pCMMObj->dwFlags & CMM_DONT_USE_PS2_FNS) || 02099 !pCMMObj->fns.pCMGetPS2ColorRenderingDictionary) 02100 { 02101 TERSE((__TEXT("CMM associated with profile could not be used"))); 02102 02103 if (pCMMObj) 02104 { 02105 pCMMObj->dwFlags |= CMM_DONT_USE_PS2_FNS; 02106 ReleaseColorMatchingModule(pCMMObj); 02107 } 02108 02109 pCMMObj = GetColorMatchingModule(CMM_WINDOWS_DEFAULT); 02110 02111 if (!pCMMObj || !pCMMObj->fns.pCMGetPS2ColorRenderingDictionary) 02112 { 02113 WARNING((__TEXT("Default CMM doesn't support CMGetPS2ColorRenderingDictionary\n"))); 02114 if (pCMMObj) 02115 { 02116 ReleaseColorMatchingModule(pCMMObj); 02117 pCMMObj = NULL; 02118 } 02119 } 02120 } 02121 } 02122 02123 ASSERT(pProfObj->pView != NULL); 02124 02125 if (pCMMObj) 02126 { 02127 rc = pCMMObj->fns.pCMGetPS2ColorRenderingDictionary(hProfile, dwIntent, 02128 pBuffer, pcbSize, pbBinary); 02129 } 02130 else 02131 { 02132 rc = InternalGetPS2ColorRenderingDictionary(pProfObj->pView, dwIntent, 02133 pBuffer, pcbSize, pbBinary); 02134 } 02135 02136 if (pCMMObj) 02137 { 02138 ReleaseColorMatchingModule(pCMMObj); 02139 } 02140 02141 VERBOSE((__TEXT("GetPS2ColorRenderingDictionary returning %s\n"), 02142 rc ? "TRUE" : "FALSE")); 02143 02144 return rc; 02145 } 02146 02147 02148 /****************************************************************************** 02149 * 02150 * GetNamedProfileInfo 02151 * 02152 * Function: 02153 * This functions returns information about the given named color space 02154 * profile. If fails if the given profile is not a named color space profile. 02155 * 02156 * Arguments: 02157 * hProfile - handle identifying the named color space profile object 02158 * pNamedProfileInfo - pointer to NAMED_PROFILE_INFO structure that is 02159 * filled on retun if successful. 02160 * 02161 * Returns: 02162 * TRUE if successful, FALSE otherwise 02163 * 02164 ******************************************************************************/ 02165 02166 BOOL WINAPI GetNamedProfileInfo( 02167 HPROFILE hProfile, 02168 PNAMED_PROFILE_INFO pNamedProfileInfo 02169 ) 02170 { 02171 PPROFOBJ pProfObj; 02172 PCMMOBJ pCMMObj; 02173 DWORD cmmID; 02174 BOOL rc; 02175 02176 TRACEAPI((__TEXT("GetNamedProfileInfo\n"))); 02177 02178 // 02179 // Validate parameters 02180 // 02181 02182 if (!ValidHandle(hProfile, OBJ_PROFILE) || 02183 !pNamedProfileInfo || 02184 IsBadWritePtr(pNamedProfileInfo, sizeof(NAMED_PROFILE_INFO))) 02185 { 02186 WARNING((__TEXT("Invalid parameter to GetNamedProfileInfo\n"))); 02187 SetLastError(ERROR_INVALID_PARAMETER); 02188 return FALSE; 02189 } 02190 02191 pProfObj = (PPROFOBJ)HDLTOPTR(hProfile); 02192 02193 ASSERT(pProfObj != NULL); 02194 02195 // 02196 // Check the integrity of the profile 02197 // 02198 02199 if (!ValidProfile(pProfObj)) 02200 { 02201 WARNING((__TEXT("Invalid profile passed to GetNamedProfileInfo\n"))); 02202 SetLastError(ERROR_INVALID_PROFILE); 02203 return FALSE; 02204 } 02205 02206 // 02207 // Check if application specified CMM is present 02208 // 02209 02210 pCMMObj = GetPreferredCMM(); 02211 if (!pCMMObj || 02212 !pCMMObj->fns.pCMGetNamedProfileInfo) 02213 { 02214 if (pCMMObj) 02215 { 02216 ReleaseColorMatchingModule(pCMMObj); 02217 } 02218 02219 // 02220 // Get CMM associated with profile. If it does not exist or does not 02221 // support the CMGetNamedProfileInfo function, get default CMM. 02222 // 02223 02224 cmmID = HEADER(pProfObj)->phCMMType; 02225 cmmID = FIX_ENDIAN(cmmID); 02226 02227 pCMMObj = GetColorMatchingModule(cmmID); 02228 02229 if (!pCMMObj || 02230 !pCMMObj->fns.pCMGetNamedProfileInfo) 02231 { 02232 TERSE((__TEXT("CMM associated with profile could not be used"))); 02233 02234 if (pCMMObj) 02235 { 02236 ReleaseColorMatchingModule(pCMMObj); 02237 } 02238 02239 pCMMObj = GetColorMatchingModule(CMM_WINDOWS_DEFAULT); 02240 02241 if (!pCMMObj || !pCMMObj->fns.pCMGetNamedProfileInfo) 02242 { 02243 RIP((__TEXT("Default CMM doesn't support CMValidateProfile"))); 02244 SetLastError(ERROR_INVALID_CMM); 02245 if (pCMMObj) 02246 { 02247 ReleaseColorMatchingModule(pCMMObj); 02248 } 02249 return FALSE; 02250 } 02251 } 02252 } 02253 02254 ASSERT(pProfObj->pView != NULL); 02255 02256 rc = pCMMObj->fns.pCMGetNamedProfileInfo(hProfile, pNamedProfileInfo); 02257 02258 ReleaseColorMatchingModule(pCMMObj); 02259 02260 return rc; 02261 } 02262 02263 02264 /****************************************************************************** 02265 * 02266 * ConvertColorNameToIndex 02267 * 02268 * Function: 02269 * This functions converts a given array of color names to color indices 02270 * using the specified named color space profile 02271 * 02272 * Arguments: 02273 * hProfile - handle identifing the named color space profile object 02274 * paColorName - pointer to array of COLOR_NAME structures 02275 * paIndex - pointer to array of DWORDs to receive the indices 02276 * dwCount - number of color names to convert 02277 * 02278 * Returns: 02279 * TRUE if successful, FALSE otherwise 02280 * 02281 ******************************************************************************/ 02282 02283 BOOL WINAPI ConvertColorNameToIndex( 02284 HPROFILE hProfile, 02285 PCOLOR_NAME paColorName, 02286 PDWORD paIndex, 02287 DWORD dwCount 02288 ) 02289 { 02290 PPROFOBJ pProfObj; 02291 PCMMOBJ pCMMObj; 02292 DWORD cmmID; 02293 BOOL rc; 02294 02295 TRACEAPI((__TEXT("ConvertColorNameToIndex\n"))); 02296 02297 // 02298 // Validate parameters 02299 // 02300 02301 if (!ValidHandle(hProfile, OBJ_PROFILE) || 02302 !paColorName || 02303 dwCount == 0 || 02304 IsBadReadPtr(paColorName, dwCount*sizeof(COLOR_NAME)) || 02305 !paIndex || 02306 IsBadWritePtr(paIndex, dwCount*sizeof(DWORD))) 02307 { 02308 WARNING((__TEXT("Invalid parameter to ConvertColorNameToIndex\n"))); 02309 SetLastError(ERROR_INVALID_PARAMETER); 02310 return FALSE; 02311 } 02312 02313 pProfObj = (PPROFOBJ)HDLTOPTR(hProfile); 02314 02315 ASSERT(pProfObj != NULL); 02316 02317 // 02318 // Check the integrity of the profile 02319 // 02320 02321 if (!ValidProfile(pProfObj)) 02322 { 02323 WARNING((__TEXT("Invalid profile passed to ConvertColorNameToIndex\n"))); 02324 SetLastError(ERROR_INVALID_PROFILE); 02325 return FALSE; 02326 } 02327 02328 // 02329 // Check if application specified CMM is present 02330 // 02331 02332 pCMMObj = GetPreferredCMM(); 02333 if (!pCMMObj || 02334 !pCMMObj->fns.pCMConvertColorNameToIndex) 02335 { 02336 if (pCMMObj) 02337 { 02338 ReleaseColorMatchingModule(pCMMObj); 02339 } 02340 02341 // 02342 // Get CMM associated with profile. If it does not exist or does not 02343 // support the CMConvertColorNameToIndex function, get default CMM. 02344 // 02345 02346 cmmID = HEADER(pProfObj)->phCMMType; 02347 cmmID = FIX_ENDIAN(cmmID); 02348 02349 pCMMObj = GetColorMatchingModule(cmmID); 02350 02351 if (!pCMMObj || 02352 !pCMMObj->fns.pCMConvertColorNameToIndex) 02353 { 02354 TERSE((__TEXT("CMM associated with profile could not be used"))); 02355 02356 if (pCMMObj) 02357 { 02358 ReleaseColorMatchingModule(pCMMObj); 02359 } 02360 02361 pCMMObj = GetColorMatchingModule(CMM_WINDOWS_DEFAULT); 02362 02363 if (!pCMMObj || !pCMMObj->fns.pCMConvertColorNameToIndex) 02364 { 02365 RIP((__TEXT("Default CMM doesn't support CMConvertColorNameToIndex"))); 02366 SetLastError(ERROR_INVALID_CMM); 02367 if (pCMMObj) 02368 { 02369 ReleaseColorMatchingModule(pCMMObj); 02370 } 02371 return FALSE; 02372 } 02373 } 02374 } 02375 02376 ASSERT(pProfObj->pView != NULL); 02377 02378 rc = pCMMObj->fns.pCMConvertColorNameToIndex( 02379 hProfile, 02380 paColorName, 02381 paIndex, 02382 dwCount); 02383 02384 ReleaseColorMatchingModule(pCMMObj); 02385 02386 return rc; 02387 } 02388 02389 02390 /****************************************************************************** 02391 * 02392 * ConvertIndexToColorName 02393 * 02394 * Function: 02395 * This functions converts a given array of color indices to color names 02396 * using the specified named color space profile 02397 * 02398 * Arguments: 02399 * hProfile - handle identifing the named color space profile object 02400 * paIndex - pointer to array of color indices 02401 * paColorName - pointer to array of COLOR_NAME structures 02402 * dwCount - number of color indices to convert 02403 * 02404 * Returns: 02405 * TRUE if successful, FALSE otherwise 02406 * 02407 ******************************************************************************/ 02408 02409 BOOL WINAPI ConvertIndexToColorName( 02410 HPROFILE hProfile, 02411 PDWORD paIndex, 02412 PCOLOR_NAME paColorName, 02413 DWORD dwCount 02414 ) 02415 { 02416 PPROFOBJ pProfObj; 02417 PCMMOBJ pCMMObj; 02418 DWORD cmmID; 02419 BOOL rc; 02420 02421 TRACEAPI((__TEXT("ConvertIndexToColorName\n"))); 02422 02423 // 02424 // Validate parameters 02425 // 02426 02427 if (!ValidHandle(hProfile, OBJ_PROFILE) || 02428 !paIndex || 02429 dwCount == 0 || 02430 IsBadWritePtr(paIndex, dwCount*sizeof(DWORD)) || 02431 !paColorName || 02432 IsBadReadPtr(paColorName, dwCount*sizeof(COLOR_NAME))) 02433 { 02434 WARNING((__TEXT("Invalid parameter to ConvertIndexToColorName\n"))); 02435 SetLastError(ERROR_INVALID_PARAMETER); 02436 return FALSE; 02437 } 02438 02439 pProfObj = (PPROFOBJ)HDLTOPTR(hProfile); 02440 02441 ASSERT(pProfObj != NULL); 02442 02443 // 02444 // Check the integrity of the profile 02445 // 02446 02447 if (!ValidProfile(pProfObj)) 02448 { 02449 WARNING((__TEXT("Invalid profile passed to ConvertIndexToColorName\n"))); 02450 SetLastError(ERROR_INVALID_PROFILE); 02451 return FALSE; 02452 } 02453 02454 // 02455 // Check if application specified CMM is present 02456 // 02457 02458 pCMMObj = GetPreferredCMM(); 02459 if (!pCMMObj || 02460 !pCMMObj->fns.pCMConvertIndexToColorName) 02461 { 02462 if (pCMMObj) 02463 { 02464 ReleaseColorMatchingModule(pCMMObj); 02465 } 02466 02467 // 02468 // Get CMM associated with profile. If it does not exist or does not 02469 // support the CMConvertIndexToColorName function, get default CMM. 02470 // 02471 02472 cmmID = HEADER(pProfObj)->phCMMType; 02473 cmmID = FIX_ENDIAN(cmmID); 02474 02475 pCMMObj = GetColorMatchingModule(cmmID); 02476 02477 if (!pCMMObj || 02478 !pCMMObj->fns.pCMConvertIndexToColorName) 02479 { 02480 TERSE((__TEXT("CMM associated with profile could not be used"))); 02481 02482 if (pCMMObj) 02483 { 02484 ReleaseColorMatchingModule(pCMMObj); 02485 } 02486 02487 pCMMObj = GetColorMatchingModule(CMM_WINDOWS_DEFAULT); 02488 02489 if (!pCMMObj || !pCMMObj->fns.pCMConvertIndexToColorName) 02490 { 02491 RIP((__TEXT("Default CMM doesn't support CMConvertIndexToColorName"))); 02492 SetLastError(ERROR_INVALID_CMM); 02493 if (pCMMObj) 02494 { 02495 ReleaseColorMatchingModule(pCMMObj); 02496 } 02497 return FALSE; 02498 } 02499 } 02500 } 02501 02502 ASSERT(pProfObj->pView != NULL); 02503 02504 rc = pCMMObj->fns.pCMConvertIndexToColorName( 02505 hProfile, 02506 paIndex, 02507 paColorName, 02508 dwCount); 02509 02510 ReleaseColorMatchingModule(pCMMObj); 02511 02512 return rc; 02513 } 02514 02515 02516 /****************************************************************************** 02517 * 02518 * CreateDeviceLinkProfile 02519 * 02520 * Function: 02521 * This functions creates a device link profile from the given set 02522 * of profiles, using specified intents. 02523 * 02524 * Arguments: 02525 * pahProfiles - pointer to array of handles of profiles 02526 * nProfiles - number of profiles in array 02527 * padwIntent - array of intents to use 02528 * nIntents - size of array - can be 1 or nProfiles 02529 * dwFlags - optimization flags 02530 * pProfileData - pointer to pointer to buffer to receive data which 02531 * this function allocates; caller needs to free. 02532 * indexPreferredCMM - zero based index of profile which specifies 02533 * preferred CMM to use. 02534 * 02535 * Returns: 02536 * TRUE if successful, FALSE otherwise 02537 * 02538 ******************************************************************************/ 02539 02540 BOOL WINAPI CreateDeviceLinkProfile( 02541 PHPROFILE pahProfiles, 02542 DWORD nProfiles, 02543 PDWORD padwIntent, 02544 DWORD nIntents, 02545 DWORD dwFlags, 02546 PBYTE *pProfileData, 02547 DWORD indexPreferredCMM 02548 ) 02549 { 02550 PPROFOBJ pProfObj; 02551 PCMMOBJ pCMMObj; 02552 DWORD cmmID, i; 02553 BOOL rc; 02554 02555 TRACEAPI((__TEXT("CreateDeviceLinkProfile\n"))); 02556 02557 // 02558 // Validate parameters 02559 // 02560 02561 if (nProfiles <= 1 || 02562 indexPreferredCMM >= nProfiles || 02563 pahProfiles == NULL || 02564 IsBadReadPtr(pahProfiles, sizeof(HPROFILE) * nProfiles) || 02565 padwIntent == NULL || 02566 ((nIntents != nProfiles) && (nIntents != 1)) || 02567 IsBadReadPtr(padwIntent, nIntents * sizeof(DWORD))) 02568 { 02569 WARNING((__TEXT("Invalid parameter to CreateDeviceLinkProfile\n"))); 02570 SetLastError(ERROR_INVALID_PARAMETER); 02571 return FALSE; 02572 } 02573 02574 for (i=0; i<nProfiles; i++) 02575 { 02576 if ((pahProfiles[i] == NULL) || 02577 ! ValidHandle(pahProfiles[i], OBJ_PROFILE)) 02578 02579 { 02580 WARNING((__TEXT("Invalid profile passed to CreateDeviceLinkProfile\n"))); 02581 SetLastError(ERROR_INVALID_PARAMETER); 02582 return FALSE; 02583 } 02584 02585 pProfObj = (PPROFOBJ)HDLTOPTR(pahProfiles[i]); 02586 02587 ASSERT(pProfObj != NULL); 02588 02589 ASSERT(pProfObj->pView != NULL); 02590 02591 // 02592 // Quick check on the integrity of the profile 02593 // 02594 02595 if (!ValidProfile(pProfObj)) 02596 { 02597 WARNING((__TEXT("Invalid profile passed to CreateDeviceLinkProfile\n"))); 02598 SetLastError(ERROR_INVALID_PROFILE); 02599 return FALSE; 02600 } 02601 02602 if (i == indexPreferredCMM) 02603 { 02604 // 02605 // Get ID of preferred CMM 02606 // 02607 02608 cmmID = HEADER(pProfObj)->phCMMType; 02609 cmmID = FIX_ENDIAN(cmmID); 02610 } 02611 } 02612 02613 // 02614 // Get CMM associated with preferred profile. If it does not exist, 02615 // get default CMM. 02616 // 02617 02618 pCMMObj = GetColorMatchingModule(cmmID); 02619 if (!pCMMObj || !pCMMObj->fns.pCMCreateDeviceLinkProfile) 02620 { 02621 TERSE((__TEXT("CMM associated with profile could not be used"))); 02622 02623 if (pCMMObj) 02624 { 02625 ReleaseColorMatchingModule(pCMMObj); 02626 } 02627 02628 pCMMObj = GetColorMatchingModule(CMM_WINDOWS_DEFAULT); 02629 if (!pCMMObj) 02630 { 02631 RIP((__TEXT("Default CMM not found\n"))); 02632 SetLastError(ERROR_INVALID_CMM); 02633 return FALSE; 02634 } 02635 } 02636 02637 ASSERT(pCMMObj->fns.pCMCreateDeviceLinkProfile != NULL); 02638 02639 rc = pCMMObj->fns.pCMCreateDeviceLinkProfile( 02640 pahProfiles, 02641 nProfiles, 02642 padwIntent, 02643 nIntents, 02644 dwFlags, 02645 pProfileData); 02646 02647 ReleaseColorMatchingModule(pCMMObj); 02648 02649 return rc; 02650 } 02651 02652 02653 /*****************************************************************************/ 02654 /***************************** Internal Functions ****************************/ 02655 /*****************************************************************************/ 02656 02657 /****************************************************************************** 02658 * 02659 * InternalOpenColorProfile 02660 * 02661 * Function: 02662 * This functions opens a color profile specified by the pProfile 02663 * parameter, creates an internal profile object, and returns a handle 02664 * to it. 02665 * 02666 * Arguments: 02667 * pProfile - ptr to a profile structure that specifies the profile 02668 * to open 02669 * dwDesiredAccess - specifies the mode in which to open the profile. 02670 * Any combination of these values can be used: 02671 * PROFILE_READ: Allows the app to read the profile. 02672 * PROFILE_READWRITE: Allows the app to read and write to the profile. 02673 * dwShareMode - specifies the mode to share the profile with other 02674 * processes if it is a file. Any combination of these 02675 * values can be used. 02676 * 0 : Prevents the file from being shared. 02677 * FILE_SHARE_READ: Allows opening for read only by other processes. 02678 * FILE_SHARE_WRITE: Allows opening for write by other processes. 02679 * dwCreationMode - specifies which actions to take on the profile while 02680 * opening it (if it is a file). Any one of the following 02681 * values can be used. 02682 * CREATE_NEW: Creates a new file. Fails if one exists already. 02683 * CREATE_ALWAYS: Always create a new file. Overwriting existing. 02684 * OPEN_EXISTING: Open exisiting file. Fail if not found. 02685 * OPEN_ALWAYS: Open existing. If not found, create a new one. 02686 * TRUNCATE_EXISTING: Open existing and truncate to zero bytes. Fail 02687 * if not found. 02688 * 02689 * Returns: 02690 * Handle to open profile on success, zero on failure. 02691 * 02692 ******************************************************************************/ 02693 02694 HPROFILE InternalOpenColorProfile( 02695 PPROFILE pProfile, 02696 DWORD dwDesiredAccess, 02697 DWORD dwShareMode, 02698 DWORD dwCreationMode 02699 ) 02700 { 02701 SECURITY_ATTRIBUTES sa; 02702 PPROFOBJ pProfObj; 02703 HPROFILE hProfile; 02704 DWORD dwMapSize; 02705 BOOL bNewFile = FALSE; 02706 BOOL bError = TRUE; // Assume failure 02707 02708 TRACEAPI((__TEXT("OpenColorProfile\n"))); 02709 02710 // 02711 // Validate parameters 02712 // 02713 02714 if (!pProfile || 02715 IsBadReadPtr(pProfile, sizeof(PROFILE)) || 02716 (pProfile->pProfileData && 02717 IsBadReadPtr(pProfile->pProfileData, pProfile->cbDataSize)) || 02718 (!pProfile->pProfileData && 02719 (pProfile->cbDataSize != 0)) || 02720 (pProfile->dwType != PROFILE_FILENAME && 02721 pProfile->dwType != PROFILE_MEMBUFFER 02722 ) || 02723 (dwDesiredAccess != PROFILE_READ && 02724 dwDesiredAccess != PROFILE_READWRITE 02725 ) 02726 ) 02727 { 02728 WARNING((__TEXT("Invalid parameter to OpenColorProfile\n"))); 02729 SetLastError(ERROR_INVALID_PARAMETER); 02730 return NULL; 02731 } 02732 02733 // 02734 // Allocate an object on the heap for the profile 02735 // 02736 02737 hProfile = AllocateHeapObject(OBJ_PROFILE); 02738 if (!hProfile) 02739 { 02740 WARNING((__TEXT("Could not allocate profile object\n"))); 02741 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 02742 return NULL; 02743 } 02744 02745 pProfObj = (PPROFOBJ)HDLTOPTR(hProfile); 02746 02747 ASSERT(pProfObj != NULL); 02748 02749 // 02750 // Copy profile information to our object 02751 // 02752 02753 pProfObj->objHdr.dwUseCount = 1; 02754 pProfObj->dwType = pProfile->dwType; 02755 pProfObj->cbDataSize = pProfile->cbDataSize; 02756 pProfObj->pProfileData = (PBYTE)MemAlloc(pProfile->cbDataSize + sizeof(TCHAR)); 02757 if (!pProfObj->pProfileData) 02758 { 02759 WARNING((__TEXT("Could not allocate memory for profile data\n"))); 02760 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 02761 goto EndOpenColorProfile; 02762 } 02763 02764 CopyMemory((PVOID)pProfObj->pProfileData, 02765 (PVOID)pProfile->pProfileData, 02766 pProfile->cbDataSize); 02767 02768 if (pProfObj->dwType == PROFILE_FILENAME) 02769 { 02770 LPTSTR lpFilename; 02771 02772 if (!pProfile->pProfileData || 02773 pProfile->cbDataSize == 0 || 02774 lstrlen((LPCTSTR)pProfile->pProfileData) > MAX_PATH || 02775 pProfile->cbDataSize > (MAX_PATH * sizeof(TCHAR))) 02776 { 02777 WARNING((__TEXT("Invalid parameter to OpenColorProfile\n"))); 02778 SetLastError(ERROR_INVALID_PARAMETER); 02779 goto EndOpenColorProfile; 02780 } 02781 02782 // 02783 // If only filename is given, it is wrt color directory 02784 // 02785 02786 lpFilename = GetFilenameFromPath((LPTSTR)pProfObj->pProfileData); 02787 if (lpFilename == pProfObj->pProfileData) 02788 { 02789 DWORD dwLen = MAX_PATH; 02790 lpFilename = MemAlloc(dwLen); 02791 if (!lpFilename) 02792 { 02793 WARNING((__TEXT("Could not allocate memory for file name\n"))); 02794 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 02795 goto EndOpenColorProfile; 02796 } 02797 (VOID)GetColorDirectory(NULL, lpFilename, &dwLen); 02798 lstrcat(lpFilename, gszBackslash); 02799 lstrcat(lpFilename, (LPTSTR)pProfObj->pProfileData); 02800 MemFree(pProfObj->pProfileData); 02801 pProfObj->pProfileData = (PVOID)lpFilename; 02802 pProfObj->cbDataSize = MAX_PATH; 02803 } 02804 02805 // 02806 // File name already null terminates as we used GHND flag which 02807 // zero initializes the allocated memory 02808 // 02809 // Create file mapping 02810 // 02811 02812 pProfObj->dwFlags |= MEMORY_MAPPED; 02813 02814 if (dwCreationMode == OPEN_ALWAYS) 02815 { 02816 // 02817 // If we find a zero length profile, we should error out 02818 // saying it is a bad profile. If we create a zero length 02819 // profile, it is fine. To distinguish these two cases, we 02820 // check for file's existence and if present, change the 02821 // creation mode to OPEN_EXISTING 02822 // 02823 02824 if (GetFileAttributes(pProfObj->pProfileData) != (DWORD)-1) 02825 { 02826 dwCreationMode = OPEN_EXISTING; 02827 } 02828 } 02829 02830 // 02831 // Set security attribute structure 02832 // 02833 02834 sa.nLength = sizeof(SECURITY_ATTRIBUTES); 02835 sa.lpSecurityDescriptor = NULL; // default security 02836 sa.bInheritHandle = FALSE; 02837 02838 pProfObj->hFile = CreateFile(pProfObj->pProfileData, 02839 (dwDesiredAccess == PROFILE_READWRITE) ? GENERIC_READ | GENERIC_WRITE : GENERIC_READ, 02840 dwShareMode, &sa, dwCreationMode, FILE_FLAG_RANDOM_ACCESS, 0); 02841 02842 if (pProfObj->hFile == INVALID_HANDLE_VALUE) 02843 { 02844 WARNING((__TEXT("Err %ld, could not open profile %s\n"), 02845 GetLastError(), pProfObj->pProfileData)); 02846 goto EndOpenColorProfile; 02847 } 02848 02849 // 02850 // Get size of file mapping. Add a cushion so that profile can 02851 // be grown. When closing the profile, the file size is truncated 02852 // to the size of the actual data. If the profile size grows beyond 02853 // the cushion, it is continually grown in chunks. 02854 // 02855 02856 dwMapSize = GetFileSize(pProfObj->hFile, NULL); 02857 if (dwMapSize == 0) 02858 { 02859 if (dwCreationMode == OPEN_EXISTING) 02860 { 02861 WARNING((__TEXT("Invalid profile - zero length\n"))); 02862 SetLastError(ERROR_INVALID_PROFILE); 02863 goto EndOpenColorProfile; 02864 02865 } 02866 else 02867 { 02868 dwMapSize = PROFILE_GROWTHCUSHION; 02869 bNewFile = TRUE; 02870 } 02871 } 02872 02873 pProfObj->hMap = CreateFileMapping(pProfObj->hFile, 0, 02874 (dwDesiredAccess == PROFILE_READWRITE) ? PAGE_READWRITE : PAGE_READONLY, 02875 0, dwMapSize, 0); 02876 02877 if (!pProfObj->hMap) 02878 { 02879 WARNING((__TEXT("Err %ld, could not create map of profile %s\n"), 02880 GetLastError(), pProfObj->pProfileData)); 02881 goto EndOpenColorProfile; 02882 } 02883 02884 pProfObj->dwMapSize = dwMapSize; 02885 02886 pProfObj->pView = (PBYTE)MapViewOfFile(pProfObj->hMap, 02887 (dwDesiredAccess == PROFILE_READWRITE) ? FILE_MAP_ALL_ACCESS : FILE_MAP_READ, 02888 0, 0, 0); 02889 02890 if (!pProfObj->pView) 02891 { 02892 WARNING((__TEXT("Err %ld, could not create view of profile %s\n"), 02893 GetLastError(), pProfObj->pProfileData)); 02894 goto EndOpenColorProfile; 02895 } 02896 02897 // 02898 // If a new profile has been created, initialize size 02899 // and tag table count 02900 // 02901 if (bNewFile && dwDesiredAccess == PROFILE_READWRITE) 02902 { 02903 HEADER(pProfObj)->phSize = FIX_ENDIAN(sizeof(PROFILEHEADER) + 02904 sizeof(DWORD)); 02905 HEADER(pProfObj)->phVersion = 0x02000000; 02906 HEADER(pProfObj)->phSignature = PROFILE_SIGNATURE; 02907 TAG_COUNT(pProfObj) = 0; 02908 } 02909 } 02910 else 02911 { 02912 if (pProfile->cbDataSize == 0) 02913 { 02914 // 02915 // Allocate a small buffer and create a new profile in it 02916 // 02917 02918 pProfObj->cbDataSize = PROFILE_GROWTHCUSHION; 02919 MemFree(pProfObj->pProfileData); 02920 pProfObj->pView = pProfObj->pProfileData = MemAlloc(pProfObj->cbDataSize); 02921 if (!pProfObj->pView) 02922 { 02923 WARNING((__TEXT("Could not allocate memory for profile data\n"))); 02924 SetLastError(ERROR_NOT_ENOUGH_MEMORY); 02925 goto EndOpenColorProfile; 02926 } 02927 02928 HEADER(pProfObj)->phSize = FIX_ENDIAN(sizeof(PROFILEHEADER) + 02929 sizeof(DWORD)); 02930 HEADER(pProfObj)->phVersion = 0x02000000; 02931 HEADER(pProfObj)->phSignature = PROFILE_SIGNATURE; 02932 TAG_COUNT(pProfObj) = 0; 02933 pProfObj->dwMapSize = pProfObj->cbDataSize; 02934 } 02935 else 02936 { 02937 // 02938 // Treat buffer as view of file 02939 // 02940 02941 pProfObj->pView = pProfObj->pProfileData; 02942 pProfObj->dwMapSize = pProfObj->cbDataSize; 02943 02944 // 02945 // Do a sanity check on the profile 02946 // 02947 02948 if (!ValidProfile(pProfObj)) 02949 { 02950 WARNING((__TEXT("Invalid profile passed to OpenColorProfile\n"))); 02951 SetLastError(ERROR_INVALID_PROFILE); 02952 goto EndOpenColorProfile; 02953 } 02954 } 02955 } 02956 02957 if (dwDesiredAccess == PROFILE_READWRITE) 02958 pProfObj->dwFlags |= READWRITE_ACCESS; 02959 02960 bError = FALSE; // Success! 02961 02962 EndOpenColorProfile: 02963 02964 if (bError) 02965 { 02966 if (hProfile) 02967 FreeProfileObject(hProfile); 02968 hProfile = NULL; 02969 } 02970 02971 return hProfile; 02972 } 02973 02974 02975 /****************************************************************************** 02976 * 02977 * InternalCreateProfileFromLCS 02978 * 02979 * Function: 02980 * This functions takes a logical color space and creates an ICC profile 02981 * 02982 * Arguments: 02983 * pLogColorSpace - Pointer to LogColorSpace structure 02984 * pBuffer - Pointer to pointer to buffer. This function allocates and 02985 * fills this buffer with the profile on success. 02986 * 02987 * Returns: 02988 * TRUE if successful, FALSE otherwise 02989 * 02990 ******************************************************************************/ 02991 02992 BOOL InternalCreateProfileFromLCS( 02993 LPLOGCOLORSPACE pLogColorSpace, 02994 PBYTE *pBuffer, 02995 BOOL bValidateParams 02996 ) 02997 { 02998 PCMMOBJ pCMMObj = NULL; 02999 BOOL rc; 03000 03001 // 03002 // Validate parameters 03003 // 03004 03005 if (bValidateParams && 03006 (! pLogColorSpace || 03007 IsBadReadPtr(pLogColorSpace, sizeof(LOGCOLORSPACE)) || 03008 pLogColorSpace->lcsFilename[0] != '\0')) 03009 { 03010 WARNING((__TEXT("Invalid parameter to CreateProfileFromLogColorSpace\n"))); 03011 SetLastError(ERROR_INVALID_PARAMETER); 03012 return FALSE; 03013 } 03014 03015 // 03016 // We use the default CMM for this 03017 // 03018 03019 pCMMObj = GetColorMatchingModule(CMM_WINDOWS_DEFAULT); 03020 if (!pCMMObj) 03021 { 03022 RIP((__TEXT("Default CMM not found\n"))); 03023 SetLastError(ERROR_INVALID_CMM); 03024 return FALSE; 03025 } 03026 03027 03028 ASSERT(pCMMObj->fns.pCMCreateProfile != NULL); 03029 03030 rc = pCMMObj->fns.pCMCreateProfile(pLogColorSpace, pBuffer); 03031 03032 ReleaseColorMatchingModule(pCMMObj); 03033 03034 return rc; 03035 } 03036 03037 03038 /****************************************************************************** 03039 * 03040 * FreeProfileObject 03041 * 03042 * Function: 03043 * This functions frees a profile object and associated memory 03044 * 03045 * Arguments: 03046 * hProfile - handle identifing the profile object to free 03047 * 03048 * Returns: 03049 * TRUE if successful, FALSE otherwise 03050 * 03051 ******************************************************************************/ 03052 03053 BOOL FreeProfileObject( 03054 HANDLE hProfile 03055 ) 03056 { 03057 PPROFOBJ pProfObj; 03058 DWORD dwFileSize; 03059 DWORD dwErr; 03060 03061 ASSERT(hProfile != NULL); 03062 03063 pProfObj = (PPROFOBJ)HDLTOPTR(hProfile); 03064 03065 ASSERT(pProfObj != NULL); 03066 03067 dwErr = GetLastError(); // remember any errors we may have set 03068 03069 // 03070 // Free memory associated with profile data 03071 // 03072 03073 if (pProfObj->pProfileData) 03074 MemFree((PVOID)pProfObj->pProfileData); 03075 03076 // 03077 // If it a memory mapped profile, unmap it 03078 // 03079 03080 if (pProfObj->dwFlags & MEMORY_MAPPED) 03081 { 03082 if (pProfObj->pView) 03083 { 03084 dwFileSize = FIX_ENDIAN(HEADER(pProfObj)->phSize); 03085 UnmapViewOfFile(pProfObj->pView); 03086 } 03087 if (pProfObj->hMap) 03088 CloseHandle(pProfObj->hMap); 03089 03090 if (pProfObj->hFile) 03091 { 03092 03093 // 03094 // Set the size of the file correctly 03095 // 03096 03097 SetFilePointer(pProfObj->hFile, dwFileSize, NULL, FILE_BEGIN); 03098 SetEndOfFile(pProfObj->hFile); 03099 CloseHandle(pProfObj->hFile); 03100 } 03101 } 03102 03103 // 03104 // Free heap object 03105 // 03106 03107 pProfObj->objHdr.dwUseCount--; // decrement before freeing 03108 FreeHeapObject(hProfile); 03109 03110 if (dwErr) 03111 { 03112 SetLastError(dwErr); // reset our error 03113 } 03114 03115 return TRUE; 03116 } 03117 03118 03119 /****************************************************************************** 03120 * 03121 * GrowProfile 03122 * 03123 * Function: 03124 * This functions grows a profile to the new size 03125 * 03126 * Arguments: 03127 * pProfObj - pointer to profile object 03128 * dwNewSize - new size for the profile 03129 * 03130 * Returns: 03131 * TRUE if successful, FALSE otherwise 03132 * 03133 ******************************************************************************/ 03134 03135 BOOL GrowProfile( 03136 PPROFOBJ pProfObj, 03137 DWORD dwNewSize 03138 ) 03139 { 03140 if (pProfObj->dwMapSize >= dwNewSize) 03141 return TRUE; 03142 03143 // 03144 // Add cushion for future growth 03145 // 03146 03147 dwNewSize += PROFILE_GROWTHCUSHION; 03148 03149 if (pProfObj->dwFlags & MEMORY_MAPPED) 03150 { 03151 // 03152 // Profile is a memory mapped file 03153 // 03154 03155 // 03156 // Close previous view and map 03157 // 03158 03159 UnmapViewOfFile(pProfObj->pView); 03160 CloseHandle(pProfObj->hMap); 03161 03162 pProfObj->hMap = CreateFileMapping(pProfObj->hFile, 0, 03163 PAGE_READWRITE, 0, dwNewSize, 0); 03164 03165 if (!pProfObj->hMap) 03166 { 03167 WARNING((__TEXT("Err %ld, could not recreate map of profile %s\n"), 03168 GetLastError(), pProfObj->pProfileData)); 03169 return FALSE; 03170 } 03171 03172 pProfObj->pView = (PBYTE) MapViewOfFile(pProfObj->hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0); 03173 if (!pProfObj->pView) 03174 { 03175 WARNING((__TEXT("Err %ld, could not recreate view of profile %s\n"), 03176 GetLastError(), pProfObj->pProfileData)); 03177 return FALSE; 03178 } 03179 03180 03181 // 03182 // Set new size 03183 // 03184 03185 pProfObj->dwMapSize = dwNewSize; 03186 } 03187 else 03188 { 03189 // 03190 // Profile is an in-memory buffer 03191 // 03192 03193 PVOID pTemp = MemReAlloc(pProfObj->pView, dwNewSize); 03194 03195 if (!pTemp) 03196 { 03197 WARNING((__TEXT("Error reallocating memory\n"))); 03198 return FALSE; 03199 } 03200 03201 pProfObj->pView = pProfObj->pProfileData = pTemp; 03202 pProfObj->cbDataSize = pProfObj->dwMapSize = dwNewSize; 03203 } 03204 03205 return TRUE; 03206 } 03207 03208 03209 /****************************************************************************** 03210 * 03211 * AddTagTableEntry 03212 * 03213 * Function: 03214 * This functions adds a tag to the tag table 03215 * 03216 * Arguments: 03217 * pProfObj - pointer to profile object 03218 * tagType - tag to add 03219 * dwOffset - offset of tag data from start of file 03220 * cbSize - size of tag data 03221 * bNewData - TRUE if new tag is not a reference to existing data 03222 * 03223 * Returns: 03224 * TRUE if successful, FALSE otherwise 03225 * 03226 ******************************************************************************/ 03227 03228 BOOL AddTagTableEntry( 03229 PPROFOBJ pProfObj, 03230 TAGTYPE tagType, 03231 DWORD dwOffset, 03232 DWORD cbSize, 03233 BOOL bNewData 03234 ) 03235 { 03236 PTAGDATA pTagData; 03237 PBYTE src, dest; 03238 DWORD nCount; 03239 DWORD cnt, i; 03240 03241 // 03242 // Get count of tag items - it is right after the profile header 03243 // 03244 03245 nCount = TAG_COUNT(pProfObj); 03246 nCount = FIX_ENDIAN(nCount); 03247 03248 // 03249 // Increase count of tag elements by 1, and add new tag to end of 03250 // tag table. Move all data below tag table downwards by the size 03251 // of one tag table entry. 03252 // 03253 03254 nCount++; 03255 03256 dest = (PBYTE)TAG_DATA(pProfObj) + nCount * sizeof(TAGDATA); 03257 src = (PBYTE)TAG_DATA(pProfObj) + (nCount - 1) * sizeof(TAGDATA); 03258 03259 // 03260 // # bytes to move = file size - header - tag count - tag table 03261 // 03262 03263 cnt = FIX_ENDIAN(HEADER(pProfObj)->phSize) - sizeof(PROFILEHEADER) - 03264 sizeof(DWORD) - (nCount - 1) * sizeof(TAGDATA); 03265 03266 if (cnt > 0) 03267 { 03268 // 03269 // NOTE: CopyMemory() doesn't work for overlapped memory. 03270 // Use internal function instead. 03271 // 03272 03273 MyCopyMemory((PVOID)dest, (PVOID)src, cnt); 03274 } 03275 03276 TAG_COUNT(pProfObj) = FIX_ENDIAN(nCount); 03277 03278 pTagData = (PTAGDATA)src; 03279 pTagData->tagType = FIX_ENDIAN(tagType); 03280 pTagData->cbSize = FIX_ENDIAN(cbSize); 03281 pTagData->dwOffset = FIX_ENDIAN(dwOffset); 03282 03283 // 03284 // Go through the tag table and update the offsets of all elements 03285 // by the size of one tag table entry that we inserted. 03286 // 03287 03288 pTagData = TAG_DATA(pProfObj); 03289 for (i=0; i<nCount; i++) 03290 { 03291 cnt = FIX_ENDIAN(pTagData->dwOffset); 03292 cnt += sizeof(TAGDATA); 03293 pTagData->dwOffset = FIX_ENDIAN(cnt); 03294 pTagData++; // Next element 03295 } 03296 03297 // 03298 // Set final file size 03299 // 03300 03301 cnt = DWORD_ALIGN(FIX_ENDIAN(HEADER(pProfObj)->phSize)) + sizeof(TAGDATA); 03302 if (bNewData) 03303 { 03304 // 03305 // The new tag is not a reference to an old tag. Increment 03306 // file size of size of new data also 03307 // 03308 03309 cnt += cbSize; 03310 } 03311 HEADER(pProfObj)->phSize = FIX_ENDIAN(cnt); 03312 03313 return TRUE; 03314 } 03315 03316 03317 /****************************************************************************** 03318 * 03319 * AddTaggedElement 03320 * 03321 * Function: 03322 * This functions adds a new tagged element to a profile 03323 * 03324 * Arguments: 03325 * pProfObj - pointer to profile object 03326 * tagType - tag to add 03327 * cbSize - size of tag data 03328 * 03329 * Returns: 03330 * TRUE if successful, FALSE otherwise 03331 * 03332 ******************************************************************************/ 03333 03334 BOOL AddTaggedElement( 03335 PPROFOBJ pProfObj, 03336 TAGTYPE tagType, 03337 DWORD cbSize 03338 ) 03339 { 03340 DWORD dwOffset, newSize; 03341 03342 ASSERT(pProfObj != NULL); 03343 ASSERT(cbSize > 0); 03344 03345 // 03346 // Resize the profile if needed. For memory buffers, we have to realloc, 03347 // and for mapped objects, we have to close and reopen the view. 03348 // 03349 03350 newSize = FIX_ENDIAN(HEADER(pProfObj)->phSize); 03351 newSize = DWORD_ALIGN(newSize) + sizeof(TAGDATA) + cbSize; 03352 03353 // 03354 // Check for overflow 03355 // 03356 03357 if (newSize < FIX_ENDIAN(HEADER(pProfObj)->phSize) || 03358 newSize < cbSize) 03359 { 03360 WARNING((__TEXT("Overflow in adding element\n"))); 03361 SetLastError(ERROR_ARITHMETIC_OVERFLOW); 03362 return FALSE; 03363 } 03364 03365 if (newSize > pProfObj->dwMapSize) 03366 { 03367 if (! GrowProfile(pProfObj, newSize)) 03368 { 03369 return FALSE; 03370 } 03371 } 03372 03373 // 03374 // Calculate location of new data - should be DWORD aligned 03375 // 03376 03377 dwOffset = FIX_ENDIAN(HEADER(pProfObj)->phSize); 03378 dwOffset = DWORD_ALIGN(dwOffset); 03379 03380 return AddTagTableEntry(pProfObj, tagType, dwOffset, cbSize, TRUE); 03381 } 03382 03383 03384 /****************************************************************************** 03385 * 03386 * DeleteTaggedElement 03387 * 03388 * Function: 03389 * This functions deletes a tagged element from the profile 03390 * 03391 * Arguments: 03392 * pProfObj - pointer to profile object 03393 * pTagData - pointer to tagged element to delete 03394 * 03395 * Returns: 03396 * TRUE if successful, FALSE otherwise 03397 * 03398 ******************************************************************************/ 03399 03400 BOOL DeleteTaggedElement( 03401 PPROFOBJ pProfObj, 03402 PTAGDATA pTagData 03403 ) 03404 { 03405 PBYTE pData; 03406 PTAGDATA pTemp; 03407 DWORD cbSize, nCount, dwOffset, i; 03408 03409 // 03410 // Remember location of data and move everything upto the data upwards 03411 // by size of one tag table entry. Then move everything below the tag data 03412 // upward by size of data plus size of one tage table entry. 03413 // 03414 03415 pData = VIEW(pProfObj) + FIX_ENDIAN(pTagData->dwOffset); 03416 cbSize = FIX_ENDIAN(pTagData->cbSize); 03417 cbSize = DWORD_ALIGN(cbSize); 03418 dwOffset = FIX_ENDIAN(pTagData->dwOffset); 03419 03420 MoveProfileData(pProfObj, (PBYTE)(pTagData+1), (PBYTE)pTagData, 03421 (LONG)(pData-(PBYTE)(pTagData+1)), FALSE); 03422 03423 // 03424 // Do not attempt to move data past the tag if we are deleting the last tag 03425 // 03426 03427 if (pData + cbSize < VIEW(pProfObj) + PROFILE_SIZE(pProfObj)) 03428 { 03429 MoveProfileData(pProfObj, pData+cbSize, pData-sizeof(TAGDATA), 03430 PROFILE_SIZE(pProfObj)-(LONG)(pData - VIEW(pProfObj)) - cbSize, TRUE); 03431 } 03432 03433 // 03434 // Get count of tag items - it is right after the profile header, and 03435 // decrement it by one. 03436 // 03437 03438 nCount = TAG_COUNT(pProfObj); 03439 nCount = FIX_ENDIAN(nCount) - 1; 03440 TAG_COUNT(pProfObj) = FIX_ENDIAN(nCount); 03441 03442 // 03443 // Go through the tag table and update the pointers 03444 // 03445 03446 pTemp = TAG_DATA(pProfObj); 03447 03448 for (i=0; i<nCount; i++) 03449 { 03450 DWORD dwTemp = FIX_ENDIAN(pTemp->dwOffset); 03451 03452 if (dwTemp > dwOffset) 03453 { 03454 dwTemp -= cbSize; // cbSize already DWORD aligned 03455 } 03456 dwTemp -= sizeof(TAGDATA); 03457 pTemp->dwOffset = FIX_ENDIAN(dwTemp); 03458 pTemp++; // Next record 03459 } 03460 03461 // 03462 // Use nCount as a placeholder to calculate file size 03463 // 03464 03465 nCount = DWORD_ALIGN(FIX_ENDIAN(HEADER(pProfObj)->phSize)); 03466 nCount -= sizeof(TAGDATA) + cbSize; 03467 HEADER(pProfObj)->phSize = FIX_ENDIAN(nCount); 03468 03469 return TRUE; 03470 } 03471 03472 03473 /****************************************************************************** 03474 * 03475 * ChangeTaggedElementSize 03476 * 03477 * Function: 03478 * This functions changes the size of a tagged element in the profile 03479 * 03480 * Arguments: 03481 * pProfObj - pointer to profile object 03482 * pTagData - pointer to tagged element whose size is to be changed 03483 * cbSize - new size for the element 03484 * 03485 * Returns: 03486 * TRUE if successful, FALSE otherwise 03487 * 03488 ******************************************************************************/ 03489 03490 BOOL ChangeTaggedElementSize( 03491 PPROFOBJ pProfObj, 03492 PTAGDATA pTagData, 03493 DWORD cbSize 03494 ) 03495 { 03496 PTAGDATA pTemp; 03497 PBYTE pData; 03498 DWORD nCount, cbOldSize; 03499 DWORD dwOffset, cnt, i; 03500 03501 ASSERT(pProfObj != NULL); 03502 ASSERT(cbSize > 0); 03503 03504 // 03505 // Get current size of element 03506 // 03507 03508 cbOldSize = FIX_ENDIAN(pTagData->cbSize); 03509 03510 if (cbOldSize == cbSize) 03511 { 03512 return TRUE; // Sizes are the same - Do nothing 03513 } 03514 pData = VIEW(pProfObj) + FIX_ENDIAN(pTagData->dwOffset); 03515 03516 // 03517 // Do not attempt to move data beyond end of file. There is no need to move 03518 // anything if the last data item is being resized. 03519 // 03520 03521 if (pData + DWORD_ALIGN(cbOldSize) < VIEW(pProfObj) + PROFILE_SIZE(pProfObj)) 03522 { 03523 MoveProfileData(pProfObj, pData + DWORD_ALIGN(cbOldSize), pData + DWORD_ALIGN(cbSize), 03524 PROFILE_SIZE(pProfObj) - (LONG)(pData - VIEW(pProfObj)) - DWORD_ALIGN(cbOldSize), TRUE); 03525 } 03526 03527 pTagData->cbSize = FIX_ENDIAN(cbSize); // Set the new size 03528 03529 // 03530 // Get count of tag items - it is right after the profile header 03531 // 03532 03533 nCount = TAG_COUNT(pProfObj); 03534 nCount = FIX_ENDIAN(nCount); 03535 03536 // 03537 // Go through the tag table and update the pointers 03538 // 03539 03540 pTemp = TAG_DATA(pProfObj); 03541 03542 dwOffset = FIX_ENDIAN(pTagData->dwOffset); 03543 for (i=0; i<nCount; i++) 03544 { 03545 DWORD dwTemp = FIX_ENDIAN(pTemp->dwOffset); 03546 03547 if (dwTemp > dwOffset) 03548 { 03549 dwTemp += DWORD_ALIGN(cbSize) - DWORD_ALIGN(cbOldSize); 03550 pTemp->dwOffset = FIX_ENDIAN(dwTemp); 03551 } 03552 pTemp++; // Next record 03553 } 03554 03555 // 03556 // Use cnt as a placeholder to calculate file size 03557 // 03558 03559 cnt = FIX_ENDIAN(HEADER(pProfObj)->phSize); 03560 cnt += DWORD_ALIGN(cbSize) - DWORD_ALIGN(cbOldSize); 03561 HEADER(pProfObj)->phSize = FIX_ENDIAN(cnt); 03562 03563 return TRUE; 03564 } 03565 03566 03567 /****************************************************************************** 03568 * 03569 * MoveProfileData 03570 * 03571 * Function: 03572 * This function moves data in a profile up or down (from src to dest), 03573 * and then zeroes out the end of the file or the extra space created. 03574 * 03575 * Arguments: 03576 * pProfObj - pointer to profile object 03577 * src - pointer to source of block to move 03578 * dest - pointer to destination for block to move to 03579 * cnt - number of bytes to move 03580 * 03581 * Returns: 03582 * TRUE if successful, FALSE otherwise 03583 * 03584 ******************************************************************************/ 03585 03586 void MoveProfileData( 03587 PPROFOBJ pProfObj, 03588 PBYTE src, 03589 PBYTE dest, 03590 LONG cnt, 03591 BOOL bZeroMemory 03592 ) 03593 { 03594 // 03595 // NOTE: CopyMemory() doesn't work for overlapped memory. 03596 // Use internal function instead. 03597 // 03598 03599 MyCopyMemory((PVOID)dest, (PVOID)src, cnt); 03600 03601 if (bZeroMemory) 03602 { 03603 cnt = ABS((LONG)(dest - src)); 03604 03605 if (dest < src) 03606 { 03607 // 03608 // Size decreased, so zero out end of file 03609 // 03610 03611 dest = VIEW(pProfObj) + FIX_ENDIAN(HEADER(pProfObj)->phSize) - 03612 (src - dest); 03613 } 03614 else 03615 { 03616 // 03617 // Size increased, so zero out the increased tagdata 03618 // 03619 03620 dest = src; 03621 } 03622 ZeroMemory(dest, cnt); 03623 } 03624 03625 return; 03626 } 03627 03628 03629 /****************************************************************************** 03630 * 03631 * IsReferenceTag 03632 * 03633 * Function: 03634 * This function checks if a given tag's data is referred to by another 03635 * tag in the profile 03636 * 03637 * Arguments: 03638 * pProfObj - pointer to profile object 03639 * pTagData - pointer to tagdata which should be checked 03640 * 03641 * Returns: 03642 * TRUE if it is a referece, FALSE otherwise 03643 * 03644 ******************************************************************************/ 03645 03646 BOOL IsReferenceTag( 03647 PPROFOBJ pProfObj, 03648 PTAGDATA pTagData 03649 ) 03650 { 03651 PTAGDATA pTemp; 03652 DWORD nCount, i; 03653 BOOL bReference = FALSE; 03654 03655 pTemp = TAG_DATA(pProfObj); 03656 nCount = TAG_COUNT(pProfObj); 03657 nCount = FIX_ENDIAN(nCount); 03658 03659 for (i=0; i<nCount; i++) 03660 { 03661 if ((pTagData->dwOffset == pTemp->dwOffset) && 03662 (pTagData->tagType != pTemp->tagType)) 03663 { 03664 bReference = TRUE; 03665 break; 03666 } 03667 pTemp++; // next record 03668 } 03669 03670 return bReference; 03671 } 03672

Generated on Sat May 15 19:41:28 2004 for test by doxygen 1.3.7