2 * MSCMS - Color Management System for Wine
4 * Copyright 2004 Hans Leidekker
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "wine/debug.h"
33 #define LCMS_API_FUNCTION(f) extern typeof(f) * p##f;
35 #undef LCMS_API_FUNCTION
37 #define IS_SEPARATOR(ch) ((ch) == '\\' || (ch) == '/')
39 static void MSCMS_basename( LPCWSTR path
, LPWSTR name
)
41 INT i
= lstrlenW( path
);
43 while (i
> 0 && !IS_SEPARATOR(path
[i
- 1])) i
--;
44 lstrcpyW( name
, &path
[i
] );
47 static const WCHAR rgbprofile
[] =
48 { 'c',':','\\','w','i','n','d','o','w','s','\\', 's','y','s','t','e','m','3','2',
49 '\\','s','p','o','o','l','\\','d','r','i','v','e','r','s',
50 '\\','c','o','l','o','r','\\','s','r','g','b',' ','c','o','l','o','r',' ',
51 's','p','a','c','e',' ','p','r','o','f','i','l','e','.','i','c','m',0 };
53 WINE_DEFAULT_DEBUG_CHANNEL(mscms
);
55 /******************************************************************************
56 * GetColorDirectoryA [MSCMS.@]
58 * See GetColorDirectoryW.
60 BOOL WINAPI
GetColorDirectoryA( PCSTR machine
, PSTR buffer
, PDWORD size
)
67 TRACE( "( %p, %p )\n", buffer
, size
);
69 if (machine
|| !size
) return FALSE
;
73 ret
= GetColorDirectoryW( NULL
, NULL
, &sizeW
);
74 *size
= sizeW
/ sizeof(WCHAR
);
78 sizeW
= *size
* sizeof(WCHAR
);
80 bufferW
= HeapAlloc( GetProcessHeap(), 0, sizeW
);
84 ret
= GetColorDirectoryW( NULL
, bufferW
, &sizeW
);
85 *size
= WideCharToMultiByte( CP_ACP
, 0, bufferW
, -1, NULL
, 0, NULL
, NULL
);
89 len
= WideCharToMultiByte( CP_ACP
, 0, bufferW
, *size
, buffer
, *size
, NULL
, NULL
);
90 if (!len
) ret
= FALSE
;
93 HeapFree( GetProcessHeap(), 0, bufferW
);
98 /******************************************************************************
99 * GetColorDirectoryW [MSCMS.@]
101 * Get the directory where color profiles are stored.
104 * machine [I] Name of the machine for which to get the color directory.
105 * Must be NULL, which indicates the local machine.
106 * buffer [I] Buffer to receive the path name.
107 * size [I/O] Size of the buffer in bytes. On return the variable holds
108 * the number of bytes actually needed.
110 BOOL WINAPI
GetColorDirectoryW( PCWSTR machine
, PWSTR buffer
, PDWORD size
)
112 /* FIXME: Get this directory from the registry? */
113 static const WCHAR colordir
[] =
114 { 'c',':','\\','w','i','n','d','o','w','s','\\', 's','y','s','t','e','m','3','2',
115 '\\','s','p','o','o','l','\\','d','r','i','v','e','r','s','\\','c','o','l','o','r',0 };
119 TRACE( "( %p, %p )\n", buffer
, size
);
121 if (machine
|| !size
) return FALSE
;
123 len
= lstrlenW( colordir
) * sizeof(WCHAR
);
125 if (len
<= *size
&& buffer
)
127 lstrcpyW( buffer
, colordir
);
136 /******************************************************************************
137 * GetColorProfileElement [MSCMS.@]
139 * Retrieve data for a specified tag type.
142 * profile [I] Handle to a color profile.
143 * type [I] ICC tag type.
144 * offset [I] Offset in bytes to start copying from.
145 * size [I/O] Size of the buffer in bytes. On return the variable holds
146 * the number of bytes actually needed.
147 * buffer [O] Buffer to receive the tag data.
148 * ref [O] Pointer to a BOOL that specifies whether more than one tag
149 * references the data.
155 BOOL WINAPI
GetColorProfileElement( HPROFILE profile
, TAGTYPE type
, DWORD offset
, PDWORD size
,
156 PVOID buffer
, PBOOL ref
)
160 icProfile
*iccprofile
= MSCMS_hprofile2iccprofile( profile
);
164 TRACE( "( %p, 0x%08lx, %ld, %p, %p, %p )\n", profile
, type
, offset
, size
, buffer
, ref
);
166 if (!iccprofile
|| !size
|| !ref
) return FALSE
;
167 count
= MSCMS_get_tag_count( iccprofile
);
169 for (i
= 0; i
< count
; i
++)
171 MSCMS_get_tag_by_index( iccprofile
, i
, &tag
);
175 if ((tag
.size
- offset
) > *size
|| !buffer
)
177 *size
= (tag
.size
- offset
);
181 MSCMS_get_tag_data( iccprofile
, &tag
, offset
, buffer
);
183 *ref
= FALSE
; /* FIXME: calculate properly */
188 #endif /* HAVE_LCMS_H */
192 /******************************************************************************
193 * GetColorProfileElementTag [MSCMS.@]
195 * Get the tag type from a color profile by index.
198 * profile [I] Handle to a color profile.
199 * index [I] Index into the tag table of the color profile.
200 * type [O] Pointer to a variable that holds the ICC tag type on return.
207 * The tag table index starts at 1.
208 * Use GetCountColorProfileElements to retrieve a count of tagged elements.
210 BOOL WINAPI
GetColorProfileElementTag( HPROFILE profile
, DWORD index
, PTAGTYPE type
)
214 icProfile
*iccprofile
= MSCMS_hprofile2iccprofile( profile
);
218 TRACE( "( %p, %ld, %p )\n", profile
, index
, type
);
220 if (!iccprofile
|| !type
) return FALSE
;
222 count
= MSCMS_get_tag_count( iccprofile
);
223 if (index
> count
|| index
< 1) return FALSE
;
225 MSCMS_get_tag_by_index( iccprofile
, index
- 1, &tag
);
230 #endif /* HAVE_LCMS_H */
234 /******************************************************************************
235 * GetColorProfileFromHandle [MSCMS.@]
237 * Retrieve an ICC color profile by handle.
240 * profile [I] Handle to a color profile.
241 * buffer [O] Buffer to receive the ICC profile.
242 * size [I/O] Size of the buffer in bytes. On return the variable holds the
243 * number of bytes actually needed.
250 * The profile returned will be in big-endian format.
252 BOOL WINAPI
GetColorProfileFromHandle( HPROFILE profile
, PBYTE buffer
, PDWORD size
)
256 icProfile
*iccprofile
= MSCMS_hprofile2iccprofile( profile
);
257 PROFILEHEADER header
;
259 TRACE( "( %p, %p, %p )\n", profile
, buffer
, size
);
261 if (!iccprofile
|| !size
) return FALSE
;
262 MSCMS_get_profile_header( iccprofile
, &header
);
264 if (!buffer
|| header
.phSize
> *size
)
266 *size
= header
.phSize
;
270 /* No endian conversion needed */
271 memcpy( buffer
, iccprofile
, header
.phSize
);
273 *size
= header
.phSize
;
276 #endif /* HAVE_LCMS_H */
280 /******************************************************************************
281 * GetColorProfileHeader [MSCMS.@]
283 * Retrieve a color profile header by handle.
286 * profile [I] Handle to a color profile.
287 * header [O] Buffer to receive the ICC profile header.
294 * The profile header returned will be adjusted for endianess.
296 BOOL WINAPI
GetColorProfileHeader( HPROFILE profile
, PPROFILEHEADER header
)
300 icProfile
*iccprofile
= MSCMS_hprofile2iccprofile( profile
);
302 TRACE( "( %p, %p )\n", profile
, header
);
304 if (!iccprofile
|| !header
) return FALSE
;
306 MSCMS_get_profile_header( iccprofile
, header
);
309 #endif /* HAVE_LCMS_H */
313 /******************************************************************************
314 * GetCountColorProfileElements [MSCMS.@]
316 * Retrieve the number of elements in a color profile.
319 * profile [I] Handle to a color profile.
320 * count [O] Pointer to a variable which is set to the number of elements
321 * in the color profile.
327 BOOL WINAPI
GetCountColorProfileElements( HPROFILE profile
, PDWORD count
)
331 icProfile
*iccprofile
= MSCMS_hprofile2iccprofile( profile
);
333 TRACE( "( %p, %p )\n", profile
, count
);
335 if (!iccprofile
|| !count
) return FALSE
;
336 *count
= MSCMS_get_tag_count( iccprofile
);
339 #endif /* HAVE_LCMS_H */
343 BOOL WINAPI
GetStandardColorSpaceProfileA( PCSTR machine
, DWORD id
, PSTR profile
, PDWORD size
)
350 TRACE( "( 0x%08lx, %p, %p )\n", id
, profile
, size
);
352 if (machine
|| !size
) return FALSE
;
354 sizeW
= *size
* sizeof(WCHAR
);
358 ret
= GetStandardColorSpaceProfileW( NULL
, id
, NULL
, &sizeW
);
359 *size
= sizeW
/ sizeof(WCHAR
);
363 profileW
= HeapAlloc( GetProcessHeap(), 0, sizeW
);
367 ret
= GetStandardColorSpaceProfileW( NULL
, id
, profileW
, &sizeW
);
368 *size
= WideCharToMultiByte( CP_ACP
, 0, profileW
, -1, NULL
, 0, NULL
, NULL
);
372 len
= WideCharToMultiByte( CP_ACP
, 0, profileW
, *size
, profile
, *size
, NULL
, NULL
);
373 if (!len
) ret
= FALSE
;
376 HeapFree( GetProcessHeap(), 0, profileW
);
381 BOOL WINAPI
GetStandardColorSpaceProfileW( PCWSTR machine
, DWORD id
, PWSTR profile
, PDWORD size
)
385 TRACE( "( 0x%08lx, %p, %p )\n", id
, profile
, size
);
387 if (machine
|| !size
) return FALSE
;
391 case 0x52474220: /* 'RGB ' */
392 len
= sizeof( rgbprofile
);
394 if (*size
< len
|| !profile
)
400 lstrcpyW( profile
, rgbprofile
);
410 /******************************************************************************
411 * InstallColorProfileA [MSCMS.@]
413 * See InstallColorProfileW.
415 BOOL WINAPI
InstallColorProfileA( PCSTR machine
, PCSTR profile
)
421 TRACE( "( %s )\n", debugstr_a(profile
) );
423 if (machine
|| !profile
) return FALSE
;
425 len
= MultiByteToWideChar( CP_ACP
, 0, profile
, -1, NULL
, 0 );
426 profileW
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) );
430 MultiByteToWideChar( CP_ACP
, 0, profile
, -1, profileW
, len
);
432 ret
= InstallColorProfileW( NULL
, profileW
);
433 HeapFree( GetProcessHeap(), 0, profileW
);
438 /******************************************************************************
439 * InstallColorProfileW [MSCMS.@]
441 * Install a color profile.
444 * machine [I] Name of the machine to install the profile on. Must be NULL,
445 * which indicates the local machine.
446 * profile [I] Full path name of the profile to install.
452 BOOL WINAPI
InstallColorProfileW( PCWSTR machine
, PCWSTR profile
)
454 WCHAR dest
[MAX_PATH
], base
[MAX_PATH
];
455 DWORD size
= sizeof(dest
);
456 static const WCHAR slash
[] = { '\\', 0 };
458 TRACE( "( %s )\n", debugstr_w(profile
) );
460 if (machine
|| !profile
) return FALSE
;
462 if (!GetColorDirectoryW( machine
, dest
, &size
)) return FALSE
;
464 MSCMS_basename( profile
, base
);
466 lstrcatW( dest
, slash
);
467 lstrcatW( dest
, base
);
469 /* Is source equal to destination? */
470 if (!lstrcmpW( profile
, dest
)) return TRUE
;
472 return CopyFileW( profile
, dest
, TRUE
);
475 /******************************************************************************
476 * IsColorProfileTagPresent [MSCMS.@]
478 * Determine if a given ICC tag type is present in a color profile.
481 * profile [I] Color profile handle.
482 * tag [I] ICC tag type.
483 * present [O] Pointer to a BOOL variable. Set to TRUE if tag type is present,
490 BOOL WINAPI
IsColorProfileTagPresent( HPROFILE profile
, TAGTYPE type
, PBOOL present
)
494 cmsHPROFILE cmsprofile
= MSCMS_hprofile2cmsprofile( profile
);
496 TRACE( "( %p, 0x%08lx, %p )\n", profile
, type
, present
);
498 if (!cmsprofile
|| !present
) return FALSE
;
499 ret
= cmsIsTag( cmsprofile
, type
);
501 #endif /* HAVE_LCMS_H */
502 return *present
= ret
;
505 /******************************************************************************
506 * IsColorProfileValid [MSCMS.@]
508 * Determine if a given color profile is valid.
511 * profile [I] Color profile handle.
512 * valid [O] Pointer to a BOOL variable. Set to TRUE if profile is valid,
519 BOOL WINAPI
IsColorProfileValid( HPROFILE profile
, PBOOL valid
)
523 icProfile
*iccprofile
= MSCMS_hprofile2iccprofile( profile
);
525 TRACE( "( %p, %p )\n", profile
, valid
);
527 if (!valid
) return FALSE
;
528 if (iccprofile
) return *valid
= TRUE
;
530 #endif /* HAVE_LCMS_H */
534 /******************************************************************************
535 * SetColorProfileElement [MSCMS.@]
537 * Set data for a specified tag type.
540 * profile [I] Handle to a color profile.
541 * type [I] ICC tag type.
542 * offset [I] Offset in bytes to start copying to.
543 * size [I/O] Size of the buffer in bytes. On return the variable holds the
544 * number of bytes actually needed.
545 * buffer [O] Buffer holding the tag data.
551 BOOL WINAPI
SetColorProfileElement( HPROFILE profile
, TAGTYPE type
, DWORD offset
, PDWORD size
,
556 icProfile
*iccprofile
= MSCMS_hprofile2iccprofile( profile
);
560 TRACE( "( %p, 0x%08lx, %ld, %p, %p )\n", profile
, type
, offset
, size
, buffer
);
562 if (!iccprofile
|| !size
|| !buffer
) return FALSE
;
563 count
= MSCMS_get_tag_count( iccprofile
);
565 for (i
= 0; i
< count
; i
++)
567 MSCMS_get_tag_by_index( iccprofile
, i
, &tag
);
571 if (offset
> tag
.size
) return FALSE
;
573 MSCMS_set_tag_data( iccprofile
, &tag
, offset
, buffer
);
578 #endif /* HAVE_LCMS_H */
582 BOOL WINAPI
SetColorProfileHeader( HPROFILE profile
, PPROFILEHEADER header
)
586 icProfile
*iccprofile
= MSCMS_hprofile2iccprofile( profile
);
588 TRACE( "( %p, %p )\n", profile
, header
);
590 if (!iccprofile
|| !header
) return FALSE
;
592 MSCMS_set_profile_header( iccprofile
, header
);
595 #endif /* HAVE_LCMS_H */
599 BOOL WINAPI
SetStandardColorSpaceProfileA( PCSTR machine
, DWORD id
, PSTR profile
)
601 FIXME( "( 0x%08lx, %p ) stub\n", id
, profile
);
606 BOOL WINAPI
SetStandardColorSpaceProfileW( PCWSTR machine
, DWORD id
, PWSTR profile
)
608 FIXME( "( 0x%08lx, %p ) stub\n", id
, profile
);
613 /******************************************************************************
614 * UninstallColorProfileA [MSCMS.@]
616 * See UninstallColorProfileW.
618 BOOL WINAPI
UninstallColorProfileA( PCSTR machine
, PCSTR profile
, BOOL
delete )
624 TRACE( "( %s, %x )\n", debugstr_a(profile
), delete );
626 if (machine
|| !profile
) return FALSE
;
628 len
= MultiByteToWideChar( CP_ACP
, 0, profile
, -1, NULL
, 0 );
629 profileW
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) );
633 MultiByteToWideChar( CP_ACP
, 0, profile
, -1, profileW
, len
);
635 ret
= UninstallColorProfileW( NULL
, profileW
, delete );
637 HeapFree( GetProcessHeap(), 0, profileW
);
642 /******************************************************************************
643 * UninstallColorProfileW [MSCMS.@]
645 * Uninstall a color profile.
648 * machine [I] Name of the machine to uninstall the profile on. Must be NULL,
649 * which indicates the local machine.
650 * profile [I] Full path name of the profile to uninstall.
651 * delete [I] Bool that specifies whether the profile file should be deleted.
657 BOOL WINAPI
UninstallColorProfileW( PCWSTR machine
, PCWSTR profile
, BOOL
delete )
659 TRACE( "( %s, %x )\n", debugstr_w(profile
), delete );
661 if (machine
|| !profile
) return FALSE
;
663 if (delete) return DeleteFileW( profile
);
668 /******************************************************************************
669 * OpenColorProfileA [MSCMS.@]
671 * See OpenColorProfileW.
673 HPROFILE WINAPI
OpenColorProfileA( PPROFILE profile
, DWORD access
, DWORD sharing
, DWORD creation
)
675 HPROFILE handle
= NULL
;
677 TRACE( "( %p, 0x%08lx, 0x%08lx, 0x%08lx )\n", profile
, access
, sharing
, creation
);
679 if (!profile
|| !profile
->pProfileData
) return NULL
;
681 /* No AW conversion needed for memory based profiles */
682 if (profile
->dwType
& PROFILE_MEMBUFFER
)
683 return OpenColorProfileW( profile
, access
, sharing
, creation
);
685 if (profile
->dwType
& PROFILE_FILENAME
)
690 profileW
.dwType
= profile
->dwType
;
692 len
= MultiByteToWideChar( CP_ACP
, 0, profile
->pProfileData
, -1, NULL
, 0 );
693 profileW
.pProfileData
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) );
695 if (profileW
.pProfileData
)
697 profileW
.cbDataSize
= len
* sizeof(WCHAR
);
698 MultiByteToWideChar( CP_ACP
, 0, profile
->pProfileData
, -1, profileW
.pProfileData
, len
);
700 handle
= OpenColorProfileW( &profileW
, access
, sharing
, creation
);
701 HeapFree( GetProcessHeap(), 0, profileW
.pProfileData
);
707 /******************************************************************************
708 * OpenColorProfileW [MSCMS.@]
710 * Open a color profile.
713 * profile [I] Pointer to a color profile structure.
714 * access [I] Desired access.
715 * sharing [I] Sharing mode.
716 * creation [I] Creation mode.
719 * Success: Handle to the opened profile.
723 * Values for access: PROFILE_READ or PROFILE_READWRITE.
724 * Values for sharing: 0 (no sharing), FILE_SHARE_READ and/or FILE_SHARE_WRITE.
725 * Values for creation: one of CREATE_NEW, CREATE_ALWAYS, OPEN_EXISTING,
726 * OPEN_ALWAYS, TRUNCATE_EXISTING.
727 * Sharing and creation flags are ignored for memory based profiles.
729 HPROFILE WINAPI
OpenColorProfileW( PPROFILE profile
, DWORD access
, DWORD sharing
, DWORD creation
)
732 cmsHPROFILE cmsprofile
= NULL
;
733 icProfile
*iccprofile
= NULL
;
734 HANDLE handle
= NULL
;
737 TRACE( "( %p, 0x%08lx, 0x%08lx, 0x%08lx )\n", profile
, access
, sharing
, creation
);
739 if (!profile
|| !profile
->pProfileData
) return NULL
;
741 if (profile
->dwType
& PROFILE_MEMBUFFER
)
743 FIXME( "access flags not implemented for memory based profiles\n" );
745 iccprofile
= profile
->pProfileData
;
746 size
= profile
->cbDataSize
;
748 cmsprofile
= cmsOpenProfileFromMem( iccprofile
, size
);
751 if (profile
->dwType
& PROFILE_FILENAME
)
753 DWORD read
, flags
= 0;
755 TRACE( "profile file: %s\n", debugstr_w( (WCHAR
*)profile
->pProfileData
) );
757 if (access
& PROFILE_READ
) flags
= GENERIC_READ
;
758 if (access
& PROFILE_READWRITE
) flags
= GENERIC_READ
|GENERIC_WRITE
;
760 if (!flags
) return NULL
;
762 handle
= CreateFileW( profile
->pProfileData
, flags
, sharing
, NULL
, creation
, 0, NULL
);
763 if (handle
== INVALID_HANDLE_VALUE
)
765 WARN( "Unable to open color profile\n" );
769 if ((size
= GetFileSize( handle
, NULL
)) == INVALID_FILE_SIZE
)
771 ERR( "Unable to retrieve size of color profile\n" );
772 CloseHandle( handle
);
776 iccprofile
= (icProfile
*)HeapAlloc( GetProcessHeap(), 0, size
);
779 ERR( "Unable to allocate memory for color profile\n" );
780 CloseHandle( handle
);
784 if (!ReadFile( handle
, iccprofile
, size
, &read
, NULL
) || read
!= size
)
786 ERR( "Unable to read color profile\n" );
788 CloseHandle( handle
);
789 HeapFree( GetProcessHeap
, 0, iccprofile
);
793 cmsprofile
= cmsOpenProfileFromMem( iccprofile
, size
);
797 return MSCMS_create_hprofile_handle( handle
, iccprofile
, cmsprofile
);
799 #endif /* HAVE_LCMS_H */
803 /******************************************************************************
804 * CloseColorProfile [MSCMS.@]
806 * Close a color profile.
809 * profile [I] Handle to the profile.
815 BOOL WINAPI
CloseColorProfile( HPROFILE profile
)
819 TRACE( "( %p )\n", profile
);
822 ret
= cmsCloseProfile( MSCMS_hprofile2cmsprofile( profile
) );
824 HeapFree( GetProcessHeap(), 0, MSCMS_hprofile2iccprofile( profile
) );
825 CloseHandle( MSCMS_hprofile2handle( profile
) );
827 MSCMS_destroy_hprofile_handle( profile
);
829 #endif /* HAVE_LCMS_H */