mcicda: Exclude unused headers.
[wine] / dlls / mscms / tests / profile.c
1 /*
2  * Tests for color profile functions
3  *
4  * Copyright 2004, 2005, 2006 Hans Leidekker
5  *
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.
10  *
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.
15  *
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #include <stdarg.h>
22
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winreg.h"
26 #include "winnls.h"
27 #include "wingdi.h"
28 #include "winuser.h"
29 #include "icm.h"
30
31 #include "wine/test.h"
32
33 HMODULE hmscms;
34
35 static BOOL     (WINAPI *pCloseColorProfile)(HPROFILE);
36 static BOOL     (WINAPI *pGetColorDirectoryA)(PCHAR,PCHAR,PDWORD);
37 static BOOL     (WINAPI *pGetColorDirectoryW)(PWCHAR,PWCHAR,PDWORD);
38 static BOOL     (WINAPI *pGetColorProfileElement)(HPROFILE,TAGTYPE,DWORD,PDWORD,PVOID,PBOOL);
39 static BOOL     (WINAPI *pGetColorProfileElementTag)(HPROFILE,DWORD,PTAGTYPE);
40 static BOOL     (WINAPI *pGetColorProfileFromHandle)(HPROFILE,PBYTE,PDWORD);
41 static BOOL     (WINAPI *pGetColorProfileHeader)(HPROFILE,PPROFILEHEADER);
42 static BOOL     (WINAPI *pGetCountColorProfileElements)(HPROFILE,PDWORD);
43 static BOOL     (WINAPI *pGetStandardColorSpaceProfileA)(PCSTR,DWORD,PSTR,PDWORD);
44 static BOOL     (WINAPI *pGetStandardColorSpaceProfileW)(PCWSTR,DWORD,PWSTR,PDWORD);
45 static BOOL     (WINAPI *pEnumColorProfilesA)(PCSTR,PENUMTYPEA,PBYTE,PDWORD,PDWORD);
46 static BOOL     (WINAPI *pEnumColorProfilesW)(PCWSTR,PENUMTYPEW,PBYTE,PDWORD,PDWORD);
47 static BOOL     (WINAPI *pInstallColorProfileA)(PCSTR,PCSTR);
48 static BOOL     (WINAPI *pInstallColorProfileW)(PCWSTR,PCWSTR);
49 static BOOL     (WINAPI *pIsColorProfileTagPresent)(HPROFILE,TAGTYPE,PBOOL);
50 static HPROFILE (WINAPI *pOpenColorProfileA)(PPROFILE,DWORD,DWORD,DWORD);
51 static HPROFILE (WINAPI *pOpenColorProfileW)(PPROFILE,DWORD,DWORD,DWORD);
52 static BOOL     (WINAPI *pSetColorProfileElement)(HPROFILE,TAGTYPE,DWORD,PDWORD,PVOID);
53 static BOOL     (WINAPI *pSetColorProfileHeader)(HPROFILE,PPROFILEHEADER);
54 static BOOL     (WINAPI *pSetStandardColorSpaceProfileA)(PCSTR,DWORD,PSTR);
55 static BOOL     (WINAPI *pSetStandardColorSpaceProfileW)(PCWSTR,DWORD,PWSTR);
56 static BOOL     (WINAPI *pUninstallColorProfileA)(PCSTR,PCSTR,BOOL);
57 static BOOL     (WINAPI *pUninstallColorProfileW)(PCWSTR,PCWSTR,BOOL);
58
59 #define GETFUNCPTR(func) p##func = (void *)GetProcAddress( hmscms, #func ); \
60     if (!p##func) return FALSE;
61
62 static BOOL init_function_ptrs( void )
63 {
64     GETFUNCPTR( CloseColorProfile )
65     GETFUNCPTR( GetColorDirectoryA )
66     GETFUNCPTR( GetColorDirectoryW )
67     GETFUNCPTR( GetColorProfileElement )
68     GETFUNCPTR( GetColorProfileElementTag )
69     GETFUNCPTR( GetColorProfileFromHandle )
70     GETFUNCPTR( GetColorProfileHeader )
71     GETFUNCPTR( GetCountColorProfileElements )
72     GETFUNCPTR( GetStandardColorSpaceProfileA )
73     GETFUNCPTR( GetStandardColorSpaceProfileW )
74     GETFUNCPTR( EnumColorProfilesA )
75     GETFUNCPTR( EnumColorProfilesW )
76     GETFUNCPTR( InstallColorProfileA )
77     GETFUNCPTR( InstallColorProfileW )
78     GETFUNCPTR( IsColorProfileTagPresent )
79     GETFUNCPTR( OpenColorProfileA )
80     GETFUNCPTR( OpenColorProfileW )
81     GETFUNCPTR( SetColorProfileElement )
82     GETFUNCPTR( SetColorProfileHeader )
83     GETFUNCPTR( SetStandardColorSpaceProfileA )
84     GETFUNCPTR( SetStandardColorSpaceProfileW )
85     GETFUNCPTR( UninstallColorProfileA )
86     GETFUNCPTR( UninstallColorProfileW )
87
88     return TRUE;
89 }
90
91 static const char machine[] = "dummy";
92 static const WCHAR machineW[] = { 'd','u','m','m','y',0 };
93
94 /*  To do any real functionality testing with this suite you need a copy of
95  *  the freely distributable standard RGB color space profile. It comes
96  *  standard with Windows, but on Wine you probably need to install it yourself
97  *  in one of the locations mentioned below. Here's a link to the profile in
98  *  a self extracting zip file:
99  *
100  *  http://download.microsoft.com/download/whistler/hwdev1/1.0/wxp/en-us/ColorProfile.exe
101  */
102
103 /* Two common places to find the standard color space profile, relative
104  * to the system directory.
105  */
106 static const char profile1[] =
107 "\\color\\srgb color space profile.icm";
108 static const char profile2[] =
109 "\\spool\\drivers\\color\\srgb color space profile.icm";
110
111 static const WCHAR profile1W[] =
112 { '\\','c','o','l','o','r','\\','s','r','g','b',' ','c','o','l','o','r',' ',
113   's','p','a','c','e',' ','p','r','o','f','i','l','e','.','i','c','m',0 };
114 static const WCHAR profile2W[] =
115 { '\\','s','p','o','o','l','\\','d','r','i','v','e','r','s','\\',
116   'c','o','l','o','r','\\','s','r','g','b',' ','c','o','l','o','r',' ',
117   's','p','a','c','e',' ','p','r','o','f','i','l','e','.','i','c','m',0 };
118
119 static const unsigned char rgbheader[] =
120 { 0x48, 0x0c, 0x00, 0x00, 0x6f, 0x6e, 0x69, 0x4c, 0x00, 0x00, 0x10, 0x02,
121   0x72, 0x74, 0x6e, 0x6d, 0x20, 0x42, 0x47, 0x52, 0x20, 0x5a, 0x59, 0x58,
122   0x02, 0x00, 0xce, 0x07, 0x06, 0x00, 0x09, 0x00, 0x00, 0x00, 0x31, 0x00,
123   0x70, 0x73, 0x63, 0x61, 0x54, 0x46, 0x53, 0x4d, 0x00, 0x00, 0x00, 0x00,
124   0x20, 0x43, 0x45, 0x49, 0x42, 0x47, 0x52, 0x73, 0x00, 0x00, 0x00, 0x00,
125   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0xf6, 0x00, 0x00,
126   0x00, 0x00, 0x01, 0x00, 0x2d, 0xd3, 0x00, 0x00, 0x20, 0x20, 0x50, 0x48 };
127
128 static LPSTR standardprofile;
129 static LPWSTR standardprofileW;
130
131 static LPSTR testprofile;
132 static LPWSTR testprofileW;
133
134 #define IS_SEPARATOR(ch)  ((ch) == '\\' || (ch) == '/')
135
136 static void MSCMS_basenameA( LPCSTR path, LPSTR name )
137 {
138     INT i = strlen( path );
139
140     while (i > 0 && !IS_SEPARATOR(path[i - 1])) i--;
141     strcpy( name, &path[i] );
142 }
143
144 static void MSCMS_basenameW( LPCWSTR path, LPWSTR name )
145 {
146     INT i = lstrlenW( path );
147
148     while (i > 0 && !IS_SEPARATOR(path[i - 1])) i--;
149     lstrcpyW( name, &path[i] );
150 }
151
152 static void test_GetColorDirectoryA(void)
153 {
154     BOOL ret;
155     DWORD size;
156     char buffer[MAX_PATH];
157
158     /* Parameter checks */
159
160     ret = pGetColorDirectoryA( NULL, NULL, NULL );
161     ok( !ret, "GetColorDirectoryA() succeeded (%d)\n", GetLastError() );
162
163     size = 0;
164
165     ret = pGetColorDirectoryA( NULL, NULL, &size );
166     ok( !ret && size > 0, "GetColorDirectoryA() succeeded (%d)\n", GetLastError() );
167
168     size = 0;
169
170     ret = pGetColorDirectoryA( NULL, buffer, &size );
171     ok( !ret && size > 0, "GetColorDirectoryA() succeeded (%d)\n", GetLastError() );
172
173     size = 1;
174
175     ret = pGetColorDirectoryA( NULL, buffer, &size );
176     ok( !ret && size > 0, "GetColorDirectoryA() succeeded (%d)\n", GetLastError() );
177
178     /* Functional checks */
179
180     size = sizeof(buffer);
181
182     ret = pGetColorDirectoryA( NULL, buffer, &size );
183     ok( ret && size > 0, "GetColorDirectoryA() failed (%d)\n", GetLastError() );
184 }
185
186 static void test_GetColorDirectoryW(void)
187 {
188     BOOL ret;
189     DWORD size;
190     WCHAR buffer[MAX_PATH];
191
192     /* Parameter checks */
193
194     /* This one crashes win2k
195     
196     ret = pGetColorDirectoryW( NULL, NULL, NULL );
197     ok( !ret, "GetColorDirectoryW() succeeded (%d)\n", GetLastError() );
198
199      */
200
201     size = 0;
202
203     ret = pGetColorDirectoryW( NULL, NULL, &size );
204     ok( !ret && size > 0, "GetColorDirectoryW() succeeded (%d)\n", GetLastError() );
205
206     size = 0;
207
208     ret = pGetColorDirectoryW( NULL, buffer, &size );
209     ok( !ret && size > 0, "GetColorDirectoryW() succeeded (%d)\n", GetLastError() );
210
211     size = 1;
212
213     ret = pGetColorDirectoryW( NULL, buffer, &size );
214     ok( !ret && size > 0, "GetColorDirectoryW() succeeded (%d)\n", GetLastError() );
215
216     /* Functional checks */
217
218     size = sizeof(buffer);
219
220     ret = pGetColorDirectoryW( NULL, buffer, &size );
221     ok( ret && size > 0, "GetColorDirectoryW() failed (%d)\n", GetLastError() );
222 }
223
224 static void test_GetColorProfileElement(void)
225 {
226     if (standardprofile)
227     {
228         PROFILE profile;
229         HPROFILE handle;
230         BOOL ret, ref;
231         DWORD size;
232         TAGTYPE tag = 0x63707274;  /* 'cprt' */
233         static char buffer[51];
234         static const char expect[] =
235             { 0x74, 0x65, 0x78, 0x74, 0x00, 0x00, 0x00, 0x00, 0x43, 0x6f, 0x70,
236               0x79, 0x72, 0x69, 0x67, 0x68, 0x74, 0x20, 0x28, 0x63, 0x29, 0x20,
237               0x31, 0x39, 0x39, 0x38, 0x20, 0x48, 0x65, 0x77, 0x6c, 0x65, 0x74,
238               0x74, 0x2d, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x72, 0x64, 0x20, 0x43,
239               0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x00 };
240
241         profile.dwType = PROFILE_FILENAME;
242         profile.pProfileData = standardprofile;
243         profile.cbDataSize = strlen(standardprofile);
244
245         handle = pOpenColorProfileA( &profile, PROFILE_READ, 0, OPEN_EXISTING );
246         ok( handle != NULL, "OpenColorProfileA() failed (%d)\n", GetLastError() );
247
248         /* Parameter checks */
249
250         ret = pGetColorProfileElement( handle, tag, 0, NULL, NULL, &ref );
251         ok( !ret, "GetColorProfileElement() succeeded (%d)\n", GetLastError() );
252
253         ret = pGetColorProfileElement( handle, tag, 0, &size, NULL, NULL );
254         ok( !ret, "GetColorProfileElement() succeeded (%d)\n", GetLastError() );
255
256         size = 0;
257
258         ret = pGetColorProfileElement( handle, tag, 0, &size, NULL, &ref );
259         ok( !ret && size > 0, "GetColorProfileElement() succeeded (%d)\n", GetLastError() );
260
261         size = sizeof(buffer);
262
263         /* Functional checks */
264
265         ret = pGetColorProfileElement( handle, tag, 0, &size, buffer, &ref );
266         ok( ret && size > 0, "GetColorProfileElement() failed (%d)\n", GetLastError() );
267
268         ok( !memcmp( buffer, expect, sizeof(expect) ), "Unexpected tag data\n" );
269
270         pCloseColorProfile( handle );
271     }
272 }
273
274 static void test_GetColorProfileElementTag(void)
275 {
276     if (standardprofile)
277     {
278         PROFILE profile;
279         HPROFILE handle;
280         BOOL ret;
281         DWORD index = 1;
282         TAGTYPE tag, expect = 0x63707274;  /* 'cprt' */
283
284         profile.dwType = PROFILE_FILENAME;
285         profile.pProfileData = standardprofile;
286         profile.cbDataSize = strlen(standardprofile);
287
288         handle = pOpenColorProfileA( &profile, PROFILE_READ, 0, OPEN_EXISTING );
289         ok( handle != NULL, "OpenColorProfileA() failed (%d)\n", GetLastError() );
290
291         /* Parameter checks */
292
293         ret = pGetColorProfileElementTag( NULL, index, &tag );
294         ok( !ret, "GetColorProfileElementTag() succeeded (%d)\n", GetLastError() );
295
296         ret = pGetColorProfileElementTag( handle, 0, &tag );
297         ok( !ret, "GetColorProfileElementTag() succeeded (%d)\n", GetLastError() );
298
299         ret = pGetColorProfileElementTag( handle, index, NULL );
300         ok( !ret, "GetColorProfileElementTag() succeeded (%d)\n", GetLastError() );
301
302         ret = pGetColorProfileElementTag( handle, 18, NULL );
303         ok( !ret, "GetColorProfileElementTag() succeeded (%d)\n", GetLastError() );
304
305         /* Functional checks */
306
307         ret = pGetColorProfileElementTag( handle, index, &tag );
308         ok( ret && tag == expect, "GetColorProfileElementTag() failed (%d)\n",
309             GetLastError() );
310
311         pCloseColorProfile( handle );
312     }
313 }
314
315 static void test_GetColorProfileFromHandle(void)
316 {
317     if (testprofile)
318     {
319         PROFILE profile;
320         HPROFILE handle;
321         DWORD size;
322         BOOL ret;
323         static const unsigned char expect[] =
324             { 0x00, 0x00, 0x0c, 0x48, 0x4c, 0x69, 0x6e, 0x6f, 0x02, 0x10, 0x00,
325               0x00, 0x6d, 0x6e, 0x74, 0x72, 0x52, 0x47, 0x42, 0x20, 0x58, 0x59,
326               0x5a, 0x20, 0x07, 0xce, 0x00, 0x02, 0x00, 0x09, 0x00, 0x06, 0x00,
327               0x31, 0x00, 0x00, 0x61, 0x63, 0x73, 0x70, 0x4d, 0x53, 0x46, 0x54,
328               0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x43, 0x20, 0x73, 0x52, 0x47,
329               0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
330               0x00, 0x00, 0x00, 0x00, 0xf6, 0xd6, 0x00, 0x01, 0x00, 0x00, 0x00,
331               0x00, 0xd3, 0x2d, 0x48, 0x50, 0x20, 0x20 };
332
333         unsigned char *buffer;
334
335         profile.dwType = PROFILE_FILENAME;
336         profile.pProfileData = testprofile;
337         profile.cbDataSize = strlen(testprofile);
338
339         handle = pOpenColorProfileA( &profile, PROFILE_READ, 0, OPEN_EXISTING );
340         ok( handle != NULL, "OpenColorProfileA() failed (%d)\n", GetLastError() );
341
342         /* Parameter checks */
343
344         size = 0;
345
346         ret = pGetColorProfileFromHandle( handle, NULL, &size );
347         ok( !ret && size > 0, "GetColorProfileFromHandle() failed (%d)\n", GetLastError() );
348
349         buffer = HeapAlloc( GetProcessHeap(), 0, size );
350
351         if (buffer)
352         {
353             ret = pGetColorProfileFromHandle( NULL, buffer, &size );
354             ok( !ret, "GetColorProfileFromHandle() succeeded (%d)\n", GetLastError() );
355
356             ret = pGetColorProfileFromHandle( handle, buffer, NULL );
357             ok( !ret, "GetColorProfileFromHandle() succeeded (%d)\n", GetLastError() );
358
359             /* Functional checks */
360
361             ret = pGetColorProfileFromHandle( handle, buffer, &size );
362             ok( ret && size > 0, "GetColorProfileFromHandle() failed (%d)\n", GetLastError() );
363
364             ok( !memcmp( buffer, expect, sizeof(expect) ), "Unexpected header data\n" );
365
366             HeapFree( GetProcessHeap(), 0, buffer );
367         }
368
369         pCloseColorProfile( handle );
370     }
371 }
372
373 static void test_GetColorProfileHeader(void)
374 {
375     if (testprofile)
376     {
377         PROFILE profile;
378         HPROFILE handle;
379         BOOL ret;
380         PROFILEHEADER header;
381
382         profile.dwType = PROFILE_FILENAME;
383         profile.pProfileData = testprofile;
384         profile.cbDataSize = strlen(testprofile);
385
386         handle = pOpenColorProfileA( &profile, PROFILE_READ, 0, OPEN_EXISTING );
387         ok( handle != NULL, "OpenColorProfileA() failed (%d)\n", GetLastError() );
388
389         /* Parameter checks */
390
391         ret = pGetColorProfileHeader( NULL, NULL );
392         ok( !ret, "GetColorProfileHeader() succeeded (%d)\n", GetLastError() );
393
394         ret = pGetColorProfileHeader( NULL, &header );
395         ok( !ret, "GetColorProfileHeader() succeeded (%d)\n", GetLastError() );
396
397         ret = pGetColorProfileHeader( handle, NULL );
398         ok( !ret, "GetColorProfileHeader() succeeded (%d)\n", GetLastError() );
399
400         /* Functional checks */
401
402         ret = pGetColorProfileHeader( handle, &header );
403         ok( ret, "GetColorProfileHeader() failed (%d)\n", GetLastError() );
404
405         ok( !memcmp( &header, rgbheader, sizeof(rgbheader) ), "Unexpected header data\n" );
406
407         pCloseColorProfile( handle );
408     }
409 }
410
411 static void test_GetCountColorProfileElements(void)
412 {
413     if (standardprofile)
414     {
415         PROFILE profile;
416         HPROFILE handle;
417         BOOL ret;
418         DWORD count, expect = 17;
419
420         profile.dwType = PROFILE_FILENAME;
421         profile.pProfileData = standardprofile;
422         profile.cbDataSize = strlen(standardprofile);
423
424         handle = pOpenColorProfileA( &profile, PROFILE_READ, 0, OPEN_EXISTING );
425         ok( handle != NULL, "OpenColorProfileA() failed (%d)\n", GetLastError() );
426
427         /* Parameter checks */
428
429         ret = pGetCountColorProfileElements( NULL, &count );
430         ok( !ret, "GetCountColorProfileElements() succeeded (%d)\n",
431             GetLastError() );
432
433         ret = pGetCountColorProfileElements( handle, NULL );
434         ok( !ret, "GetCountColorProfileElements() succeeded (%d)\n",
435             GetLastError() );
436
437         /* Functional checks */
438
439         ret = pGetCountColorProfileElements( handle, &count );
440         ok( ret && count == expect,
441             "GetCountColorProfileElements() failed (%d)\n", GetLastError() );
442
443         pCloseColorProfile( handle );
444     }
445 }
446
447 typedef struct colorspace_description_struct {
448     DWORD dwID;
449     const char *szName;
450     BOOL registered;
451     char filename[MAX_PATH];
452 } colorspace_descr;
453
454 #define describe_colorspace(id) {id, #id, FALSE, ""}
455
456 colorspace_descr known_colorspaces[] = { 
457     describe_colorspace(SPACE_XYZ),
458     describe_colorspace(SPACE_Lab),
459     describe_colorspace(SPACE_Luv),
460     describe_colorspace(SPACE_YCbCr),
461     describe_colorspace(SPACE_Yxy),
462     describe_colorspace(SPACE_RGB),
463     describe_colorspace(SPACE_GRAY),
464     describe_colorspace(SPACE_HSV),
465     describe_colorspace(SPACE_HLS),
466     describe_colorspace(SPACE_CMYK),
467     describe_colorspace(SPACE_CMY),
468     describe_colorspace(SPACE_2_CHANNEL),
469     describe_colorspace(SPACE_3_CHANNEL),
470     describe_colorspace(SPACE_4_CHANNEL),
471     describe_colorspace(SPACE_5_CHANNEL),
472     describe_colorspace(SPACE_6_CHANNEL),
473     describe_colorspace(SPACE_7_CHANNEL),
474     describe_colorspace(SPACE_8_CHANNEL)
475 };
476
477 static void enum_registered_color_profiles(void)
478 {
479     BOOL ret;
480     DWORD size, count, i, present;
481     CHAR profile[MAX_PATH];
482
483     size = sizeof(profile);
484     count = sizeof(known_colorspaces)/sizeof(known_colorspaces[0]);
485
486     present = 0;
487     trace("\n");
488     trace("Querying registered standard colorspace profiles via GetStandardColorSpaceProfileA():\n");
489     for (i=0; i<count; i++)
490     {
491         ret = pGetStandardColorSpaceProfileA(NULL, known_colorspaces[i].dwID, profile, &size);
492         if (ret) 
493         {
494             lstrcpynA(known_colorspaces[i].filename, profile, MAX_PATH);
495             known_colorspaces[i].registered = TRUE;
496             present++;
497             trace(" found %s, pointing to '%s' (%d chars)\n", known_colorspaces[i].szName, profile, lstrlenA(profile));
498         }
499     }
500     trace("Total profiles found: %d.\n", present);
501     trace("\n");
502 }
503
504 static colorspace_descr *query_colorspace(DWORD dwID)
505 {
506     DWORD count, i;
507
508     count = sizeof(known_colorspaces)/sizeof(known_colorspaces[0]);
509
510     for (i=0; i<count; i++)
511         if (known_colorspaces[i].dwID == dwID)
512         {
513             if (!known_colorspaces[i].registered) break;
514             return &known_colorspaces[i];
515         }
516     return NULL;
517 }
518
519 static HKEY reg_open_mscms_key(void)
520 {
521     char win9x[] = "SOFTWARE\\Microsoft\\Windows";
522     char winNT[] = "SOFTWARE\\Microsoft\\Windows NT";
523     char ICM[] = "CurrentVersion\\ICM\\RegisteredProfiles";
524     HKEY win9x_key, winNT_key, ICM_key;
525
526     RegOpenKeyExA( HKEY_LOCAL_MACHINE, win9x, 0, KEY_READ, &win9x_key );
527     RegOpenKeyExA( HKEY_LOCAL_MACHINE, winNT, 0, KEY_READ, &winNT_key );
528
529     if (RegOpenKeyExA( winNT_key, ICM, 0, KEY_READ, &ICM_key )) 
530         RegOpenKeyExA( win9x_key, ICM, 0, KEY_READ, &ICM_key );
531     RegCloseKey( win9x_key );
532     RegCloseKey( winNT_key );
533
534     return ICM_key;
535 }
536
537 static void check_registry(void)
538 {
539     HKEY hkIcmKey;
540     LONG res;
541     DWORD i, dwValCount;
542     char szName[16383];
543     char szData[MAX_PATH+1];
544     DWORD dwNameLen, dwDataLen, dwType;
545
546     hkIcmKey = reg_open_mscms_key();
547     if (!hkIcmKey)
548     {
549         trace("Key 'HKLM\\SOFTWARE\\Microsoft\\Windows*\\CurrentVersion\\ICM\\RegisteredProfiles' not found\n" );
550         return;
551     }
552
553     res = RegQueryInfoKeyA(hkIcmKey, NULL, NULL, NULL, NULL, NULL, NULL, &dwValCount, NULL, NULL, NULL, NULL);
554     if (!res) 
555     {
556         trace("RegQueryInfoKeyA() failed\n");
557         return;
558     }
559
560     trace("Count of profile entries found directly in the registry: %d\n", dwValCount);
561
562     for (i = 0; i<dwValCount; i++) 
563     {
564         dwNameLen = sizeof(szName);
565         dwDataLen = sizeof(szData);
566         res = RegEnumValueA( hkIcmKey, i, szName, &dwNameLen, NULL, &dwType, (LPBYTE)szData, &dwDataLen );
567         if (res != ERROR_SUCCESS) 
568         {
569             trace("RegEnumValueA() failed (%d), cannot enumerate profiles\n", res);
570             break;
571         }
572         ok( dwType == REG_SZ, "RegEnumValueA() returned unexpected value type (%d)\n", dwType );
573         if (dwType != REG_SZ) break;
574         trace(" found '%s' value containing '%s' (%d chars)\n", szName, szData, lstrlenA(szData));
575     } 
576
577     RegCloseKey( hkIcmKey );
578 }
579
580 static void test_GetStandardColorSpaceProfileA(void)
581 {
582     BOOL ret;
583     DWORD size;
584     CHAR oldprofile[MAX_PATH];
585     CHAR newprofile[MAX_PATH];
586     const CHAR emptyA[] = "";
587     DWORD zero = 0;
588     DWORD sizeP = sizeof(newprofile);
589
590     /* Parameter checks */
591
592     /* Single invalid parameter checks: */
593
594     SetLastError(0xfaceabee); /* 1st param, */
595     ret = pGetStandardColorSpaceProfileA(machine, SPACE_RGB, newprofile, &sizeP);
596     ok( !ret && GetLastError() == ERROR_NOT_SUPPORTED, "GetStandardColorSpaceProfileA() returns %d (GLE=%d)\n", ret, GetLastError() );
597
598     SetLastError(0xfaceabee); /* 2nd param, */
599     ret = pGetStandardColorSpaceProfileA(NULL, (DWORD)-1, newprofile, &sizeP);
600     ok( !ret && GetLastError() == ERROR_FILE_NOT_FOUND, "GetStandardColorSpaceProfileA() returns %d (GLE=%d)\n", ret, GetLastError() );
601
602     SetLastError(0xfaceabee); /* 4th param, */
603     ret = pGetStandardColorSpaceProfileA(NULL, SPACE_RGB, newprofile, NULL);
604     ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER, "GetStandardColorSpaceProfileA() returns %d (GLE=%d)\n", ret, GetLastError() );
605
606     if (query_colorspace(SPACE_RGB)) 
607     {
608         SetLastError(0xfaceabee); /* 3rd param, */
609         ret = pGetStandardColorSpaceProfileA(NULL, SPACE_RGB, NULL, &sizeP);
610         ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetStandardColorSpaceProfileA() returns %d (GLE=%d)\n", ret, GetLastError() );
611
612         SetLastError(0xfaceabee); /* dereferenced 4th param, */
613         ret = pGetStandardColorSpaceProfileA(NULL, SPACE_RGB, newprofile, &zero);
614         ok( !ret && (GetLastError() == ERROR_MORE_DATA || GetLastError() == ERROR_INSUFFICIENT_BUFFER), "GetStandardColorSpaceProfileA() returns %d (GLE=%d)\n", ret, GetLastError() );
615     } else {
616         SetLastError(0xfaceabee); /* 3rd param, */
617         ret = pGetStandardColorSpaceProfileA(NULL, SPACE_RGB, NULL, &sizeP);
618         ok( !ret && GetLastError() == ERROR_FILE_NOT_FOUND, "GetStandardColorSpaceProfileA() returns %d (GLE=%d)\n", ret, GetLastError() );
619
620         SetLastError(0xfaceabee); /* dereferenced 4th param. */
621         ret = pGetStandardColorSpaceProfileA(NULL, SPACE_RGB, newprofile, &sizeP);
622         ok( !ret && GetLastError() == ERROR_FILE_NOT_FOUND, "GetStandardColorSpaceProfileA() returns %d (GLE=%d)\n", ret, GetLastError() );
623     }
624
625     /* Several invalid parameter checks: */
626
627     SetLastError(0xfaceabee); /* 1st, maybe 2nd and then dereferenced 4th param, */
628     ret = pGetStandardColorSpaceProfileA(machine, 0, newprofile, &zero);
629     ok( !ret && (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_NOT_SUPPORTED), "GetStandardColorSpaceProfileA() returns %d (GLE=%d)\n", ret, GetLastError() );
630
631     SetLastError(0xfaceabee); /* maybe 2nd and then 4th param, */
632     ret = pGetStandardColorSpaceProfileA(NULL, 0, newprofile, NULL);
633     ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER, "GetStandardColorSpaceProfileA() returns %d (GLE=%d)\n", ret, GetLastError() );
634
635     SetLastError(0xfaceabee); /* maybe 2nd, then 3rd and dereferenced 4th param, */
636     ret = pGetStandardColorSpaceProfileA(NULL, 0, NULL, &zero);
637     ok( !ret && (GetLastError() == ERROR_INSUFFICIENT_BUFFER || GetLastError() == ERROR_FILE_NOT_FOUND), "GetStandardColorSpaceProfileA() returns %d (GLE=%d)\n", ret, GetLastError() );
638
639     SetLastError(0xfaceabee); /* maybe 2nd param. */
640     ret = pGetStandardColorSpaceProfileA(NULL, 0, newprofile, &sizeP);
641     if (!ret) ok( GetLastError() == ERROR_FILE_NOT_FOUND, "GetStandardColorSpaceProfileA() returns %d (GLE=%d)\n", ret, GetLastError() );
642     else ok( !lstrcmpiA( newprofile, emptyA ) && GetLastError() == 0xfaceabee, "GetStandardColorSpaceProfileA() returns %d (GLE=%d)\n", ret, GetLastError() );
643
644     /* Functional checks */
645
646     if (standardprofile)
647     {
648         size = sizeof(oldprofile);
649
650         ret = pGetStandardColorSpaceProfileA( NULL, SPACE_RGB, oldprofile, &size );
651         ok( ret, "GetStandardColorSpaceProfileA() failed (%d)\n", GetLastError() );
652
653         ret = pSetStandardColorSpaceProfileA( NULL, SPACE_RGB, standardprofile );
654         ok( ret, "SetStandardColorSpaceProfileA() failed (%d)\n", GetLastError() );
655
656         size = sizeof(newprofile);
657
658         ret = pGetStandardColorSpaceProfileA( NULL, SPACE_RGB, newprofile, &size );
659         ok( ret, "GetStandardColorSpaceProfileA() failed (%d)\n", GetLastError() );
660
661         ok( !lstrcmpiA( (LPSTR)&newprofile, standardprofile ), "Unexpected profile\n" );
662
663         ret = pSetStandardColorSpaceProfileA( NULL, SPACE_RGB, oldprofile );
664         ok( ret, "SetStandardColorSpaceProfileA() failed (%d)\n", GetLastError() );
665     }
666 }
667
668 static void test_GetStandardColorSpaceProfileW(void)
669 {
670     BOOL ret;
671     DWORD size;
672     WCHAR oldprofile[MAX_PATH];
673     WCHAR newprofile[MAX_PATH];
674     const WCHAR emptyW[] = {0};
675     DWORD zero = 0;
676     DWORD sizeP = sizeof(newprofile);
677
678     /* Parameter checks */
679
680     /* Single invalid parameter checks: */
681
682     SetLastError(0xfaceabee); /* 1st param, */
683     ret = pGetStandardColorSpaceProfileW(machineW, SPACE_RGB, newprofile, &sizeP);
684     ok( !ret && GetLastError() == ERROR_NOT_SUPPORTED, "GetStandardColorSpaceProfileW() returns %d (GLE=%d)\n", ret, GetLastError() );
685
686     SetLastError(0xfaceabee); /* 2nd param, */
687     ret = pGetStandardColorSpaceProfileW(NULL, (DWORD)-1, newprofile, &sizeP);
688     ok( !ret && GetLastError() == ERROR_FILE_NOT_FOUND, "GetStandardColorSpaceProfileW() returns %d (GLE=%d)\n", ret, GetLastError() );
689
690     SetLastError(0xfaceabee); /* 3th param, */
691     ret = pGetStandardColorSpaceProfileW(NULL, SPACE_RGB, NULL, &sizeP);
692     ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetStandardColorSpaceProfileW() returns %d (GLE=%d)\n", ret, GetLastError() );
693
694     SetLastError(0xfaceabee); /* 4th param, */
695     ret = pGetStandardColorSpaceProfileW(NULL, SPACE_RGB, newprofile, NULL);
696     ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER, "GetStandardColorSpaceProfileW() returns %d (GLE=%d)\n", ret, GetLastError() );
697
698     SetLastError(0xfaceabee); /* dereferenced 4th param. */
699     ret = pGetStandardColorSpaceProfileW(NULL, SPACE_RGB, newprofile, &zero);
700     ok( !ret && (GetLastError() == ERROR_MORE_DATA || GetLastError() == ERROR_INSUFFICIENT_BUFFER), "GetStandardColorSpaceProfileW() returns %d (GLE=%d)\n", ret, GetLastError() );
701
702     /* Several invalid parameter checks: */
703
704     SetLastError(0xfaceabee); /* 1st, maybe 2nd and then dereferenced 4th param, */
705     ret = pGetStandardColorSpaceProfileW(machineW, 0, newprofile, &zero);
706     ok( !ret && (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_NOT_SUPPORTED), "GetStandardColorSpaceProfileW() returns %d (GLE=%d)\n", ret, GetLastError() );
707
708     SetLastError(0xfaceabee); /* maybe 2nd and then 4th param, */
709     ret = pGetStandardColorSpaceProfileW(NULL, 0, newprofile, NULL);
710     ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER, "GetStandardColorSpaceProfileW() returns %d (GLE=%d)\n", ret, GetLastError() );
711
712     SetLastError(0xfaceabee); /* maybe 2nd, then 3rd and dereferenced 4th param, */
713     ret = pGetStandardColorSpaceProfileW(NULL, 0, NULL, &zero);
714     ok( !ret && (GetLastError() == ERROR_INSUFFICIENT_BUFFER || GetLastError() == ERROR_FILE_NOT_FOUND), "GetStandardColorSpaceProfileW() returns %d (GLE=%d)\n", ret, GetLastError() );
715
716     SetLastError(0xfaceabee); /* maybe 2nd param. */
717     ret = pGetStandardColorSpaceProfileW(NULL, 0, newprofile, &sizeP);
718     if (!ret) ok( GetLastError() == ERROR_FILE_NOT_FOUND, "GetStandardColorSpaceProfileW() returns %d (GLE=%d)\n", ret, GetLastError() );
719     else ok( !lstrcmpiW( newprofile, emptyW ) && GetLastError() == 0xfaceabee, "GetStandardColorSpaceProfileW() returns %d (GLE=%d)\n", ret, GetLastError() );
720
721     /* Functional checks */
722
723     if (standardprofileW)
724     {
725         size = sizeof(oldprofile);
726
727         ret = pGetStandardColorSpaceProfileW( NULL, SPACE_RGB, oldprofile, &size );
728         ok( ret, "GetStandardColorSpaceProfileW() failed (%d)\n", GetLastError() );
729
730         ret = pSetStandardColorSpaceProfileW( NULL, SPACE_RGB, standardprofileW );
731         ok( ret, "SetStandardColorSpaceProfileW() failed (%d)\n", GetLastError() );
732
733         size = sizeof(newprofile);
734
735         ret = pGetStandardColorSpaceProfileW( NULL, SPACE_RGB, newprofile, &size );
736         ok( ret, "GetStandardColorSpaceProfileW() failed (%d)\n", GetLastError() );
737
738         ok( !lstrcmpiW( (LPWSTR)&newprofile, standardprofileW ), "Unexpected profile\n" );
739
740         ret = pSetStandardColorSpaceProfileW( NULL, SPACE_RGB, oldprofile );
741         ok( ret, "SetStandardColorSpaceProfileW() failed (%d)\n", GetLastError() );
742     }
743 }
744
745 static void test_EnumColorProfilesA(void)
746 {
747     BOOL ret;
748     DWORD size, number;
749     ENUMTYPEA record;
750     BYTE buffer[MAX_PATH];
751
752     /* Parameter checks */
753
754     size = sizeof(buffer);
755     memset( &record, 0, sizeof(ENUMTYPEA) );
756
757     record.dwSize = sizeof(ENUMTYPEA);
758     record.dwVersion = ENUM_TYPE_VERSION;
759     record.dwFields |= ET_DATACOLORSPACE;
760     record.dwDataColorSpace = SPACE_RGB;
761
762     ret = pEnumColorProfilesA( machine, &record, buffer, &size, &number );
763     ok( !ret, "EnumColorProfilesA() succeeded (%d)\n", GetLastError() );
764
765     ret = pEnumColorProfilesA( NULL, NULL, buffer, &size, &number );
766     ok( !ret, "EnumColorProfilesA() succeeded (%d)\n", GetLastError() );
767
768     ret = pEnumColorProfilesA( NULL, &record, buffer, NULL, &number );
769     ok( !ret, "EnumColorProfilesA() succeeded (%d)\n", GetLastError() );
770
771     if (standardprofile)
772     {
773         ret = pEnumColorProfilesA( NULL, &record, buffer, &size, &number );
774         ok( ret, "EnumColorProfilesA() failed (%d)\n", GetLastError() );
775     }
776
777     size = 0;
778
779     ret = pEnumColorProfilesA( NULL, &record, buffer, &size, &number );
780     ok( !ret, "EnumColorProfilesA() succeeded (%d)\n", GetLastError() );
781
782     /* Functional checks */
783
784     if (standardprofile)
785     {
786         size = sizeof(buffer);
787
788         ret = pEnumColorProfilesA( NULL, &record, buffer, &size, &number );
789         ok( ret, "EnumColorProfilesA() failed (%d)\n", GetLastError() );
790     }
791 }
792
793 static void test_EnumColorProfilesW(void)
794 {
795     BOOL ret;
796     DWORD size, number;
797     ENUMTYPEW record;
798     BYTE buffer[MAX_PATH * sizeof(WCHAR)];
799
800     /* Parameter checks */
801
802     size = sizeof(buffer);
803     memset( &record, 0, sizeof(ENUMTYPEW) );
804
805     record.dwSize = sizeof(ENUMTYPEW);
806     record.dwVersion = ENUM_TYPE_VERSION;
807     record.dwFields |= ET_DATACOLORSPACE;
808     record.dwDataColorSpace = SPACE_RGB;
809
810     ret = pEnumColorProfilesW( machineW, &record, buffer, &size, &number );
811     ok( !ret, "EnumColorProfilesW() succeeded (%d)\n", GetLastError() );
812
813     ret = pEnumColorProfilesW( NULL, NULL, buffer, &size, &number );
814     ok( !ret, "EnumColorProfilesW() succeeded (%d)\n", GetLastError() );
815
816     ret = pEnumColorProfilesW( NULL, &record, buffer, NULL, &number );
817     ok( !ret, "EnumColorProfilesW() succeeded (%d)\n", GetLastError() );
818
819     if (standardprofileW)
820     {
821         ret = pEnumColorProfilesW( NULL, &record, buffer, &size, NULL );
822         ok( ret, "EnumColorProfilesW() failed (%d)\n", GetLastError() );
823     }
824
825     size = 0;
826
827     ret = pEnumColorProfilesW( NULL, &record, buffer, &size, &number );
828     ok( !ret, "EnumColorProfilesW() succeeded (%d)\n", GetLastError() );
829
830     /* Functional checks */
831
832     if (standardprofileW)
833     {
834         size = sizeof(buffer);
835
836         ret = pEnumColorProfilesW( NULL, &record, buffer, &size, &number );
837         ok( ret, "EnumColorProfilesW() failed (%d)\n", GetLastError() );
838     }
839 }
840
841 static void test_InstallColorProfileA(void)
842 {
843     BOOL ret;
844
845     /* Parameter checks */
846
847     ret = pInstallColorProfileA( NULL, NULL );
848     ok( !ret, "InstallColorProfileA() succeeded (%d)\n", GetLastError() );
849
850     ret = pInstallColorProfileA( machine, NULL );
851     ok( !ret, "InstallColorProfileA() succeeded (%d)\n", GetLastError() );
852
853     ret = pInstallColorProfileA( NULL, machine );
854     ok( !ret, "InstallColorProfileA() succeeded (%d)\n", GetLastError() );
855
856     if (standardprofile)
857     {
858         ret = pInstallColorProfileA( NULL, standardprofile );
859         ok( ret, "InstallColorProfileA() failed (%d)\n", GetLastError() );
860     }
861
862     /* Functional checks */
863
864     if (testprofile)
865     {
866         CHAR dest[MAX_PATH], base[MAX_PATH];
867         DWORD size = sizeof(dest);
868         CHAR slash[] = "\\";
869         HANDLE handle;
870
871         ret = pInstallColorProfileA( NULL, testprofile );
872         ok( ret, "InstallColorProfileA() failed (%d)\n", GetLastError() );
873
874         ret = pGetColorDirectoryA( NULL, dest, &size );
875         ok( ret, "GetColorDirectoryA() failed (%d)\n", GetLastError() );
876
877         MSCMS_basenameA( testprofile, base );
878
879         lstrcatA( dest, slash );
880         lstrcatA( dest, base );
881
882         /* Check if the profile is really there */ 
883         handle = CreateFileA( dest, 0 , 0, NULL, OPEN_EXISTING, 0, NULL );
884         ok( handle != INVALID_HANDLE_VALUE, "Couldn't find the profile (%d)\n", GetLastError() );
885         CloseHandle( handle );
886         
887         ret = pUninstallColorProfileA( NULL, dest, TRUE );
888         ok( ret, "UninstallColorProfileA() failed (%d)\n", GetLastError() );
889     }
890 }
891
892 static void test_InstallColorProfileW(void)
893 {
894     BOOL ret;
895
896     /* Parameter checks */
897
898     ret = pInstallColorProfileW( NULL, NULL );
899     ok( !ret, "InstallColorProfileW() succeeded (%d)\n", GetLastError() );
900
901     ret = pInstallColorProfileW( machineW, NULL );
902     ok( !ret, "InstallColorProfileW() succeeded (%d)\n", GetLastError() );
903
904     ret = pInstallColorProfileW( NULL, machineW );
905     ok( !ret, "InstallColorProfileW() failed (%d)\n", GetLastError() );
906
907     if (standardprofileW)
908     {
909         ret = pInstallColorProfileW( NULL, standardprofileW );
910         ok( ret, "InstallColorProfileW() failed (%d)\n", GetLastError() );
911     }
912
913     /* Functional checks */
914
915     if (testprofileW)
916     {
917         WCHAR dest[MAX_PATH], base[MAX_PATH];
918         DWORD size = sizeof(dest);
919         WCHAR slash[] = { '\\', 0 };
920         HANDLE handle;
921
922         ret = pInstallColorProfileW( NULL, testprofileW );
923         ok( ret, "InstallColorProfileW() failed (%d)\n", GetLastError() );
924
925         ret = pGetColorDirectoryW( NULL, dest, &size );
926         ok( ret, "GetColorDirectoryW() failed (%d)\n", GetLastError() );
927
928         MSCMS_basenameW( testprofileW, base );
929
930         lstrcatW( dest, slash );
931         lstrcatW( dest, base );
932
933         /* Check if the profile is really there */
934         handle = CreateFileW( dest, 0 , 0, NULL, OPEN_EXISTING, 0, NULL );
935         ok( handle != INVALID_HANDLE_VALUE, "Couldn't find the profile (%d)\n", GetLastError() );
936         CloseHandle( handle );
937
938         ret = pUninstallColorProfileW( NULL, dest, TRUE );
939         ok( ret, "UninstallColorProfileW() failed (%d)\n", GetLastError() );
940     }
941 }
942
943 static void test_IsColorProfileTagPresent(void)
944 {
945     if (standardprofile)
946     {
947         PROFILE profile;
948         HPROFILE handle;
949         BOOL ret, present;
950         TAGTYPE tag;
951
952         profile.dwType = PROFILE_FILENAME;
953         profile.pProfileData = standardprofile;
954         profile.cbDataSize = strlen(standardprofile);
955
956         handle = pOpenColorProfileA( &profile, PROFILE_READ, 0, OPEN_EXISTING );
957         ok( handle != NULL, "OpenColorProfileA() failed (%d)\n", GetLastError() );
958
959         /* Parameter checks */
960
961         tag = 0;
962
963         ret = pIsColorProfileTagPresent( handle, tag, &present );
964         ok( !(ret && present), "IsColorProfileTagPresent() succeeded (%d)\n", GetLastError() );
965
966         tag = 0x63707274;  /* 'cprt' */
967
968         ret = pIsColorProfileTagPresent( NULL, tag, &present );
969         ok( !ret, "IsColorProfileTagPresent() succeeded (%d)\n", GetLastError() );
970
971         ret = pIsColorProfileTagPresent( handle, tag, NULL );
972         ok( !ret, "IsColorProfileTagPresent() succeeded (%d)\n", GetLastError() );
973
974         /* Functional checks */
975
976         ret = pIsColorProfileTagPresent( handle, tag, &present );
977         ok( ret && present, "IsColorProfileTagPresent() failed (%d)\n", GetLastError() );
978
979         pCloseColorProfile( handle );
980     }
981 }
982
983 static void test_OpenColorProfileA(void)
984 {
985     PROFILE profile;
986     HPROFILE handle;
987     BOOL ret;
988
989     profile.dwType = PROFILE_FILENAME;
990     profile.pProfileData = NULL;
991     profile.cbDataSize = 0;
992
993     /* Parameter checks */
994
995     handle = pOpenColorProfileA( NULL, 0, 0, 0 );
996     ok( handle == NULL, "OpenColorProfileA() failed (%d)\n", GetLastError() );
997
998     handle = pOpenColorProfileA( &profile, 0, 0, 0 );
999     ok( handle == NULL, "OpenColorProfileA() failed (%d)\n", GetLastError() );
1000
1001     handle = pOpenColorProfileA( &profile, PROFILE_READ, 0, 0 );
1002     ok( handle == NULL, "OpenColorProfileA() failed (%d)\n", GetLastError() );
1003
1004     handle = pOpenColorProfileA( &profile, PROFILE_READWRITE, 0, 0 );
1005     ok( handle == NULL, "OpenColorProfileA() failed (%d)\n", GetLastError() );
1006
1007     ok ( !pCloseColorProfile( NULL ), "CloseColorProfile() succeeded\n" );
1008
1009     if (standardprofile)
1010     {
1011         profile.pProfileData = standardprofile;
1012         profile.cbDataSize = strlen(standardprofile);
1013
1014         handle = pOpenColorProfileA( &profile, 0, 0, 0 );
1015         ok( handle == NULL, "OpenColorProfileA() failed (%d)\n", GetLastError() );
1016
1017         handle = pOpenColorProfileA( &profile, PROFILE_READ, 0, 0 );
1018         ok( handle == NULL, "OpenColorProfileA() failed (%d)\n", GetLastError() );
1019
1020         handle = pOpenColorProfileA( &profile, PROFILE_READ|PROFILE_READWRITE, 0, 0 );
1021         ok( handle == NULL, "OpenColorProfileA() failed (%d)\n", GetLastError() );
1022
1023         /* Functional checks */
1024
1025         handle = pOpenColorProfileA( &profile, PROFILE_READ, 0, OPEN_EXISTING );
1026         ok( handle != NULL, "OpenColorProfileA() failed (%d)\n", GetLastError() );
1027
1028         ret = pCloseColorProfile( handle );
1029         ok( ret, "CloseColorProfile() failed (%d)\n", GetLastError() );
1030     }
1031 }
1032
1033 static void test_OpenColorProfileW(void)
1034 {
1035     PROFILE profile;
1036     HPROFILE handle;
1037     BOOL ret;
1038
1039     profile.dwType = PROFILE_FILENAME;
1040     profile.pProfileData = NULL;
1041     profile.cbDataSize = 0;
1042
1043     /* Parameter checks */
1044
1045     handle = pOpenColorProfileW( NULL, 0, 0, 0 );
1046     ok( handle == NULL, "OpenColorProfileW() failed (%d)\n", GetLastError() );
1047
1048     handle = pOpenColorProfileW( &profile, 0, 0, 0 );
1049     ok( handle == NULL, "OpenColorProfileW() failed (%d)\n", GetLastError() );
1050
1051     handle = pOpenColorProfileW( &profile, PROFILE_READ, 0, 0 );
1052     ok( handle == NULL, "OpenColorProfileW() failed (%d)\n", GetLastError() );
1053
1054     handle = pOpenColorProfileW( &profile, PROFILE_READWRITE, 0, 0 );
1055     ok( handle == NULL, "OpenColorProfileW() failed (%d)\n", GetLastError() );
1056
1057     ok ( !pCloseColorProfile( NULL ), "CloseColorProfile() succeeded\n" );
1058
1059     if (standardprofileW)
1060     {
1061         profile.pProfileData = standardprofileW;
1062         profile.cbDataSize = lstrlenW(standardprofileW) * sizeof(WCHAR);
1063
1064         handle = pOpenColorProfileW( &profile, 0, 0, 0 );
1065         ok( handle == NULL, "OpenColorProfileW() failed (%d)\n", GetLastError() );
1066
1067         handle = pOpenColorProfileW( &profile, PROFILE_READ, 0, 0 );
1068         ok( handle == NULL, "OpenColorProfileW() failed (%d)\n", GetLastError() );
1069
1070         handle = pOpenColorProfileW( &profile, PROFILE_READ|PROFILE_READWRITE, 0, 0 );
1071         ok( handle == NULL, "OpenColorProfileW() failed (%d)\n", GetLastError() );
1072
1073         /* Functional checks */
1074
1075         handle = pOpenColorProfileW( &profile, PROFILE_READ, 0, OPEN_EXISTING );
1076         ok( handle != NULL, "OpenColorProfileW() failed (%d)\n", GetLastError() );
1077
1078         ret = pCloseColorProfile( handle );
1079         ok( ret, "CloseColorProfile() failed (%d)\n", GetLastError() );
1080     }
1081 }
1082
1083 static void test_SetColorProfileElement(void)
1084 {
1085     if (testprofile)
1086     {
1087         PROFILE profile;
1088         HPROFILE handle;
1089         DWORD size;
1090         BOOL ret, ref;
1091
1092         TAGTYPE tag = 0x63707274;  /* 'cprt' */
1093         static char data[] = "(c) The Wine Project";
1094         static char buffer[51];
1095
1096         profile.dwType = PROFILE_FILENAME;
1097         profile.pProfileData = testprofile;
1098         profile.cbDataSize = strlen(testprofile);
1099
1100         /* Parameter checks */
1101
1102         handle = pOpenColorProfileA( &profile, PROFILE_READ, 0, OPEN_EXISTING );
1103         ok( handle != NULL, "OpenColorProfileA() failed (%d)\n", GetLastError() );
1104
1105         ret = pSetColorProfileElement( handle, tag, 0, &size, data );
1106         ok( !ret, "SetColorProfileElement() succeeded (%d)\n", GetLastError() );
1107
1108         pCloseColorProfile( handle );
1109
1110         handle = pOpenColorProfileA( &profile, PROFILE_READWRITE, 0, OPEN_EXISTING );
1111         ok( handle != NULL, "OpenColorProfileA() failed (%d)\n", GetLastError() );
1112
1113         ret = pSetColorProfileElement( NULL, 0, 0, NULL, NULL );
1114         ok( !ret, "SetColorProfileElement() succeeded (%d)\n", GetLastError() );
1115
1116         ret = pSetColorProfileElement( handle, 0, 0, NULL, NULL );
1117         ok( !ret, "SetColorProfileElement() succeeded (%d)\n", GetLastError() );
1118
1119         ret = pSetColorProfileElement( handle, tag, 0, NULL, NULL );
1120         ok( !ret, "SetColorProfileElement() succeeded (%d)\n", GetLastError() );
1121
1122         ret = pSetColorProfileElement( handle, tag, 0, &size, NULL );
1123         ok( !ret, "SetColorProfileElement() succeeded (%d)\n", GetLastError() );
1124
1125         /* Functional checks */
1126
1127         size = sizeof(data);
1128
1129         ret = pSetColorProfileElement( handle, tag, 0, &size, data );
1130         ok( ret, "SetColorProfileElement() failed (%d)\n", GetLastError() );
1131
1132         size = sizeof(buffer);
1133
1134         ret = pGetColorProfileElement( handle, tag, 0, &size, buffer, &ref );
1135         ok( ret && size > 0, "GetColorProfileElement() failed (%d)\n", GetLastError() );
1136
1137         ok( !memcmp( data, buffer, sizeof(data) ),
1138             "Unexpected tag data, expected %s, got %s (%d)\n",
1139             data, buffer, GetLastError() );
1140
1141         pCloseColorProfile( handle );
1142     }
1143 }
1144
1145 static void test_SetColorProfileHeader(void)
1146 {
1147     if (testprofile)
1148     {
1149         PROFILE profile;
1150         HPROFILE handle;
1151         BOOL ret;
1152         PROFILEHEADER header;
1153
1154         profile.dwType = PROFILE_FILENAME;
1155         profile.pProfileData = testprofile;
1156         profile.cbDataSize = strlen(testprofile);
1157
1158         header.phSize = 0x00000c48;
1159         header.phCMMType = 0x4c696e6f;
1160         header.phVersion = 0x02100000;
1161         header.phClass = 0x6d6e7472;
1162         header.phDataColorSpace = 0x52474220;
1163         header.phConnectionSpace  = 0x58595a20;
1164         header.phDateTime[0] = 0x07ce0002;
1165         header.phDateTime[1] = 0x00090006;
1166         header.phDateTime[2] = 0x00310000;
1167         header.phSignature = 0x61637370;
1168         header.phPlatform = 0x4d534654;
1169         header.phProfileFlags = 0x00000000;
1170         header.phManufacturer = 0x49454320;
1171         header.phModel = 0x73524742;
1172         header.phAttributes[0] = 0x00000000;
1173         header.phAttributes[1] = 0x00000000;
1174         header.phRenderingIntent = 0x00000000;
1175         header.phIlluminant.ciexyzX = 0x0000f6d6;
1176         header.phIlluminant.ciexyzY = 0x00010000;
1177         header.phIlluminant.ciexyzZ = 0x0000d32d;
1178         header.phCreator = 0x48502020;
1179
1180         /* Parameter checks */
1181
1182         handle = pOpenColorProfileA( &profile, PROFILE_READ, 0, OPEN_EXISTING );
1183         ok( handle != NULL, "OpenColorProfileA() failed (%d)\n", GetLastError() );
1184
1185         ret = pSetColorProfileHeader( handle, &header );
1186         ok( !ret, "SetColorProfileHeader() succeeded (%d)\n", GetLastError() );
1187
1188         pCloseColorProfile( handle );
1189
1190         handle = pOpenColorProfileA( &profile, PROFILE_READWRITE, 0, OPEN_EXISTING );
1191         ok( handle != NULL, "OpenColorProfileA() failed (%d)\n", GetLastError() );
1192
1193         ret = pSetColorProfileHeader( NULL, NULL );
1194         ok( !ret, "SetColorProfileHeader() succeeded (%d)\n", GetLastError() );
1195
1196         ret = pSetColorProfileHeader( handle, NULL );
1197         ok( !ret, "SetColorProfileHeader() succeeded (%d)\n", GetLastError() );
1198
1199         ret = pSetColorProfileHeader( NULL, &header );
1200         ok( !ret, "SetColorProfileHeader() succeeded (%d)\n", GetLastError() );
1201
1202         /* Functional checks */
1203
1204         ret = pSetColorProfileHeader( handle, &header );
1205         ok( ret, "SetColorProfileHeader() failed (%d)\n", GetLastError() );
1206
1207         ret = pGetColorProfileHeader( handle, &header );
1208         ok( ret, "GetColorProfileHeader() failed (%d)\n", GetLastError() );
1209
1210         ok( !memcmp( &header, rgbheader, sizeof(rgbheader) ), "Unexpected header data\n" );
1211
1212         pCloseColorProfile( handle );
1213     }
1214 }
1215
1216 static void test_UninstallColorProfileA(void)
1217 {
1218     BOOL ret;
1219
1220     /* Parameter checks */
1221
1222     ret = pUninstallColorProfileA( NULL, NULL, FALSE );
1223     ok( !ret, "UninstallColorProfileA() succeeded (%d)\n", GetLastError() );
1224
1225     ret = pUninstallColorProfileA( machine, NULL, FALSE );
1226     ok( !ret, "UninstallColorProfileA() succeeded (%d)\n", GetLastError() );
1227
1228     /* Functional checks */
1229
1230     if (testprofile)
1231     {
1232         CHAR dest[MAX_PATH], base[MAX_PATH];
1233         DWORD size = sizeof(dest);
1234         CHAR slash[] = "\\";
1235         HANDLE handle;
1236
1237         ret = pInstallColorProfileA( NULL, testprofile );
1238         ok( ret, "InstallColorProfileA() failed (%d)\n", GetLastError() );
1239
1240         ret = pGetColorDirectoryA( NULL, dest, &size );
1241         ok( ret, "GetColorDirectoryA() failed (%d)\n", GetLastError() );
1242
1243         MSCMS_basenameA( testprofile, base );
1244
1245         lstrcatA( dest, slash );
1246         lstrcatA( dest, base );
1247
1248         ret = pUninstallColorProfileA( NULL, dest, TRUE );
1249         ok( ret, "UninstallColorProfileA() failed (%d)\n", GetLastError() );
1250
1251         /* Check if the profile is really gone */
1252         handle = CreateFileA( dest, 0 , 0, NULL, OPEN_EXISTING, 0, NULL );
1253         ok( handle == INVALID_HANDLE_VALUE, "Found the profile (%d)\n", GetLastError() );
1254         CloseHandle( handle );
1255     }
1256 }
1257
1258 static void test_UninstallColorProfileW(void)
1259 {
1260     BOOL ret;
1261
1262     /* Parameter checks */
1263
1264     ret = pUninstallColorProfileW( NULL, NULL, FALSE );
1265     ok( !ret, "UninstallColorProfileW() succeeded (%d)\n", GetLastError() );
1266
1267     ret = pUninstallColorProfileW( machineW, NULL, FALSE );
1268     ok( !ret, "UninstallColorProfileW() succeeded (%d)\n", GetLastError() );
1269
1270     /* Functional checks */
1271
1272     if (testprofileW)
1273     {
1274         WCHAR dest[MAX_PATH], base[MAX_PATH];
1275         char destA[MAX_PATH];
1276         DWORD size = sizeof(dest);
1277         WCHAR slash[] = { '\\', 0 };
1278         HANDLE handle;
1279         int bytes_copied;
1280
1281         ret = pInstallColorProfileW( NULL, testprofileW );
1282         ok( ret, "InstallColorProfileW() failed (%d)\n", GetLastError() );
1283
1284         ret = pGetColorDirectoryW( NULL, dest, &size );
1285         ok( ret, "GetColorDirectoryW() failed (%d)\n", GetLastError() );
1286
1287         MSCMS_basenameW( testprofileW, base );
1288
1289         lstrcatW( dest, slash );
1290         lstrcatW( dest, base );
1291
1292         ret = pUninstallColorProfileW( NULL, dest, TRUE );
1293         ok( ret, "UninstallColorProfileW() failed (%d)\n", GetLastError() );
1294
1295         bytes_copied = WideCharToMultiByte(CP_ACP, 0, dest, -1, destA, MAX_PATH, NULL, NULL);
1296         ok( bytes_copied > 0 , "WideCharToMultiByte() returns %d\n", bytes_copied);
1297         /* Check if the profile is really gone */
1298         handle = CreateFileA( destA, 0 , 0, NULL, OPEN_EXISTING, 0, NULL );
1299         ok( handle == INVALID_HANDLE_VALUE, "Found the profile (%d)\n", GetLastError() );
1300         CloseHandle( handle );
1301     }
1302 }
1303
1304 START_TEST(profile)
1305 {
1306     UINT len;
1307     HANDLE handle;
1308     char path[MAX_PATH], file[MAX_PATH];
1309     char profilefile1[MAX_PATH], profilefile2[MAX_PATH];
1310     WCHAR profilefile1W[MAX_PATH], profilefile2W[MAX_PATH];
1311     WCHAR fileW[MAX_PATH];
1312     UINT ret;
1313
1314     hmscms = LoadLibraryA( "mscms.dll" );
1315     if (!hmscms) return;
1316
1317     if (!init_function_ptrs())
1318     {
1319         FreeLibrary( hmscms );
1320         return;
1321     }
1322
1323     /* See if we can find the standard color profile */
1324     ret = GetSystemDirectoryA( profilefile1, sizeof(profilefile1) );
1325     ok( ret > 0, "GetSystemDirectoryA() returns %d, LastError = %d\n", ret, GetLastError());
1326     ok( lstrlenA(profilefile1) > 0 && lstrlenA(profilefile1) < MAX_PATH, 
1327         "GetSystemDirectoryA() returns %d, LastError = %d\n", ret, GetLastError());
1328     MultiByteToWideChar(CP_ACP, 0, profilefile1, -1, profilefile1W, MAX_PATH);
1329     ok( lstrlenW(profilefile1W) > 0 && lstrlenW(profilefile1W) < MAX_PATH, 
1330         "GetSystemDirectoryA() returns %d, LastError = %d\n", ret, GetLastError());
1331     lstrcpyA(profilefile2, profilefile1);
1332     lstrcpyW(profilefile2W, profilefile1W);
1333
1334     lstrcatA( profilefile1, profile1 );
1335     lstrcatW( profilefile1W, profile1W );
1336     handle = CreateFileA( profilefile1, 0 , 0, NULL, OPEN_EXISTING, 0, NULL );
1337
1338     if (handle != INVALID_HANDLE_VALUE)
1339     {
1340         standardprofile = profilefile1;
1341         standardprofileW = profilefile1W;
1342         CloseHandle( handle );
1343     }
1344
1345     lstrcatA( profilefile2, profile2 );
1346     lstrcatW( profilefile2W, profile2W );
1347     handle = CreateFileA( profilefile2, 0 , 0, NULL, OPEN_EXISTING, 0, NULL );
1348
1349     if (handle != INVALID_HANDLE_VALUE)
1350     {
1351         standardprofile = profilefile2;
1352         standardprofileW = profilefile2W;
1353         CloseHandle( handle );
1354     }
1355
1356     /* If found, create a temporary copy for testing purposes */
1357     if (standardprofile && GetTempPath( sizeof(path), path ))
1358     {
1359         if (GetTempFileName( path, "rgb", 0, file ))
1360         {
1361             if (CopyFileA( standardprofile, file, FALSE ))
1362             {
1363                 testprofile = (LPSTR)&file;
1364
1365                 len = MultiByteToWideChar( CP_ACP, 0, testprofile, -1, NULL, 0 );
1366                 MultiByteToWideChar( CP_ACP, 0, testprofile, -1, fileW, len );
1367
1368                 testprofileW = (LPWSTR)&fileW;
1369             }
1370         }
1371     }
1372
1373     test_GetColorDirectoryA();
1374     test_GetColorDirectoryW();
1375
1376     test_GetColorProfileElement();
1377     test_GetColorProfileElementTag();
1378
1379     test_GetColorProfileFromHandle();
1380     test_GetColorProfileHeader();
1381
1382     test_GetCountColorProfileElements();
1383
1384     enum_registered_color_profiles();
1385     check_registry();
1386
1387     test_GetStandardColorSpaceProfileA();
1388     test_GetStandardColorSpaceProfileW();
1389
1390     test_EnumColorProfilesA();
1391     test_EnumColorProfilesW();
1392
1393     test_InstallColorProfileA();
1394     test_InstallColorProfileW();
1395
1396     test_IsColorProfileTagPresent();
1397
1398     test_OpenColorProfileA();
1399     test_OpenColorProfileW();
1400
1401     test_SetColorProfileElement();
1402     test_SetColorProfileHeader();
1403
1404     test_UninstallColorProfileA();
1405     test_UninstallColorProfileW();
1406
1407     /* Clean up */
1408     if (testprofile)
1409         DeleteFileA( testprofile );
1410     
1411     FreeLibrary( hmscms );
1412 }