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