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