2 * MSCMS - Color Management System for Wine
4 * Copyright 2004, 2005 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 /* FIXME: Get this directory from the registry? */
48 static const WCHAR colorsubdir
[] = { '\\','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',0 };
52 WINE_DEFAULT_DEBUG_CHANNEL(mscms
);
54 /******************************************************************************
55 * GetColorDirectoryA [MSCMS.@]
57 * See GetColorDirectoryW.
59 BOOL WINAPI
GetColorDirectoryA( PCSTR machine
, PSTR buffer
, PDWORD size
)
66 TRACE( "( %p, %p )\n", buffer
, size
);
68 if (machine
|| !size
) return FALSE
;
72 ret
= GetColorDirectoryW( NULL
, NULL
, &sizeW
);
73 *size
= sizeW
/ sizeof(WCHAR
);
77 sizeW
= *size
* sizeof(WCHAR
);
79 bufferW
= HeapAlloc( GetProcessHeap(), 0, sizeW
);
83 ret
= GetColorDirectoryW( NULL
, bufferW
, &sizeW
);
84 *size
= WideCharToMultiByte( CP_ACP
, 0, bufferW
, -1, NULL
, 0, NULL
, NULL
);
88 len
= WideCharToMultiByte( CP_ACP
, 0, bufferW
, *size
, buffer
, *size
, NULL
, NULL
);
89 if (!len
) ret
= FALSE
;
92 HeapFree( GetProcessHeap(), 0, bufferW
);
97 /******************************************************************************
98 * GetColorDirectoryW [MSCMS.@]
100 * Get the directory where color profiles are stored.
103 * machine [I] Name of the machine for which to get the color directory.
104 * Must be NULL, which indicates the local machine.
105 * buffer [I] Buffer to receive the path name.
106 * size [I/O] Size of the buffer in bytes. On return the variable holds
107 * the number of bytes actually needed.
109 BOOL WINAPI
GetColorDirectoryW( PCWSTR machine
, PWSTR buffer
, PDWORD size
)
111 WCHAR colordir
[MAX_PATH
];
114 TRACE( "( %p, %p )\n", buffer
, size
);
116 if (machine
|| !size
) return FALSE
;
118 GetWindowsDirectoryW( colordir
, sizeof(colordir
) / sizeof(WCHAR
) );
119 lstrcatW( colordir
, colorsubdir
);
121 len
= lstrlenW( colordir
) * sizeof(WCHAR
);
123 if (len
<= *size
&& buffer
)
125 lstrcpyW( buffer
, colordir
);
134 /******************************************************************************
135 * GetColorProfileElement [MSCMS.@]
137 * Retrieve data for a specified tag type.
140 * profile [I] Handle to a color profile.
141 * type [I] ICC tag type.
142 * offset [I] Offset in bytes to start copying from.
143 * size [I/O] Size of the buffer in bytes. On return the variable holds
144 * the number of bytes actually needed.
145 * buffer [O] Buffer to receive the tag data.
146 * ref [O] Pointer to a BOOL that specifies whether more than one tag
147 * references the data.
153 BOOL WINAPI
GetColorProfileElement( HPROFILE profile
, TAGTYPE type
, DWORD offset
, PDWORD size
,
154 PVOID buffer
, PBOOL ref
)
158 icProfile
*iccprofile
= MSCMS_hprofile2iccprofile( profile
);
162 TRACE( "( %p, 0x%08lx, %ld, %p, %p, %p )\n", profile
, type
, offset
, size
, buffer
, ref
);
164 if (!iccprofile
|| !size
|| !ref
) return FALSE
;
165 count
= MSCMS_get_tag_count( iccprofile
);
167 for (i
= 0; i
< count
; i
++)
169 MSCMS_get_tag_by_index( iccprofile
, i
, &tag
);
173 if ((tag
.size
- offset
) > *size
|| !buffer
)
175 *size
= (tag
.size
- offset
);
179 MSCMS_get_tag_data( iccprofile
, &tag
, offset
, buffer
);
181 *ref
= FALSE
; /* FIXME: calculate properly */
186 #endif /* HAVE_LCMS_H */
190 /******************************************************************************
191 * GetColorProfileElementTag [MSCMS.@]
193 * Get the tag type from a color profile by index.
196 * profile [I] Handle to a color profile.
197 * index [I] Index into the tag table of the color profile.
198 * type [O] Pointer to a variable that holds the ICC tag type on return.
205 * The tag table index starts at 1.
206 * Use GetCountColorProfileElements to retrieve a count of tagged elements.
208 BOOL WINAPI
GetColorProfileElementTag( HPROFILE profile
, DWORD index
, PTAGTYPE type
)
212 icProfile
*iccprofile
= MSCMS_hprofile2iccprofile( profile
);
216 TRACE( "( %p, %ld, %p )\n", profile
, index
, type
);
218 if (!iccprofile
|| !type
) return FALSE
;
220 count
= MSCMS_get_tag_count( iccprofile
);
221 if (index
> count
|| index
< 1) return FALSE
;
223 MSCMS_get_tag_by_index( iccprofile
, index
- 1, &tag
);
228 #endif /* HAVE_LCMS_H */
232 /******************************************************************************
233 * GetColorProfileFromHandle [MSCMS.@]
235 * Retrieve an ICC color profile by handle.
238 * profile [I] Handle to a color profile.
239 * buffer [O] Buffer to receive the ICC profile.
240 * size [I/O] Size of the buffer in bytes. On return the variable holds the
241 * number of bytes actually needed.
248 * The profile returned will be in big-endian format.
250 BOOL WINAPI
GetColorProfileFromHandle( HPROFILE profile
, PBYTE buffer
, PDWORD size
)
254 icProfile
*iccprofile
= MSCMS_hprofile2iccprofile( profile
);
255 PROFILEHEADER header
;
257 TRACE( "( %p, %p, %p )\n", profile
, buffer
, size
);
259 if (!iccprofile
|| !size
) return FALSE
;
260 MSCMS_get_profile_header( iccprofile
, &header
);
262 if (!buffer
|| header
.phSize
> *size
)
264 *size
= header
.phSize
;
268 /* No endian conversion needed */
269 memcpy( buffer
, iccprofile
, header
.phSize
);
271 *size
= header
.phSize
;
274 #endif /* HAVE_LCMS_H */
278 /******************************************************************************
279 * GetColorProfileHeader [MSCMS.@]
281 * Retrieve a color profile header by handle.
284 * profile [I] Handle to a color profile.
285 * header [O] Buffer to receive the ICC profile header.
292 * The profile header returned will be adjusted for endianess.
294 BOOL WINAPI
GetColorProfileHeader( HPROFILE profile
, PPROFILEHEADER header
)
298 icProfile
*iccprofile
= MSCMS_hprofile2iccprofile( profile
);
300 TRACE( "( %p, %p )\n", profile
, header
);
302 if (!iccprofile
|| !header
) return FALSE
;
304 MSCMS_get_profile_header( iccprofile
, header
);
307 #endif /* HAVE_LCMS_H */
311 /******************************************************************************
312 * GetCountColorProfileElements [MSCMS.@]
314 * Retrieve the number of elements in a color profile.
317 * profile [I] Handle to a color profile.
318 * count [O] Pointer to a variable which is set to the number of elements
319 * in the color profile.
325 BOOL WINAPI
GetCountColorProfileElements( HPROFILE profile
, PDWORD count
)
329 icProfile
*iccprofile
= MSCMS_hprofile2iccprofile( profile
);
331 TRACE( "( %p, %p )\n", profile
, count
);
333 if (!iccprofile
|| !count
) return FALSE
;
334 *count
= MSCMS_get_tag_count( iccprofile
);
337 #endif /* HAVE_LCMS_H */
341 /******************************************************************************
342 * GetStandardColorSpaceProfileA [MSCMS.@]
344 * See GetStandardColorSpaceProfileW.
346 BOOL WINAPI
GetStandardColorSpaceProfileA( PCSTR machine
, DWORD id
, PSTR profile
, PDWORD size
)
353 TRACE( "( 0x%08lx, %p, %p )\n", id
, profile
, size
);
355 if (machine
|| !size
) return FALSE
;
357 sizeW
= *size
* sizeof(WCHAR
);
361 ret
= GetStandardColorSpaceProfileW( NULL
, id
, NULL
, &sizeW
);
362 *size
= sizeW
/ sizeof(WCHAR
);
366 profileW
= HeapAlloc( GetProcessHeap(), 0, sizeW
);
370 ret
= GetStandardColorSpaceProfileW( NULL
, id
, profileW
, &sizeW
);
371 *size
= WideCharToMultiByte( CP_ACP
, 0, profileW
, -1, NULL
, 0, NULL
, NULL
);
375 len
= WideCharToMultiByte( CP_ACP
, 0, profileW
, *size
, profile
, *size
, NULL
, NULL
);
376 if (!len
) ret
= FALSE
;
379 HeapFree( GetProcessHeap(), 0, profileW
);
384 /******************************************************************************
385 * GetStandardColorSpaceProfileW [MSCMS.@]
387 * Retrieve the profile filename for a given standard color space id.
390 * machine [I] Name of the machine for which to get the standard color space.
391 * Must be NULL, which indicates the local machine.
392 * id [I] Id of a standard color space.
393 * profile [O] Buffer to receive the profile filename.
394 * size [I/O] Size of the filename buffer in bytes.
400 BOOL WINAPI
GetStandardColorSpaceProfileW( PCWSTR machine
, DWORD id
, PWSTR profile
, PDWORD size
)
402 static const WCHAR rgbprofilefile
[] = { '\\','s','r','g','b',' ','c','o','l','o','r',' ',
403 's','p','a','c','e',' ','p','r','o','f','i','l','e','.','i','c','m',0 };
404 WCHAR rgbprofile
[MAX_PATH
];
407 TRACE( "( 0x%08lx, %p, %p )\n", id
, profile
, size
);
409 if (machine
|| !size
) return FALSE
;
413 case 0x52474220: /* 'RGB ' */
414 GetWindowsDirectoryW( rgbprofile
, sizeof( rgbprofile
) / sizeof( WCHAR
) );
415 lstrcatW( rgbprofile
, colorsubdir
);
416 lstrcatW( rgbprofile
, rgbprofilefile
);
418 len
= lstrlenW( rgbprofile
) * sizeof( WCHAR
);
420 if (*size
< len
|| !profile
)
426 lstrcpyW( profile
, rgbprofile
);
436 /******************************************************************************
437 * InstallColorProfileA [MSCMS.@]
439 * See InstallColorProfileW.
441 BOOL WINAPI
InstallColorProfileA( PCSTR machine
, PCSTR profile
)
447 TRACE( "( %s )\n", debugstr_a(profile
) );
449 if (machine
|| !profile
) return FALSE
;
451 len
= MultiByteToWideChar( CP_ACP
, 0, profile
, -1, NULL
, 0 );
452 profileW
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) );
456 MultiByteToWideChar( CP_ACP
, 0, profile
, -1, profileW
, len
);
458 ret
= InstallColorProfileW( NULL
, profileW
);
459 HeapFree( GetProcessHeap(), 0, profileW
);
464 /******************************************************************************
465 * InstallColorProfileW [MSCMS.@]
467 * Install a color profile.
470 * machine [I] Name of the machine to install the profile on. Must be NULL,
471 * which indicates the local machine.
472 * profile [I] Full path name of the profile to install.
478 BOOL WINAPI
InstallColorProfileW( PCWSTR machine
, PCWSTR profile
)
480 WCHAR dest
[MAX_PATH
], base
[MAX_PATH
];
481 DWORD size
= sizeof(dest
);
482 static const WCHAR slash
[] = { '\\', 0 };
484 TRACE( "( %s )\n", debugstr_w(profile
) );
486 if (machine
|| !profile
) return FALSE
;
488 if (!GetColorDirectoryW( machine
, dest
, &size
)) return FALSE
;
490 MSCMS_basename( profile
, base
);
492 lstrcatW( dest
, slash
);
493 lstrcatW( dest
, base
);
495 /* Is source equal to destination? */
496 if (!lstrcmpW( profile
, dest
)) return TRUE
;
498 return CopyFileW( profile
, dest
, TRUE
);
501 /******************************************************************************
502 * IsColorProfileTagPresent [MSCMS.@]
504 * Determine if a given ICC tag type is present in a color profile.
507 * profile [I] Color profile handle.
508 * tag [I] ICC tag type.
509 * present [O] Pointer to a BOOL variable. Set to TRUE if tag type is present,
516 BOOL WINAPI
IsColorProfileTagPresent( HPROFILE profile
, TAGTYPE type
, PBOOL present
)
520 icProfile
*iccprofile
= MSCMS_hprofile2iccprofile( profile
);
524 TRACE( "( %p, 0x%08lx, %p )\n", profile
, type
, present
);
526 if (!iccprofile
|| !present
) return FALSE
;
528 count
= MSCMS_get_tag_count( iccprofile
);
530 for (i
= 0; i
< count
; i
++)
532 MSCMS_get_tag_by_index( iccprofile
, i
, &tag
);
536 *present
= ret
= TRUE
;
541 #endif /* HAVE_LCMS_H */
545 /******************************************************************************
546 * IsColorProfileValid [MSCMS.@]
548 * Determine if a given color profile is valid.
551 * profile [I] Color profile handle.
552 * valid [O] Pointer to a BOOL variable. Set to TRUE if profile is valid,
559 BOOL WINAPI
IsColorProfileValid( HPROFILE profile
, PBOOL valid
)
563 icProfile
*iccprofile
= MSCMS_hprofile2iccprofile( profile
);
565 TRACE( "( %p, %p )\n", profile
, valid
);
567 if (!valid
) return FALSE
;
568 if (iccprofile
) return *valid
= TRUE
;
570 #endif /* HAVE_LCMS_H */
574 /******************************************************************************
575 * SetColorProfileElement [MSCMS.@]
577 * Set data for a specified tag type.
580 * profile [I] Handle to a color profile.
581 * type [I] ICC tag type.
582 * offset [I] Offset in bytes to start copying to.
583 * size [I/O] Size of the buffer in bytes. On return the variable holds the
584 * number of bytes actually needed.
585 * buffer [O] Buffer holding the tag data.
591 BOOL WINAPI
SetColorProfileElement( HPROFILE profile
, TAGTYPE type
, DWORD offset
, PDWORD size
,
596 icProfile
*iccprofile
= MSCMS_hprofile2iccprofile( profile
);
597 DWORD i
, count
, access
= MSCMS_hprofile2access( profile
);
600 TRACE( "( %p, 0x%08lx, %ld, %p, %p )\n", profile
, type
, offset
, size
, buffer
);
602 if (!iccprofile
|| !size
|| !buffer
) return FALSE
;
603 if (!(access
& PROFILE_READWRITE
)) return FALSE
;
605 count
= MSCMS_get_tag_count( iccprofile
);
607 for (i
= 0; i
< count
; i
++)
609 MSCMS_get_tag_by_index( iccprofile
, i
, &tag
);
613 if (offset
> tag
.size
) return FALSE
;
615 MSCMS_set_tag_data( iccprofile
, &tag
, offset
, buffer
);
620 #endif /* HAVE_LCMS_H */
624 /******************************************************************************
625 * SetColorProfileHeader [MSCMS.@]
627 * Set header data for a given profile.
630 * profile [I] Handle to a color profile.
631 * header [I] Buffer holding the header data.
637 BOOL WINAPI
SetColorProfileHeader( HPROFILE profile
, PPROFILEHEADER header
)
641 icProfile
*iccprofile
= MSCMS_hprofile2iccprofile( profile
);
642 DWORD access
= MSCMS_hprofile2access( profile
);
644 TRACE( "( %p, %p )\n", profile
, header
);
646 if (!iccprofile
|| !header
) return FALSE
;
647 if (!(access
& PROFILE_READWRITE
)) return FALSE
;
649 MSCMS_set_profile_header( iccprofile
, header
);
652 #endif /* HAVE_LCMS_H */
656 /******************************************************************************
657 * UninstallColorProfileA [MSCMS.@]
659 * See UninstallColorProfileW.
661 BOOL WINAPI
UninstallColorProfileA( PCSTR machine
, PCSTR profile
, BOOL
delete )
667 TRACE( "( %s, %x )\n", debugstr_a(profile
), delete );
669 if (machine
|| !profile
) return FALSE
;
671 len
= MultiByteToWideChar( CP_ACP
, 0, profile
, -1, NULL
, 0 );
672 profileW
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) );
676 MultiByteToWideChar( CP_ACP
, 0, profile
, -1, profileW
, len
);
678 ret
= UninstallColorProfileW( NULL
, profileW
, delete );
680 HeapFree( GetProcessHeap(), 0, profileW
);
685 /******************************************************************************
686 * UninstallColorProfileW [MSCMS.@]
688 * Uninstall a color profile.
691 * machine [I] Name of the machine to uninstall the profile on. Must be NULL,
692 * which indicates the local machine.
693 * profile [I] Full path name of the profile to uninstall.
694 * delete [I] Bool that specifies whether the profile file should be deleted.
700 BOOL WINAPI
UninstallColorProfileW( PCWSTR machine
, PCWSTR profile
, BOOL
delete )
702 TRACE( "( %s, %x )\n", debugstr_w(profile
), delete );
704 if (machine
|| !profile
) return FALSE
;
706 if (delete) return DeleteFileW( profile
);
711 /******************************************************************************
712 * OpenColorProfileA [MSCMS.@]
714 * See OpenColorProfileW.
716 HPROFILE WINAPI
OpenColorProfileA( PPROFILE profile
, DWORD access
, DWORD sharing
, DWORD creation
)
718 HPROFILE handle
= NULL
;
720 TRACE( "( %p, 0x%08lx, 0x%08lx, 0x%08lx )\n", profile
, access
, sharing
, creation
);
722 if (!profile
|| !profile
->pProfileData
) return NULL
;
724 /* No AW conversion needed for memory based profiles */
725 if (profile
->dwType
& PROFILE_MEMBUFFER
)
726 return OpenColorProfileW( profile
, access
, sharing
, creation
);
728 if (profile
->dwType
& PROFILE_FILENAME
)
733 profileW
.dwType
= profile
->dwType
;
735 len
= MultiByteToWideChar( CP_ACP
, 0, profile
->pProfileData
, -1, NULL
, 0 );
736 profileW
.pProfileData
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) );
738 if (profileW
.pProfileData
)
740 profileW
.cbDataSize
= len
* sizeof(WCHAR
);
741 MultiByteToWideChar( CP_ACP
, 0, profile
->pProfileData
, -1, profileW
.pProfileData
, len
);
743 handle
= OpenColorProfileW( &profileW
, access
, sharing
, creation
);
744 HeapFree( GetProcessHeap(), 0, profileW
.pProfileData
);
750 /******************************************************************************
751 * OpenColorProfileW [MSCMS.@]
753 * Open a color profile.
756 * profile [I] Pointer to a color profile structure.
757 * access [I] Desired access.
758 * sharing [I] Sharing mode.
759 * creation [I] Creation mode.
762 * Success: Handle to the opened profile.
766 * Values for access: PROFILE_READ or PROFILE_READWRITE.
767 * Values for sharing: 0 (no sharing), FILE_SHARE_READ and/or FILE_SHARE_WRITE.
768 * Values for creation: one of CREATE_NEW, CREATE_ALWAYS, OPEN_EXISTING,
769 * OPEN_ALWAYS, TRUNCATE_EXISTING.
770 * Sharing and creation flags are ignored for memory based profiles.
772 HPROFILE WINAPI
OpenColorProfileW( PPROFILE profile
, DWORD access
, DWORD sharing
, DWORD creation
)
775 cmsHPROFILE cmsprofile
= NULL
;
776 icProfile
*iccprofile
= NULL
;
777 HANDLE handle
= NULL
;
780 TRACE( "( %p, 0x%08lx, 0x%08lx, 0x%08lx )\n", profile
, access
, sharing
, creation
);
782 if (!profile
|| !profile
->pProfileData
) return NULL
;
784 if (profile
->dwType
& PROFILE_MEMBUFFER
)
786 FIXME( "access flags not implemented for memory based profiles\n" );
788 iccprofile
= profile
->pProfileData
;
789 size
= profile
->cbDataSize
;
791 cmsprofile
= cmsOpenProfileFromMem( iccprofile
, size
);
794 if (profile
->dwType
& PROFILE_FILENAME
)
796 DWORD read
, flags
= 0;
798 TRACE( "profile file: %s\n", debugstr_w( (WCHAR
*)profile
->pProfileData
) );
800 if (access
& PROFILE_READ
) flags
= GENERIC_READ
;
801 if (access
& PROFILE_READWRITE
) flags
= GENERIC_READ
|GENERIC_WRITE
;
803 if (!flags
) return NULL
;
805 handle
= CreateFileW( profile
->pProfileData
, flags
, sharing
, NULL
, creation
, 0, NULL
);
806 if (handle
== INVALID_HANDLE_VALUE
)
808 WARN( "Unable to open color profile\n" );
812 if ((size
= GetFileSize( handle
, NULL
)) == INVALID_FILE_SIZE
)
814 ERR( "Unable to retrieve size of color profile\n" );
815 CloseHandle( handle
);
819 iccprofile
= HeapAlloc( GetProcessHeap(), 0, size
);
822 ERR( "Unable to allocate memory for color profile\n" );
823 CloseHandle( handle
);
827 if (!ReadFile( handle
, iccprofile
, size
, &read
, NULL
) || read
!= size
)
829 ERR( "Unable to read color profile\n" );
831 CloseHandle( handle
);
832 HeapFree( GetProcessHeap
, 0, iccprofile
);
836 cmsprofile
= cmsOpenProfileFromMem( iccprofile
, size
);
840 return MSCMS_create_hprofile_handle( handle
, iccprofile
, cmsprofile
, access
);
842 #endif /* HAVE_LCMS_H */
846 /******************************************************************************
847 * CloseColorProfile [MSCMS.@]
849 * Close a color profile.
852 * profile [I] Handle to the profile.
858 BOOL WINAPI
CloseColorProfile( HPROFILE profile
)
862 icProfile
*iccprofile
= MSCMS_hprofile2iccprofile( profile
);
863 HANDLE file
= MSCMS_hprofile2handle( profile
);
864 DWORD access
= MSCMS_hprofile2access( profile
);
866 TRACE( "( %p )\n", profile
);
868 if (file
&& (access
& PROFILE_READWRITE
))
870 DWORD written
, size
= MSCMS_get_profile_size( iccprofile
);
872 if (SetFilePointer( file
, 0, NULL
, FILE_BEGIN
) ||
873 !WriteFile( file
, iccprofile
, size
, &written
, NULL
) || written
!= size
)
874 ERR( "Unable to write color profile\n" );
877 ret
= cmsCloseProfile( MSCMS_hprofile2cmsprofile( profile
) );
878 HeapFree( GetProcessHeap(), 0, MSCMS_hprofile2iccprofile( profile
) );
880 CloseHandle( MSCMS_hprofile2handle( profile
) );
881 MSCMS_destroy_hprofile_handle( profile
);
883 #endif /* HAVE_LCMS_H */