From 3e30e298479a1edb35b341963c4e291bd221dd8e Mon Sep 17 00:00:00 2001 From: Hans Leidekker Date: Mon, 24 Mar 2008 21:33:06 +0100 Subject: [PATCH] mscms: Rewrite handle management to be thread-safe. Allocate handles dynamically. --- dlls/mscms/handle.c | 293 ++++++++++++++++++---------------------- dlls/mscms/mscms_main.c | 3 + dlls/mscms/mscms_priv.h | 48 +++++-- dlls/mscms/profile.c | 224 ++++++++++++++++++------------ dlls/mscms/transform.c | 82 +++++++---- 5 files changed, 356 insertions(+), 294 deletions(-) diff --git a/dlls/mscms/handle.c b/dlls/mscms/handle.c index 09c2cc659b..84f1d8ba30 100644 --- a/dlls/mscms/handle.c +++ b/dlls/mscms/handle.c @@ -1,7 +1,7 @@ /* * MSCMS - Color Management System for Wine * - * Copyright 2004, 2005 Hans Leidekker + * Copyright 2004, 2005, 2008 Hans Leidekker * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -19,6 +19,8 @@ */ #include "config.h" +#include "wine/debug.h" + #include #include "windef.h" @@ -41,247 +43,208 @@ 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 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 set to - * INVALID_HANDLE_VALUE. The 'access' field records the access parameter - * supplied to an OpenColorProfile() call, i.e. PROFILE_READ or PROFILE_READWRITE. - */ +static struct profile *profiletable; +static struct transform *transformtable; -struct profile -{ - HANDLE file; - DWORD access; - icProfile *iccprofile; - cmsHPROFILE cmsprofile; -}; +static unsigned int num_profile_handles; +static unsigned int num_transform_handles; -struct transform -{ - cmsHTRANSFORM cmstransform; -}; +WINE_DEFAULT_DEBUG_CHANNEL(mscms); -#define CMSMAXHANDLES 0x80 - -static struct profile profiletable[CMSMAXHANDLES]; -static struct transform transformtable[CMSMAXHANDLES]; - -HPROFILE MSCMS_handle2hprofile( HANDLE file ) +void free_handle_tables( void ) { - HPROFILE profile = NULL; - DWORD_PTR i; - - if (!file) return NULL; - - EnterCriticalSection( &MSCMS_handle_cs ); + HeapFree( GetProcessHeap(), 0, profiletable ); + profiletable = NULL; + num_profile_handles = 0; - for (i = 0; i <= CMSMAXHANDLES; i++) - { - if (profiletable[i].file == file) - { - profile = (HPROFILE)(i + 1); goto out; - } - } - -out: - LeaveCriticalSection( &MSCMS_handle_cs ); - return profile; + HeapFree( GetProcessHeap(), 0, transformtable ); + transformtable = NULL; + num_transform_handles = 0; } -HANDLE MSCMS_hprofile2handle( HPROFILE profile ) +struct profile *grab_profile( HPROFILE handle ) { - HANDLE file; - DWORD_PTR i; + DWORD_PTR index; EnterCriticalSection( &MSCMS_handle_cs ); - i = (DWORD_PTR)profile - 1; - file = profiletable[i].file; - - LeaveCriticalSection( &MSCMS_handle_cs ); - return file; + index = (DWORD_PTR)handle - 1; + if (index > num_profile_handles) + { + LeaveCriticalSection( &MSCMS_handle_cs ); + return NULL; + } + return &profiletable[index]; } -DWORD MSCMS_hprofile2access( HPROFILE profile ) +void release_profile( struct profile *profile ) { - DWORD access; - DWORD_PTR i; - - EnterCriticalSection( &MSCMS_handle_cs ); - - i = (DWORD_PTR)profile - 1; - access = profiletable[i].access; - LeaveCriticalSection( &MSCMS_handle_cs ); - return access; } -HPROFILE MSCMS_cmsprofile2hprofile( cmsHPROFILE cmsprofile ) +struct transform *grab_transform( HTRANSFORM handle ) { - HPROFILE profile = NULL; - DWORD_PTR i; - - if (!cmsprofile) return NULL; + DWORD_PTR index; EnterCriticalSection( &MSCMS_handle_cs ); - for (i = 0; i <= CMSMAXHANDLES; i++) + index = (DWORD_PTR)handle - 1; + if (index > num_transform_handles) { - if (profiletable[i].cmsprofile == cmsprofile) - { - profile = (HPROFILE)(i + 1); goto out; - } + LeaveCriticalSection( &MSCMS_handle_cs ); + return NULL; } - -out: - LeaveCriticalSection( &MSCMS_handle_cs ); - return profile; + return &transformtable[index]; } -cmsHPROFILE MSCMS_hprofile2cmsprofile( HPROFILE profile ) +void release_transform( struct transform *transform ) { - cmsHPROFILE cmsprofile; - DWORD_PTR i; - - EnterCriticalSection( &MSCMS_handle_cs ); - - i = (DWORD_PTR)profile - 1; - cmsprofile = profiletable[i].cmsprofile; - LeaveCriticalSection( &MSCMS_handle_cs ); - return cmsprofile; } -HPROFILE MSCMS_iccprofile2hprofile( const icProfile *iccprofile ) +static HPROFILE alloc_profile_handle( void ) { - HPROFILE profile = NULL; - DWORD_PTR i; + DWORD_PTR index; + struct profile *p; + unsigned int count = 128; - if (!iccprofile) return NULL; - - EnterCriticalSection( &MSCMS_handle_cs ); - - for (i = 0; i <= CMSMAXHANDLES; i++) + for (index = 0; index < num_profile_handles; index++) { - if (profiletable[i].iccprofile == iccprofile) - { - profile = (HPROFILE)(i + 1); goto out; - } + if (!profiletable[index].iccprofile) return (HPROFILE)(index + 1); } + if (!profiletable) + { + p = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, count * sizeof(struct profile) ); + } + else + { + count = num_profile_handles * 2; + p = HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, profiletable, count * sizeof(struct profile) ); + } + if (!p) return NULL; -out: - LeaveCriticalSection( &MSCMS_handle_cs ); - return profile; + profiletable = p; + num_profile_handles = count; + + return (HPROFILE)(index + 1); } -icProfile *MSCMS_hprofile2iccprofile( HPROFILE profile ) +HPROFILE create_profile( struct profile *profile ) { - icProfile *iccprofile; - DWORD_PTR i; + HPROFILE handle; EnterCriticalSection( &MSCMS_handle_cs ); - i = (DWORD_PTR)profile - 1; - iccprofile = profiletable[i].iccprofile; - + if ((handle = alloc_profile_handle())) + { + DWORD_PTR index = (DWORD_PTR)handle - 1; + memcpy( &profiletable[index], profile, sizeof(struct profile) ); + } LeaveCriticalSection( &MSCMS_handle_cs ); - return iccprofile; + return handle; } -HPROFILE MSCMS_create_hprofile_handle( HANDLE file, icProfile *iccprofile, - cmsHPROFILE cmsprofile, DWORD access ) +BOOL close_profile( HPROFILE handle ) { - HPROFILE profile = NULL; - DWORD_PTR i; - - if (!cmsprofile || !iccprofile) return NULL; + DWORD_PTR index; + struct profile *profile; EnterCriticalSection( &MSCMS_handle_cs ); - for (i = 0; i <= CMSMAXHANDLES; i++) + index = (DWORD_PTR)handle - 1; + if (index > num_profile_handles) { - if (profiletable[i].iccprofile == 0) - { - profiletable[i].file = file; - profiletable[i].access = access; - profiletable[i].iccprofile = iccprofile; - profiletable[i].cmsprofile = cmsprofile; + LeaveCriticalSection( &MSCMS_handle_cs ); + return FALSE; + } + profile = &profiletable[index]; - profile = (HPROFILE)(i + 1); goto out; + if (profile->file != INVALID_HANDLE_VALUE) + { + if (profile->access & PROFILE_READWRITE) + { + DWORD written, size = MSCMS_get_profile_size( profile->iccprofile ); + + if (SetFilePointer( profile->file, 0, NULL, FILE_BEGIN ) || + !WriteFile( profile->file, profile->iccprofile, size, &written, NULL ) || + written != size) + { + ERR( "Unable to write color profile\n" ); + } } + CloseHandle( profile->file ); } + cmsCloseProfile( profile->cmsprofile ); + HeapFree( GetProcessHeap(), 0, profile->iccprofile ); + + memset( profile, 0, sizeof(struct profile) ); -out: LeaveCriticalSection( &MSCMS_handle_cs ); - return profile; + return TRUE; } -void MSCMS_destroy_hprofile_handle( HPROFILE profile ) +static HTRANSFORM alloc_transform_handle( void ) { - DWORD_PTR i; + DWORD_PTR index; + struct transform *p; + unsigned int count = 128; - if (profile) + for (index = 0; index < num_transform_handles; index++) { - EnterCriticalSection( &MSCMS_handle_cs ); - - i = (DWORD_PTR)profile - 1; - memset( &profiletable[i], 0, sizeof(struct profile) ); - - LeaveCriticalSection( &MSCMS_handle_cs ); + if (!transformtable[index].cmstransform) return (HTRANSFORM)(index + 1); } -} - -cmsHTRANSFORM MSCMS_htransform2cmstransform( HTRANSFORM transform ) -{ - cmsHTRANSFORM cmstransform; - DWORD_PTR i; - - EnterCriticalSection( &MSCMS_handle_cs ); + if (!transformtable) + { + p = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, count * sizeof(struct transform) ); + } + else + { + count = num_transform_handles * 2; + p = HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, transformtable, count * sizeof(struct transform) ); + } + if (!p) return NULL; - i = (DWORD_PTR)transform - 1; - cmstransform = transformtable[i].cmstransform; + transformtable = p; + num_transform_handles = count; - LeaveCriticalSection( &MSCMS_handle_cs ); - return cmstransform; + return (HTRANSFORM)(index + 1); } -HTRANSFORM MSCMS_create_htransform_handle( cmsHTRANSFORM cmstransform ) +HTRANSFORM create_transform( struct transform *transform ) { - HTRANSFORM transform = NULL; - DWORD_PTR i; - - if (!cmstransform) return NULL; + HTRANSFORM handle; EnterCriticalSection( &MSCMS_handle_cs ); - for (i = 0; i <= CMSMAXHANDLES; i++) + if ((handle = alloc_transform_handle())) { - if (transformtable[i].cmstransform == 0) - { - transformtable[i].cmstransform = cmstransform; - transform = (HTRANSFORM)(i + 1); goto out; - } + DWORD_PTR index = (DWORD_PTR)handle - 1; + memcpy( &transformtable[index], transform, sizeof(struct transform) ); } - -out: LeaveCriticalSection( &MSCMS_handle_cs ); - return transform; + return handle; } -void MSCMS_destroy_htransform_handle( HTRANSFORM transform ) +BOOL close_transform( HTRANSFORM handle ) { - DWORD_PTR i; - - if (transform) - { - EnterCriticalSection( &MSCMS_handle_cs ); + DWORD_PTR index; + struct transform *transform; - i = (DWORD_PTR)transform - 1; - memset( &transformtable[i], 0, sizeof(struct transform) ); + EnterCriticalSection( &MSCMS_handle_cs ); + index = (DWORD_PTR)handle - 1; + if (index > num_transform_handles) + { LeaveCriticalSection( &MSCMS_handle_cs ); + return FALSE; } + transform = &transformtable[index]; + + cmsDeleteTransform( transform->cmstransform ); + memset( transform, 0, sizeof(struct transform) ); + + LeaveCriticalSection( &MSCMS_handle_cs ); + return TRUE; } #endif /* HAVE_LCMS */ diff --git a/dlls/mscms/mscms_main.c b/dlls/mscms/mscms_main.c index df449b1d93..a7cf23bc8b 100644 --- a/dlls/mscms/mscms_main.c +++ b/dlls/mscms/mscms_main.c @@ -32,6 +32,8 @@ #include "winuser.h" #include "icm.h" +#include "mscms_priv.h" + WINE_DEFAULT_DEBUG_CHANNEL(mscms); BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved ) @@ -44,6 +46,7 @@ BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved ) DisableThreadLibraryCalls( hinst ); break; case DLL_PROCESS_DETACH: + free_handle_tables(); break; } return TRUE; diff --git a/dlls/mscms/mscms_priv.h b/dlls/mscms/mscms_priv.h index 2f9be8bc75..c979ea85fe 100644 --- a/dlls/mscms/mscms_priv.h +++ b/dlls/mscms/mscms_priv.h @@ -66,21 +66,39 @@ #define DWORD DWORD #define LPDWORD LPDWORD -extern DWORD MSCMS_hprofile2access( HPROFILE ); -extern HPROFILE MSCMS_handle2hprofile( HANDLE file ); -extern HPROFILE MSCMS_cmsprofile2hprofile( cmsHPROFILE cmsprofile ); -extern HPROFILE MSCMS_iccprofile2hprofile( const 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, icProfile *iccprofile, - cmsHPROFILE cmsprofile, DWORD access ); -extern void MSCMS_destroy_hprofile_handle( HPROFILE profile ); - -extern cmsHTRANSFORM MSCMS_htransform2cmstransform( HTRANSFORM transform ); -extern HTRANSFORM MSCMS_create_htransform_handle( cmsHTRANSFORM cmstransform ); -extern void MSCMS_destroy_htransform_handle( HTRANSFORM transform ); +/* A simple structure to tie together a pointer to an icc profile, an lcms + * color profile handle and a Windows file handle. If the profile is memory + * based the file handle field is set to INVALID_HANDLE_VALUE. The 'access' + * field records the access parameter supplied to an OpenColorProfile() + * call, i.e. PROFILE_READ or PROFILE_READWRITE. + */ + +struct profile +{ + HANDLE file; + DWORD access; + icProfile *iccprofile; + cmsHPROFILE cmsprofile; +}; + +struct transform +{ + cmsHTRANSFORM cmstransform; +}; + +extern HPROFILE create_profile( struct profile * ); +extern BOOL close_profile( HPROFILE ); + +extern HTRANSFORM create_transform( struct transform * ); +extern BOOL close_transform( HTRANSFORM ); + +struct profile *grab_profile( HPROFILE ); +struct transform *grab_transform( HTRANSFORM ); + +void release_profile( struct profile * ); +void release_transform( struct transform * ); + +extern void free_handle_tables( void ); extern DWORD MSCMS_get_tag_count( const icProfile *iccprofile ); extern void MSCMS_get_tag_by_index( icProfile *iccprofile, DWORD index, icTag *tag ); diff --git a/dlls/mscms/profile.c b/dlls/mscms/profile.c index 2fd3e13829..2f9970c3d7 100644 --- a/dlls/mscms/profile.c +++ b/dlls/mscms/profile.c @@ -333,38 +333,46 @@ BOOL WINAPI GetColorDirectoryW( PCWSTR machine, PWSTR buffer, PDWORD size ) * Success: TRUE * Failure: FALSE */ -BOOL WINAPI GetColorProfileElement( HPROFILE profile, TAGTYPE type, DWORD offset, PDWORD size, +BOOL WINAPI GetColorProfileElement( HPROFILE handle, TAGTYPE type, DWORD offset, PDWORD size, PVOID buffer, PBOOL ref ) { BOOL ret = FALSE; #ifdef HAVE_LCMS - icProfile *iccprofile = MSCMS_hprofile2iccprofile( profile ); + struct profile *profile = grab_profile( handle ); DWORD i, count; icTag tag; - TRACE( "( %p, 0x%08x, %d, %p, %p, %p )\n", profile, type, offset, size, buffer, ref ); + TRACE( "( %p, 0x%08x, %d, %p, %p, %p )\n", handle, type, offset, size, buffer, ref ); - if (!iccprofile || !size || !ref) return FALSE; - count = MSCMS_get_tag_count( iccprofile ); + if (!profile) return FALSE; + + if (!size || !ref) + { + release_profile( profile ); + return FALSE; + } + count = MSCMS_get_tag_count( profile->iccprofile ); for (i = 0; i < count; i++) { - MSCMS_get_tag_by_index( iccprofile, i, &tag ); + MSCMS_get_tag_by_index( profile->iccprofile, i, &tag ); if (tag.sig == type) { if ((tag.size - offset) > *size || !buffer) { *size = (tag.size - offset); + release_profile( profile ); return FALSE; } - - MSCMS_get_tag_data( iccprofile, &tag, offset, buffer ); + MSCMS_get_tag_data( profile->iccprofile, &tag, offset, buffer ); *ref = FALSE; /* FIXME: calculate properly */ + release_profile( profile ); return TRUE; } } + release_profile( profile ); #endif /* HAVE_LCMS */ return ret; @@ -388,24 +396,33 @@ BOOL WINAPI GetColorProfileElement( HPROFILE profile, TAGTYPE type, DWORD offset * The tag table index starts at 1. * Use GetCountColorProfileElements to retrieve a count of tagged elements. */ -BOOL WINAPI GetColorProfileElementTag( HPROFILE profile, DWORD index, PTAGTYPE type ) +BOOL WINAPI GetColorProfileElementTag( HPROFILE handle, DWORD index, PTAGTYPE type ) { BOOL ret = FALSE; #ifdef HAVE_LCMS - icProfile *iccprofile = MSCMS_hprofile2iccprofile( profile ); + struct profile *profile = grab_profile( handle ); DWORD count; icTag tag; - TRACE( "( %p, %d, %p )\n", profile, index, type ); - - if (!iccprofile || !type) return FALSE; + TRACE( "( %p, %d, %p )\n", handle, index, type ); - count = MSCMS_get_tag_count( iccprofile ); - if (index > count || index < 1) return FALSE; + if (!profile) return FALSE; - MSCMS_get_tag_by_index( iccprofile, index - 1, &tag ); + if (!type) + { + release_profile( profile ); + return FALSE; + } + count = MSCMS_get_tag_count( profile->iccprofile ); + if (index > count || index < 1) + { + release_profile( profile ); + return FALSE; + } + MSCMS_get_tag_by_index( profile->iccprofile, index - 1, &tag ); *type = tag.sig; + release_profile( profile ); ret = TRUE; #endif /* HAVE_LCMS */ @@ -430,28 +447,36 @@ BOOL WINAPI GetColorProfileElementTag( HPROFILE profile, DWORD index, PTAGTYPE t * NOTES * The profile returned will be in big-endian format. */ -BOOL WINAPI GetColorProfileFromHandle( HPROFILE profile, PBYTE buffer, PDWORD size ) +BOOL WINAPI GetColorProfileFromHandle( HPROFILE handle, PBYTE buffer, PDWORD size ) { BOOL ret = FALSE; #ifdef HAVE_LCMS - icProfile *iccprofile = MSCMS_hprofile2iccprofile( profile ); + struct profile *profile = grab_profile( handle ); PROFILEHEADER header; - TRACE( "( %p, %p, %p )\n", profile, buffer, size ); + TRACE( "( %p, %p, %p )\n", handle, buffer, size ); - if (!iccprofile || !size) return FALSE; - MSCMS_get_profile_header( iccprofile, &header ); + if (!profile) return FALSE; + + if (!size) + { + release_profile( profile ); + return FALSE; + } + MSCMS_get_profile_header( profile->iccprofile, &header ); if (!buffer || header.phSize > *size) { *size = header.phSize; + release_profile( profile ); return FALSE; } /* No endian conversion needed */ - memcpy( buffer, iccprofile, header.phSize ); - + memcpy( buffer, profile->iccprofile, header.phSize ); *size = header.phSize; + + release_profile( profile ); ret = TRUE; #endif /* HAVE_LCMS */ @@ -474,16 +499,23 @@ BOOL WINAPI GetColorProfileFromHandle( HPROFILE profile, PBYTE buffer, PDWORD si * NOTES * The profile header returned will be adjusted for endianess. */ -BOOL WINAPI GetColorProfileHeader( HPROFILE profile, PPROFILEHEADER header ) +BOOL WINAPI GetColorProfileHeader( HPROFILE handle, PPROFILEHEADER header ) { #ifdef HAVE_LCMS - icProfile *iccprofile = MSCMS_hprofile2iccprofile( profile ); + struct profile *profile = grab_profile( handle ); + + TRACE( "( %p, %p )\n", handle, header ); - TRACE( "( %p, %p )\n", profile, header ); + if (!profile) return FALSE; - if (!iccprofile || !header) return FALSE; + if (!header) + { + release_profile( profile ); + return FALSE; + } + MSCMS_get_profile_header( profile->iccprofile, header ); - MSCMS_get_profile_header( iccprofile, header ); + release_profile( profile ); return TRUE; #else @@ -505,16 +537,24 @@ BOOL WINAPI GetColorProfileHeader( HPROFILE profile, PPROFILEHEADER header ) * Success: TRUE * Failure: FALSE */ -BOOL WINAPI GetCountColorProfileElements( HPROFILE profile, PDWORD count ) +BOOL WINAPI GetCountColorProfileElements( HPROFILE handle, PDWORD count ) { BOOL ret = FALSE; #ifdef HAVE_LCMS - icProfile *iccprofile = MSCMS_hprofile2iccprofile( profile ); + struct profile *profile = grab_profile( handle ); - TRACE( "( %p, %p )\n", profile, count ); + TRACE( "( %p, %p )\n", handle, count ); - if (!iccprofile || !count) return FALSE; - *count = MSCMS_get_tag_count( iccprofile ); + if (!profile) return FALSE; + + if (!count) + { + release_profile( profile ); + return FALSE; + } + *count = MSCMS_get_tag_count( profile->iccprofile ); + + release_profile( profile ); ret = TRUE; #endif /* HAVE_LCMS */ @@ -1113,23 +1153,28 @@ BOOL WINAPI InstallColorProfileW( PCWSTR machine, PCWSTR profile ) * Success: TRUE * Failure: FALSE */ -BOOL WINAPI IsColorProfileTagPresent( HPROFILE profile, TAGTYPE type, PBOOL present ) +BOOL WINAPI IsColorProfileTagPresent( HPROFILE handle, TAGTYPE type, PBOOL present ) { BOOL ret = FALSE; #ifdef HAVE_LCMS - icProfile *iccprofile = MSCMS_hprofile2iccprofile( profile ); + struct profile *profile = grab_profile( handle ); DWORD i, count; icTag tag; - TRACE( "( %p, 0x%08x, %p )\n", profile, type, present ); + TRACE( "( %p, 0x%08x, %p )\n", handle, type, present ); - if (!iccprofile || !present) return FALSE; + if (!profile) return FALSE; - count = MSCMS_get_tag_count( iccprofile ); + if (!present) + { + release_profile( profile ); + return FALSE; + } + count = MSCMS_get_tag_count( profile->iccprofile ); for (i = 0; i < count; i++) { - MSCMS_get_tag_by_index( iccprofile, i, &tag ); + MSCMS_get_tag_by_index( profile->iccprofile, i, &tag ); if (tag.sig == type) { @@ -1137,6 +1182,7 @@ BOOL WINAPI IsColorProfileTagPresent( HPROFILE profile, TAGTYPE type, PBOOL pres break; } } + release_profile( profile ); #endif /* HAVE_LCMS */ return ret; @@ -1156,16 +1202,23 @@ BOOL WINAPI IsColorProfileTagPresent( HPROFILE profile, TAGTYPE type, PBOOL pres * Success: TRUE * Failure: FALSE */ -BOOL WINAPI IsColorProfileValid( HPROFILE profile, PBOOL valid ) +BOOL WINAPI IsColorProfileValid( HPROFILE handle, PBOOL valid ) { BOOL ret = FALSE; #ifdef HAVE_LCMS - icProfile *iccprofile = MSCMS_hprofile2iccprofile( profile ); + struct profile *profile = grab_profile( handle ); + + TRACE( "( %p, %p )\n", handle, valid ); - TRACE( "( %p, %p )\n", profile, valid ); + if (!profile) return FALSE; - if (!valid) return FALSE; - if (iccprofile) return *valid = TRUE; + if (!valid) + { + release_profile( profile ); + return FALSE; + } + if (profile->iccprofile) ret = *valid = TRUE; + release_profile( profile ); #endif /* HAVE_LCMS */ return ret; @@ -1188,34 +1241,44 @@ BOOL WINAPI IsColorProfileValid( HPROFILE profile, PBOOL valid ) * Success: TRUE * Failure: FALSE */ -BOOL WINAPI SetColorProfileElement( HPROFILE profile, TAGTYPE type, DWORD offset, PDWORD size, +BOOL WINAPI SetColorProfileElement( HPROFILE handle, TAGTYPE type, DWORD offset, PDWORD size, PVOID buffer ) { BOOL ret = FALSE; #ifdef HAVE_LCMS - icProfile *iccprofile = MSCMS_hprofile2iccprofile( profile ); - DWORD i, count, access = MSCMS_hprofile2access( profile ); + struct profile *profile = grab_profile( handle ); + DWORD i, count; icTag tag; - TRACE( "( %p, 0x%08x, %d, %p, %p )\n", profile, type, offset, size, buffer ); + TRACE( "( %p, 0x%08x, %d, %p, %p )\n", handle, type, offset, size, buffer ); - if (!iccprofile || !size || !buffer) return FALSE; - if (!(access & PROFILE_READWRITE)) return FALSE; + if (!profile) return FALSE; - count = MSCMS_get_tag_count( iccprofile ); + if (!size || !buffer || !(profile->access & PROFILE_READWRITE)) + { + release_profile( profile ); + return FALSE; + } + count = MSCMS_get_tag_count( profile->iccprofile ); for (i = 0; i < count; i++) { - MSCMS_get_tag_by_index( iccprofile, i, &tag ); + MSCMS_get_tag_by_index( profile->iccprofile, i, &tag ); if (tag.sig == type) { - if (offset > tag.size) return FALSE; + if (offset > tag.size) + { + release_profile( profile ); + return FALSE; + } + MSCMS_set_tag_data( profile->iccprofile, &tag, offset, buffer ); - MSCMS_set_tag_data( iccprofile, &tag, offset, buffer ); + release_profile( profile ); return TRUE; } } + release_profile( profile ); #endif /* HAVE_LCMS */ return ret; @@ -1234,18 +1297,23 @@ BOOL WINAPI SetColorProfileElement( HPROFILE profile, TAGTYPE type, DWORD offset * Success: TRUE * Failure: FALSE */ -BOOL WINAPI SetColorProfileHeader( HPROFILE profile, PPROFILEHEADER header ) +BOOL WINAPI SetColorProfileHeader( HPROFILE handle, PPROFILEHEADER header ) { #ifdef HAVE_LCMS - icProfile *iccprofile = MSCMS_hprofile2iccprofile( profile ); - DWORD access = MSCMS_hprofile2access( profile ); + struct profile *profile = grab_profile( handle ); - TRACE( "( %p, %p )\n", profile, header ); + TRACE( "( %p, %p )\n", handle, header ); - if (!iccprofile || !header) return FALSE; - if (!(access & PROFILE_READWRITE)) return FALSE; + if (!profile) return FALSE; - MSCMS_set_profile_header( iccprofile, header ); + if (!header || !(profile->access & PROFILE_READWRITE)) + { + release_profile( profile ); + return FALSE; + } + MSCMS_set_profile_header( profile->iccprofile, header ); + + release_profile( profile ); return TRUE; #else @@ -1441,7 +1509,16 @@ HPROFILE WINAPI OpenColorProfileW( PPROFILE profile, DWORD access, DWORD sharing } if (cmsprofile) - return MSCMS_create_hprofile_handle( handle, iccprofile, cmsprofile, access ); + { + struct profile profile; + + profile.file = handle; + profile.access = access; + profile.iccprofile = iccprofile; + profile.cmsprofile = cmsprofile; + + return create_profile( &profile ); + } #endif /* HAVE_LCMS */ return NULL; @@ -1463,30 +1540,9 @@ BOOL WINAPI CloseColorProfile( HPROFILE profile ) { BOOL ret = FALSE; #ifdef HAVE_LCMS - icProfile *iccprofile = MSCMS_hprofile2iccprofile( profile ); - HANDLE file = MSCMS_hprofile2handle( profile ); - DWORD access = MSCMS_hprofile2access( profile ); TRACE( "( %p )\n", profile ); - - if (file != INVALID_HANDLE_VALUE) - { - if (access & PROFILE_READWRITE) - { - DWORD written, size = MSCMS_get_profile_size( iccprofile ); - - if (SetFilePointer( file, 0, NULL, FILE_BEGIN ) || - !WriteFile( file, iccprofile, size, &written, NULL ) || written != size) - { - ERR( "Unable to write color profile\n" ); - } - } - CloseHandle( file ); - } - ret = cmsCloseProfile( MSCMS_hprofile2cmsprofile( profile ) ); - HeapFree( GetProcessHeap(), 0, iccprofile ); - - MSCMS_destroy_hprofile_handle( profile ); + ret = close_profile( profile ); #endif /* HAVE_LCMS */ return ret; diff --git a/dlls/mscms/transform.c b/dlls/mscms/transform.c index ec33a1086b..2ed65d13d7 100644 --- a/dlls/mscms/transform.c +++ b/dlls/mscms/transform.c @@ -135,15 +135,21 @@ HTRANSFORM WINAPI CreateColorTransformW( LPLOGCOLORSPACEW space, HPROFILE dest, { HTRANSFORM ret = NULL; #ifdef HAVE_LCMS - cmsHTRANSFORM cmstransform; + struct transform transform; + struct profile *dst, *tgt = NULL; cmsHPROFILE cmsinput, cmsoutput, cmstarget = NULL; DWORD in_format, out_format, proofing = 0; int intent; TRACE( "( %p, %p, %p, 0x%08x )\n", space, dest, target, flags ); - if (!space || !dest) return FALSE; + if (!space || !(dst = grab_profile( dest ))) return FALSE; + if (target && !(tgt = grab_profile( target ))) + { + release_profile( dst ); + return FALSE; + } intent = space->lcsIntent > 3 ? INTENT_PERCEPTUAL : space->lcsIntent; TRACE( "lcsIntent: %x\n", space->lcsIntent ); @@ -157,13 +163,16 @@ HTRANSFORM WINAPI CreateColorTransformW( LPLOGCOLORSPACEW space, HPROFILE dest, if (target) { proofing = cmsFLAGS_SOFTPROOFING; - cmstarget = MSCMS_hprofile2cmsprofile( target ); + cmstarget = tgt->cmsprofile; } - cmsoutput = MSCMS_hprofile2cmsprofile( dest ); - cmstransform = cmsCreateProofingTransform(cmsinput, in_format, cmsoutput, out_format, cmstarget, - intent, INTENT_ABSOLUTE_COLORIMETRIC, proofing); + cmsoutput = dst->cmsprofile; + transform.cmstransform = cmsCreateProofingTransform(cmsinput, in_format, cmsoutput, out_format, cmstarget, + intent, INTENT_ABSOLUTE_COLORIMETRIC, proofing); - ret = MSCMS_create_htransform_handle( cmstransform ); + ret = create_transform( &transform ); + + if (tgt) release_profile( tgt ); + release_profile( dst ); #endif /* HAVE_LCMS */ return ret; @@ -191,7 +200,8 @@ HTRANSFORM WINAPI CreateMultiProfileTransform( PHPROFILE profiles, DWORD nprofil HTRANSFORM ret = NULL; #ifdef HAVE_LCMS cmsHPROFILE *cmsprofiles, cmsconvert = NULL; - cmsHTRANSFORM cmstransform; + struct transform transform; + struct profile *profile0, *profile1; DWORD in_format, out_format; TRACE( "( %p, 0x%08x, %p, 0x%08x, 0x%08x, 0x%08x )\n", @@ -205,6 +215,14 @@ HTRANSFORM WINAPI CreateMultiProfileTransform( PHPROFILE profiles, DWORD nprofil return NULL; } + profile0 = grab_profile( profiles[0] ); + if (!profile0) return NULL; + profile1 = grab_profile( profiles[1] ); + if (!profile1) + { + release_profile( profile0 ); + return NULL; + } in_format = from_profile( profiles[0] ); out_format = from_profile( profiles[nprofiles - 1] ); @@ -218,23 +236,26 @@ HTRANSFORM WINAPI CreateMultiProfileTransform( PHPROFILE profiles, DWORD nprofil cmsprofiles = HeapAlloc( GetProcessHeap(), 0, (nprofiles + 1) * sizeof(cmsHPROFILE *) ); if (cmsprofiles) { - cmsprofiles[0] = MSCMS_hprofile2cmsprofile( profiles[0] ); + cmsprofiles[0] = profile0->cmsprofile; if (cmsconvert) { cmsprofiles[1] = cmsconvert; - cmsprofiles[2] = MSCMS_hprofile2cmsprofile( profiles[1] ); + cmsprofiles[2] = profile1->cmsprofile; nprofiles++; } else { - cmsprofiles[1] = MSCMS_hprofile2cmsprofile( profiles[1] ); + cmsprofiles[1] = profile1->cmsprofile; } - cmstransform = cmsCreateMultiprofileTransform( cmsprofiles, nprofiles, in_format, out_format, *intents, 0 ); + transform.cmstransform = cmsCreateMultiprofileTransform( cmsprofiles, nprofiles, in_format, out_format, *intents, 0 ); HeapFree( GetProcessHeap(), 0, cmsprofiles ); - ret = MSCMS_create_htransform_handle( cmstransform ); + ret = create_transform( &transform ); } + release_profile( profile0 ); + release_profile( profile1 ); + #endif /* HAVE_LCMS */ return ret; } @@ -251,19 +272,14 @@ HTRANSFORM WINAPI CreateMultiProfileTransform( PHPROFILE profiles, DWORD nprofil * Success: TRUE * Failure: FALSE */ -BOOL WINAPI DeleteColorTransform( HTRANSFORM transform ) +BOOL WINAPI DeleteColorTransform( HTRANSFORM handle ) { BOOL ret = FALSE; #ifdef HAVE_LCMS - cmsHTRANSFORM cmstransform; - TRACE( "( %p )\n", transform ); + TRACE( "( %p )\n", handle ); - cmstransform = MSCMS_htransform2cmstransform( transform ); - cmsDeleteTransform( cmstransform ); - - MSCMS_destroy_htransform_handle( transform ); - ret = TRUE; + ret = close_transform( handle ); #endif /* HAVE_LCMS */ return ret; @@ -291,22 +307,23 @@ BOOL WINAPI DeleteColorTransform( HTRANSFORM transform ) * Success: TRUE * Failure: FALSE */ -BOOL WINAPI TranslateBitmapBits( HTRANSFORM transform, PVOID srcbits, BMFORMAT input, +BOOL WINAPI TranslateBitmapBits( HTRANSFORM handle, PVOID srcbits, BMFORMAT input, DWORD width, DWORD height, DWORD inputstride, PVOID destbits, BMFORMAT output, DWORD outputstride, PBMCALLBACKFN callback, ULONG data ) { BOOL ret = FALSE; #ifdef HAVE_LCMS - cmsHTRANSFORM cmstransform; + struct transform *transform = grab_transform( handle ); TRACE( "( %p, %p, 0x%08x, 0x%08x, 0x%08x, 0x%08x, %p, 0x%08x, 0x%08x, %p, 0x%08x )\n", - transform, srcbits, input, width, height, inputstride, destbits, output, + handle, srcbits, input, width, height, inputstride, destbits, output, outputstride, callback, data ); - cmstransform = MSCMS_htransform2cmstransform( transform ); - cmsChangeBuffersFormat( cmstransform, from_bmformat(input), from_bmformat(output) ); + if (!transform) return FALSE; + cmsChangeBuffersFormat( transform->cmstransform, from_bmformat(input), from_bmformat(output) ); - cmsDoTransform( cmstransform, srcbits, destbits, width * height ); + cmsDoTransform( transform->cmstransform, srcbits, destbits, width * height ); + release_transform( transform ); ret = TRUE; #endif /* HAVE_LCMS */ @@ -330,16 +347,20 @@ BOOL WINAPI TranslateBitmapBits( HTRANSFORM transform, PVOID srcbits, BMFORMAT i * Success: TRUE * Failure: FALSE */ -BOOL WINAPI TranslateColors( HTRANSFORM transform, PCOLOR in, DWORD count, +BOOL WINAPI TranslateColors( HTRANSFORM handle, PCOLOR in, DWORD count, COLORTYPE input_type, PCOLOR out, COLORTYPE output_type ) { BOOL ret = FALSE; #ifdef HAVE_LCMS - cmsHTRANSFORM xfrm = MSCMS_htransform2cmstransform( transform ); + struct transform *transform = grab_transform( handle ); + cmsHTRANSFORM xfrm; unsigned int i; - TRACE( "( %p, %p, %d, %d, %p, %d )\n", transform, in, count, input_type, out, output_type ); + TRACE( "( %p, %p, %d, %d, %p, %d )\n", handle, in, count, input_type, out, output_type ); + + if (!transform) return FALSE; + xfrm = transform->cmstransform; cmsChangeBuffersFormat( xfrm, from_type(input_type), from_type(output_type) ); switch (input_type) @@ -418,6 +439,7 @@ BOOL WINAPI TranslateColors( HTRANSFORM transform, PCOLOR in, DWORD count, FIXME("unhandled input/output pair: %d/%d\n", input_type, output_type); break; } + release_transform( transform ); #endif /* HAVE_LCMS */ return ret; -- 2.33.8