crypt32: Introduce function to encode an array of items as a set.
[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         if (0) /* Crashes on Vista */
398         {
399             ret = pGetColorProfileHeader( handle, NULL );
400             ok( !ret, "GetColorProfileHeader() succeeded (%d)\n", GetLastError() );
401         }
402
403         /* Functional checks */
404
405         ret = pGetColorProfileHeader( handle, &header );
406         ok( ret, "GetColorProfileHeader() failed (%d)\n", GetLastError() );
407
408         ok( !memcmp( &header, rgbheader, sizeof(rgbheader) ), "Unexpected header data\n" );
409
410         pCloseColorProfile( handle );
411     }
412 }
413
414 static void test_GetCountColorProfileElements(void)
415 {
416     if (standardprofile)
417     {
418         PROFILE profile;
419         HPROFILE handle;
420         BOOL ret;
421         DWORD count, expect = 17;
422
423         profile.dwType = PROFILE_FILENAME;
424         profile.pProfileData = standardprofile;
425         profile.cbDataSize = strlen(standardprofile);
426
427         handle = pOpenColorProfileA( &profile, PROFILE_READ, 0, OPEN_EXISTING );
428         ok( handle != NULL, "OpenColorProfileA() failed (%d)\n", GetLastError() );
429
430         /* Parameter checks */
431
432         ret = pGetCountColorProfileElements( NULL, &count );
433         ok( !ret, "GetCountColorProfileElements() succeeded (%d)\n",
434             GetLastError() );
435
436         ret = pGetCountColorProfileElements( handle, NULL );
437         ok( !ret, "GetCountColorProfileElements() succeeded (%d)\n",
438             GetLastError() );
439
440         /* Functional checks */
441
442         ret = pGetCountColorProfileElements( handle, &count );
443         ok( ret && count == expect,
444             "GetCountColorProfileElements() failed (%d)\n", GetLastError() );
445
446         pCloseColorProfile( handle );
447     }
448 }
449
450 typedef struct colorspace_description_struct {
451     DWORD dwID;
452     const char *szName;
453     BOOL registered;
454     char filename[MAX_PATH];
455 } colorspace_descr;
456
457 #define describe_colorspace(id) {id, #id, FALSE, ""}
458
459 colorspace_descr known_colorspaces[] = { 
460     describe_colorspace(SPACE_XYZ),
461     describe_colorspace(SPACE_Lab),
462     describe_colorspace(SPACE_Luv),
463     describe_colorspace(SPACE_YCbCr),
464     describe_colorspace(SPACE_Yxy),
465     describe_colorspace(SPACE_RGB),
466     describe_colorspace(SPACE_GRAY),
467     describe_colorspace(SPACE_HSV),
468     describe_colorspace(SPACE_HLS),
469     describe_colorspace(SPACE_CMYK),
470     describe_colorspace(SPACE_CMY),
471     describe_colorspace(SPACE_2_CHANNEL),
472     describe_colorspace(SPACE_3_CHANNEL),
473     describe_colorspace(SPACE_4_CHANNEL),
474     describe_colorspace(SPACE_5_CHANNEL),
475     describe_colorspace(SPACE_6_CHANNEL),
476     describe_colorspace(SPACE_7_CHANNEL),
477     describe_colorspace(SPACE_8_CHANNEL)
478 };
479
480 static void enum_registered_color_profiles(void)
481 {
482     BOOL ret;
483     DWORD size, count, i, present;
484     CHAR profile[MAX_PATH];
485
486     size = sizeof(profile);
487     count = sizeof(known_colorspaces)/sizeof(known_colorspaces[0]);
488
489     present = 0;
490     trace("\n");
491     trace("Querying registered standard colorspace profiles via GetStandardColorSpaceProfileA():\n");
492     for (i=0; i<count; i++)
493     {
494         ret = pGetStandardColorSpaceProfileA(NULL, known_colorspaces[i].dwID, profile, &size);
495         if (ret) 
496         {
497             lstrcpynA(known_colorspaces[i].filename, profile, MAX_PATH);
498             known_colorspaces[i].registered = TRUE;
499             present++;
500             trace(" found %s, pointing to '%s' (%d chars)\n", known_colorspaces[i].szName, profile, lstrlenA(profile));
501         }
502     }
503     trace("Total profiles found: %d.\n", present);
504     trace("\n");
505 }
506
507 static colorspace_descr *query_colorspace(DWORD dwID)
508 {
509     DWORD count, i;
510
511     count = sizeof(known_colorspaces)/sizeof(known_colorspaces[0]);
512
513     for (i=0; i<count; i++)
514         if (known_colorspaces[i].dwID == dwID)
515         {
516             if (!known_colorspaces[i].registered) break;
517             return &known_colorspaces[i];
518         }
519     return NULL;
520 }
521
522 static HKEY reg_open_mscms_key(void)
523 {
524     char win9x[] = "SOFTWARE\\Microsoft\\Windows";
525     char winNT[] = "SOFTWARE\\Microsoft\\Windows NT";
526     char ICM[] = "CurrentVersion\\ICM\\RegisteredProfiles";
527     HKEY win9x_key, winNT_key, ICM_key;
528
529     RegOpenKeyExA( HKEY_LOCAL_MACHINE, win9x, 0, KEY_READ, &win9x_key );
530     RegOpenKeyExA( HKEY_LOCAL_MACHINE, winNT, 0, KEY_READ, &winNT_key );
531
532     if (RegOpenKeyExA( winNT_key, ICM, 0, KEY_READ, &ICM_key )) 
533         RegOpenKeyExA( win9x_key, ICM, 0, KEY_READ, &ICM_key );
534     RegCloseKey( win9x_key );
535     RegCloseKey( winNT_key );
536
537     return ICM_key;
538 }
539
540 static void check_registry(void)
541 {
542     HKEY hkIcmKey;
543     LONG res;
544     DWORD i, dwValCount;
545     char szName[16383];
546     char szData[MAX_PATH+1];
547     DWORD dwNameLen, dwDataLen, dwType;
548
549     hkIcmKey = reg_open_mscms_key();
550     if (!hkIcmKey)
551     {
552         trace("Key 'HKLM\\SOFTWARE\\Microsoft\\Windows*\\CurrentVersion\\ICM\\RegisteredProfiles' not found\n" );
553         return;
554     }
555
556     res = RegQueryInfoKeyA(hkIcmKey, NULL, NULL, NULL, NULL, NULL, NULL, &dwValCount, NULL, NULL, NULL, NULL);
557     if (res) 
558     {
559         trace("RegQueryInfoKeyA() failed : %d\n", res);
560         return;
561     }
562
563     trace("Count of profile entries found directly in the registry: %d\n", dwValCount);
564
565     for (i = 0; i<dwValCount; i++) 
566     {
567         dwNameLen = sizeof(szName);
568         dwDataLen = sizeof(szData);
569         res = RegEnumValueA( hkIcmKey, i, szName, &dwNameLen, NULL, &dwType, (LPBYTE)szData, &dwDataLen );
570         if (res != ERROR_SUCCESS) 
571         {
572             trace("RegEnumValueA() failed (%d), cannot enumerate profiles\n", res);
573             break;
574         }
575         ok( dwType == REG_SZ, "RegEnumValueA() returned unexpected value type (%d)\n", dwType );
576         if (dwType != REG_SZ) break;
577         trace(" found '%s' value containing '%s' (%d chars)\n", szName, szData, lstrlenA(szData));
578     } 
579
580     RegCloseKey( hkIcmKey );
581 }
582
583 static void test_GetStandardColorSpaceProfileA(void)
584 {
585     BOOL ret;
586     DWORD size;
587     CHAR oldprofile[MAX_PATH];
588     CHAR newprofile[MAX_PATH];
589     const CHAR emptyA[] = "";
590     DWORD zero = 0;
591     DWORD sizeP = sizeof(newprofile);
592
593     /* Parameter checks */
594
595     /* Single invalid parameter checks: */
596
597     SetLastError(0xfaceabee); /* 1st param, */
598     ret = pGetStandardColorSpaceProfileA(machine, SPACE_RGB, newprofile, &sizeP);
599     ok( !ret && GetLastError() == ERROR_NOT_SUPPORTED, "GetStandardColorSpaceProfileA() returns %d (GLE=%d)\n", ret, GetLastError() );
600
601     SetLastError(0xfaceabee); /* 2nd param, */
602     ret = pGetStandardColorSpaceProfileA(NULL, (DWORD)-1, newprofile, &sizeP);
603     ok( !ret && GetLastError() == ERROR_FILE_NOT_FOUND, "GetStandardColorSpaceProfileA() returns %d (GLE=%d)\n", ret, GetLastError() );
604
605     SetLastError(0xfaceabee); /* 4th param, */
606     ret = pGetStandardColorSpaceProfileA(NULL, SPACE_RGB, newprofile, NULL);
607     ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER, "GetStandardColorSpaceProfileA() returns %d (GLE=%d)\n", ret, GetLastError() );
608
609     if (query_colorspace(SPACE_RGB)) 
610     {
611         SetLastError(0xfaceabee); /* 3rd param, */
612         ret = pGetStandardColorSpaceProfileA(NULL, SPACE_RGB, NULL, &sizeP);
613         ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetStandardColorSpaceProfileA() returns %d (GLE=%d)\n", ret, GetLastError() );
614
615         SetLastError(0xfaceabee); /* dereferenced 4th param, */
616         ret = pGetStandardColorSpaceProfileA(NULL, SPACE_RGB, newprofile, &zero);
617         ok( !ret && (GetLastError() == ERROR_MORE_DATA || GetLastError() == ERROR_INSUFFICIENT_BUFFER), "GetStandardColorSpaceProfileA() returns %d (GLE=%d)\n", ret, GetLastError() );
618     } else {
619         SetLastError(0xfaceabee); /* 3rd param, */
620         ret = pGetStandardColorSpaceProfileA(NULL, SPACE_RGB, NULL, &sizeP);
621         ok( !ret && GetLastError() == ERROR_FILE_NOT_FOUND, "GetStandardColorSpaceProfileA() returns %d (GLE=%d)\n", ret, GetLastError() );
622
623         SetLastError(0xfaceabee); /* dereferenced 4th param. */
624         ret = pGetStandardColorSpaceProfileA(NULL, SPACE_RGB, newprofile, &sizeP);
625         ok( !ret && GetLastError() == ERROR_FILE_NOT_FOUND, "GetStandardColorSpaceProfileA() returns %d (GLE=%d)\n", ret, GetLastError() );
626     }
627
628     /* Several invalid parameter checks: */
629
630     SetLastError(0xfaceabee); /* 1st, maybe 2nd and then dereferenced 4th param, */
631     ret = pGetStandardColorSpaceProfileA(machine, 0, newprofile, &zero);
632     ok( !ret && (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_NOT_SUPPORTED), "GetStandardColorSpaceProfileA() returns %d (GLE=%d)\n", ret, GetLastError() );
633
634     SetLastError(0xfaceabee); /* maybe 2nd and then 4th param, */
635     ret = pGetStandardColorSpaceProfileA(NULL, 0, newprofile, NULL);
636     ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER, "GetStandardColorSpaceProfileA() returns %d (GLE=%d)\n", ret, GetLastError() );
637
638     SetLastError(0xfaceabee); /* maybe 2nd, then 3rd and dereferenced 4th param, */
639     ret = pGetStandardColorSpaceProfileA(NULL, 0, NULL, &zero);
640     ok( !ret && (GetLastError() == ERROR_INSUFFICIENT_BUFFER || GetLastError() == ERROR_FILE_NOT_FOUND), "GetStandardColorSpaceProfileA() returns %d (GLE=%d)\n", ret, GetLastError() );
641
642     SetLastError(0xfaceabee); /* maybe 2nd param. */
643     ret = pGetStandardColorSpaceProfileA(NULL, 0, newprofile, &sizeP);
644     if (!ret) ok( GetLastError() == ERROR_FILE_NOT_FOUND, "GetStandardColorSpaceProfileA() returns %d (GLE=%d)\n", ret, GetLastError() );
645     else ok( !lstrcmpiA( newprofile, emptyA ) && GetLastError() == 0xfaceabee, "GetStandardColorSpaceProfileA() returns %d (GLE=%d)\n", ret, GetLastError() );
646
647     /* Functional checks */
648
649     if (standardprofile)
650     {
651         size = sizeof(oldprofile);
652
653         ret = pGetStandardColorSpaceProfileA( NULL, SPACE_RGB, oldprofile, &size );
654         ok( ret, "GetStandardColorSpaceProfileA() failed (%d)\n", GetLastError() );
655
656         SetLastError(0xdeadbeef);
657         ret = pSetStandardColorSpaceProfileA( NULL, SPACE_RGB, standardprofile );
658         if (!ret && (GetLastError() == ERROR_ACCESS_DENIED))
659         {
660             skip("Not enough rights for SetStandardColorSpaceProfileA\n");
661             return;
662         }
663         ok( ret, "SetStandardColorSpaceProfileA() failed (%d)\n", GetLastError() );
664
665         size = sizeof(newprofile);
666
667         ret = pGetStandardColorSpaceProfileA( NULL, SPACE_RGB, newprofile, &size );
668         ok( ret, "GetStandardColorSpaceProfileA() failed (%d)\n", GetLastError() );
669
670         ok( !lstrcmpiA( (LPSTR)&newprofile, standardprofile ), "Unexpected profile\n" );
671
672         ret = pSetStandardColorSpaceProfileA( NULL, SPACE_RGB, oldprofile );
673         ok( ret, "SetStandardColorSpaceProfileA() failed (%d)\n", GetLastError() );
674     }
675 }
676
677 static void test_GetStandardColorSpaceProfileW(void)
678 {
679     BOOL ret;
680     DWORD size;
681     WCHAR oldprofile[MAX_PATH];
682     WCHAR newprofile[MAX_PATH];
683     const WCHAR emptyW[] = {0};
684     DWORD zero = 0;
685     DWORD sizeP = sizeof(newprofile);
686
687     /* Parameter checks */
688
689     /* Single invalid parameter checks: */
690
691     SetLastError(0xfaceabee); /* 1st param, */
692     ret = pGetStandardColorSpaceProfileW(machineW, SPACE_RGB, newprofile, &sizeP);
693     ok( !ret && GetLastError() == ERROR_NOT_SUPPORTED, "GetStandardColorSpaceProfileW() returns %d (GLE=%d)\n", ret, GetLastError() );
694
695     SetLastError(0xfaceabee); /* 2nd param, */
696     ret = pGetStandardColorSpaceProfileW(NULL, (DWORD)-1, newprofile, &sizeP);
697     ok( !ret && GetLastError() == ERROR_FILE_NOT_FOUND, "GetStandardColorSpaceProfileW() returns %d (GLE=%d)\n", ret, GetLastError() );
698
699     SetLastError(0xfaceabee); /* 3th param, */
700     ret = pGetStandardColorSpaceProfileW(NULL, SPACE_RGB, NULL, &sizeP);
701     ok( !ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER, "GetStandardColorSpaceProfileW() returns %d (GLE=%d)\n", ret, GetLastError() );
702
703     SetLastError(0xfaceabee); /* 4th param, */
704     ret = pGetStandardColorSpaceProfileW(NULL, SPACE_RGB, newprofile, NULL);
705     ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER, "GetStandardColorSpaceProfileW() returns %d (GLE=%d)\n", ret, GetLastError() );
706
707     SetLastError(0xfaceabee); /* dereferenced 4th param. */
708     ret = pGetStandardColorSpaceProfileW(NULL, SPACE_RGB, newprofile, &zero);
709     ok( !ret && (GetLastError() == ERROR_MORE_DATA || GetLastError() == ERROR_INSUFFICIENT_BUFFER), "GetStandardColorSpaceProfileW() returns %d (GLE=%d)\n", ret, GetLastError() );
710
711     /* Several invalid parameter checks: */
712
713     SetLastError(0xfaceabee); /* 1st, maybe 2nd and then dereferenced 4th param, */
714     ret = pGetStandardColorSpaceProfileW(machineW, 0, newprofile, &zero);
715     ok( !ret && (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_NOT_SUPPORTED), "GetStandardColorSpaceProfileW() returns %d (GLE=%d)\n", ret, GetLastError() );
716
717     SetLastError(0xfaceabee); /* maybe 2nd and then 4th param, */
718     ret = pGetStandardColorSpaceProfileW(NULL, 0, newprofile, NULL);
719     ok( !ret && GetLastError() == ERROR_INVALID_PARAMETER, "GetStandardColorSpaceProfileW() returns %d (GLE=%d)\n", ret, GetLastError() );
720
721     SetLastError(0xfaceabee); /* maybe 2nd, then 3rd and dereferenced 4th param, */
722     ret = pGetStandardColorSpaceProfileW(NULL, 0, NULL, &zero);
723     ok( !ret && (GetLastError() == ERROR_INSUFFICIENT_BUFFER || GetLastError() == ERROR_FILE_NOT_FOUND), "GetStandardColorSpaceProfileW() returns %d (GLE=%d)\n", ret, GetLastError() );
724
725     SetLastError(0xfaceabee); /* maybe 2nd param. */
726     ret = pGetStandardColorSpaceProfileW(NULL, 0, newprofile, &sizeP);
727     if (!ret) ok( GetLastError() == ERROR_FILE_NOT_FOUND, "GetStandardColorSpaceProfileW() returns %d (GLE=%d)\n", ret, GetLastError() );
728     else ok( !lstrcmpiW( newprofile, emptyW ) && GetLastError() == 0xfaceabee, "GetStandardColorSpaceProfileW() returns %d (GLE=%d)\n", ret, GetLastError() );
729
730     /* Functional checks */
731
732     if (standardprofileW)
733     {
734         size = sizeof(oldprofile);
735
736         ret = pGetStandardColorSpaceProfileW( NULL, SPACE_RGB, oldprofile, &size );
737         ok( ret, "GetStandardColorSpaceProfileW() failed (%d)\n", GetLastError() );
738
739         SetLastError(0xdeadbeef);
740         ret = pSetStandardColorSpaceProfileW( NULL, SPACE_RGB, standardprofileW );
741         if (!ret && (GetLastError() == ERROR_ACCESS_DENIED))
742         {
743             skip("Not enough rights for SetStandardColorSpaceProfileW\n");
744             return;
745         }
746         ok( ret, "SetStandardColorSpaceProfileW() failed (%d)\n", GetLastError() );
747
748         size = sizeof(newprofile);
749
750         ret = pGetStandardColorSpaceProfileW( NULL, SPACE_RGB, newprofile, &size );
751         ok( ret, "GetStandardColorSpaceProfileW() failed (%d)\n", GetLastError() );
752
753         ok( !lstrcmpiW( (LPWSTR)&newprofile, standardprofileW ), "Unexpected profile\n" );
754
755         ret = pSetStandardColorSpaceProfileW( NULL, SPACE_RGB, oldprofile );
756         ok( ret, "SetStandardColorSpaceProfileW() failed (%d)\n", GetLastError() );
757     }
758 }
759
760 static void test_EnumColorProfilesA(void)
761 {
762     BOOL ret;
763     DWORD size, number;
764     ENUMTYPEA record;
765     BYTE buffer[MAX_PATH];
766
767     /* Parameter checks */
768
769     size = sizeof(buffer);
770     memset( &record, 0, sizeof(ENUMTYPEA) );
771
772     record.dwSize = sizeof(ENUMTYPEA);
773     record.dwVersion = ENUM_TYPE_VERSION;
774     record.dwFields |= ET_DATACOLORSPACE;
775     record.dwDataColorSpace = SPACE_RGB;
776
777     ret = pEnumColorProfilesA( machine, &record, buffer, &size, &number );
778     ok( !ret, "EnumColorProfilesA() succeeded (%d)\n", GetLastError() );
779
780     ret = pEnumColorProfilesA( NULL, NULL, buffer, &size, &number );
781     ok( !ret, "EnumColorProfilesA() succeeded (%d)\n", GetLastError() );
782
783     ret = pEnumColorProfilesA( NULL, &record, buffer, NULL, &number );
784     ok( !ret, "EnumColorProfilesA() succeeded (%d)\n", GetLastError() );
785
786     if (standardprofile)
787     {
788         ret = pEnumColorProfilesA( NULL, &record, buffer, &size, &number );
789         ok( ret, "EnumColorProfilesA() failed (%d)\n", GetLastError() );
790     }
791
792     size = 0;
793
794     ret = pEnumColorProfilesA( NULL, &record, buffer, &size, &number );
795     ok( !ret, "EnumColorProfilesA() succeeded (%d)\n", GetLastError() );
796
797     /* Functional checks */
798
799     if (standardprofile)
800     {
801         size = sizeof(buffer);
802
803         ret = pEnumColorProfilesA( NULL, &record, buffer, &size, &number );
804         ok( ret, "EnumColorProfilesA() failed (%d)\n", GetLastError() );
805     }
806 }
807
808 static void test_EnumColorProfilesW(void)
809 {
810     BOOL ret;
811     DWORD size, number;
812     ENUMTYPEW record;
813     BYTE buffer[MAX_PATH * sizeof(WCHAR)];
814
815     /* Parameter checks */
816
817     size = sizeof(buffer);
818     memset( &record, 0, sizeof(ENUMTYPEW) );
819
820     record.dwSize = sizeof(ENUMTYPEW);
821     record.dwVersion = ENUM_TYPE_VERSION;
822     record.dwFields |= ET_DATACOLORSPACE;
823     record.dwDataColorSpace = SPACE_RGB;
824
825     ret = pEnumColorProfilesW( machineW, &record, buffer, &size, &number );
826     ok( !ret, "EnumColorProfilesW() succeeded (%d)\n", GetLastError() );
827
828     ret = pEnumColorProfilesW( NULL, NULL, buffer, &size, &number );
829     ok( !ret, "EnumColorProfilesW() succeeded (%d)\n", GetLastError() );
830
831     ret = pEnumColorProfilesW( NULL, &record, buffer, NULL, &number );
832     ok( !ret, "EnumColorProfilesW() succeeded (%d)\n", GetLastError() );
833
834     if (standardprofileW)
835     {
836         ret = pEnumColorProfilesW( NULL, &record, buffer, &size, NULL );
837         ok( ret, "EnumColorProfilesW() failed (%d)\n", GetLastError() );
838     }
839
840     size = 0;
841
842     ret = pEnumColorProfilesW( NULL, &record, buffer, &size, &number );
843     ok( !ret, "EnumColorProfilesW() succeeded (%d)\n", GetLastError() );
844
845     /* Functional checks */
846
847     if (standardprofileW)
848     {
849         size = sizeof(buffer);
850
851         ret = pEnumColorProfilesW( NULL, &record, buffer, &size, &number );
852         ok( ret, "EnumColorProfilesW() failed (%d)\n", GetLastError() );
853     }
854 }
855
856 static void test_InstallColorProfileA(void)
857 {
858     BOOL ret;
859
860     /* Parameter checks */
861
862     ret = pInstallColorProfileA( NULL, NULL );
863     ok( !ret, "InstallColorProfileA() succeeded (%d)\n", GetLastError() );
864
865     ret = pInstallColorProfileA( machine, NULL );
866     ok( !ret, "InstallColorProfileA() succeeded (%d)\n", GetLastError() );
867
868     ret = pInstallColorProfileA( NULL, machine );
869     ok( !ret, "InstallColorProfileA() succeeded (%d)\n", GetLastError() );
870
871     if (standardprofile)
872     {
873         ret = pInstallColorProfileA( NULL, standardprofile );
874         ok( ret, "InstallColorProfileA() failed (%d)\n", GetLastError() );
875     }
876
877     /* Functional checks */
878
879     if (testprofile)
880     {
881         CHAR dest[MAX_PATH], base[MAX_PATH];
882         DWORD size = sizeof(dest);
883         CHAR slash[] = "\\";
884         HANDLE handle;
885
886         SetLastError(0xdeadbeef);
887         ret = pInstallColorProfileA( NULL, testprofile );
888         if (!ret && (GetLastError() == ERROR_ACCESS_DENIED))
889         {
890             skip("Not enough rights for InstallColorProfileA\n");
891             return;
892         }
893         ok( ret, "InstallColorProfileA() failed (%d)\n", GetLastError() );
894
895         ret = pGetColorDirectoryA( NULL, dest, &size );
896         ok( ret, "GetColorDirectoryA() failed (%d)\n", GetLastError() );
897
898         MSCMS_basenameA( testprofile, base );
899
900         lstrcatA( dest, slash );
901         lstrcatA( dest, base );
902
903         /* Check if the profile is really there */ 
904         handle = CreateFileA( dest, 0 , 0, NULL, OPEN_EXISTING, 0, NULL );
905         ok( handle != INVALID_HANDLE_VALUE, "Couldn't find the profile (%d)\n", GetLastError() );
906         CloseHandle( handle );
907         
908         ret = pUninstallColorProfileA( NULL, dest, TRUE );
909         ok( ret, "UninstallColorProfileA() failed (%d)\n", GetLastError() );
910     }
911 }
912
913 static void test_InstallColorProfileW(void)
914 {
915     BOOL ret;
916
917     /* Parameter checks */
918
919     ret = pInstallColorProfileW( NULL, NULL );
920     ok( !ret, "InstallColorProfileW() succeeded (%d)\n", GetLastError() );
921
922     ret = pInstallColorProfileW( machineW, NULL );
923     ok( !ret, "InstallColorProfileW() succeeded (%d)\n", GetLastError() );
924
925     ret = pInstallColorProfileW( NULL, machineW );
926     ok( !ret, "InstallColorProfileW() failed (%d)\n", GetLastError() );
927
928     if (standardprofileW)
929     {
930         ret = pInstallColorProfileW( NULL, standardprofileW );
931         ok( ret, "InstallColorProfileW() failed (%d)\n", GetLastError() );
932     }
933
934     /* Functional checks */
935
936     if (testprofileW)
937     {
938         WCHAR dest[MAX_PATH], base[MAX_PATH];
939         DWORD size = sizeof(dest);
940         WCHAR slash[] = { '\\', 0 };
941         HANDLE handle;
942
943         SetLastError(0xdeadbeef);
944         ret = pInstallColorProfileW( NULL, testprofileW );
945         if (!ret && (GetLastError() == ERROR_ACCESS_DENIED))
946         {
947             skip("Not enough rights for InstallColorProfileW\n");
948             return;
949         }
950         ok( ret, "InstallColorProfileW() failed (%d)\n", GetLastError() );
951
952         ret = pGetColorDirectoryW( NULL, dest, &size );
953         ok( ret, "GetColorDirectoryW() failed (%d)\n", GetLastError() );
954
955         MSCMS_basenameW( testprofileW, base );
956
957         lstrcatW( dest, slash );
958         lstrcatW( dest, base );
959
960         /* Check if the profile is really there */
961         handle = CreateFileW( dest, 0 , 0, NULL, OPEN_EXISTING, 0, NULL );
962         ok( handle != INVALID_HANDLE_VALUE, "Couldn't find the profile (%d)\n", GetLastError() );
963         CloseHandle( handle );
964
965         ret = pUninstallColorProfileW( NULL, dest, TRUE );
966         ok( ret, "UninstallColorProfileW() failed (%d)\n", GetLastError() );
967     }
968 }
969
970 static void test_IsColorProfileTagPresent(void)
971 {
972     if (standardprofile)
973     {
974         PROFILE profile;
975         HPROFILE handle;
976         BOOL ret, present;
977         TAGTYPE tag;
978
979         profile.dwType = PROFILE_FILENAME;
980         profile.pProfileData = standardprofile;
981         profile.cbDataSize = strlen(standardprofile);
982
983         handle = pOpenColorProfileA( &profile, PROFILE_READ, 0, OPEN_EXISTING );
984         ok( handle != NULL, "OpenColorProfileA() failed (%d)\n", GetLastError() );
985
986         /* Parameter checks */
987
988         tag = 0;
989
990         ret = pIsColorProfileTagPresent( handle, tag, &present );
991         ok( !(ret && present), "IsColorProfileTagPresent() succeeded (%d)\n", GetLastError() );
992
993         tag = 0x63707274;  /* 'cprt' */
994
995         ret = pIsColorProfileTagPresent( NULL, tag, &present );
996         ok( !ret, "IsColorProfileTagPresent() succeeded (%d)\n", GetLastError() );
997
998         ret = pIsColorProfileTagPresent( handle, tag, NULL );
999         ok( !ret, "IsColorProfileTagPresent() succeeded (%d)\n", GetLastError() );
1000
1001         /* Functional checks */
1002
1003         ret = pIsColorProfileTagPresent( handle, tag, &present );
1004         ok( ret && present, "IsColorProfileTagPresent() failed (%d)\n", GetLastError() );
1005
1006         pCloseColorProfile( handle );
1007     }
1008 }
1009
1010 static void test_OpenColorProfileA(void)
1011 {
1012     PROFILE profile;
1013     HPROFILE handle;
1014     BOOL ret;
1015
1016     profile.dwType = PROFILE_FILENAME;
1017     profile.pProfileData = NULL;
1018     profile.cbDataSize = 0;
1019
1020     /* Parameter checks */
1021
1022     handle = pOpenColorProfileA( NULL, 0, 0, 0 );
1023     ok( handle == NULL, "OpenColorProfileA() failed (%d)\n", GetLastError() );
1024
1025     handle = pOpenColorProfileA( &profile, 0, 0, 0 );
1026     ok( handle == NULL, "OpenColorProfileA() failed (%d)\n", GetLastError() );
1027
1028     handle = pOpenColorProfileA( &profile, PROFILE_READ, 0, 0 );
1029     ok( handle == NULL, "OpenColorProfileA() failed (%d)\n", GetLastError() );
1030
1031     handle = pOpenColorProfileA( &profile, PROFILE_READWRITE, 0, 0 );
1032     ok( handle == NULL, "OpenColorProfileA() failed (%d)\n", GetLastError() );
1033
1034     ok ( !pCloseColorProfile( NULL ), "CloseColorProfile() succeeded\n" );
1035
1036     if (standardprofile)
1037     {
1038         profile.pProfileData = standardprofile;
1039         profile.cbDataSize = strlen(standardprofile);
1040
1041         handle = pOpenColorProfileA( &profile, 0, 0, 0 );
1042         ok( handle == NULL, "OpenColorProfileA() failed (%d)\n", GetLastError() );
1043
1044         handle = pOpenColorProfileA( &profile, PROFILE_READ, 0, 0 );
1045         ok( handle == NULL, "OpenColorProfileA() failed (%d)\n", GetLastError() );
1046
1047         handle = pOpenColorProfileA( &profile, PROFILE_READ|PROFILE_READWRITE, 0, 0 );
1048         ok( handle == NULL, "OpenColorProfileA() failed (%d)\n", GetLastError() );
1049
1050         /* Functional checks */
1051
1052         handle = pOpenColorProfileA( &profile, PROFILE_READ, 0, OPEN_EXISTING );
1053         ok( handle != NULL, "OpenColorProfileA() failed (%d)\n", GetLastError() );
1054
1055         ret = pCloseColorProfile( handle );
1056         ok( ret, "CloseColorProfile() failed (%d)\n", GetLastError() );
1057     }
1058 }
1059
1060 static void test_OpenColorProfileW(void)
1061 {
1062     PROFILE profile;
1063     HPROFILE handle;
1064     BOOL ret;
1065
1066     profile.dwType = PROFILE_FILENAME;
1067     profile.pProfileData = NULL;
1068     profile.cbDataSize = 0;
1069
1070     /* Parameter checks */
1071
1072     handle = pOpenColorProfileW( NULL, 0, 0, 0 );
1073     ok( handle == NULL, "OpenColorProfileW() failed (%d)\n", GetLastError() );
1074
1075     handle = pOpenColorProfileW( &profile, 0, 0, 0 );
1076     ok( handle == NULL, "OpenColorProfileW() failed (%d)\n", GetLastError() );
1077
1078     handle = pOpenColorProfileW( &profile, PROFILE_READ, 0, 0 );
1079     ok( handle == NULL, "OpenColorProfileW() failed (%d)\n", GetLastError() );
1080
1081     handle = pOpenColorProfileW( &profile, PROFILE_READWRITE, 0, 0 );
1082     ok( handle == NULL, "OpenColorProfileW() failed (%d)\n", GetLastError() );
1083
1084     ok ( !pCloseColorProfile( NULL ), "CloseColorProfile() succeeded\n" );
1085
1086     if (standardprofileW)
1087     {
1088         profile.pProfileData = standardprofileW;
1089         profile.cbDataSize = lstrlenW(standardprofileW) * sizeof(WCHAR);
1090
1091         handle = pOpenColorProfileW( &profile, 0, 0, 0 );
1092         ok( handle == NULL, "OpenColorProfileW() failed (%d)\n", GetLastError() );
1093
1094         handle = pOpenColorProfileW( &profile, PROFILE_READ, 0, 0 );
1095         ok( handle == NULL, "OpenColorProfileW() failed (%d)\n", GetLastError() );
1096
1097         handle = pOpenColorProfileW( &profile, PROFILE_READ|PROFILE_READWRITE, 0, 0 );
1098         ok( handle == NULL, "OpenColorProfileW() failed (%d)\n", GetLastError() );
1099
1100         /* Functional checks */
1101
1102         handle = pOpenColorProfileW( &profile, PROFILE_READ, 0, OPEN_EXISTING );
1103         ok( handle != NULL, "OpenColorProfileW() failed (%d)\n", GetLastError() );
1104
1105         ret = pCloseColorProfile( handle );
1106         ok( ret, "CloseColorProfile() failed (%d)\n", GetLastError() );
1107     }
1108 }
1109
1110 static void test_SetColorProfileElement(void)
1111 {
1112     if (testprofile)
1113     {
1114         PROFILE profile;
1115         HPROFILE handle;
1116         DWORD size;
1117         BOOL ret, ref;
1118
1119         TAGTYPE tag = 0x63707274;  /* 'cprt' */
1120         static char data[] = "(c) The Wine Project";
1121         static char buffer[51];
1122
1123         profile.dwType = PROFILE_FILENAME;
1124         profile.pProfileData = testprofile;
1125         profile.cbDataSize = strlen(testprofile);
1126
1127         /* Parameter checks */
1128
1129         handle = pOpenColorProfileA( &profile, PROFILE_READ, 0, OPEN_EXISTING );
1130         ok( handle != NULL, "OpenColorProfileA() failed (%d)\n", GetLastError() );
1131
1132         ret = pSetColorProfileElement( handle, tag, 0, &size, data );
1133         ok( !ret, "SetColorProfileElement() succeeded (%d)\n", GetLastError() );
1134
1135         pCloseColorProfile( handle );
1136
1137         handle = pOpenColorProfileA( &profile, PROFILE_READWRITE, 0, OPEN_EXISTING );
1138         ok( handle != NULL, "OpenColorProfileA() failed (%d)\n", GetLastError() );
1139
1140         ret = pSetColorProfileElement( NULL, 0, 0, NULL, NULL );
1141         ok( !ret, "SetColorProfileElement() succeeded (%d)\n", GetLastError() );
1142
1143         ret = pSetColorProfileElement( handle, 0, 0, NULL, NULL );
1144         ok( !ret, "SetColorProfileElement() succeeded (%d)\n", GetLastError() );
1145
1146         ret = pSetColorProfileElement( handle, tag, 0, NULL, NULL );
1147         ok( !ret, "SetColorProfileElement() succeeded (%d)\n", GetLastError() );
1148
1149         ret = pSetColorProfileElement( handle, tag, 0, &size, NULL );
1150         ok( !ret, "SetColorProfileElement() succeeded (%d)\n", GetLastError() );
1151
1152         /* Functional checks */
1153
1154         size = sizeof(data);
1155
1156         ret = pSetColorProfileElement( handle, tag, 0, &size, data );
1157         ok( ret, "SetColorProfileElement() failed (%d)\n", GetLastError() );
1158
1159         size = sizeof(buffer);
1160
1161         ret = pGetColorProfileElement( handle, tag, 0, &size, buffer, &ref );
1162         ok( ret && size > 0, "GetColorProfileElement() failed (%d)\n", GetLastError() );
1163
1164         ok( !memcmp( data, buffer, sizeof(data) ),
1165             "Unexpected tag data, expected %s, got %s (%d)\n",
1166             data, buffer, GetLastError() );
1167
1168         pCloseColorProfile( handle );
1169     }
1170 }
1171
1172 static void test_SetColorProfileHeader(void)
1173 {
1174     if (testprofile)
1175     {
1176         PROFILE profile;
1177         HPROFILE handle;
1178         BOOL ret;
1179         PROFILEHEADER header;
1180
1181         profile.dwType = PROFILE_FILENAME;
1182         profile.pProfileData = testprofile;
1183         profile.cbDataSize = strlen(testprofile);
1184
1185         header.phSize = 0x00000c48;
1186         header.phCMMType = 0x4c696e6f;
1187         header.phVersion = 0x02100000;
1188         header.phClass = 0x6d6e7472;
1189         header.phDataColorSpace = 0x52474220;
1190         header.phConnectionSpace  = 0x58595a20;
1191         header.phDateTime[0] = 0x07ce0002;
1192         header.phDateTime[1] = 0x00090006;
1193         header.phDateTime[2] = 0x00310000;
1194         header.phSignature = 0x61637370;
1195         header.phPlatform = 0x4d534654;
1196         header.phProfileFlags = 0x00000000;
1197         header.phManufacturer = 0x49454320;
1198         header.phModel = 0x73524742;
1199         header.phAttributes[0] = 0x00000000;
1200         header.phAttributes[1] = 0x00000000;
1201         header.phRenderingIntent = 0x00000000;
1202         header.phIlluminant.ciexyzX = 0x0000f6d6;
1203         header.phIlluminant.ciexyzY = 0x00010000;
1204         header.phIlluminant.ciexyzZ = 0x0000d32d;
1205         header.phCreator = 0x48502020;
1206
1207         /* Parameter checks */
1208
1209         handle = pOpenColorProfileA( &profile, PROFILE_READ, 0, OPEN_EXISTING );
1210         ok( handle != NULL, "OpenColorProfileA() failed (%d)\n", GetLastError() );
1211
1212         ret = pSetColorProfileHeader( handle, &header );
1213         ok( !ret, "SetColorProfileHeader() succeeded (%d)\n", GetLastError() );
1214
1215         pCloseColorProfile( handle );
1216
1217         handle = pOpenColorProfileA( &profile, PROFILE_READWRITE, 0, OPEN_EXISTING );
1218         ok( handle != NULL, "OpenColorProfileA() failed (%d)\n", GetLastError() );
1219
1220         ret = pSetColorProfileHeader( NULL, NULL );
1221         ok( !ret, "SetColorProfileHeader() succeeded (%d)\n", GetLastError() );
1222
1223         ret = pSetColorProfileHeader( handle, NULL );
1224         ok( !ret, "SetColorProfileHeader() succeeded (%d)\n", GetLastError() );
1225
1226         ret = pSetColorProfileHeader( NULL, &header );
1227         ok( !ret, "SetColorProfileHeader() succeeded (%d)\n", GetLastError() );
1228
1229         /* Functional checks */
1230
1231         ret = pSetColorProfileHeader( handle, &header );
1232         ok( ret, "SetColorProfileHeader() failed (%d)\n", GetLastError() );
1233
1234         ret = pGetColorProfileHeader( handle, &header );
1235         ok( ret, "GetColorProfileHeader() failed (%d)\n", GetLastError() );
1236
1237         ok( !memcmp( &header, rgbheader, sizeof(rgbheader) ), "Unexpected header data\n" );
1238
1239         pCloseColorProfile( handle );
1240     }
1241 }
1242
1243 static void test_UninstallColorProfileA(void)
1244 {
1245     BOOL ret;
1246
1247     /* Parameter checks */
1248
1249     ret = pUninstallColorProfileA( NULL, NULL, FALSE );
1250     ok( !ret, "UninstallColorProfileA() succeeded (%d)\n", GetLastError() );
1251
1252     ret = pUninstallColorProfileA( machine, NULL, FALSE );
1253     ok( !ret, "UninstallColorProfileA() succeeded (%d)\n", GetLastError() );
1254
1255     /* Functional checks */
1256
1257     if (testprofile)
1258     {
1259         CHAR dest[MAX_PATH], base[MAX_PATH];
1260         DWORD size = sizeof(dest);
1261         CHAR slash[] = "\\";
1262         HANDLE handle;
1263
1264         SetLastError(0xdeadbeef);
1265         ret = pInstallColorProfileA( NULL, testprofile );
1266         if (!ret && (GetLastError() == ERROR_ACCESS_DENIED))
1267         {
1268             skip("Not enough rights for InstallColorProfileA\n");
1269             return;
1270         }
1271         ok( ret, "InstallColorProfileA() failed (%d)\n", GetLastError() );
1272
1273         ret = pGetColorDirectoryA( NULL, dest, &size );
1274         ok( ret, "GetColorDirectoryA() failed (%d)\n", GetLastError() );
1275
1276         MSCMS_basenameA( testprofile, base );
1277
1278         lstrcatA( dest, slash );
1279         lstrcatA( dest, base );
1280
1281         ret = pUninstallColorProfileA( NULL, dest, TRUE );
1282         ok( ret, "UninstallColorProfileA() failed (%d)\n", GetLastError() );
1283
1284         /* Check if the profile is really gone */
1285         handle = CreateFileA( dest, 0 , 0, NULL, OPEN_EXISTING, 0, NULL );
1286         ok( handle == INVALID_HANDLE_VALUE, "Found the profile (%d)\n", GetLastError() );
1287         CloseHandle( handle );
1288     }
1289 }
1290
1291 static void test_UninstallColorProfileW(void)
1292 {
1293     BOOL ret;
1294
1295     /* Parameter checks */
1296
1297     ret = pUninstallColorProfileW( NULL, NULL, FALSE );
1298     ok( !ret, "UninstallColorProfileW() succeeded (%d)\n", GetLastError() );
1299
1300     ret = pUninstallColorProfileW( machineW, NULL, FALSE );
1301     ok( !ret, "UninstallColorProfileW() succeeded (%d)\n", GetLastError() );
1302
1303     /* Functional checks */
1304
1305     if (testprofileW)
1306     {
1307         WCHAR dest[MAX_PATH], base[MAX_PATH];
1308         char destA[MAX_PATH];
1309         DWORD size = sizeof(dest);
1310         WCHAR slash[] = { '\\', 0 };
1311         HANDLE handle;
1312         int bytes_copied;
1313
1314         SetLastError(0xdeadbeef);
1315         ret = pInstallColorProfileW( NULL, testprofileW );
1316         if (!ret && (GetLastError() == ERROR_ACCESS_DENIED))
1317         {
1318             skip("Not enough rights for InstallColorProfileW\n");
1319             return;
1320         }
1321         ok( ret, "InstallColorProfileW() failed (%d)\n", GetLastError() );
1322
1323         ret = pGetColorDirectoryW( NULL, dest, &size );
1324         ok( ret, "GetColorDirectoryW() failed (%d)\n", GetLastError() );
1325
1326         MSCMS_basenameW( testprofileW, base );
1327
1328         lstrcatW( dest, slash );
1329         lstrcatW( dest, base );
1330
1331         ret = pUninstallColorProfileW( NULL, dest, TRUE );
1332         ok( ret, "UninstallColorProfileW() failed (%d)\n", GetLastError() );
1333
1334         bytes_copied = WideCharToMultiByte(CP_ACP, 0, dest, -1, destA, MAX_PATH, NULL, NULL);
1335         ok( bytes_copied > 0 , "WideCharToMultiByte() returns %d\n", bytes_copied);
1336         /* Check if the profile is really gone */
1337         handle = CreateFileA( destA, 0 , 0, NULL, OPEN_EXISTING, 0, NULL );
1338         ok( handle == INVALID_HANDLE_VALUE, "Found the profile (%d)\n", GetLastError() );
1339         CloseHandle( handle );
1340     }
1341 }
1342
1343 START_TEST(profile)
1344 {
1345     UINT len;
1346     HANDLE handle;
1347     char path[MAX_PATH], file[MAX_PATH];
1348     char profilefile1[MAX_PATH], profilefile2[MAX_PATH];
1349     WCHAR profilefile1W[MAX_PATH], profilefile2W[MAX_PATH];
1350     WCHAR fileW[MAX_PATH];
1351     UINT ret;
1352
1353     hmscms = LoadLibraryA( "mscms.dll" );
1354     if (!hmscms) return;
1355
1356     if (!init_function_ptrs())
1357     {
1358         FreeLibrary( hmscms );
1359         return;
1360     }
1361
1362     /* See if we can find the standard color profile */
1363     ret = GetSystemDirectoryA( profilefile1, sizeof(profilefile1) );
1364     ok( ret > 0, "GetSystemDirectoryA() returns %d, LastError = %d\n", ret, GetLastError());
1365     ok( lstrlenA(profilefile1) > 0 && lstrlenA(profilefile1) < MAX_PATH, 
1366         "GetSystemDirectoryA() returns %d, LastError = %d\n", ret, GetLastError());
1367     MultiByteToWideChar(CP_ACP, 0, profilefile1, -1, profilefile1W, MAX_PATH);
1368     ok( lstrlenW(profilefile1W) > 0 && lstrlenW(profilefile1W) < MAX_PATH, 
1369         "GetSystemDirectoryA() returns %d, LastError = %d\n", ret, GetLastError());
1370     lstrcpyA(profilefile2, profilefile1);
1371     lstrcpyW(profilefile2W, profilefile1W);
1372
1373     lstrcatA( profilefile1, profile1 );
1374     lstrcatW( profilefile1W, profile1W );
1375     handle = CreateFileA( profilefile1, 0 , 0, NULL, OPEN_EXISTING, 0, NULL );
1376
1377     if (handle != INVALID_HANDLE_VALUE)
1378     {
1379         standardprofile = profilefile1;
1380         standardprofileW = profilefile1W;
1381         CloseHandle( handle );
1382     }
1383
1384     lstrcatA( profilefile2, profile2 );
1385     lstrcatW( profilefile2W, profile2W );
1386     handle = CreateFileA( profilefile2, 0 , 0, NULL, OPEN_EXISTING, 0, NULL );
1387
1388     if (handle != INVALID_HANDLE_VALUE)
1389     {
1390         standardprofile = profilefile2;
1391         standardprofileW = profilefile2W;
1392         CloseHandle( handle );
1393     }
1394
1395     /* If found, create a temporary copy for testing purposes */
1396     if (standardprofile && GetTempPath( sizeof(path), path ))
1397     {
1398         if (GetTempFileName( path, "rgb", 0, file ))
1399         {
1400             if (CopyFileA( standardprofile, file, FALSE ))
1401             {
1402                 testprofile = (LPSTR)&file;
1403
1404                 len = MultiByteToWideChar( CP_ACP, 0, testprofile, -1, NULL, 0 );
1405                 MultiByteToWideChar( CP_ACP, 0, testprofile, -1, fileW, len );
1406
1407                 testprofileW = (LPWSTR)&fileW;
1408             }
1409         }
1410     }
1411
1412     test_GetColorDirectoryA();
1413     test_GetColorDirectoryW();
1414
1415     test_GetColorProfileElement();
1416     test_GetColorProfileElementTag();
1417
1418     test_GetColorProfileFromHandle();
1419     test_GetColorProfileHeader();
1420
1421     test_GetCountColorProfileElements();
1422
1423     enum_registered_color_profiles();
1424     check_registry();
1425
1426     test_GetStandardColorSpaceProfileA();
1427     test_GetStandardColorSpaceProfileW();
1428
1429     test_EnumColorProfilesA();
1430     test_EnumColorProfilesW();
1431
1432     test_InstallColorProfileA();
1433     test_InstallColorProfileW();
1434
1435     test_IsColorProfileTagPresent();
1436
1437     test_OpenColorProfileA();
1438     test_OpenColorProfileW();
1439
1440     test_SetColorProfileElement();
1441     test_SetColorProfileHeader();
1442
1443     test_UninstallColorProfileA();
1444     test_UninstallColorProfileW();
1445
1446     /* Clean up */
1447     if (testprofile)
1448         DeleteFileA( testprofile );
1449     
1450     FreeLibrary( hmscms );
1451 }