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