From: Hans Leidekker Date: Tue, 30 Nov 2004 21:06:14 +0000 (+0000) Subject: Infrastructure for handling ICC profiles. X-Git-Tag: wine-20041201~13 X-Git-Url: http://git.etersoft.ru/projects/?a=commitdiff_plain;h=7c98f0115908aae9c25505fea1aee1f29f3dc02e;p=wine%2Feterwine.git Infrastructure for handling ICC profiles. Always load color profiles into memory. Implement and test GetColorProfileElement and GetColorProfileHeader. Implement GetColorProfileFromHandle and SetColorProfileHeader. --- diff --git a/dlls/mscms/handle.c b/dlls/mscms/handle.c index c13c46c00c..8cbce6f12c 100644 --- a/dlls/mscms/handle.c +++ b/dlls/mscms/handle.c @@ -41,15 +41,16 @@ static CRITICAL_SECTION_DEBUG MSCMS_handle_cs_debug = }; static CRITICAL_SECTION MSCMS_handle_cs = { &MSCMS_handle_cs_debug, -1, 0, 0, 0, 0 }; -/* A simple structure to tie together Windows file handles and lcms color - * profile handles. Windows color profile handles are built from indexes - * into an array of these structures. The 'file' field is set to NULL in - * case of a memory based profile +/* A simple structure to tie together a pointer to an icc profile, an lcms + * color profile handle and a Windows file handle. Windows color profile + * handles are built from indexes into an array of these structures. If + * the profile is memory based the file handle field is NULL. */ struct handlemap { HANDLE file; + icProfile *iccprofile; cmsHPROFILE cmsprofile; }; @@ -57,12 +58,50 @@ struct handlemap static struct handlemap handlemaptable[CMSMAXHANDLES]; +HPROFILE MSCMS_handle2hprofile( HANDLE file ) +{ + HPROFILE profile = NULL; + unsigned int i; + + if (!file) return NULL; + + EnterCriticalSection( &MSCMS_handle_cs ); + + for (i = 0; i <= CMSMAXHANDLES; i++) + { + if (handlemaptable[i].file == file) + { + profile = (HPROFILE)(i + 1); goto out; + } + } + +out: + LeaveCriticalSection( &MSCMS_handle_cs ); + + return profile; +} + +HANDLE MSCMS_hprofile2handle( HPROFILE profile ) +{ + HANDLE file; + unsigned int i; + + EnterCriticalSection( &MSCMS_handle_cs ); + + i = (unsigned int)profile - 1; + file = handlemaptable[i].file; + + LeaveCriticalSection( &MSCMS_handle_cs ); + + return file; +} + HPROFILE MSCMS_cmsprofile2hprofile( cmsHPROFILE cmsprofile ) { - HPROFILE ret = NULL; + HPROFILE profile = NULL; unsigned int i; - if (!cmsprofile) return ret; + if (!cmsprofile) return NULL; EnterCriticalSection( &MSCMS_handle_cs ); @@ -70,70 +109,94 @@ HPROFILE MSCMS_cmsprofile2hprofile( cmsHPROFILE cmsprofile ) { if (handlemaptable[i].cmsprofile == cmsprofile) { - ret = (HPROFILE)(i + 1); goto out; + profile = (HPROFILE)(i + 1); goto out; } } out: LeaveCriticalSection( &MSCMS_handle_cs ); - return ret; + return profile; } cmsHPROFILE MSCMS_hprofile2cmsprofile( HPROFILE profile ) { - HANDLE ret; + cmsHPROFILE cmshprofile; unsigned int i; EnterCriticalSection( &MSCMS_handle_cs ); i = (unsigned int)profile - 1; - ret = handlemaptable[i].cmsprofile; + cmshprofile = handlemaptable[i].cmsprofile; LeaveCriticalSection( &MSCMS_handle_cs ); - return ret; + return cmshprofile; } -HANDLE MSCMS_hprofile2handle( HPROFILE profile ) +HPROFILE MSCMS_iccprofile2hprofile( icProfile *iccprofile ) +{ + HPROFILE profile = NULL; + unsigned int i; + + if (!iccprofile) return NULL; + + EnterCriticalSection( &MSCMS_handle_cs ); + + for (i = 0; i <= CMSMAXHANDLES; i++) + { + if (handlemaptable[i].iccprofile == iccprofile) + { + profile = (HPROFILE)(i + 1); goto out; + } + } + +out: + LeaveCriticalSection( &MSCMS_handle_cs ); + + return profile; +} + +icProfile *MSCMS_hprofile2iccprofile( HPROFILE profile ) { - HANDLE ret; + icProfile *iccprofile; unsigned int i; EnterCriticalSection( &MSCMS_handle_cs ); i = (unsigned int)profile - 1; - ret = handlemaptable[i].file; + iccprofile = handlemaptable[i].iccprofile; LeaveCriticalSection( &MSCMS_handle_cs ); - return ret; + return iccprofile; } -HPROFILE MSCMS_create_hprofile_handle( HANDLE file, cmsHPROFILE cmsprofile ) +HPROFILE MSCMS_create_hprofile_handle( HANDLE file, icProfile *iccprofile, cmsHPROFILE cmsprofile ) { - HPROFILE ret = NULL; + HPROFILE profile = NULL; unsigned int i; - if (!cmsprofile) return ret; + if (!cmsprofile || !iccprofile) return NULL; EnterCriticalSection( &MSCMS_handle_cs ); for (i = 0; i <= CMSMAXHANDLES; i++) { - if (handlemaptable[i].cmsprofile == 0) + if (handlemaptable[i].iccprofile == 0) { handlemaptable[i].file = file; + handlemaptable[i].iccprofile = iccprofile; handlemaptable[i].cmsprofile = cmsprofile; - ret = (HPROFILE)(i + 1); goto out; + profile = (HPROFILE)(i + 1); goto out; } } out: LeaveCriticalSection( &MSCMS_handle_cs ); - return ret; + return profile; } void MSCMS_destroy_hprofile_handle( HPROFILE profile ) diff --git a/dlls/mscms/mscms.spec b/dlls/mscms/mscms.spec index 075de40b9b..f5dc86c99a 100644 --- a/dlls/mscms/mscms.spec +++ b/dlls/mscms/mscms.spec @@ -20,10 +20,10 @@ @ stub GetCMMInfo @ stdcall GetColorDirectoryA(ptr ptr long) @ stdcall GetColorDirectoryW(ptr ptr long) -@ stub GetColorProfileElement +@ stdcall GetColorProfileElement(ptr long long ptr ptr ptr) @ stdcall GetColorProfileElementTag(ptr long ptr) -@ stub GetColorProfileFromHandle -@ stub GetColorProfileHeader +@ stdcall GetColorProfileFromHandle(ptr ptr ptr) +@ stdcall GetColorProfileHeader(ptr ptr) @ stdcall GetCountColorProfileElements(ptr long) @ stub GetNamedProfileInfo @ stub GetPS2ColorRenderingDictionary @@ -49,7 +49,7 @@ @ stub SetColorProfileElement @ stub SetColorProfileElementReference @ stub SetColorProfileElementSize -@ stub SetColorProfileHeader +@ stdcall SetColorProfileHeader(ptr ptr) @ stub SetStandardColorSpaceProfileA @ stub SetStandardColorSpaceProfileW @ stub SpoolerCopyFileEvent diff --git a/dlls/mscms/mscms_priv.h b/dlls/mscms/mscms_priv.h index d5bc570c21..8a96cbc9c5 100644 --- a/dlls/mscms/mscms_priv.h +++ b/dlls/mscms/mscms_priv.h @@ -25,7 +25,7 @@ #ifdef HAVE_LCMS_H /* These basic Windows types are defined in lcms.h when compiling on - * a non-Windows platforms (why?), so they would normally not conflict + * a non-Windows platform (why?), so they would normally not conflict * with anything included earlier. But since we are building Wine they * most certainly will have been defined before we include lcms.h. * The preprocessor comes to the rescue. @@ -68,11 +68,14 @@ #define DWORD DWORD #define LPDWORD LPDWORD +extern HPROFILE MSCMS_handle2hprofile( HANDLE file ); extern HPROFILE MSCMS_cmsprofile2hprofile( cmsHPROFILE cmsprofile ); -extern cmsHPROFILE MSCMS_hprofile2cmsprofile( HPROFILE profile ); +extern HPROFILE MSCMS_iccprofile2hprofile( icProfile *iccprofile ); extern HANDLE MSCMS_hprofile2handle( HPROFILE profile ); +extern cmsHPROFILE MSCMS_hprofile2cmsprofile( HPROFILE profile ); +extern icProfile *MSCMS_hprofile2iccprofile( HPROFILE profile ); -extern HPROFILE MSCMS_create_hprofile_handle( HANDLE file, cmsHPROFILE cmsprofile ); +extern HPROFILE MSCMS_create_hprofile_handle( HANDLE file, icProfile *iccprofile, cmsHPROFILE cmsprofile ); extern void MSCMS_destroy_hprofile_handle( HPROFILE profile ); #endif /* HAVE_LCMS_H */ diff --git a/dlls/mscms/profile.c b/dlls/mscms/profile.c index 7535e3de62..61da583a5d 100644 --- a/dlls/mscms/profile.c +++ b/dlls/mscms/profile.c @@ -44,6 +44,144 @@ static void MSCMS_basename( LPCWSTR path, LPWSTR name ) lstrcpyW( name, &path[i] ); } +#ifdef HAVE_LCMS_H +static BOOL MSCMS_cpu_is_little_endian() +{ + long l = 1; + void *p = &l; + char b = *(char *)p; + + return b ? TRUE : FALSE; +} + +static void MSCMS_endian_swap16( BYTE *byte ) +{ + BYTE tmp; + + tmp = byte[0]; + byte[0] = byte[1]; + byte[1] = tmp; +} + +static void MSCMS_endian_swap32( BYTE *byte ) +{ + BYTE tmp1, tmp2; + + tmp1 = *byte++; + tmp2 = *byte++; + + *(byte - 1) = *byte; + *byte++ = tmp2; + *(byte - 3) = *byte; + *byte = tmp1; +} + +static void MSCMS_adjust_endianess32( BYTE *byte ) +{ + if (MSCMS_cpu_is_little_endian()) + MSCMS_endian_swap32( byte ); +} + +static void MSCMS_get_profile_header( icProfile *iccprofile, PROFILEHEADER *header ) +{ + memcpy( header, iccprofile, sizeof(PROFILEHEADER) ); + + /* ICC format is big-endian, swap bytes if necessary */ + + if (MSCMS_cpu_is_little_endian()) + { + MSCMS_endian_swap32( (BYTE *)&header->phSize ); + MSCMS_endian_swap32( (BYTE *)&header->phCMMType ); + MSCMS_endian_swap32( (BYTE *)&header->phVersion ); + MSCMS_endian_swap32( (BYTE *)&header->phClass ); + MSCMS_endian_swap32( (BYTE *)&header->phDataColorSpace ); + MSCMS_endian_swap32( (BYTE *)&header->phConnectionSpace ); + + MSCMS_endian_swap32( (BYTE *)&header->phDateTime[0] ); + MSCMS_endian_swap32( (BYTE *)&header->phDateTime[1] ); + MSCMS_endian_swap32( (BYTE *)&header->phDateTime[2] ); + + MSCMS_endian_swap32( (BYTE *)&header->phSignature ); + MSCMS_endian_swap32( (BYTE *)&header->phPlatform ); + MSCMS_endian_swap32( (BYTE *)&header->phProfileFlags ); + MSCMS_endian_swap32( (BYTE *)&header->phManufacturer ); + MSCMS_endian_swap32( (BYTE *)&header->phModel ); + + MSCMS_endian_swap32( (BYTE *)&header->phAttributes[0] ); + MSCMS_endian_swap32( (BYTE *)&header->phAttributes[1] ); + + MSCMS_endian_swap32( (BYTE *)&header->phRenderingIntent ); + MSCMS_endian_swap32( (BYTE *)&header->phIlluminant ); + MSCMS_endian_swap32( (BYTE *)&header->phCreator ); + } +} + +static void MSCMS_set_profile_header( icProfile *iccprofile, PROFILEHEADER *header ) +{ + icHeader *iccheader = (icHeader *)iccprofile; + + memcpy( iccprofile, header, sizeof(PROFILEHEADER) ); + + /* ICC format is big-endian, swap bytes if necessary */ + + if (MSCMS_cpu_is_little_endian()) + { + MSCMS_endian_swap32( (BYTE *)&iccheader->size ); + MSCMS_endian_swap32( (BYTE *)&iccheader->cmmId ); + MSCMS_endian_swap32( (BYTE *)&iccheader->version ); + MSCMS_endian_swap32( (BYTE *)&iccheader->deviceClass ); + MSCMS_endian_swap32( (BYTE *)&iccheader->colorSpace ); + MSCMS_endian_swap32( (BYTE *)&iccheader->pcs ); + + MSCMS_endian_swap16( (BYTE *)&iccheader->date.year ); + MSCMS_endian_swap16( (BYTE *)&iccheader->date.month ); + MSCMS_endian_swap16( (BYTE *)&iccheader->date.day ); + MSCMS_endian_swap16( (BYTE *)&iccheader->date.hours ); + MSCMS_endian_swap16( (BYTE *)&iccheader->date.minutes ); + MSCMS_endian_swap16( (BYTE *)&iccheader->date.seconds ); + + MSCMS_endian_swap32( (BYTE *)&iccheader->magic ); + MSCMS_endian_swap32( (BYTE *)&iccheader->platform ); + MSCMS_endian_swap32( (BYTE *)&iccheader->flags ); + MSCMS_endian_swap32( (BYTE *)&iccheader->manufacturer ); + MSCMS_endian_swap32( (BYTE *)&iccheader->model ); + + MSCMS_endian_swap32( (BYTE *)&iccheader->attributes[0] ); + MSCMS_endian_swap32( (BYTE *)&iccheader->attributes[1] ); + + MSCMS_endian_swap32( (BYTE *)&iccheader->renderingIntent ); + MSCMS_endian_swap32( (BYTE *)&iccheader->illuminant ); + MSCMS_endian_swap32( (BYTE *)&iccheader->creator ); + } +} + +static DWORD MSCMS_get_tag_count( icProfile *iccprofile ) +{ + DWORD count = iccprofile->count; + + MSCMS_adjust_endianess32( (BYTE *)&count ); + return count; +} + +static void MSCMS_get_tag_by_index( icProfile *iccprofile, DWORD index, icTag *tag ) +{ + icTag *tmp = (icTag *)&iccprofile->data + (index * sizeof(icTag)); + + tag->sig = tmp->sig; + tag->offset = tmp->offset; + tag->size = tmp->size; + + MSCMS_adjust_endianess32( (BYTE *)&tag->sig ); + MSCMS_adjust_endianess32( (BYTE *)&tag->offset ); + MSCMS_adjust_endianess32( (BYTE *)&tag->size ); +} + +static void MSCMS_get_tag_data( icProfile *iccprofile, icTag *tag, DWORD offset, void *buffer ) +{ + memcpy( buffer, (char *)iccprofile + tag->offset + offset, tag->size - offset ); +} +#endif /* HAVE_LCMS_H */ + WINE_DEFAULT_DEBUG_CHANNEL(mscms); /****************************************************************************** @@ -117,6 +255,43 @@ BOOL WINAPI GetColorDirectoryW( PCWSTR machine, PWSTR buffer, PDWORD size ) return FALSE; } +BOOL WINAPI GetColorProfileElement( HPROFILE profile, TAGTYPE type, DWORD offset, PDWORD size, + PVOID buffer, PBOOL ref ) +{ + BOOL ret = FALSE; +#ifdef HAVE_LCMS_H + icProfile *iccprofile = MSCMS_hprofile2iccprofile( profile ); + DWORD i, count; + icTag tag; + + TRACE( "( %p, 0x%08lx, %ld, %p, %p, %p )\n", profile, type, offset, size, buffer, ref ); + + if (!iccprofile || !ref) return FALSE; + count = MSCMS_get_tag_count( iccprofile ); + + for (i = 0; i < count; i++) + { + MSCMS_get_tag_by_index( iccprofile, i, &tag ); + + if (tag.sig == type) + { + if ((tag.size - offset) > *size || !buffer) + { + *size = (tag.size - offset); + return FALSE; + } + + MSCMS_get_tag_data( iccprofile, &tag, offset, buffer ); + + *ref = FALSE; /* FIXME: calculate properly */ + return TRUE; + } + } + +#endif /* HAVE_LCMS_H */ + return ret; +} + /****************************************************************************** * GetColorProfileElementTag [MSCMS.@] * @@ -135,20 +310,69 @@ BOOL WINAPI GetColorDirectoryW( PCWSTR machine, PWSTR buffer, PDWORD size ) * The tag table index starts at 1. * Use GetCountColorProfileElements to retrieve a count of tagged elements. */ -BOOL WINAPI GetColorProfileElementTag( HPROFILE profile, DWORD index, PTAGTYPE tag ) +BOOL WINAPI GetColorProfileElementTag( HPROFILE profile, DWORD index, PTAGTYPE type ) { BOOL ret = FALSE; #ifdef HAVE_LCMS_H - LCMSICCPROFILE *cmsprofile = (LCMSICCPROFILE *)MSCMS_hprofile2cmsprofile( profile ); + icProfile *iccprofile = MSCMS_hprofile2iccprofile( profile ); + DWORD count; + icTag tag; - TRACE( "( %p, %ld, %p )\n", profile, index, tag ); + TRACE( "( %p, %ld, %p )\n", profile, index, type ); - if (cmsprofile) + if (!iccprofile) return FALSE; + + count = MSCMS_get_tag_count( iccprofile ); + if (index > count) return FALSE; + + MSCMS_get_tag_by_index( iccprofile, index - 1, &tag ); + *type = tag.sig; + + ret = TRUE; + +#endif /* HAVE_LCMS_H */ + return ret; +} + +BOOL WINAPI GetColorProfileFromHandle( HPROFILE profile, PBYTE buffer, PDWORD size ) +{ + BOOL ret = FALSE; +#ifdef HAVE_LCMS_H + icProfile *iccprofile = MSCMS_hprofile2iccprofile( profile ); + PROFILEHEADER header; + + TRACE( "( %p, %p, %p )\n", profile, buffer, size ); + + if (!iccprofile) return FALSE; + MSCMS_get_profile_header( profile, &header ); + + if (!buffer || header.phSize > *size) { - *tag = cmsprofile->TagNames[index - 1]; - ret = TRUE; + *size = header.phSize; + return FALSE; } + /* FIXME: no endian conversion */ + memcpy( buffer, iccprofile, header.phSize ); + ret = TRUE; + +#endif /* HAVE_LCMS_H */ + return ret; +} + +BOOL WINAPI GetColorProfileHeader( HPROFILE profile, PPROFILEHEADER header ) +{ + BOOL ret = FALSE; +#ifdef HAVE_LCMS_H + icProfile *iccprofile = MSCMS_hprofile2iccprofile( profile ); + + TRACE( "( %p, %p )\n", profile, header ); + + if (!iccprofile || !header) return FALSE; + + MSCMS_get_profile_header( iccprofile, header ); + return TRUE; + #endif /* HAVE_LCMS_H */ return ret; } @@ -171,15 +395,13 @@ BOOL WINAPI GetCountColorProfileElements( HPROFILE profile, PDWORD count ) { BOOL ret = FALSE; #ifdef HAVE_LCMS_H - LCMSICCPROFILE *cmsprofile = (LCMSICCPROFILE *)MSCMS_hprofile2cmsprofile( profile ); + icProfile *iccprofile = MSCMS_hprofile2iccprofile( profile ); TRACE( "( %p, %p )\n", profile, count ); - if (cmsprofile) - { - *count = cmsprofile->TagCount; - ret = TRUE; - } + if (!count) return FALSE; + *count = MSCMS_get_tag_count( iccprofile ); + ret = TRUE; #endif /* HAVE_LCMS_H */ return ret; @@ -307,6 +529,8 @@ BOOL WINAPI IsColorProfileTagPresent( HPROFILE profile, TAGTYPE tag, PBOOL prese TRACE( "( %p, 0x%08lx, %p )\n", profile, tag, present ); + if (!present) return FALSE; + #ifdef HAVE_LCMS_H ret = cmsIsTag( MSCMS_hprofile2cmsprofile( profile ), tag ); @@ -330,9 +554,34 @@ BOOL WINAPI IsColorProfileTagPresent( HPROFILE profile, TAGTYPE tag, PBOOL prese */ BOOL WINAPI IsColorProfileValid( HPROFILE profile, PBOOL valid ) { - FIXME( "( %p, %p ) stub\n", profile, valid ); + BOOL ret = FALSE; +#ifdef HAVE_LCMS_H + icProfile *iccprofile = MSCMS_hprofile2iccprofile( profile ); + + TRACE( "( %p, %p )\n", profile, valid ); - return *valid = TRUE; + if (!valid) return FALSE; + if (iccprofile) return *valid = TRUE; + +#endif /* HAVE_LCMS_H */ + return ret; +} + +BOOL WINAPI SetColorProfileHeader( HPROFILE profile, PPROFILEHEADER header ) +{ + BOOL ret = FALSE; +#ifdef HAVE_LCMS_H + icProfile *iccprofile = MSCMS_hprofile2iccprofile( profile ); + + TRACE( "( %p, %p )\n", profile, header ); + + if (!iccprofile || !header) return FALSE; + + MSCMS_set_profile_header( iccprofile, header ); + return TRUE; + +#endif /* HAVE_LCMS_H */ + return ret; } /****************************************************************************** @@ -385,8 +634,7 @@ BOOL WINAPI UninstallColorProfileW( PCWSTR machine, PCWSTR profile, BOOL delete if (machine || !profile) return FALSE; - if (delete) - return DeleteFileW( profile ); + if (delete) return DeleteFileW( profile ); return TRUE; } @@ -450,12 +698,15 @@ HPROFILE WINAPI OpenColorProfileA( PPROFILE profile, DWORD access, DWORD sharing * Values for sharing: 0 (no sharing), FILE_SHARE_READ and/or FILE_SHARE_WRITE. * Values for creation: one of CREATE_NEW, CREATE_ALWAYS, OPEN_EXISTING, * OPEN_ALWAYS, TRUNCATE_EXISTING. + * Sharing and creation flags are ignored for memory based profiles. */ HPROFILE WINAPI OpenColorProfileW( PPROFILE profile, DWORD access, DWORD sharing, DWORD creation ) { #ifdef HAVE_LCMS_H cmsHPROFILE cmsprofile = NULL; + icProfile *iccprofile = NULL; HANDLE handle = NULL; + DWORD size; TRACE( "( %p, 0x%08lx, 0x%08lx, 0x%08lx )\n", profile, access, sharing, creation ); @@ -463,15 +714,19 @@ HPROFILE WINAPI OpenColorProfileW( PPROFILE profile, DWORD access, DWORD sharing if (profile->dwType & PROFILE_MEMBUFFER) { - FIXME( "Memory based profile not yet supported.\n" ); return NULL; + FIXME( "access flags not implemented for memory based profiles\n" ); + + iccprofile = profile->pProfileData; + size = profile->cbDataSize; + + cmsprofile = cmsOpenProfileFromMem( iccprofile, size ); } if (profile->dwType & PROFILE_FILENAME) { - char *unixname; - DWORD flags = 0; + DWORD read, flags = 0; - TRACE("profile file: %s\n", debugstr_w( (WCHAR *)profile->pProfileData )); + TRACE( "profile file: %s\n", debugstr_w( (WCHAR *)profile->pProfileData ) ); if (access & PROFILE_READ) flags = GENERIC_READ; if (access & PROFILE_READWRITE) flags = GENERIC_READ|GENERIC_WRITE; @@ -479,18 +734,41 @@ HPROFILE WINAPI OpenColorProfileW( PPROFILE profile, DWORD access, DWORD sharing if (!flags) return NULL; handle = CreateFileW( profile->pProfileData, flags, sharing, NULL, creation, 0, NULL ); - if (handle == INVALID_HANDLE_VALUE) return NULL; + if (handle == INVALID_HANDLE_VALUE) + { + WARN( "Unable to open color profile\n" ); + return NULL; + } - unixname = wine_get_unix_file_name( (WCHAR *)profile->pProfileData ); + if ((size = GetFileSize( handle, NULL )) == INVALID_FILE_SIZE) + { + ERR( "Unable to retrieve size of color profile\n" ); + CloseHandle( handle ); + return NULL; + } - if (unixname) + iccprofile = (icProfile *)HeapAlloc( GetProcessHeap(), 0, size ); + if (!iccprofile) { - cmsprofile = cmsOpenProfileFromFile( unixname, flags & GENERIC_READ ? "r" : "w" ); - HeapFree( GetProcessHeap(), 0, unixname ); + ERR( "Unable to allocate memory for color profile\n" ); + CloseHandle( handle ); + return NULL; } + + if (!ReadFile( handle, iccprofile, size, &read, NULL ) || read != size) + { + ERR( "Unable to read color profile\n" ); + + CloseHandle( handle ); + HeapFree( GetProcessHeap, 0, iccprofile ); + return NULL; + } + + cmsprofile = cmsOpenProfileFromMem( iccprofile, size ); } - if (cmsprofile) return MSCMS_create_hprofile_handle( handle, cmsprofile ); + if (cmsprofile) + return MSCMS_create_hprofile_handle( handle, iccprofile, cmsprofile ); #endif /* HAVE_LCMS_H */ return NULL; @@ -510,16 +788,18 @@ HPROFILE WINAPI OpenColorProfileW( PPROFILE profile, DWORD access, DWORD sharing */ BOOL WINAPI CloseColorProfile( HPROFILE profile ) { - BOOL ret1, ret2 = FALSE; + BOOL ret = FALSE; TRACE( "( %p )\n", profile ); #ifdef HAVE_LCMS_H - ret1 = cmsCloseProfile( MSCMS_hprofile2cmsprofile( profile ) ); - ret2 = CloseHandle( MSCMS_hprofile2handle( profile ) ); + ret = cmsCloseProfile( MSCMS_hprofile2cmsprofile( profile ) ); + + HeapFree( GetProcessHeap(), 0, MSCMS_hprofile2iccprofile( profile ) ); + CloseHandle( MSCMS_hprofile2handle( profile ) ); MSCMS_destroy_hprofile_handle( profile ); #endif /* HAVE_LCMS_H */ - return ret1 && ret2; + return ret; } diff --git a/dlls/mscms/tests/profile.c b/dlls/mscms/tests/profile.c index 52c5ac43d6..5770539e6f 100644 --- a/dlls/mscms/tests/profile.c +++ b/dlls/mscms/tests/profile.c @@ -144,6 +144,46 @@ static void test_GetColorDirectoryW() ok( ret, "GetColorDirectoryW() failed (%ld)\n", GetLastError() ); } +static void test_GetColorProfileElement() +{ + if (standardprofile) + { + PROFILE profile; + HPROFILE handle; + BOOL ret, ref; + DWORD size; + TAGTYPE tag = 0x63707274; /* 'cprt' */ + static char buffer[51]; + static char expect[] = + { 0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x43, 0x6f, 0x70, + 0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x28, 0x63, 0x29, 0x20, + 0x31, 0x39, 0x39, 0x38, 0x20, 0x48, 0x65, 0x77, 0x6c, 0x65, 0x74, + 0x74, 0x2d, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x72, 0x64, 0x20, 0x43, + 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x00 }; + + profile.dwType = PROFILE_FILENAME; + profile.pProfileData = standardprofile; + profile.cbDataSize = strlen(standardprofile); + + handle = OpenColorProfileA( &profile, PROFILE_READ, 0, OPEN_EXISTING ); + ok( handle != NULL, "OpenColorProfileA() failed (%ld)\n", GetLastError() ); + + size = 0; + + ret = GetColorProfileElement( handle, tag, 0, &size, NULL, &ref ); + ok( !ret, "GetColorProfileElement() succeeded (%ld)\n", GetLastError() ); + + size = sizeof(buffer); + + ret = GetColorProfileElement( handle, tag, 0, &size, buffer, &ref ); + ok( ret, "GetColorProfileElement() failed (%ld)\n", GetLastError() ); + + ok( !memcmp( buffer, expect, sizeof(expect) ), "Unexpected tag data\n" ); + + CloseColorProfile( handle ); + } +} + static void test_GetColorProfileElementTag() { if (standardprofile) @@ -162,7 +202,39 @@ static void test_GetColorProfileElementTag() ok( handle != NULL, "OpenColorProfileA() failed (%ld)\n", GetLastError() ); ret = GetColorProfileElementTag( handle, index, &tag ); - ok( ret && tag == expect, "GetColorProfileElementTag() failed (%ld)\n", GetLastError() ); + ok( ret && tag == expect, "GetColorProfileElementTag() failed (%ld) 0x%08lx\n", + GetLastError(), tag ); + + CloseColorProfile( handle ); + } +} + +static void test_GetColorProfileHeader() +{ + if (testprofile) + { + PROFILE profile; + HPROFILE handle; + BOOL ret; + static PROFILEHEADER header; + static PROFILEHEADER expect = + { 0x00000c48, 0x4c696e6f, 0x02100000, 0x6d6e7472, 0x52474220, 0x58595a20, + { 0x07ce0002, 0x00090006, 0x61637370 }, 0x61637370, 0x4d534654, 0x00000000, + 0x49454320, 0x73524742, { 0x00000000, 0x00000000 }, 0x00000000, { 0x0000f6d6, + 0x00000100, 0x2dd30000 }, 0x48502020 }; + + profile.dwType = PROFILE_FILENAME; + profile.pProfileData = testprofile; + profile.cbDataSize = strlen(testprofile); + + handle = OpenColorProfileA( &profile, PROFILE_READ, 0, OPEN_EXISTING ); + ok( handle != NULL, "OpenColorProfileA() failed (%ld)\n", GetLastError() ); + + ret = GetColorProfileHeader( handle, &header ); + ok( ret, "GetColorProfileHeader() failed (%ld)\n", GetLastError() ); + + ok( memcmp( &header, &expect, FIELD_OFFSET(PROFILEHEADER, phReserved) ), + "Unexpected header data\n" ); CloseColorProfile( handle ); } @@ -549,7 +621,10 @@ START_TEST(profile) test_GetColorDirectoryA(); test_GetColorDirectoryW(); + test_GetColorProfileElement(); test_GetColorProfileElementTag(); + + test_GetColorProfileHeader(); test_GetCountColorProfileElements(); test_InstallColorProfileA(); diff --git a/include/icm.h b/include/icm.h index c55abb8aaf..3edabd2600 100644 --- a/include/icm.h +++ b/include/icm.h @@ -87,7 +87,7 @@ typedef struct tagPROFILEHEADER DWORD phProfileFlags; DWORD phManufacturer; DWORD phModel; - DWORD phAttributes; + DWORD phAttributes[2]; DWORD phRenderingIntent; CIEXYZ phIlluminant; DWORD phCreator; @@ -160,6 +160,7 @@ BOOL WINAPI GetColorDirectoryW(PCWSTR,PWSTR,PDWORD); #define GetColorDirectory WINELIB_NAME_AW(GetColorDirectory) BOOL WINAPI GetColorProfileElement(HPROFILE,TAGTYPE,DWORD,PDWORD,PVOID,PBOOL); BOOL WINAPI GetColorProfileElementTag(HPROFILE,DWORD,PTAGTYPE); +BOOL WINAPI GetColorProfileHeader(HPROFILE,PPROFILEHEADER); BOOL WINAPI GetCountColorProfileElements(HPROFILE,PDWORD); BOOL WINAPI GetStandardColorSpaceProfileA(PCSTR,DWORD,PSTR,PDWORD); BOOL WINAPI GetStandardColorSpaceProfileW(PCWSTR,DWORD,PWSTR,PDWORD); @@ -172,6 +173,7 @@ BOOL WINAPI IsColorProfileValid(HPROFILE,PBOOL); HPROFILE WINAPI OpenColorProfileA(PPROFILE,DWORD,DWORD,DWORD); HPROFILE WINAPI OpenColorProfileW(PPROFILE,DWORD,DWORD,DWORD); #define OpenColorProfile WINELIB_NAME_AW(OpenColorProfile) +BOOL WINAPI SetColorProfileHeader(HPROFILE,PPROFILEHEADER); BOOL WINAPI SetupColorMatchingA(PCOLORMATCHSETUPA); BOOL WINAPI SetupColorMatchingW(PCOLORMATCHSETUPW); #define SetupColorMatching WINELIB_NAME_AW(SetupColorMatching)