mscms: Rewrite handle management to be thread-safe. Allocate handles dynamically.

This commit is contained in:
Hans Leidekker 2008-03-24 21:33:06 +01:00 committed by Alexandre Julliard
parent 46489aeda2
commit 3e30e29847
5 changed files with 412 additions and 350 deletions

View File

@ -1,7 +1,7 @@
/* /*
* MSCMS - Color Management System for Wine * 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 * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -19,6 +19,8 @@
*/ */
#include "config.h" #include "config.h"
#include "wine/debug.h"
#include <stdarg.h> #include <stdarg.h>
#include "windef.h" #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 }; 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 static struct profile *profiletable;
* color profile handle and a Windows file handle. Windows color profile static struct transform *transformtable;
* 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.
*/
struct profile static unsigned int num_profile_handles;
static unsigned int num_transform_handles;
WINE_DEFAULT_DEBUG_CHANNEL(mscms);
void free_handle_tables( void )
{ {
HANDLE file; HeapFree( GetProcessHeap(), 0, profiletable );
DWORD access; profiletable = NULL;
icProfile *iccprofile; num_profile_handles = 0;
cmsHPROFILE cmsprofile;
};
struct transform HeapFree( GetProcessHeap(), 0, transformtable );
transformtable = NULL;
num_transform_handles = 0;
}
struct profile *grab_profile( HPROFILE handle )
{ {
cmsHTRANSFORM cmstransform; DWORD_PTR index;
};
#define CMSMAXHANDLES 0x80
static struct profile profiletable[CMSMAXHANDLES];
static struct transform transformtable[CMSMAXHANDLES];
HPROFILE MSCMS_handle2hprofile( HANDLE file )
{
HPROFILE profile = NULL;
DWORD_PTR i;
if (!file) return NULL;
EnterCriticalSection( &MSCMS_handle_cs ); EnterCriticalSection( &MSCMS_handle_cs );
for (i = 0; i <= CMSMAXHANDLES; i++) index = (DWORD_PTR)handle - 1;
if (index > num_profile_handles)
{ {
if (profiletable[i].file == file)
{
profile = (HPROFILE)(i + 1); goto out;
}
}
out:
LeaveCriticalSection( &MSCMS_handle_cs ); LeaveCriticalSection( &MSCMS_handle_cs );
return profile; return NULL;
}
return &profiletable[index];
} }
HANDLE MSCMS_hprofile2handle( HPROFILE profile ) void release_profile( struct profile *profile )
{ {
HANDLE file; LeaveCriticalSection( &MSCMS_handle_cs );
DWORD_PTR i; }
struct transform *grab_transform( HTRANSFORM handle )
{
DWORD_PTR index;
EnterCriticalSection( &MSCMS_handle_cs ); EnterCriticalSection( &MSCMS_handle_cs );
i = (DWORD_PTR)profile - 1; index = (DWORD_PTR)handle - 1;
file = profiletable[i].file; if (index > num_transform_handles)
{
LeaveCriticalSection( &MSCMS_handle_cs ); LeaveCriticalSection( &MSCMS_handle_cs );
return file; return NULL;
}
return &transformtable[index];
} }
DWORD MSCMS_hprofile2access( HPROFILE profile ) void release_transform( struct transform *transform )
{ {
DWORD access; LeaveCriticalSection( &MSCMS_handle_cs );
DWORD_PTR i; }
static HPROFILE alloc_profile_handle( void )
{
DWORD_PTR index;
struct profile *p;
unsigned int count = 128;
for (index = 0; index < num_profile_handles; index++)
{
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;
profiletable = p;
num_profile_handles = count;
return (HPROFILE)(index + 1);
}
HPROFILE create_profile( struct profile *profile )
{
HPROFILE handle;
EnterCriticalSection( &MSCMS_handle_cs ); EnterCriticalSection( &MSCMS_handle_cs );
i = (DWORD_PTR)profile - 1; if ((handle = alloc_profile_handle()))
access = profiletable[i].access; {
DWORD_PTR index = (DWORD_PTR)handle - 1;
memcpy( &profiletable[index], profile, sizeof(struct profile) );
}
LeaveCriticalSection( &MSCMS_handle_cs ); LeaveCriticalSection( &MSCMS_handle_cs );
return access; return handle;
} }
HPROFILE MSCMS_cmsprofile2hprofile( cmsHPROFILE cmsprofile ) BOOL close_profile( HPROFILE handle )
{ {
HPROFILE profile = NULL; DWORD_PTR index;
DWORD_PTR i; struct profile *profile;
if (!cmsprofile) return NULL;
EnterCriticalSection( &MSCMS_handle_cs ); EnterCriticalSection( &MSCMS_handle_cs );
for (i = 0; i <= CMSMAXHANDLES; i++) index = (DWORD_PTR)handle - 1;
if (index > num_profile_handles)
{ {
if (profiletable[i].cmsprofile == cmsprofile)
{
profile = (HPROFILE)(i + 1); goto out;
}
}
out:
LeaveCriticalSection( &MSCMS_handle_cs ); LeaveCriticalSection( &MSCMS_handle_cs );
return profile; return FALSE;
}
profile = &profiletable[index];
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) );
LeaveCriticalSection( &MSCMS_handle_cs );
return TRUE;
} }
cmsHPROFILE MSCMS_hprofile2cmsprofile( HPROFILE profile ) static HTRANSFORM alloc_transform_handle( void )
{ {
cmsHPROFILE cmsprofile; DWORD_PTR index;
DWORD_PTR i; struct transform *p;
unsigned int count = 128;
for (index = 0; index < num_transform_handles; index++)
{
if (!transformtable[index].cmstransform) return (HTRANSFORM)(index + 1);
}
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;
transformtable = p;
num_transform_handles = count;
return (HTRANSFORM)(index + 1);
}
HTRANSFORM create_transform( struct transform *transform )
{
HTRANSFORM handle;
EnterCriticalSection( &MSCMS_handle_cs ); EnterCriticalSection( &MSCMS_handle_cs );
i = (DWORD_PTR)profile - 1; if ((handle = alloc_transform_handle()))
cmsprofile = profiletable[i].cmsprofile; {
DWORD_PTR index = (DWORD_PTR)handle - 1;
memcpy( &transformtable[index], transform, sizeof(struct transform) );
}
LeaveCriticalSection( &MSCMS_handle_cs ); LeaveCriticalSection( &MSCMS_handle_cs );
return cmsprofile; return handle;
} }
HPROFILE MSCMS_iccprofile2hprofile( const icProfile *iccprofile ) BOOL close_transform( HTRANSFORM handle )
{ {
HPROFILE profile = NULL; DWORD_PTR index;
DWORD_PTR i; struct transform *transform;
if (!iccprofile) return NULL;
EnterCriticalSection( &MSCMS_handle_cs ); EnterCriticalSection( &MSCMS_handle_cs );
for (i = 0; i <= CMSMAXHANDLES; i++) index = (DWORD_PTR)handle - 1;
if (index > num_transform_handles)
{ {
if (profiletable[i].iccprofile == iccprofile)
{
profile = (HPROFILE)(i + 1); goto out;
}
}
out:
LeaveCriticalSection( &MSCMS_handle_cs ); LeaveCriticalSection( &MSCMS_handle_cs );
return profile; return FALSE;
} }
transform = &transformtable[index];
icProfile *MSCMS_hprofile2iccprofile( HPROFILE profile ) cmsDeleteTransform( transform->cmstransform );
{ memset( transform, 0, sizeof(struct transform) );
icProfile *iccprofile;
DWORD_PTR i;
EnterCriticalSection( &MSCMS_handle_cs );
i = (DWORD_PTR)profile - 1;
iccprofile = profiletable[i].iccprofile;
LeaveCriticalSection( &MSCMS_handle_cs ); LeaveCriticalSection( &MSCMS_handle_cs );
return iccprofile; return TRUE;
}
HPROFILE MSCMS_create_hprofile_handle( HANDLE file, icProfile *iccprofile,
cmsHPROFILE cmsprofile, DWORD access )
{
HPROFILE profile = NULL;
DWORD_PTR i;
if (!cmsprofile || !iccprofile) return NULL;
EnterCriticalSection( &MSCMS_handle_cs );
for (i = 0; i <= CMSMAXHANDLES; i++)
{
if (profiletable[i].iccprofile == 0)
{
profiletable[i].file = file;
profiletable[i].access = access;
profiletable[i].iccprofile = iccprofile;
profiletable[i].cmsprofile = cmsprofile;
profile = (HPROFILE)(i + 1); goto out;
}
}
out:
LeaveCriticalSection( &MSCMS_handle_cs );
return profile;
}
void MSCMS_destroy_hprofile_handle( HPROFILE profile )
{
DWORD_PTR i;
if (profile)
{
EnterCriticalSection( &MSCMS_handle_cs );
i = (DWORD_PTR)profile - 1;
memset( &profiletable[i], 0, sizeof(struct profile) );
LeaveCriticalSection( &MSCMS_handle_cs );
}
}
cmsHTRANSFORM MSCMS_htransform2cmstransform( HTRANSFORM transform )
{
cmsHTRANSFORM cmstransform;
DWORD_PTR i;
EnterCriticalSection( &MSCMS_handle_cs );
i = (DWORD_PTR)transform - 1;
cmstransform = transformtable[i].cmstransform;
LeaveCriticalSection( &MSCMS_handle_cs );
return cmstransform;
}
HTRANSFORM MSCMS_create_htransform_handle( cmsHTRANSFORM cmstransform )
{
HTRANSFORM transform = NULL;
DWORD_PTR i;
if (!cmstransform) return NULL;
EnterCriticalSection( &MSCMS_handle_cs );
for (i = 0; i <= CMSMAXHANDLES; i++)
{
if (transformtable[i].cmstransform == 0)
{
transformtable[i].cmstransform = cmstransform;
transform = (HTRANSFORM)(i + 1); goto out;
}
}
out:
LeaveCriticalSection( &MSCMS_handle_cs );
return transform;
}
void MSCMS_destroy_htransform_handle( HTRANSFORM transform )
{
DWORD_PTR i;
if (transform)
{
EnterCriticalSection( &MSCMS_handle_cs );
i = (DWORD_PTR)transform - 1;
memset( &transformtable[i], 0, sizeof(struct transform) );
LeaveCriticalSection( &MSCMS_handle_cs );
}
} }
#endif /* HAVE_LCMS */ #endif /* HAVE_LCMS */

