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