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