test: profile.c Source File

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