mscms: Rewrite handle management to be thread-safe. Allocate handles dynamically.
authorHans Leidekker <hans@it.vu.nl>
Mon, 24 Mar 2008 20:33:06 +0000 (21:33 +0100)
committerAlexandre Julliard <julliard@winehq.org>
Tue, 25 Mar 2008 11:48:22 +0000 (12:48 +0100)
dlls/mscms/handle.c
dlls/mscms/mscms_main.c
dlls/mscms/mscms_priv.h
dlls/mscms/profile.c
dlls/mscms/transform.c

index 09c2cc659b02f526080d005df35ecdb8c30359dc..84f1d8ba30f070e3af7d711c05050dc5501b99cc 100644 (file)
@@ -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 <stdarg.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 };
 
-/*  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 */
index df449b1d935e48b8e20bf18cbc2118d610e91249..a7cf23bc8bce304f25e021f456fa3fd7b3c10d9b 100644 (file)
@@ -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;
index 2f9be8bc75028297851f38a9ef96a3c60ec5ca40..c979ea85fef9449954c8d636c3b751e55162ff47 100644 (file)
 #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 );
index 2fd3e13829520a61f563ea1aecf75488b9568bfd..2f9970c3d7ca234a3ebb328144cfa9e18270ec28 100644 (file)
@@ -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;
index ec33a1086bb9f6a43a21abb7395d73ed769d9c1b..2ed65d13d7a28382f7fa8a1e8df829d284a57263 100644 (file)
@@ -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;