wintrust: Add a helper function to initialize chain creation parameters.
[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 total, size, number;
764     ENUMTYPEA record;
765     BYTE *buffer;
766
767     /* Parameter checks */
768
769     memset( &record, 0, sizeof(ENUMTYPEA) );
770
771     record.dwSize = sizeof(ENUMTYPEA);
772     record.dwVersion = ENUM_TYPE_VERSION;
773     record.dwFields |= ET_DATACOLORSPACE;
774     record.dwDataColorSpace = SPACE_RGB;
775
776     total = 0;
777     ret = pEnumColorProfilesA( NULL, &record, NULL, &total, &number );
778     ok( !ret, "EnumColorProfilesA() failed (%d)\n", GetLastError() );
779     buffer = HeapAlloc( GetProcessHeap(), 0, total );
780
781     size = total;
782     ret = pEnumColorProfilesA( machine, &record, buffer, &size, &number );
783     ok( !ret, "EnumColorProfilesA() succeeded (%d)\n", GetLastError() );
784
785     ret = pEnumColorProfilesA( NULL, NULL, buffer, &size, &number );
786     ok( !ret, "EnumColorProfilesA() succeeded (%d)\n", GetLastError() );
787
788     ret = pEnumColorProfilesA( NULL, &record, buffer, NULL, &number );
789     ok( !ret, "EnumColorProfilesA() succeeded (%d)\n", GetLastError() );
790
791     if (standardprofile)
792     {
793         ret = pEnumColorProfilesA( NULL, &record, buffer, &size, &number );
794         ok( ret, "EnumColorProfilesA() failed (%d)\n", GetLastError() );
795     }
796
797     size = 0;
798
799     ret = pEnumColorProfilesA( NULL, &record, buffer, &size, &number );
800     ok( !ret, "EnumColorProfilesA() succeeded (%d)\n", GetLastError() );
801
802     /* Functional checks */
803
804     if (standardprofile)
805     {
806         size = total;
807
808         ret = pEnumColorProfilesA( NULL, &record, buffer, &size, &number );
809         ok( ret, "EnumColorProfilesA() failed (%d)\n", GetLastError() );
810     }
811     HeapFree( GetProcessHeap(), 0, buffer );
812 }
813
814 static void test_EnumColorProfilesW(void)
815 {
816     BOOL ret;
817     DWORD total, size, number;
818     ENUMTYPEW record;
819     BYTE *buffer;
820
821     /* Parameter checks */
822
823     memset( &record, 0, sizeof(ENUMTYPEW) );
824
825     record.dwSize = sizeof(ENUMTYPEW);
826     record.dwVersion = ENUM_TYPE_VERSION;
827     record.dwFields |= ET_DATACOLORSPACE;
828     record.dwDataColorSpace = SPACE_RGB;
829
830     total = 0;
831     ret = pEnumColorProfilesW( NULL, &record, NULL, &total, &number );
832     ok( !ret, "EnumColorProfilesW() failed (%d)\n", GetLastError() );
833     buffer = HeapAlloc( GetProcessHeap(), 0, total * sizeof(WCHAR) );
834
835     size = total;
836     ret = pEnumColorProfilesW( machineW, &record, buffer, &size, &number );
837     ok( !ret, "EnumColorProfilesW() succeeded (%d)\n", GetLastError() );
838
839     ret = pEnumColorProfilesW( NULL, NULL, buffer, &size, &number );
840     ok( !ret, "EnumColorProfilesW() succeeded (%d)\n", GetLastError() );
841
842     ret = pEnumColorProfilesW( NULL, &record, buffer, NULL, &number );
843     ok( !ret, "EnumColorProfilesW() succeeded (%d)\n", GetLastError() );
844
845     if (standardprofileW)
846     {
847         ret = pEnumColorProfilesW( NULL, &record, buffer, &size, &number );
848         ok( ret, "EnumColorProfilesW() failed (%d)\n", GetLastError() );
849     }
850
851     size = 0;
852
853     ret = pEnumColorProfilesW( NULL, &record, buffer, &size, &number );
854     ok( !ret, "EnumColorProfilesW() succeeded (%d)\n", GetLastError() );
855
856     /* Functional checks */
857
858     if (standardprofileW)
859     {
860         size = total;
861
862         ret = pEnumColorProfilesW( NULL, &record, buffer, &size, &number );
863         ok( ret, "EnumColorProfilesW() failed (%d)\n", GetLastError() );
864     }
865     HeapFree( GetProcessHeap(), 0, buffer );
866 }
867
868 static void test_InstallColorProfileA(void)
869 {
870     BOOL ret;
871
872     /* Parameter checks */
873
874     ret = pInstallColorProfileA( NULL, NULL );
875     ok( !ret, "InstallColorProfileA() succeeded (%d)\n", GetLastError() );
876
877     ret = pInstallColorProfileA( machine, NULL );
878     ok( !ret, "InstallColorProfileA() succeeded (%d)\n", GetLastError() );
879
880     ret = pInstallColorProfileA( NULL, machine );
881     ok( !ret, "InstallColorProfileA() succeeded (%d)\n", GetLastError() );
882
883     if (standardprofile)
884     {
885         ret = pInstallColorProfileA( NULL, standardprofile );
886         ok( ret, "InstallColorProfileA() failed (%d)\n", GetLastError() );
887     }
888
889     /* Functional checks */
890
891     if (testprofile)
892     {
893         CHAR dest[MAX_PATH], base[MAX_PATH];
894         DWORD size = sizeof(dest);
895         CHAR slash[] = "\\";
896         HANDLE handle;
897
898         SetLastError(0xdeadbeef);
899         ret = pInstallColorProfileA( NULL, testprofile );
900         if (!ret && (GetLastError() == ERROR_ACCESS_DENIED))
901         {
902             skip("Not enough rights for InstallColorProfileA\n");
903             return;
904         }
905         ok( ret, "InstallColorProfileA() failed (%d)\n", GetLastError() );
906
907         ret = pGetColorDirectoryA( NULL, dest, &size );
908         ok( ret, "GetColorDirectoryA() failed (%d)\n", GetLastError() );
909
910         MSCMS_basenameA( testprofile, base );
911
912         lstrcatA( dest, slash );
913         lstrcatA( dest, base );
914
915         /* Check if the profile is really there */ 
916         handle = CreateFileA( dest, 0 , 0, NULL, OPEN_EXISTING, 0, NULL );
917         ok( handle != INVALID_HANDLE_VALUE, "Couldn't find the profile (%d)\n", GetLastError() );
918         CloseHandle( handle );
919         
920         ret = pUninstallColorProfileA( NULL, dest, TRUE );
921         ok( ret, "UninstallColorProfileA() failed (%d)\n", GetLastError() );
922     }
923 }
924
925 static void test_InstallColorProfileW(void)
926 {
927     BOOL ret;
928
929     /* Parameter checks */
930
931     ret = pInstallColorProfileW( NULL, NULL );
932     ok( !ret, "InstallColorProfileW() succeeded (%d)\n", GetLastError() );
933
934     ret = pInstallColorProfileW( machineW, NULL );
935     ok( !ret, "InstallColorProfileW() succeeded (%d)\n", GetLastError() );
936
937     ret = pInstallColorProfileW( NULL, machineW );
938     ok( !ret, "InstallColorProfileW() failed (%d)\n", GetLastError() );
939
940     if (standardprofileW)
941     {
942         ret = pInstallColorProfileW( NULL, standardprofileW );
943         ok( ret, "InstallColorProfileW() failed (%d)\n", GetLastError() );
944     }
945
946     /* Functional checks */
947
948     if (testprofileW)
949     {
950         WCHAR dest[MAX_PATH], base[MAX_PATH];
951         DWORD size = sizeof(dest);
952         WCHAR slash[] = { '\\', 0 };
953         HANDLE handle;
954
955         SetLastError(0xdeadbeef);
956         ret = pInstallColorProfileW( NULL, testprofileW );
957         if (!ret && (GetLastError() == ERROR_ACCESS_DENIED))
958         {
959             skip("Not enough rights for InstallColorProfileW\n");
960             return;
961         }
962         ok( ret, "InstallColorProfileW() failed (%d)\n", GetLastError() );
963
964         ret = pGetColorDirectoryW( NULL, dest, &size );
965         ok( ret, "GetColorDirectoryW() failed (%d)\n", GetLastError() );
966
967         MSCMS_basenameW( testprofileW, base );
968
969         lstrcatW( dest, slash );
970         lstrcatW( dest, base );
971
972         /* Check if the profile is really there */
973         handle = CreateFileW( dest, 0 , 0, NULL, OPEN_EXISTING, 0, NULL );
974         ok( handle != INVALID_HANDLE_VALUE, "Couldn't find the profile (%d)\n", GetLastError() );
975         CloseHandle( handle );
976
977         ret = pUninstallColorProfileW( NULL, dest, TRUE );
978         ok( ret, "UninstallColorProfileW() failed (%d)\n", GetLastError() );
979     }
980 }
981
982 static void test_IsColorProfileTagPresent(void)
983 {
984     if (standardprofile)
985     {
986         PROFILE profile;
987         HPROFILE handle;
988         BOOL ret, present;
989         TAGTYPE tag;
990
991         profile.dwType = PROFILE_FILENAME;
992         profile.pProfileData = standardprofile;
993         profile.cbDataSize = strlen(standardprofile);
994
995         handle = pOpenColorProfileA( &profile, PROFILE_READ, 0, OPEN_EXISTING );
996         ok( handle != NULL, "OpenColorProfileA() failed (%d)\n", GetLastError() );
997
998         /* Parameter checks */
999
1000         tag = 0;
1001
1002         ret = pIsColorProfileTagPresent( handle, tag, &present );
1003         ok( !(ret && present), "IsColorProfileTagPresent() succeeded (%d)\n", GetLastError() );
1004
1005         tag = 0x63707274;  /* 'cprt' */
1006
1007         ret = pIsColorProfileTagPresent( NULL, tag, &present );
1008         ok( !ret, "IsColorProfileTagPresent() succeeded (%d)\n", GetLastError() );
1009
1010         ret = pIsColorProfileTagPresent( handle, tag, NULL );
1011         ok( !ret, "IsColorProfileTagPresent() succeeded (%d)\n", GetLastError() );
1012
1013         /* Functional checks */
1014
1015         ret = pIsColorProfileTagPresent( handle, tag, &present );
1016         ok( ret && present, "IsColorProfileTagPresent() failed (%d)\n", GetLastError() );
1017
1018         pCloseColorProfile( handle );
1019     }
1020 }
1021
1022 static void test_OpenColorProfileA(void)
1023 {
1024     PROFILE profile;
1025     HPROFILE handle;
1026     BOOL ret;
1027
1028     profile.dwType = PROFILE_FILENAME;
1029     profile.pProfileData = NULL;
1030     profile.cbDataSize = 0;
1031
1032     /* Parameter checks */
1033
1034     handle = pOpenColorProfileA( NULL, 0, 0, 0 );
1035     ok( handle == NULL, "OpenColorProfileA() failed (%d)\n", GetLastError() );
1036
1037     handle = pOpenColorProfileA( &profile, 0, 0, 0 );
1038     ok( handle == NULL, "OpenColorProfileA() failed (%d)\n", GetLastError() );
1039
1040     handle = pOpenColorProfileA( &profile, PROFILE_READ, 0, 0 );
1041     ok( handle == NULL, "OpenColorProfileA() failed (%d)\n", GetLastError() );
1042
1043     handle = pOpenColorProfileA( &profile, PROFILE_READWRITE, 0, 0 );
1044     ok( handle == NULL, "OpenColorProfileA() failed (%d)\n", GetLastError() );
1045
1046     ok ( !pCloseColorProfile( NULL ), "CloseColorProfile() succeeded\n" );
1047
1048     if (standardprofile)
1049     {
1050         profile.pProfileData = standardprofile;
1051         profile.cbDataSize = strlen(standardprofile);
1052
1053         handle = pOpenColorProfileA( &profile, 0, 0, 0 );
1054         ok( handle == NULL, "OpenColorProfileA() failed (%d)\n", GetLastError() );
1055
1056         handle = pOpenColorProfileA( &profile, PROFILE_READ, 0, 0 );
1057         ok( handle == NULL, "OpenColorProfileA() failed (%d)\n", GetLastError() );
1058
1059         handle = pOpenColorProfileA( &profile, PROFILE_READ|PROFILE_READWRITE, 0, 0 );
1060         ok( handle == NULL, "OpenColorProfileA() failed (%d)\n", GetLastError() );
1061
1062         /* Functional checks */
1063
1064         handle = pOpenColorProfileA( &profile, PROFILE_READ, 0, OPEN_EXISTING );
1065         ok( handle != NULL, "OpenColorProfileA() failed (%d)\n", GetLastError() );
1066
1067         ret = pCloseColorProfile( handle );
1068         ok( ret, "CloseColorProfile() failed (%d)\n", GetLastError() );
1069     }
1070 }
1071
1072 static void test_OpenColorProfileW(void)
1073 {
1074     PROFILE profile;
1075     HPROFILE handle;
1076     BOOL ret;
1077
1078     profile.dwType = PROFILE_FILENAME;
1079     profile.pProfileData = NULL;
1080     profile.cbDataSize = 0;
1081
1082     /* Parameter checks */
1083
1084     handle = pOpenColorProfileW( NULL, 0, 0, 0 );
1085     ok( handle == NULL, "OpenColorProfileW() failed (%d)\n", GetLastError() );
1086
1087     handle = pOpenColorProfileW( &profile, 0, 0, 0 );
1088     ok( handle == NULL, "OpenColorProfileW() failed (%d)\n", GetLastError() );
1089
1090     handle = pOpenColorProfileW( &profile, PROFILE_READ, 0, 0 );
1091     ok( handle == NULL, "OpenColorProfileW() failed (%d)\n", GetLastError() );
1092
1093     handle = pOpenColorProfileW( &profile, PROFILE_READWRITE, 0, 0 );
1094     ok( handle == NULL, "OpenColorProfileW() failed (%d)\n", GetLastError() );
1095
1096     ok ( !pCloseColorProfile( NULL ), "CloseColorProfile() succeeded\n" );
1097
1098     if (standardprofileW)
1099     {
1100         profile.pProfileData = standardprofileW;
1101         profile.cbDataSize = lstrlenW(standardprofileW) * sizeof(WCHAR);
1102
1103         handle = pOpenColorProfileW( &profile, 0, 0, 0 );
1104         ok( handle == NULL, "OpenColorProfileW() failed (%d)\n", GetLastError() );
1105
1106         handle = pOpenColorProfileW( &profile, PROFILE_READ, 0, 0 );
1107         ok( handle == NULL, "OpenColorProfileW() failed (%d)\n", GetLastError() );
1108
1109         handle = pOpenColorProfileW( &profile, PROFILE_READ|PROFILE_READWRITE, 0, 0 );
1110         ok( handle == NULL, "OpenColorProfileW() failed (%d)\n", GetLastError() );
1111
1112         /* Functional checks */
1113
1114         handle = pOpenColorProfileW( &profile, PROFILE_READ, 0, OPEN_EXISTING );
1115         ok( handle != NULL, "OpenColorProfileW() failed (%d)\n", GetLastError() );
1116
1117         ret = pCloseColorProfile( handle );
1118         ok( ret, "CloseColorProfile() failed (%d)\n", GetLastError() );
1119     }
1120 }
1121
1122 static void test_SetColorProfileElement(void)
1123 {
1124     if (testprofile)
1125     {
1126         PROFILE profile;
1127         HPROFILE handle;
1128         DWORD size;
1129         BOOL ret, ref;
1130
1131         TAGTYPE tag = 0x63707274;  /* 'cprt' */
1132         static char data[] = "(c) The Wine Project";
1133         static char buffer[51];
1134
1135         profile.dwType = PROFILE_FILENAME;
1136         profile.pProfileData = testprofile;
1137         profile.cbDataSize = strlen(testprofile);
1138
1139         /* Parameter checks */
1140
1141         handle = pOpenColorProfileA( &profile, PROFILE_READ, 0, OPEN_EXISTING );
1142         ok( handle != NULL, "OpenColorProfileA() failed (%d)\n", GetLastError() );
1143
1144         ret = pSetColorProfileElement( handle, tag, 0, &size, data );
1145         ok( !ret, "SetColorProfileElement() succeeded (%d)\n", GetLastError() );
1146
1147         pCloseColorProfile( handle );
1148
1149         handle = pOpenColorProfileA( &profile, PROFILE_READWRITE, 0, OPEN_EXISTING );
1150         ok( handle != NULL, "OpenColorProfileA() failed (%d)\n", GetLastError() );
1151
1152         ret = pSetColorProfileElement( NULL, 0, 0, NULL, NULL );
1153         ok( !ret, "SetColorProfileElement() succeeded (%d)\n", GetLastError() );
1154
1155         ret = pSetColorProfileElement( handle, 0, 0, NULL, NULL );
1156         ok( !ret, "SetColorProfileElement() succeeded (%d)\n", GetLastError() );
1157
1158         ret = pSetColorProfileElement( handle, tag, 0, NULL, NULL );
1159         ok( !ret, "SetColorProfileElement() succeeded (%d)\n", GetLastError() );
1160
1161         ret = pSetColorProfileElement( handle, tag, 0, &size, NULL );
1162         ok( !ret, "SetColorProfileElement() succeeded (%d)\n", GetLastError() );
1163
1164         /* Functional checks */
1165
1166         size = sizeof(data);
1167
1168         ret = pSetColorProfileElement( handle, tag, 0, &size, data );
1169         ok( ret, "SetColorProfileElement() failed (%d)\n", GetLastError() );
1170
1171         size = sizeof(buffer);
1172
1173         ret = pGetColorProfileElement( handle, tag, 0, &size, buffer, &ref );
1174         ok( ret && size > 0, "GetColorProfileElement() failed (%d)\n", GetLastError() );
1175
1176         ok( !memcmp( data, buffer, sizeof(data) ),
1177             "Unexpected tag data, expected %s, got %s (%d)\n",
1178             data, buffer, GetLastError() );
1179
1180         pCloseColorProfile( handle );
1181     }
1182 }
1183
1184 static void test_SetColorProfileHeader(void)
1185 {
1186     if (testprofile)
1187     {
1188         PROFILE profile;
1189         HPROFILE handle;
1190         BOOL ret;
1191         PROFILEHEADER header;
1192
1193         profile.dwType = PROFILE_FILENAME;
1194         profile.pProfileData = testprofile;
1195         profile.cbDataSize = strlen(testprofile);
1196
1197         header.phSize = 0x00000c48;
1198         header.phCMMType = 0x4c696e6f;
1199         header.phVersion = 0x02100000;
1200         header.phClass = 0x6d6e7472;
1201         header.phDataColorSpace = 0x52474220;
1202         header.phConnectionSpace  = 0x58595a20;
1203         header.phDateTime[0] = 0x07ce0002;
1204         header.phDateTime[1] = 0x00090006;
1205         header.phDateTime[2] = 0x00310000;
1206         header.phSignature = 0x61637370;
1207         header.phPlatform = 0x4d534654;
1208         header.phProfileFlags = 0x00000000;
1209         header.phManufacturer = 0x49454320;
1210         header.phModel = 0x73524742;
1211         header.phAttributes[0] = 0x00000000;
1212         header.phAttributes[1] = 0x00000000;
1213         header.phRenderingIntent = 0x00000000;
1214         header.phIlluminant.ciexyzX = 0x0000f6d6;
1215         header.phIlluminant.ciexyzY = 0x00010000;
1216         header.phIlluminant.ciexyzZ = 0x0000d32d;
1217         header.phCreator = 0x48502020;
1218
1219         /* Parameter checks */
1220
1221         handle = pOpenColorProfileA( &profile, PROFILE_READ, 0, OPEN_EXISTING );
1222         ok( handle != NULL, "OpenColorProfileA() failed (%d)\n", GetLastError() );
1223
1224         ret = pSetColorProfileHeader( handle, &header );
1225         ok( !ret, "SetColorProfileHeader() succeeded (%d)\n", GetLastError() );
1226
1227         pCloseColorProfile( handle );
1228
1229         handle = pOpenColorProfileA( &profile, PROFILE_READWRITE, 0, OPEN_EXISTING );
1230         ok( handle != NULL, "OpenColorProfileA() failed (%d)\n", GetLastError() );
1231
1232         ret = pSetColorProfileHeader( NULL, NULL );
1233         ok( !ret, "SetColorProfileHeader() succeeded (%d)\n", GetLastError() );
1234
1235         ret = pSetColorProfileHeader( handle, NULL );
1236         ok( !ret, "SetColorProfileHeader() succeeded (%d)\n", GetLastError() );
1237
1238         ret = pSetColorProfileHeader( NULL, &header );
1239         ok( !ret, "SetColorProfileHeader() succeeded (%d)\n", GetLastError() );
1240
1241         /* Functional checks */
1242
1243         ret = pSetColorProfileHeader( handle, &header );
1244         ok( ret, "SetColorProfileHeader() failed (%d)\n", GetLastError() );
1245
1246         ret = pGetColorProfileHeader( handle, &header );
1247         ok( ret, "GetColorProfileHeader() failed (%d)\n", GetLastError() );
1248
1249         ok( !memcmp( &header, rgbheader, sizeof(rgbheader) ), "Unexpected header data\n" );
1250
1251         pCloseColorProfile( handle );
1252     }
1253 }
1254
1255 static void test_UninstallColorProfileA(void)
1256 {
1257     BOOL ret;
1258
1259     /* Parameter checks */
1260
1261     ret = pUninstallColorProfileA( NULL, NULL, FALSE );
1262     ok( !ret, "UninstallColorProfileA() succeeded (%d)\n", GetLastError() );
1263
1264     ret = pUninstallColorProfileA( machine, NULL, FALSE );
1265     ok( !ret, "UninstallColorProfileA() succeeded (%d)\n", GetLastError() );
1266
1267     /* Functional checks */
1268
1269     if (testprofile)
1270     {
1271         CHAR dest[MAX_PATH], base[MAX_PATH];
1272         DWORD size = sizeof(dest);
1273         CHAR slash[] = "\\";
1274         HANDLE handle;
1275
1276         SetLastError(0xdeadbeef);
1277         ret = pInstallColorProfileA( NULL, testprofile );
1278         if (!ret && (GetLastError() == ERROR_ACCESS_DENIED))
1279         {
1280             skip("Not enough rights for InstallColorProfileA\n");
1281             return;
1282         }
1283         ok( ret, "InstallColorProfileA() failed (%d)\n", GetLastError() );
1284
1285         ret = pGetColorDirectoryA( NULL, dest, &size );
1286         ok( ret, "GetColorDirectoryA() failed (%d)\n", GetLastError() );
1287
1288         MSCMS_basenameA( testprofile, base );
1289
1290         lstrcatA( dest, slash );
1291         lstrcatA( dest, base );
1292
1293         ret = pUninstallColorProfileA( NULL, dest, TRUE );
1294         ok( ret, "UninstallColorProfileA() failed (%d)\n", GetLastError() );
1295
1296         /* Check if the profile is really gone */
1297         handle = CreateFileA( dest, 0 , 0, NULL, OPEN_EXISTING, 0, NULL );
1298         ok( handle == INVALID_HANDLE_VALUE, "Found the profile (%d)\n", GetLastError() );
1299         CloseHandle( handle );
1300     }
1301 }
1302
1303 static void test_UninstallColorProfileW(void)
1304 {
1305     BOOL ret;
1306
1307     /* Parameter checks */
1308
1309     ret = pUninstallColorProfileW( NULL, NULL, FALSE );
1310     ok( !ret, "UninstallColorProfileW() succeeded (%d)\n", GetLastError() );
1311
1312     ret = pUninstallColorProfileW( machineW, NULL, FALSE );
1313     ok( !ret, "UninstallColorProfileW() succeeded (%d)\n", GetLastError() );
1314
1315     /* Functional checks */
1316
1317     if (testprofileW)
1318     {
1319         WCHAR dest[MAX_PATH], base[MAX_PATH];
1320         char destA[MAX_PATH];
1321         DWORD size = sizeof(dest);
1322         WCHAR slash[] = { '\\', 0 };
1323         HANDLE handle;
1324         int bytes_copied;
1325
1326         SetLastError(0xdeadbeef);
1327         ret = pInstallColorProfileW( NULL, testprofileW );
1328         if (!ret && (GetLastError() == ERROR_ACCESS_DENIED))
1329         {
1330             skip("Not enough rights for InstallColorProfileW\n");
1331             return;
1332         }
1333         ok( ret, "InstallColorProfileW() failed (%d)\n", GetLastError() );
1334
1335         ret = pGetColorDirectoryW( NULL, dest, &size );
1336         ok( ret, "GetColorDirectoryW() failed (%d)\n", GetLastError() );
1337
1338         MSCMS_basenameW( testprofileW, base );
1339
1340         lstrcatW( dest, slash );
1341         lstrcatW( dest, base );
1342
1343         ret = pUninstallColorProfileW( NULL, dest, TRUE );
1344         ok( ret, "UninstallColorProfileW() failed (%d)\n", GetLastError() );
1345
1346         bytes_copied = WideCharToMultiByte(CP_ACP, 0, dest, -1, destA, MAX_PATH, NULL, NULL);
1347         ok( bytes_copied > 0 , "WideCharToMultiByte() returns %d\n", bytes_copied);
1348         /* Check if the profile is really gone */
1349         handle = CreateFileA( destA, 0 , 0, NULL, OPEN_EXISTING, 0, NULL );
1350         ok( handle == INVALID_HANDLE_VALUE, "Found the profile (%d)\n", GetLastError() );
1351         CloseHandle( handle );
1352     }
1353 }
1354
1355 START_TEST(profile)
1356 {
1357     UINT len;
1358     HANDLE handle;
1359     char path[MAX_PATH], file[MAX_PATH];
1360     char profilefile1[MAX_PATH], profilefile2[MAX_PATH];
1361     WCHAR profilefile1W[MAX_PATH], profilefile2W[MAX_PATH];
1362     WCHAR fileW[MAX_PATH];
1363     UINT ret;
1364
1365     hmscms = LoadLibraryA( "mscms.dll" );
1366     if (!hmscms) return;
1367
1368     if (!init_function_ptrs())
1369     {
1370         FreeLibrary( hmscms );
1371         return;
1372     }
1373
1374     /* See if we can find the standard color profile */
1375     ret = GetSystemDirectoryA( profilefile1, sizeof(profilefile1) );
1376     ok( ret > 0, "GetSystemDirectoryA() returns %d, LastError = %d\n", ret, GetLastError());
1377     ok( lstrlenA(profilefile1) > 0 && lstrlenA(profilefile1) < MAX_PATH, 
1378         "GetSystemDirectoryA() returns %d, LastError = %d\n", ret, GetLastError());
1379     MultiByteToWideChar(CP_ACP, 0, profilefile1, -1, profilefile1W, MAX_PATH);
1380     ok( lstrlenW(profilefile1W) > 0 && lstrlenW(profilefile1W) < MAX_PATH, 
1381         "GetSystemDirectoryA() returns %d, LastError = %d\n", ret, GetLastError());
1382     lstrcpyA(profilefile2, profilefile1);
1383     lstrcpyW(profilefile2W, profilefile1W);
1384
1385     lstrcatA( profilefile1, profile1 );
1386     lstrcatW( profilefile1W, profile1W );
1387     handle = CreateFileA( profilefile1, 0 , 0, NULL, OPEN_EXISTING, 0, NULL );
1388
1389     if (handle != INVALID_HANDLE_VALUE)
1390     {
1391         standardprofile = profilefile1;
1392         standardprofileW = profilefile1W;
1393         CloseHandle( handle );
1394     }
1395
1396     lstrcatA( profilefile2, profile2 );
1397     lstrcatW( profilefile2W, profile2W );
1398     handle = CreateFileA( profilefile2, 0 , 0, NULL, OPEN_EXISTING, 0, NULL );
1399
1400     if (handle != INVALID_HANDLE_VALUE)
1401     {
1402         standardprofile = profilefile2;
1403         standardprofileW = profilefile2W;
1404         CloseHandle( handle );
1405     }
1406
1407     /* If found, create a temporary copy for testing purposes */
1408     if (standardprofile && GetTempPath( sizeof(path), path ))
1409     {
1410         if (GetTempFileName( path, "rgb", 0, file ))
1411         {
1412             if (CopyFileA( standardprofile, file, FALSE ))
1413             {
1414                 testprofile = (LPSTR)&file;
1415
1416                 len = MultiByteToWideChar( CP_ACP, 0, testprofile, -1, NULL, 0 );
1417                 MultiByteToWideChar( CP_ACP, 0, testprofile, -1, fileW, len );
1418
1419                 testprofileW = (LPWSTR)&fileW;
1420             }
1421         }
1422     }
1423
1424     test_GetColorDirectoryA();
1425     test_GetColorDirectoryW();
1426
1427     test_GetColorProfileElement();
1428     test_GetColorProfileElementTag();
1429
1430     test_GetColorProfileFromHandle();
1431     test_GetColorProfileHeader();
1432
1433     test_GetCountColorProfileElements();
1434
1435     enum_registered_color_profiles();
1436     check_registry();
1437
1438     test_GetStandardColorSpaceProfileA();
1439     test_GetStandardColorSpaceProfileW();
1440
1441     test_EnumColorProfilesA();
1442     test_EnumColorProfilesW();
1443
1444     test_InstallColorProfileA();
1445     test_InstallColorProfileW();
1446
1447     test_IsColorProfileTagPresent();
1448
1449     test_OpenColorProfileA();
1450     test_OpenColorProfileW();
1451
1452     test_SetColorProfileElement();
1453     test_SetColorProfileHeader();
1454
1455     test_UninstallColorProfileA();
1456     test_UninstallColorProfileW();
1457
1458     /* Clean up */
1459     if (testprofile)
1460         DeleteFileA( testprofile );
1461     
1462     FreeLibrary( hmscms );
1463 }