View File

@ -32,6 +32,8 @@
#include "winuser.h" #include "winuser.h"
#include "icm.h" #include "icm.h"
#include "mscms_priv.h"
WINE_DEFAULT_DEBUG_CHANNEL(mscms); WINE_DEFAULT_DEBUG_CHANNEL(mscms);
BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved ) BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
@ -44,6 +46,7 @@ BOOL WINAPI DllMain( HINSTANCE hinst, DWORD reason, LPVOID reserved )
DisableThreadLibraryCalls( hinst ); DisableThreadLibraryCalls( hinst );
break; break;
case DLL_PROCESS_DETACH: case DLL_PROCESS_DETACH:
free_handle_tables();
break; break;
} }
return TRUE; return TRUE;

View File

@ -66,21 +66,39 @@
#define DWORD DWORD #define DWORD DWORD
#define LPDWORD LPDWORD #define LPDWORD LPDWORD
extern DWORD MSCMS_hprofile2access( HPROFILE ); /* A simple structure to tie together a pointer to an icc profile, an lcms
extern HPROFILE MSCMS_handle2hprofile( HANDLE file ); * color profile handle and a Windows file handle. If the profile is memory
extern HPROFILE MSCMS_cmsprofile2hprofile( cmsHPROFILE cmsprofile ); * based the file handle field is set to INVALID_HANDLE_VALUE. The 'access'
extern HPROFILE MSCMS_iccprofile2hprofile( const icProfile *iccprofile ); * field records the access parameter supplied to an OpenColorProfile()
extern HANDLE MSCMS_hprofile2handle( HPROFILE profile ); * call, i.e. PROFILE_READ or PROFILE_READWRITE.
extern cmsHPROFILE MSCMS_hprofile2cmsprofile( HPROFILE profile ); */
extern icProfile *MSCMS_hprofile2iccprofile( HPROFILE profile );
extern HPROFILE MSCMS_create_hprofile_handle( HANDLE file, icProfile *iccprofile, struct profile
cmsHPROFILE cmsprofile, DWORD access ); {
extern void MSCMS_destroy_hprofile_handle( HPROFILE profile ); HANDLE file;
DWORD access;
icProfile *iccprofile;
cmsHPROFILE cmsprofile;
};
extern cmsHTRANSFORM MSCMS_htransform2cmstransform( HTRANSFORM transform ); struct transform
extern HTRANSFORM MSCMS_create_htransform_handle( cmsHTRANSFORM cmstransform ); {
extern void MSCMS_destroy_htransform_handle( HTRANSFORM 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 DWORD MSCMS_get_tag_count( const icProfile *iccprofile );
extern void MSCMS_get_tag_by_index( icProfile *iccprofile, DWORD index, icTag *tag ); extern void MSCMS_get_tag_by_index( icProfile *iccprofile, DWORD index, icTag *tag );

View File

@ -333,38 +333,46 @@ BOOL WINAPI GetColorDirectoryW( PCWSTR machine, PWSTR buffer, PDWORD size )
* Success: TRUE * Success: TRUE
* Failure: FALSE * 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 ) PVOID buffer, PBOOL ref )
{ {
BOOL ret = FALSE; BOOL ret = FALSE;
#ifdef HAVE_LCMS #ifdef HAVE_LCMS
icProfile *iccprofile = MSCMS_hprofile2iccprofile( profile ); struct profile *profile = grab_profile( handle );
DWORD i, count; DWORD i, count;
icTag tag; 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; if (!profile) return FALSE;
count = MSCMS_get_tag_count( iccprofile );
if (!size || !ref)
{
release_profile( profile );
return FALSE;
}
count = MSCMS_get_tag_count( profile->iccprofile );
for (i = 0; i < count; i++) 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.sig == type)
{ {
if ((tag.size - offset) > *size || !buffer) if ((tag.size - offset) > *size || !buffer)
{ {
*size = (tag.size - offset); *size = (tag.size - offset);
release_profile( profile );
return FALSE; return FALSE;
} }
MSCMS_get_tag_data( profile->iccprofile, &tag, offset, buffer );
MSCMS_get_tag_data( iccprofile, &tag, offset, buffer );
*ref = FALSE; /* FIXME: calculate properly */ *ref = FALSE; /* FIXME: calculate properly */
release_profile( profile );
return TRUE; return TRUE;
} }
} }
release_profile( profile );
#endif /* HAVE_LCMS */ #endif /* HAVE_LCMS */
return ret; return ret;
@ -388,24 +396,33 @@ BOOL WINAPI GetColorProfileElement( HPROFILE profile, TAGTYPE type, DWORD offset
* The tag table index starts at 1. * The tag table index starts at 1.
* Use GetCountColorProfileElements to retrieve a count of tagged elements. * 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; BOOL ret = FALSE;
#ifdef HAVE_LCMS #ifdef HAVE_LCMS
icProfile *iccprofile = MSCMS_hprofile2iccprofile( profile ); struct profile *profile = grab_profile( handle );
DWORD count; DWORD count;
icTag tag; icTag tag;
TRACE( "( %p, %d, %p )\n", profile, index, type ); TRACE( "( %p, %d, %p )\n", handle, index, type );
if (!iccprofile || !type) return FALSE; if (!profile) return FALSE;
count = MSCMS_get_tag_count( iccprofile ); if (!type)
if (index > count || index < 1) return FALSE; {
release_profile( profile );
MSCMS_get_tag_by_index( iccprofile, index - 1, &tag ); 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; *type = tag.sig;
release_profile( profile );
ret = TRUE; ret = TRUE;
#endif /* HAVE_LCMS */ #endif /* HAVE_LCMS */
@ -430,28 +447,36 @@ BOOL WINAPI GetColorProfileElementTag( HPROFILE profile, DWORD index, PTAGTYPE t
* NOTES * NOTES
* The profile returned will be in big-endian format. * 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; BOOL ret = FALSE;
#ifdef HAVE_LCMS #ifdef HAVE_LCMS
icProfile *iccprofile = MSCMS_hprofile2iccprofile( profile ); struct profile *profile = grab_profile( handle );
PROFILEHEADER header; PROFILEHEADER header;
TRACE( "( %p, %p, %p )\n", profile, buffer, size ); TRACE( "( %p, %p, %p )\n", handle, buffer, size );
if (!iccprofile || !size) return FALSE; if (!profile) return FALSE;
MSCMS_get_profile_header( iccprofile, &header );
if (!size)
{
release_profile( profile );
return FALSE;
}
MSCMS_get_profile_header( profile->iccprofile, &header );
if (!buffer || header.phSize > *size) if (!buffer || header.phSize > *size)
{ {
*size = header.phSize; *size = header.phSize;
release_profile( profile );
return FALSE; return FALSE;
} }
/* No endian conversion needed */ /* No endian conversion needed */
memcpy( buffer, iccprofile, header.phSize ); memcpy( buffer, profile->iccprofile, header.phSize );
*size = header.phSize; *size = header.phSize;
release_profile( profile );
ret = TRUE; ret = TRUE;
#endif /* HAVE_LCMS */ #endif /* HAVE_LCMS */
@ -474,16 +499,23 @@ BOOL WINAPI GetColorProfileFromHandle( HPROFILE profile, PBYTE buffer, PDWORD si
* NOTES * NOTES
* The profile header returned will be adjusted for endianess. * 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 #ifdef HAVE_LCMS
icProfile *iccprofile = MSCMS_hprofile2iccprofile( 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 (!profile) return FALSE;
MSCMS_get_profile_header( iccprofile, header ); if (!header)
{
release_profile( profile );
return FALSE;
}
MSCMS_get_profile_header( profile->iccprofile, header );
release_profile( profile );
return TRUE; return TRUE;
#else #else
@ -505,16 +537,24 @@ BOOL WINAPI GetColorProfileHeader( HPROFILE profile, PPROFILEHEADER header )
* Success: TRUE * Success: TRUE
* Failure: FALSE * Failure: FALSE
*/ */
BOOL WINAPI GetCountColorProfileElements( HPROFILE profile, PDWORD count ) BOOL WINAPI GetCountColorProfileElements( HPROFILE handle, PDWORD count )
{ {
BOOL ret = FALSE; BOOL ret = FALSE;
#ifdef HAVE_LCMS #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; if (!profile) return FALSE;
*count = MSCMS_get_tag_count( iccprofile );
if (!count)
{
release_profile( profile );
return FALSE;
}
*count = MSCMS_get_tag_count( profile->iccprofile );
release_profile( profile );
ret = TRUE; ret = TRUE;
#endif /* HAVE_LCMS */ #endif /* HAVE_LCMS */
@ -1113,23 +1153,28 @@ BOOL WINAPI InstallColorProfileW( PCWSTR machine, PCWSTR profile )
* Success: TRUE * Success: TRUE
* Failure: FALSE * Failure: FALSE
*/ */
BOOL WINAPI IsColorProfileTagPresent( HPROFILE profile, TAGTYPE type, PBOOL present ) BOOL WINAPI IsColorProfileTagPresent( HPROFILE handle, TAGTYPE type, PBOOL present )
{ {
BOOL ret = FALSE; BOOL ret = FALSE;
#ifdef HAVE_LCMS #ifdef HAVE_LCMS
icProfile *iccprofile = MSCMS_hprofile2iccprofile( profile ); struct profile *profile = grab_profile( handle );
DWORD i, count; DWORD i, count;
icTag tag; 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++) 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.sig == type)
{ {
@ -1137,6 +1182,7 @@ BOOL WINAPI IsColorProfileTagPresent( HPROFILE profile, TAGTYPE type, PBOOL pres
break; break;
} }
} }
release_profile( profile );
#endif /* HAVE_LCMS */ #endif /* HAVE_LCMS */
return ret; return ret;
@ -1156,16 +1202,23 @@ BOOL WINAPI IsColorProfileTagPresent( HPROFILE profile, TAGTYPE type, PBOOL pres
* Success: TRUE * Success: TRUE
* Failure: FALSE * Failure: FALSE
*/ */
BOOL WINAPI IsColorProfileValid( HPROFILE profile, PBOOL valid ) BOOL WINAPI IsColorProfileValid( HPROFILE handle, PBOOL valid )
{ {
BOOL ret = FALSE; BOOL ret = FALSE;
#ifdef HAVE_LCMS #ifdef HAVE_LCMS
icProfile *iccprofile = MSCMS_hprofile2iccprofile( profile ); struct profile *profile = grab_profile( handle );
TRACE( "( %p, %p )\n", profile, valid ); TRACE( "( %p, %p )\n", handle, valid );
if (!valid) return FALSE; if (!profile) 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 */ #endif /* HAVE_LCMS */
return ret; return ret;
@ -1188,34 +1241,44 @@ BOOL WINAPI IsColorProfileValid( HPROFILE profile, PBOOL valid )
* Success: TRUE * Success: TRUE
* Failure: FALSE * 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 ) PVOID buffer )
{ {
BOOL ret = FALSE; BOOL ret = FALSE;
#ifdef HAVE_LCMS #ifdef HAVE_LCMS
icProfile *iccprofile = MSCMS_hprofile2iccprofile( profile ); struct profile *profile = grab_profile( handle );
DWORD i, count, access = MSCMS_hprofile2access( profile ); DWORD i, count;
icTag tag; 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 (!profile) return FALSE;
if (!(access & PROFILE_READWRITE)) 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++) 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.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; return TRUE;
} }
} }
release_profile( profile );
#endif /* HAVE_LCMS */ #endif /* HAVE_LCMS */
return ret; return ret;
@ -1234,18 +1297,23 @@ BOOL WINAPI SetColorProfileElement( HPROFILE profile, TAGTYPE type, DWORD offset
* Success: TRUE * Success: TRUE
* Failure: FALSE * Failure: FALSE
*/ */
BOOL WINAPI SetColorProfileHeader( HPROFILE profile, PPROFILEHEADER header ) BOOL WINAPI SetColorProfileHeader( HPROFILE handle, PPROFILEHEADER header )
{ {
#ifdef HAVE_LCMS #ifdef HAVE_LCMS
icProfile *iccprofile = MSCMS_hprofile2iccprofile( profile ); struct profile *profile = grab_profile( handle );
DWORD access = MSCMS_hprofile2access( profile );
TRACE( "( %p, %p )\n", profile, header ); TRACE( "( %p, %p )\n", handle, header );
if (!iccprofile || !header) return FALSE; if (!profile) return FALSE;
if (!(access & PROFILE_READWRITE)) 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; return TRUE;
#else #else
@ -1441,7 +1509,16 @@ HPROFILE WINAPI OpenColorProfileW( PPROFILE profile, DWORD access, DWORD sharing
} }
if (cmsprofile) 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 */ #endif /* HAVE_LCMS */
return NULL; return NULL;
@ -1463,30 +1540,9 @@ BOOL WINAPI CloseColorProfile( HPROFILE profile )
{ {
BOOL ret = FALSE; BOOL ret = FALSE;
#ifdef HAVE_LCMS #ifdef HAVE_LCMS
icProfile *iccprofile = MSCMS_hprofile2iccprofile( profile );
HANDLE file = MSCMS_hprofile2handle( profile );
DWORD access = MSCMS_hprofile2access( profile );
TRACE( "( %p )\n", profile ); TRACE( "( %p )\n", profile );
ret = close_profile( 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 );
#endif /* HAVE_LCMS */ #endif /* HAVE_LCMS */
return ret; return ret;

View File

@ -135,15 +135,21 @@ HTRANSFORM WINAPI CreateColorTransformW( LPLOGCOLORSPACEW space, HPROFILE dest,
{ {
HTRANSFORM ret = NULL; HTRANSFORM ret = NULL;
#ifdef HAVE_LCMS #ifdef HAVE_LCMS
cmsHTRANSFORM cmstransform; struct transform transform;
struct profile *dst, *tgt = NULL;
cmsHPROFILE cmsinput, cmsoutput, cmstarget = NULL; cmsHPROFILE cmsinput, cmsoutput, cmstarget = NULL;
DWORD in_format, out_format, proofing = 0; DWORD in_format, out_format, proofing = 0;
int intent; int intent;
TRACE( "( %p, %p, %p, 0x%08x )\n", space, dest, target, flags ); 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; intent = space->lcsIntent > 3 ? INTENT_PERCEPTUAL : space->lcsIntent;
TRACE( "lcsIntent: %x\n", space->lcsIntent ); TRACE( "lcsIntent: %x\n", space->lcsIntent );
@ -157,13 +163,16 @@ HTRANSFORM WINAPI CreateColorTransformW( LPLOGCOLORSPACEW space, HPROFILE dest,
if (target) if (target)
{ {
proofing = cmsFLAGS_SOFTPROOFING; proofing = cmsFLAGS_SOFTPROOFING;
cmstarget = MSCMS_hprofile2cmsprofile( target ); cmstarget = tgt->cmsprofile;
} }
cmsoutput = MSCMS_hprofile2cmsprofile( dest ); cmsoutput = dst->cmsprofile;
cmstransform = cmsCreateProofingTransform(cmsinput, in_format, cmsoutput, out_format, cmstarget, transform.cmstransform = cmsCreateProofingTransform(cmsinput, in_format, cmsoutput, out_format, cmstarget,
intent, INTENT_ABSOLUTE_COLORIMETRIC, proofing); 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 */ #endif /* HAVE_LCMS */
return ret; return ret;
@ -191,7 +200,8 @@ HTRANSFORM WINAPI CreateMultiProfileTransform( PHPROFILE profiles, DWORD nprofil
HTRANSFORM ret = NULL; HTRANSFORM ret = NULL;
#ifdef HAVE_LCMS #ifdef HAVE_LCMS
cmsHPROFILE *cmsprofiles, cmsconvert = NULL; cmsHPROFILE *cmsprofiles, cmsconvert = NULL;
cmsHTRANSFORM cmstransform; struct transform transform;
struct profile *profile0, *profile1;
DWORD in_format, out_format; DWORD in_format, out_format;
TRACE( "( %p, 0x%08x, %p, 0x%08x, 0x%08x, 0x%08x )\n", 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; 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] ); in_format = from_profile( profiles[0] );
out_format = from_profile( profiles[nprofiles - 1] ); 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 *) ); cmsprofiles = HeapAlloc( GetProcessHeap(), 0, (nprofiles + 1) * sizeof(cmsHPROFILE *) );
if (cmsprofiles) if (cmsprofiles)
{ {
cmsprofiles[0] = MSCMS_hprofile2cmsprofile( profiles[0] ); cmsprofiles[0] = profile0->cmsprofile;
if (cmsconvert) if (cmsconvert)
{ {
cmsprofiles[1] = cmsconvert; cmsprofiles[1] = cmsconvert;
cmsprofiles[2] = MSCMS_hprofile2cmsprofile( profiles[1] ); cmsprofiles[2] = profile1->cmsprofile;
nprofiles++; nprofiles++;
} }
else 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 ); HeapFree( GetProcessHeap(), 0, cmsprofiles );
ret = MSCMS_create_htransform_handle( cmstransform ); ret = create_transform( &transform );
} }
release_profile( profile0 );
release_profile( profile1 );
#endif /* HAVE_LCMS */ #endif /* HAVE_LCMS */
return ret; return ret;
} }
@ -251,19 +272,14 @@ HTRANSFORM WINAPI CreateMultiProfileTransform( PHPROFILE profiles, DWORD nprofil
* Success: TRUE * Success: TRUE
* Failure: FALSE * Failure: FALSE
*/ */
BOOL WINAPI DeleteColorTransform( HTRANSFORM transform ) BOOL WINAPI DeleteColorTransform( HTRANSFORM handle )
{ {
BOOL ret = FALSE; BOOL ret = FALSE;
#ifdef HAVE_LCMS #ifdef HAVE_LCMS
cmsHTRANSFORM cmstransform;
TRACE( "( %p )\n", transform ); TRACE( "( %p )\n", handle );
cmstransform = MSCMS_htransform2cmstransform( transform ); ret = close_transform( handle );
cmsDeleteTransform( cmstransform );
MSCMS_destroy_htransform_handle( transform );
ret = TRUE;
#endif /* HAVE_LCMS */ #endif /* HAVE_LCMS */
return ret; return ret;
@ -291,22 +307,23 @@ BOOL WINAPI DeleteColorTransform( HTRANSFORM transform )
* Success: TRUE * Success: TRUE
* Failure: FALSE * 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 width, DWORD height, DWORD inputstride, PVOID destbits, BMFORMAT output,
DWORD outputstride, PBMCALLBACKFN callback, ULONG data ) DWORD outputstride, PBMCALLBACKFN callback, ULONG data )
{ {
BOOL ret = FALSE; BOOL ret = FALSE;
#ifdef HAVE_LCMS #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", 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 ); outputstride, callback, data );
cmstransform = MSCMS_htransform2cmstransform( transform ); if (!transform) return FALSE;
cmsChangeBuffersFormat( cmstransform, from_bmformat(input), from_bmformat(output) ); 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; ret = TRUE;
#endif /* HAVE_LCMS */ #endif /* HAVE_LCMS */
@ -330,16 +347,20 @@ BOOL WINAPI TranslateBitmapBits( HTRANSFORM transform, PVOID srcbits, BMFORMAT i
* Success: TRUE * Success: TRUE
* Failure: FALSE * 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 ) COLORTYPE input_type, PCOLOR out, COLORTYPE output_type )
{ {
BOOL ret = FALSE; BOOL ret = FALSE;
#ifdef HAVE_LCMS #ifdef HAVE_LCMS
cmsHTRANSFORM xfrm = MSCMS_htransform2cmstransform( transform ); struct transform *transform = grab_transform( handle );
cmsHTRANSFORM xfrm;
unsigned int i; 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) ); cmsChangeBuffersFormat( xfrm, from_type(input_type), from_type(output_type) );
switch (input_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); FIXME("unhandled input/output pair: %d/%d\n", input_type, output_type);
break; break;
} }
release_transform( transform );
#endif /* HAVE_LCMS */ #endif /* HAVE_LCMS */
return ret; return ret;