palette.c 29.5 KB
Newer Older
Alexandre Julliard's avatar
Alexandre Julliard committed
1 2 3
/*
 * GDI palette objects
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
4
 * Copyright 1993,1994 Alexandre Julliard
Alexandre Julliard's avatar
Alexandre Julliard committed
5
 * Copyright 1996 Alex Korobka
Alexandre Julliard's avatar
Alexandre Julliard committed
6
 *
7 8 9 10 11 12 13 14 15 16 17 18
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 21
 *
 * NOTES:
Alexandre Julliard's avatar
Alexandre Julliard committed
22 23
 * PALETTEOBJ is documented in the Dr. Dobbs Journal May 1993.
 * Information in the "Undocumented Windows" is incorrect.
Alexandre Julliard's avatar
Alexandre Julliard committed
24
 */
Alexandre Julliard's avatar
Alexandre Julliard committed
25

26
#include <stdarg.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
27
#include <stdlib.h>
Alexandre Julliard's avatar
Alexandre Julliard committed
28
#include <string.h>
29

30
#include "windef.h"
31
#include "winbase.h"
32
#include "wingdi.h"
Michael Stefaniuc's avatar
Michael Stefaniuc committed
33
#include "wownt32.h"
34
#include "wine/winuser16.h"
35
#include "gdi_private.h"
36
#include "wine/debug.h"
37
#include "winerror.h"
Alexandre Julliard's avatar
Alexandre Julliard committed
38

39
WINE_DEFAULT_DEBUG_CHANNEL(palette);
40

41 42 43 44 45 46 47
typedef struct tagPALETTEOBJ
{
    GDIOBJHDR           header;
    const DC_FUNCTIONS *funcs;      /* DC function table */
    LOGPALETTE          logpalette; /* _MUST_ be the last field */
} PALETTEOBJ;

48 49 50 51 52 53 54 55 56 57 58 59 60 61
static INT PALETTE_GetObject( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
static BOOL PALETTE_UnrealizeObject( HGDIOBJ handle, void *obj );
static BOOL PALETTE_DeleteObject( HGDIOBJ handle, void *obj );

static const struct gdi_obj_funcs palette_funcs =
{
    NULL,                     /* pSelectObject */
    PALETTE_GetObject,        /* pGetObject16 */
    PALETTE_GetObject,        /* pGetObjectA */
    PALETTE_GetObject,        /* pGetObjectW */
    PALETTE_UnrealizeObject,  /* pUnrealizeObject */
    PALETTE_DeleteObject      /* pDeleteObject */
};

62 63
/* Pointers to USER implementation of SelectPalette/RealizePalette */
/* they will be patched by USER on startup */
64 65
HPALETTE (WINAPI *pfnSelectPalette)(HDC hdc, HPALETTE hpal, WORD bkgnd ) = GDISelectPalette;
UINT (WINAPI *pfnRealizePalette)(HDC hdc) = GDIRealizePalette;
Alexandre Julliard's avatar
Alexandre Julliard committed
66

67
static UINT SystemPaletteUse = SYSPAL_STATIC;  /* currently not considered */
Alexandre Julliard's avatar
Alexandre Julliard committed
68

69 70
static HPALETTE hPrimaryPalette = 0; /* used for WM_PALETTECHANGED */
static HPALETTE hLastRealizedPalette = 0; /* UnrealizeObject() needs it */
71

72 73
#define NB_RESERVED_COLORS  20   /* number of fixed colors in system palette */

74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
static const PALETTEENTRY sys_pal_template[NB_RESERVED_COLORS] =
{
    /* first 10 entries in the system palette */
    /* red  green blue  flags */
    { 0x00, 0x00, 0x00, 0 },
    { 0x80, 0x00, 0x00, 0 },
    { 0x00, 0x80, 0x00, 0 },
    { 0x80, 0x80, 0x00, 0 },
    { 0x00, 0x00, 0x80, 0 },
    { 0x80, 0x00, 0x80, 0 },
    { 0x00, 0x80, 0x80, 0 },
    { 0xc0, 0xc0, 0xc0, 0 },
    { 0xc0, 0xdc, 0xc0, 0 },
    { 0xa6, 0xca, 0xf0, 0 },

    /* ... c_min/2 dynamic colorcells */

    /* ... gap (for sparse palettes) */

    /* ... c_min/2 dynamic colorcells */

    { 0xff, 0xfb, 0xf0, 0 },
    { 0xa0, 0xa0, 0xa4, 0 },
    { 0x80, 0x80, 0x80, 0 },
    { 0xff, 0x00, 0x00, 0 },
    { 0x00, 0xff, 0x00, 0 },
    { 0xff, 0xff, 0x00, 0 },
    { 0x00, 0x00, 0xff, 0 },
    { 0xff, 0x00, 0xff, 0 },
    { 0x00, 0xff, 0xff, 0 },
    { 0xff, 0xff, 0xff, 0 }     /* last 10 */
};
Alexandre Julliard's avatar
Alexandre Julliard committed
106

Alexandre Julliard's avatar
Alexandre Julliard committed
107 108 109 110 111
/***********************************************************************
 *           PALETTE_Init
 *
 * Create the system palette.
 */
112
HPALETTE PALETTE_Init(void)
Alexandre Julliard's avatar
Alexandre Julliard committed
113
{
114
    HPALETTE          hpalette;
Alexandre Julliard's avatar
Alexandre Julliard committed
115 116 117 118
    LOGPALETTE *        palPtr;

    /* create default palette (20 system colors) */

Alexandre Julliard's avatar
Alexandre Julliard committed
119 120
    palPtr = HeapAlloc( GetProcessHeap(), 0,
             sizeof(LOGPALETTE) + (NB_RESERVED_COLORS-1)*sizeof(PALETTEENTRY));
Alexandre Julliard's avatar
Alexandre Julliard committed
121 122 123 124
    if (!palPtr) return FALSE;

    palPtr->palVersion = 0x300;
    palPtr->palNumEntries = NB_RESERVED_COLORS;
125
    memcpy( palPtr->palPalEntry, sys_pal_template, sizeof(sys_pal_template) );
126
    hpalette = CreatePalette( palPtr );
127
    HeapFree( GetProcessHeap(), 0, palPtr );
Alexandre Julliard's avatar
Alexandre Julliard committed
128 129 130
    return hpalette;
}

Alexandre Julliard's avatar
Alexandre Julliard committed
131

Alexandre Julliard's avatar
Alexandre Julliard committed
132
/***********************************************************************
Jon Griffiths's avatar
Jon Griffiths committed
133 134 135
 * CreatePalette [GDI32.@]
 *
 * Creates a logical color palette.
Alexandre Julliard's avatar
Alexandre Julliard committed
136 137 138 139
 *
 * RETURNS
 *    Success: Handle to logical palette
 *    Failure: NULL
Alexandre Julliard's avatar
Alexandre Julliard committed
140
 */
141
HPALETTE WINAPI CreatePalette(
Alexandre Julliard's avatar
Alexandre Julliard committed
142
    const LOGPALETTE* palette) /* [in] Pointer to logical color palette */
Alexandre Julliard's avatar
Alexandre Julliard committed
143 144
{
    PALETTEOBJ * palettePtr;
145
    HPALETTE hpalette;
146
    int size;
147

148
    if (!palette) return 0;
149
    TRACE("entries=%i\n", palette->palNumEntries);
Alexandre Julliard's avatar
Alexandre Julliard committed
150

151 152
    size = sizeof(LOGPALETTE) + (palette->palNumEntries - 1) * sizeof(PALETTEENTRY);

153
    if (!(palettePtr = GDI_AllocObject( size + sizeof(int*) +sizeof(GDIOBJHDR),
Michael Stefaniuc's avatar
Michael Stefaniuc committed
154 155
                                        PALETTE_MAGIC, (HGDIOBJ *)&hpalette,
					&palette_funcs ))) return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
156
    memcpy( &palettePtr->logpalette, palette, size );
157
    palettePtr->funcs = NULL;
158
    GDI_ReleaseObj( hpalette );
Alexandre Julliard's avatar
Alexandre Julliard committed
159

160
    TRACE("   returning %p\n", hpalette);
Alexandre Julliard's avatar
Alexandre Julliard committed
161 162 163
    return hpalette;
}

Alexandre Julliard's avatar
Alexandre Julliard committed
164

Brad Pepers's avatar
Brad Pepers committed
165
/***********************************************************************
Jon Griffiths's avatar
Jon Griffiths committed
166 167 168
 * CreateHalftonePalette [GDI32.@]
 *
 * Creates a halftone palette.
Brad Pepers's avatar
Brad Pepers committed
169 170 171 172 173
 *
 * RETURNS
 *    Success: Handle to logical halftone palette
 *    Failure: 0
 *
Jon Griffiths's avatar
Jon Griffiths committed
174
 * FIXME: This simply creates the halftone palette derived from running
175
 *        tests on a windows NT machine. This is assuming a color depth
176
 *        of greater that 256 color. On a 256 color device the halftone
Jon Griffiths's avatar
Jon Griffiths committed
177
 *        palette will be different and this function will be incorrect
Brad Pepers's avatar
Brad Pepers committed
178
 */
179 180
HPALETTE WINAPI CreateHalftonePalette(
    HDC hdc) /* [in] Handle to device context */
Brad Pepers's avatar
Brad Pepers committed
181
{
182
    int i;
Brad Pepers's avatar
Brad Pepers committed
183 184 185 186
    struct {
	WORD Version;
	WORD NumberOfEntries;
	PALETTEENTRY aEntries[256];
187
    } Palette;
Brad Pepers's avatar
Brad Pepers committed
188

189 190
    Palette.Version = 0x300;
    Palette.NumberOfEntries = 256;
191
    GetSystemPaletteEntries(hdc, 0, 256, Palette.aEntries);
Brad Pepers's avatar
Brad Pepers committed
192

193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
    Palette.NumberOfEntries = 20;

    for (i = 0; i < Palette.NumberOfEntries; i++)
    {
        Palette.aEntries[i].peRed=0xff;
        Palette.aEntries[i].peGreen=0xff;
        Palette.aEntries[i].peBlue=0xff;
        Palette.aEntries[i].peFlags=0x00;
    }

    Palette.aEntries[0].peRed=0x00;
    Palette.aEntries[0].peBlue=0x00;
    Palette.aEntries[0].peGreen=0x00;

    /* the first 6 */
    for (i=1; i <= 6; i++)
    {
        Palette.aEntries[i].peRed=(i%2)?0x80:0;
        Palette.aEntries[i].peGreen=(i==2)?0x80:(i==3)?0x80:(i==6)?0x80:0;
        Palette.aEntries[i].peBlue=(i>3)?0x80:0;
    }
214

215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
    for (i=7;  i <= 12; i++)
    {
        switch(i)
        {
            case 7:
                Palette.aEntries[i].peRed=0xc0;
                Palette.aEntries[i].peBlue=0xc0;
                Palette.aEntries[i].peGreen=0xc0;
                break;
            case 8:
                Palette.aEntries[i].peRed=0xc0;
                Palette.aEntries[i].peGreen=0xdc;
                Palette.aEntries[i].peBlue=0xc0;
                break;
            case 9:
                Palette.aEntries[i].peRed=0xa6;
                Palette.aEntries[i].peGreen=0xca;
                Palette.aEntries[i].peBlue=0xf0;
                break;
234
            case 10:
235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257
                Palette.aEntries[i].peRed=0xff;
                Palette.aEntries[i].peGreen=0xfb;
                Palette.aEntries[i].peBlue=0xf0;
                break;
            case 11:
                Palette.aEntries[i].peRed=0xa0;
                Palette.aEntries[i].peGreen=0xa0;
                Palette.aEntries[i].peBlue=0xa4;
                break;
            case 12:
                Palette.aEntries[i].peRed=0x80;
                Palette.aEntries[i].peGreen=0x80;
                Palette.aEntries[i].peBlue=0x80;
        }
    }

   for (i=13; i <= 18; i++)
    {
        Palette.aEntries[i].peRed=(i%2)?0xff:0;
        Palette.aEntries[i].peGreen=(i==14)?0xff:(i==15)?0xff:(i==18)?0xff:0;
        Palette.aEntries[i].peBlue=(i>15)?0xff:0x00;
    }

258
    return CreatePalette((LOGPALETTE *)&Palette);
Alexandre Julliard's avatar
Alexandre Julliard committed
259
}
Alexandre Julliard's avatar
Alexandre Julliard committed
260

Alexandre Julliard's avatar
Alexandre Julliard committed
261

Alexandre Julliard's avatar
Alexandre Julliard committed
262
/***********************************************************************
Jon Griffiths's avatar
Jon Griffiths committed
263 264 265
 * GetPaletteEntries [GDI32.@]
 *
 * Retrieves palette entries.
Alexandre Julliard's avatar
Alexandre Julliard committed
266 267 268 269
 *
 * RETURNS
 *    Success: Number of entries from logical palette
 *    Failure: 0
Alexandre Julliard's avatar
Alexandre Julliard committed
270
 */
271 272 273 274
UINT WINAPI GetPaletteEntries(
    HPALETTE hpalette,    /* [in]  Handle of logical palette */
    UINT start,           /* [in]  First entry to receive */
    UINT count,           /* [in]  Number of entries to receive */
Alexandre Julliard's avatar
Alexandre Julliard committed
275
    LPPALETTEENTRY entries) /* [out] Address of array receiving entries */
Alexandre Julliard's avatar
Alexandre Julliard committed
276 277
{
    PALETTEOBJ * palPtr;
278
    UINT numEntries;
Alexandre Julliard's avatar
Alexandre Julliard committed
279

280
    TRACE("hpal = %p, count=%i\n", hpalette, count );
281

Alexandre Julliard's avatar
Alexandre Julliard committed
282 283
    palPtr = (PALETTEOBJ *) GDI_GetObjPtr( hpalette, PALETTE_MAGIC );
    if (!palPtr) return 0;
284

285 286
    /* NOTE: not documented but test show this to be the case */
    if (count == 0)
287
    {
288 289 290 291
        int rc = palPtr->logpalette.palNumEntries;
	    GDI_ReleaseObj( hpalette );
        return rc;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
292

Alexandre Julliard's avatar
Alexandre Julliard committed
293
    numEntries = palPtr->logpalette.palNumEntries;
Alexandre Julliard's avatar
Alexandre Julliard committed
294 295
    if (start+count > numEntries) count = numEntries - start;
    if (entries)
296 297
    {
      if (start >= numEntries)
Alexandre Julliard's avatar
Alexandre Julliard committed
298
      {
299
	GDI_ReleaseObj( hpalette );
Alexandre Julliard's avatar
Alexandre Julliard committed
300 301 302 303 304 305 306
	return 0;
      }
      memcpy( entries, &palPtr->logpalette.palPalEntry[start],
	      count * sizeof(PALETTEENTRY) );
      for( numEntries = 0; numEntries < count ; numEntries++ )
	   if (entries[numEntries].peFlags & 0xF0)
	       entries[numEntries].peFlags = 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
307
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
308

309
    GDI_ReleaseObj( hpalette );
Alexandre Julliard's avatar
Alexandre Julliard committed
310 311 312 313
    return count;
}


Alexandre Julliard's avatar
Alexandre Julliard committed
314
/***********************************************************************
Jon Griffiths's avatar
Jon Griffiths committed
315 316 317
 * SetPaletteEntries [GDI32.@]
 *
 * Sets color values for range in palette.
Alexandre Julliard's avatar
Alexandre Julliard committed
318 319 320 321
 *
 * RETURNS
 *    Success: Number of entries that were set
 *    Failure: 0
Alexandre Julliard's avatar
Alexandre Julliard committed
322
 */
323 324 325 326
UINT WINAPI SetPaletteEntries(
    HPALETTE hpalette,    /* [in] Handle of logical palette */
    UINT start,           /* [in] Index of first entry to set */
    UINT count,           /* [in] Number of entries to set */
327
    const PALETTEENTRY *entries) /* [in] Address of array of structures */
Alexandre Julliard's avatar
Alexandre Julliard committed
328 329
{
    PALETTEOBJ * palPtr;
330
    UINT numEntries;
Alexandre Julliard's avatar
Alexandre Julliard committed
331

332
    TRACE("hpal=%p,start=%i,count=%i\n",hpalette,start,count );
Alexandre Julliard's avatar
Alexandre Julliard committed
333

334
    if (hpalette == GetStockObject(DEFAULT_PALETTE)) return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
335 336
    palPtr = (PALETTEOBJ *) GDI_GetObjPtr( hpalette, PALETTE_MAGIC );
    if (!palPtr) return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
337

Alexandre Julliard's avatar
Alexandre Julliard committed
338
    numEntries = palPtr->logpalette.palNumEntries;
339
    if (start >= numEntries)
Alexandre Julliard's avatar
Alexandre Julliard committed
340
    {
341
      GDI_ReleaseObj( hpalette );
Alexandre Julliard's avatar
Alexandre Julliard committed
342 343
      return 0;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
344 345 346
    if (start+count > numEntries) count = numEntries - start;
    memcpy( &palPtr->logpalette.palPalEntry[start], entries,
	    count * sizeof(PALETTEENTRY) );
347
    UnrealizeObject( hpalette );
348
    GDI_ReleaseObj( hpalette );
Alexandre Julliard's avatar
Alexandre Julliard committed
349 350 351
    return count;
}

Alexandre Julliard's avatar
Alexandre Julliard committed
352

Alexandre Julliard's avatar
Alexandre Julliard committed
353
/***********************************************************************
Jon Griffiths's avatar
Jon Griffiths committed
354 355 356
 * ResizePalette [GDI32.@]
 *
 * Resizes logical palette.
Alexandre Julliard's avatar
Alexandre Julliard committed
357 358 359 360
 *
 * RETURNS
 *    Success: TRUE
 *    Failure: FALSE
Alexandre Julliard's avatar
Alexandre Julliard committed
361
 */
362 363 364
BOOL WINAPI ResizePalette(
    HPALETTE hPal, /* [in] Handle of logical palette */
    UINT cEntries) /* [in] Number of entries in logical palette */
Alexandre Julliard's avatar
Alexandre Julliard committed
365
{
Alexandre Julliard's avatar
Alexandre Julliard committed
366
    PALETTEOBJ * palPtr = (PALETTEOBJ *) GDI_GetObjPtr( hPal, PALETTE_MAGIC );
367
    UINT	 cPrevEnt, prevVer;
Alexandre Julliard's avatar
Alexandre Julliard committed
368 369
    int		 prevsize, size = sizeof(LOGPALETTE) + (cEntries - 1) * sizeof(PALETTEENTRY);

370 371
    TRACE("hpal = %p, prev = %i, new = %i\n",
          hPal, palPtr ? palPtr->logpalette.palNumEntries : -1, cEntries );
Alexandre Julliard's avatar
Alexandre Julliard committed
372 373 374 375 376 377
    if( !palPtr ) return FALSE;
    cPrevEnt = palPtr->logpalette.palNumEntries;
    prevVer = palPtr->logpalette.palVersion;
    prevsize = sizeof(LOGPALETTE) + (cPrevEnt - 1) * sizeof(PALETTEENTRY) +
	      				sizeof(int*) + sizeof(GDIOBJHDR);
    size += sizeof(int*) + sizeof(GDIOBJHDR);
378

379
    if (!(palPtr = GDI_ReallocObject( size, hPal, palPtr ))) return FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
380

381
    PALETTE_UnrealizeObject( hPal, palPtr );
382

383
    if( cEntries > cPrevEnt ) memset( (BYTE*)palPtr + prevsize, 0, size - prevsize );
Alexandre Julliard's avatar
Alexandre Julliard committed
384 385
    palPtr->logpalette.palNumEntries = cEntries;
    palPtr->logpalette.palVersion = prevVer;
386
    GDI_ReleaseObj( hPal );
Alexandre Julliard's avatar
Alexandre Julliard committed
387
    return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
388 389
}

Alexandre Julliard's avatar
Alexandre Julliard committed
390

Alexandre Julliard's avatar
Alexandre Julliard committed
391
/***********************************************************************
Jon Griffiths's avatar
Jon Griffiths committed
392 393 394
 * AnimatePalette [GDI32.@]
 *
 * Replaces entries in logical palette.
Alexandre Julliard's avatar
Alexandre Julliard committed
395 396 397 398
 *
 * RETURNS
 *    Success: TRUE
 *    Failure: FALSE
Alexandre Julliard's avatar
Alexandre Julliard committed
399
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
400 401
 * FIXME
 *    Should use existing mapping when animating a primary palette
Alexandre Julliard's avatar
Alexandre Julliard committed
402
 */
403 404 405 406
BOOL WINAPI AnimatePalette(
    HPALETTE hPal,              /* [in] Handle to logical palette */
    UINT StartIndex,            /* [in] First entry in palette */
    UINT NumEntries,            /* [in] Count of entries in palette */
407
    const PALETTEENTRY* PaletteColors) /* [in] Pointer to first replacement */
Alexandre Julliard's avatar
Alexandre Julliard committed
408
{
409
    TRACE("%p (%i - %i)\n", hPal, StartIndex,StartIndex+NumEntries);
Alexandre Julliard's avatar
Alexandre Julliard committed
410

411
    if( hPal != GetStockObject(DEFAULT_PALETTE) )
Alexandre Julliard's avatar
Alexandre Julliard committed
412
    {
413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441
        PALETTEOBJ * palPtr;
        UINT pal_entries;
        const PALETTEENTRY *pptr = PaletteColors;

        palPtr = (PALETTEOBJ *) GDI_GetObjPtr( hPal, PALETTE_MAGIC );
        if (!palPtr) return 0;

        pal_entries = palPtr->logpalette.palNumEntries;
        if (StartIndex >= pal_entries)
        {
          GDI_ReleaseObj( hPal );
          return 0;
        }
        if (StartIndex+NumEntries > pal_entries) NumEntries = pal_entries - StartIndex;
        
        for (NumEntries += StartIndex; StartIndex < NumEntries; StartIndex++, pptr++) {
          /* According to MSDN, only animate PC_RESERVED colours */
          if (palPtr->logpalette.palPalEntry[StartIndex].peFlags & PC_RESERVED) {
            TRACE("Animating colour (%d,%d,%d) to (%d,%d,%d)\n",
              palPtr->logpalette.palPalEntry[StartIndex].peRed,
              palPtr->logpalette.palPalEntry[StartIndex].peGreen,
              palPtr->logpalette.palPalEntry[StartIndex].peBlue,
              pptr->peRed, pptr->peGreen, pptr->peBlue);
            memcpy( &palPtr->logpalette.palPalEntry[StartIndex], pptr,
                    sizeof(PALETTEENTRY) );
          } else {
            TRACE("Not animating entry %d -- not PC_RESERVED\n", StartIndex);
          }
        }
442 443
        if (palPtr->funcs && palPtr->funcs->pRealizePalette)
            palPtr->funcs->pRealizePalette( NULL, hPal, hPal == hPrimaryPalette );
444

445
        GDI_ReleaseObj( hPal );
Alexandre Julliard's avatar
Alexandre Julliard committed
446
    }
447
    return TRUE;
Alexandre Julliard's avatar
Alexandre Julliard committed
448
}
Alexandre Julliard's avatar
Alexandre Julliard committed
449

Alexandre Julliard's avatar
Alexandre Julliard committed
450 451

/***********************************************************************
452
 * SetSystemPaletteUse [GDI32.@]
Alexandre Julliard's avatar
Alexandre Julliard committed
453
 *
454 455
 * Specify whether the system palette contains 2 or 20 static colors.
 *
Alexandre Julliard's avatar
Alexandre Julliard committed
456 457 458
 * RETURNS
 *    Success: Previous system palette
 *    Failure: SYSPAL_ERROR
Alexandre Julliard's avatar
Alexandre Julliard committed
459
 */
460 461 462
UINT WINAPI SetSystemPaletteUse(
    HDC hdc,  /* [in] Handle of device context */
    UINT use) /* [in] Palette-usage flag */
Alexandre Julliard's avatar
Alexandre Julliard committed
463
{
464
    UINT old = SystemPaletteUse;
465 466 467 468 469 470 471 472 473 474 475 476 477 478 479

    /* Device doesn't support colour palettes */
    if (!(GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE)) {
        return SYSPAL_ERROR;
    }

    switch (use) {
        case SYSPAL_NOSTATIC:
        case SYSPAL_NOSTATIC256:        /* WINVER >= 0x0500 */
        case SYSPAL_STATIC:
            SystemPaletteUse = use;
            return old;
        default:
            return SYSPAL_ERROR;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
480 481 482
}


Alexandre Julliard's avatar
Alexandre Julliard committed
483
/***********************************************************************
Jon Griffiths's avatar
Jon Griffiths committed
484 485 486
 * GetSystemPaletteUse [GDI32.@]
 *
 * Gets state of system palette.
Alexandre Julliard's avatar
Alexandre Julliard committed
487 488 489
 *
 * RETURNS
 *    Current state of system palette
Alexandre Julliard's avatar
Alexandre Julliard committed
490
 */
491 492
UINT WINAPI GetSystemPaletteUse(
    HDC hdc) /* [in] Handle of device context */
Alexandre Julliard's avatar
Alexandre Julliard committed
493
{
Alexandre Julliard's avatar
Alexandre Julliard committed
494
    return SystemPaletteUse;
Alexandre Julliard's avatar
Alexandre Julliard committed
495 496
}

Alexandre Julliard's avatar
Alexandre Julliard committed
497

Alexandre Julliard's avatar
Alexandre Julliard committed
498
/***********************************************************************
Jon Griffiths's avatar
Jon Griffiths committed
499 500 501
 * GetSystemPaletteEntries [GDI32.@]
 *
 * Gets range of palette entries.
Alexandre Julliard's avatar
Alexandre Julliard committed
502 503 504 505
 *
 * RETURNS
 *    Success: Number of entries retrieved from palette
 *    Failure: 0
Alexandre Julliard's avatar
Alexandre Julliard committed
506
 */
507 508 509 510
UINT WINAPI GetSystemPaletteEntries(
    HDC hdc,              /* [in]  Handle of device context */
    UINT start,           /* [in]  Index of first entry to be retrieved */
    UINT count,           /* [in]  Number of entries to be retrieved */
Alexandre Julliard's avatar
Alexandre Julliard committed
511
    LPPALETTEENTRY entries) /* [out] Array receiving system-palette entries */
Alexandre Julliard's avatar
Alexandre Julliard committed
512
{
513 514
    UINT ret = 0;
    DC *dc;
Alexandre Julliard's avatar
Alexandre Julliard committed
515

516
    TRACE("hdc=%p,start=%i,count=%i\n", hdc,start,count);
Alexandre Julliard's avatar
Alexandre Julliard committed
517

518
    if ((dc = DC_GetDCPtr( hdc )))
Alexandre Julliard's avatar
Alexandre Julliard committed
519
    {
520 521 522
        if (dc->funcs->pGetSystemPaletteEntries)
            ret = dc->funcs->pGetSystemPaletteEntries( dc->physDev, start, count, entries );
        GDI_ReleaseObj( hdc );
Alexandre Julliard's avatar
Alexandre Julliard committed
523
    }
524
    return ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
525 526 527
}


Alexandre Julliard's avatar
Alexandre Julliard committed
528
/***********************************************************************
Jon Griffiths's avatar
Jon Griffiths committed
529 530 531
 * GetNearestPaletteIndex [GDI32.@]
 *
 * Gets palette index for color.
Alexandre Julliard's avatar
Alexandre Julliard committed
532 533 534 535 536 537 538
 *
 * NOTES
 *    Should index be initialized to CLR_INVALID instead of 0?
 *
 * RETURNS
 *    Success: Index of entry in logical palette
 *    Failure: CLR_INVALID
Alexandre Julliard's avatar
Alexandre Julliard committed
539
 */
540 541
UINT WINAPI GetNearestPaletteIndex(
    HPALETTE hpalette, /* [in] Handle of logical color palette */
Alexandre Julliard's avatar
Alexandre Julliard committed
542
    COLORREF color)      /* [in] Color to be matched */
Alexandre Julliard's avatar
Alexandre Julliard committed
543
{
Alexandre Julliard's avatar
Alexandre Julliard committed
544
    PALETTEOBJ*	palObj = (PALETTEOBJ*)GDI_GetObjPtr( hpalette, PALETTE_MAGIC );
545
    UINT index  = 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
546 547

    if( palObj )
548
    {
549 550 551
        int i, diff = 0x7fffffff;
        int r,g,b;
        PALETTEENTRY* entry = palObj->logpalette.palPalEntry;
Alexandre Julliard's avatar
Alexandre Julliard committed
552

553 554 555 556 557 558 559 560 561 562 563
        for( i = 0; i < palObj->logpalette.palNumEntries && diff ; i++, entry++)
        {
            r = entry->peRed - GetRValue(color);
            g = entry->peGreen - GetGValue(color);
            b = entry->peBlue - GetBValue(color);

            r = r*r + g*g + b*b;

            if( r < diff ) { index = i; diff = r; }
        }
        GDI_ReleaseObj( hpalette );
564
    }
565
    TRACE("(%p,%06x): returning %d\n", hpalette, color, index );
Alexandre Julliard's avatar
Alexandre Julliard committed
566 567 568 569
    return index;
}


Alexandre Julliard's avatar
Alexandre Julliard committed
570
/***********************************************************************
Jon Griffiths's avatar
Jon Griffiths committed
571 572 573
 * GetNearestColor [GDI32.@]
 *
 * Gets a system color to match.
Alexandre Julliard's avatar
Alexandre Julliard committed
574 575 576 577
 *
 * RETURNS
 *    Success: Color from system palette that corresponds to given color
 *    Failure: CLR_INVALID
Alexandre Julliard's avatar
Alexandre Julliard committed
578
 */
579 580
COLORREF WINAPI GetNearestColor(
    HDC hdc,      /* [in] Handle of device context */
Alexandre Julliard's avatar
Alexandre Julliard committed
581
    COLORREF color) /* [in] Color to be matched */
Alexandre Julliard's avatar
Alexandre Julliard committed
582
{
583 584
    unsigned char spec_type;
    COLORREF nearest;
Alexandre Julliard's avatar
Alexandre Julliard committed
585 586
    DC 		*dc;

587 588 589 590 591 592 593 594 595 596 597 598
    if (!(dc = DC_GetDCPtr( hdc ))) return CLR_INVALID;

    if (dc->funcs->pGetNearestColor)
    {
        nearest = dc->funcs->pGetNearestColor( dc->physDev, color );
        GDI_ReleaseObj( hdc );
        return nearest;
    }

    if (!(GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE))
    {
        GDI_ReleaseObj( hdc );
599 600
        return color;
    }
601 602 603

    spec_type = color >> 24;
    if (spec_type == 1 || spec_type == 2)
Alexandre Julliard's avatar
Alexandre Julliard committed
604
    {
605
        /* we need logical palette for PALETTERGB and PALETTEINDEX colorrefs */
606

607 608 609 610 611 612 613 614 615 616 617
        UINT index;
        PALETTEENTRY entry;
        HPALETTE hpal = dc->hPalette ? dc->hPalette : GetStockObject( DEFAULT_PALETTE );

        if (spec_type == 2) /* PALETTERGB */
            index = GetNearestPaletteIndex( hpal, color );
        else  /* PALETTEINDEX */
            index = LOWORD(color);

        if (!GetPaletteEntries( hpal, index, 1, &entry ))
        {
618
            WARN("RGB(%x) : idx %d is out of bounds, assuming NULL\n", color, index );
619 620 621 622 623 624 625
            if (!GetPaletteEntries( hpal, 0, 1, &entry ))
            {
                GDI_ReleaseObj( hdc );
                return CLR_INVALID;
            }
        }
        color = RGB( entry.peRed, entry.peGreen, entry.peBlue );
Alexandre Julliard's avatar
Alexandre Julliard committed
626
    }
627 628
    nearest = color & 0x00ffffff;
    GDI_ReleaseObj( hdc );
Alexandre Julliard's avatar
Alexandre Julliard committed
629

630
    TRACE("(%06x): returning %06x\n", color, nearest );
Alexandre Julliard's avatar
Alexandre Julliard committed
631 632 633 634
    return nearest;
}


Alexandre Julliard's avatar
Alexandre Julliard committed
635 636 637
/***********************************************************************
 *           PALETTE_GetObject
 */
638
static INT PALETTE_GetObject( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
Alexandre Julliard's avatar
Alexandre Julliard committed
639
{
640 641
    PALETTEOBJ *palette = obj;

642 643 644
    if( !buffer )
        return sizeof(WORD);

Alexandre Julliard's avatar
Alexandre Julliard committed
645 646 647 648
    if (count > sizeof(WORD)) count = sizeof(WORD);
    memcpy( buffer, &palette->logpalette.palNumEntries, count );
    return count;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
649 650


Alexandre Julliard's avatar
Alexandre Julliard committed
651 652 653
/***********************************************************************
 *           PALETTE_UnrealizeObject
 */
654
static BOOL PALETTE_UnrealizeObject( HGDIOBJ handle, void *obj )
Alexandre Julliard's avatar
Alexandre Julliard committed
655
{
656 657
    PALETTEOBJ *palette = obj;

658 659 660 661 662 663
    if (palette->funcs)
    {
        if (palette->funcs->pUnrealizePalette)
            palette->funcs->pUnrealizePalette( handle );
        palette->funcs = NULL;
    }
664

665 666
    if (hLastRealizedPalette == handle)
    {
667
        TRACE("unrealizing palette %p\n", handle);
668 669
        hLastRealizedPalette = 0;
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
670 671 672 673 674 675 676
    return TRUE;
}


/***********************************************************************
 *           PALETTE_DeleteObject
 */
677
static BOOL PALETTE_DeleteObject( HGDIOBJ handle, void *obj )
Alexandre Julliard's avatar
Alexandre Julliard committed
678
{
679
    PALETTE_UnrealizeObject( handle, obj );
680
    return GDI_FreeObject( handle, obj );
Alexandre Julliard's avatar
Alexandre Julliard committed
681 682 683
}


Alexandre Julliard's avatar
Alexandre Julliard committed
684
/***********************************************************************
685
 *           GDISelectPalette    (Not a Windows API)
Alexandre Julliard's avatar
Alexandre Julliard committed
686
 */
687
HPALETTE WINAPI GDISelectPalette( HDC hdc, HPALETTE hpal, WORD wBkg)
Alexandre Julliard's avatar
Alexandre Julliard committed
688
{
689
    HPALETTE ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
690 691
    DC *dc;

692
    TRACE("%p %p\n", hdc, hpal );
693

694
    if (GetObjectType(hpal) != OBJ_PAL)
695
    {
696
      WARN("invalid selected palette %p\n",hpal);
697 698
      return 0;
    }
699
    if (!(dc = DC_GetDCPtr( hdc ))) return 0;
700 701 702 703 704 705 706 707
    ret = dc->hPalette;
    if (dc->funcs->pSelectPalette) hpal = dc->funcs->pSelectPalette( dc->physDev, hpal, FALSE );
    if (hpal)
    {
        dc->hPalette = hpal;
        if (!wBkg) hPrimaryPalette = hpal;
    }
    else ret = 0;
708
    GDI_ReleaseObj( hdc );
709
    return ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
710 711 712 713
}


/***********************************************************************
714
 *           GDIRealizePalette    (Not a Windows API)
Alexandre Julliard's avatar
Alexandre Julliard committed
715
 */
716
UINT WINAPI GDIRealizePalette( HDC hdc )
Alexandre Julliard's avatar
Alexandre Julliard committed
717
{
718
    UINT realized = 0;
719 720 721
    DC* dc = DC_GetDCPtr( hdc );

    if (!dc) return 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
722

723
    TRACE("%p...\n", hdc );
724

725 726
    if( dc->hPalette == GetStockObject( DEFAULT_PALETTE ))
    {
727 728
        if (dc->funcs->pRealizeDefaultPalette)
            realized = dc->funcs->pRealizeDefaultPalette( dc->physDev );
729
    }
730
    else if(dc->hPalette != hLastRealizedPalette )
Alexandre Julliard's avatar
Alexandre Julliard committed
731
    {
732
        if (dc->funcs->pRealizePalette)
733 734 735 736 737 738 739 740 741 742
        {
            PALETTEOBJ *palPtr = GDI_GetObjPtr( dc->hPalette, PALETTE_MAGIC );
            if (palPtr)
            {
                realized = dc->funcs->pRealizePalette( dc->physDev, dc->hPalette,
                                                       (dc->hPalette == hPrimaryPalette) );
                palPtr->funcs = dc->funcs;
                GDI_ReleaseObj( dc->hPalette );
            }
        }
743
        hLastRealizedPalette = dc->hPalette;
Alexandre Julliard's avatar
Alexandre Julliard committed
744
    }
745
    else TRACE("  skipping (hLastRealizedPalette = %p)\n", hLastRealizedPalette);
Alexandre Julliard's avatar
Alexandre Julliard committed
746

747
    GDI_ReleaseObj( hdc );
748
    TRACE("   realized %i colors.\n", realized );
749
    return realized;
Alexandre Julliard's avatar
Alexandre Julliard committed
750 751 752
}


Alexandre Julliard's avatar
Alexandre Julliard committed
753
/***********************************************************************
Alexandre Julliard's avatar
Alexandre Julliard committed
754
 *           RealizeDefaultPalette    (GDI.365)
Alexandre Julliard's avatar
Alexandre Julliard committed
755
 */
756
UINT16 WINAPI RealizeDefaultPalette16( HDC16 hdc )
Alexandre Julliard's avatar
Alexandre Julliard committed
757
{
758
    UINT16 ret = 0;
Alexandre Julliard's avatar
Alexandre Julliard committed
759
    DC          *dc;
Alexandre Julliard's avatar
Alexandre Julliard committed
760

761
    TRACE("%04x\n", hdc );
Alexandre Julliard's avatar
Alexandre Julliard committed
762

Michael Stefaniuc's avatar
Michael Stefaniuc committed
763
    if (!(dc = DC_GetDCPtr( HDC_32(hdc) ))) return 0;
764

765
    if (dc->funcs->pRealizeDefaultPalette) ret = dc->funcs->pRealizeDefaultPalette( dc->physDev );
Michael Stefaniuc's avatar
Michael Stefaniuc committed
766
    GDI_ReleaseObj( HDC_32(hdc) );
767
    return ret;
Alexandre Julliard's avatar
Alexandre Julliard committed
768
}
Alexandre Julliard's avatar
Alexandre Julliard committed
769

Alexandre Julliard's avatar
Alexandre Julliard committed
770
/***********************************************************************
Alexandre Julliard's avatar
Alexandre Julliard committed
771
 *           IsDCCurrentPalette   (GDI.412)
Alexandre Julliard's avatar
Alexandre Julliard committed
772
 */
773
BOOL16 WINAPI IsDCCurrentPalette16(HDC16 hDC)
Alexandre Julliard's avatar
Alexandre Julliard committed
774
{
Michael Stefaniuc's avatar
Michael Stefaniuc committed
775
    DC *dc = DC_GetDCPtr( HDC_32(hDC) );
776
    if (dc)
Alexandre Julliard's avatar
Alexandre Julliard committed
777
    {
778
      BOOL bRet = dc->hPalette == hPrimaryPalette;
Michael Stefaniuc's avatar
Michael Stefaniuc committed
779
      GDI_ReleaseObj( HDC_32(hDC) );
780
      return bRet;
Alexandre Julliard's avatar
Alexandre Julliard committed
781 782
    }
    return FALSE;
Alexandre Julliard's avatar
Alexandre Julliard committed
783 784
}

Alexandre Julliard's avatar
Alexandre Julliard committed
785

Alexandre Julliard's avatar
Alexandre Julliard committed
786
/***********************************************************************
Jon Griffiths's avatar
Jon Griffiths committed
787 788 789
 * SelectPalette [GDI32.@]
 *
 * Selects logical palette into DC.
Alexandre Julliard's avatar
Alexandre Julliard committed
790 791 792 793
 *
 * RETURNS
 *    Success: Previous logical palette
 *    Failure: NULL
Alexandre Julliard's avatar
Alexandre Julliard committed
794
 */
795 796 797 798
HPALETTE WINAPI SelectPalette(
    HDC hDC,               /* [in] Handle of device context */
    HPALETTE hPal,         /* [in] Handle of logical color palette */
    BOOL bForceBackground) /* [in] Foreground/background mode */
Alexandre Julliard's avatar
Alexandre Julliard committed
799
{
800
    return pfnSelectPalette( hDC, hPal, bForceBackground );
Alexandre Julliard's avatar
Alexandre Julliard committed
801 802
}

Alexandre Julliard's avatar
Alexandre Julliard committed
803

Alexandre Julliard's avatar
Alexandre Julliard committed
804
/***********************************************************************
Jon Griffiths's avatar
Jon Griffiths committed
805 806 807
 * RealizePalette [GDI32.@]
 *
 * Maps palette entries to system palette.
Alexandre Julliard's avatar
Alexandre Julliard committed
808 809 810 811
 *
 * RETURNS
 *    Success: Number of entries in logical palette
 *    Failure: GDI_ERROR
Alexandre Julliard's avatar
Alexandre Julliard committed
812
 */
813 814
UINT WINAPI RealizePalette(
    HDC hDC) /* [in] Handle of device context */
Alexandre Julliard's avatar
Alexandre Julliard committed
815
{
816
    return pfnRealizePalette( hDC );
Alexandre Julliard's avatar
Alexandre Julliard committed
817 818
}

Alexandre Julliard's avatar
Alexandre Julliard committed
819

820 821
typedef HWND (WINAPI *WindowFromDC_funcptr)( HDC );
typedef BOOL (WINAPI *RedrawWindow_funcptr)( HWND, const RECT *, HRGN, UINT );
822

Alexandre Julliard's avatar
Alexandre Julliard committed
823
/**********************************************************************
Jon Griffiths's avatar
Jon Griffiths committed
824 825 826
 * UpdateColors [GDI32.@]
 *
 * Remaps current colors to logical palette.
827 828 829 830
 *
 * RETURNS
 *    Success: TRUE
 *    Failure: FALSE
Alexandre Julliard's avatar
Alexandre Julliard committed
831
 */
832 833
BOOL WINAPI UpdateColors(
    HDC hDC) /* [in] Handle of device context */
Alexandre Julliard's avatar
Alexandre Julliard committed
834
{
835
    HMODULE mod;
836
    int size = GetDeviceCaps( hDC, SIZEPALETTE );
837

838
    if (!size) return 0;
839

840 841 842 843 844 845 846 847 848 849 850 851 852
    mod = GetModuleHandleA("user32.dll");
    if (mod)
    {
        WindowFromDC_funcptr pWindowFromDC = (WindowFromDC_funcptr)GetProcAddress(mod,"WindowFromDC");
        if (pWindowFromDC)
        {
            HWND hWnd = pWindowFromDC( hDC );

            /* Docs say that we have to remap current drawable pixel by pixel
             * but it would take forever given the speed of XGet/PutPixel.
             */
            if (hWnd && size)
            {
853
                RedrawWindow_funcptr pRedrawWindow = (void *)GetProcAddress( mod, "RedrawWindow" );
854 855 856
                if (pRedrawWindow) pRedrawWindow( hWnd, NULL, 0, RDW_INVALIDATE );
            }
        }
857
    }
Alexandre Julliard's avatar
Alexandre Julliard committed
858 859
    return 0x666;
}
Alexandre Julliard's avatar
Alexandre Julliard committed
860

Alexandre Julliard's avatar
Alexandre Julliard committed
861

862
/*********************************************************************
863
 *           SetMagicColors   (GDI.606)
864 865 866
 */
VOID WINAPI SetMagicColors16(HDC16 hDC, COLORREF color, UINT16 index)
{
867
    FIXME("(hDC %04x, color %04x, index %04x): stub\n", hDC, (int)color, index);
868 869

}
870

871 872 873 874 875
/*********************************************************************
 *           SetMagicColors   (GDI.@)
 */
BOOL WINAPI SetMagicColors(HDC hdc, ULONG u1, ULONG u2)
{
876
    FIXME("(%p 0x%08x 0x%08x): stub\n", hdc, u1, u2);
877 878 879
    return TRUE;
}

880
/**********************************************************************
881
 * GetICMProfileA [GDI32.@]
882 883 884 885 886 887
 *
 * Returns the filename of the specified device context's color
 * management profile, even if color management is not enabled
 * for that DC.
 *
 * RETURNS
888
 *    TRUE if name copied successfully OR lpszFilename is NULL
889 890 891 892 893 894 895 896 897 898 899 900
 *    FALSE if the buffer length pointed to by lpcbName is too small
 *
 * NOTE
 *    The buffer length pointed to by lpcbName is ALWAYS updated to
 *    the length required regardless of other actions this function
 *    may take.
 *
 * FIXME
 *    How does Windows assign these?  Some registry key?
 */


901 902
/*********************************************************************/

903 904 905
BOOL WINAPI GetICMProfileA(HDC hDC, LPDWORD lpcbName, LPSTR lpszFilename)
{
    DWORD callerLen;
906
    static const char icm[] = "winefake.icm";
907

908
    FIXME("(%p, %p, %p): partial stub\n", hDC, lpcbName, lpszFilename);
909 910 911 912

    callerLen = *lpcbName;

    /* all 3 behaviors require the required buffer size to be set */
913
    *lpcbName = sizeof(icm);
914 915

    /* behavior 1: if lpszFilename is NULL, return size of string and no error */
916
    if (!lpszFilename) return TRUE;
917

918
    /* behavior 2: if buffer size too small, return size of string and error */
919
    if (callerLen < sizeof(icm))
920 921 922 923 924 925
    {
	SetLastError(ERROR_INSUFFICIENT_BUFFER);
	return FALSE;
    }

    /* behavior 3: if buffer size OK and pointer not NULL, copy and return size */
926 927 928 929
    memcpy(lpszFilename, icm, sizeof(icm));
    return TRUE;
}

930 931 932
/**********************************************************************
 * GetICMProfileW [GDI32.@]
 **/
933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956
BOOL WINAPI GetICMProfileW(HDC hDC, LPDWORD lpcbName, LPWSTR lpszFilename)
{
    DWORD callerLen;
    static const WCHAR icm[] = { 'w','i','n','e','f','a','k','e','.','i','c','m', 0 };

    FIXME("(%p, %p, %p): partial stub\n", hDC, lpcbName, lpszFilename);

    callerLen = *lpcbName;

    /* all 3 behaviors require the required buffer size to be set */
    *lpcbName = sizeof(icm) / sizeof(WCHAR);

    /* behavior 1: if lpszFilename is NULL, return size of string and no error */
    if (!lpszFilename) return TRUE;

    /* behavior 2: if buffer size too small, return size of string and error */
    if (callerLen < sizeof(icm)/sizeof(WCHAR))
    {
        SetLastError(ERROR_INSUFFICIENT_BUFFER);
        return FALSE;
    }

    /* behavior 3: if buffer size OK and pointer not NULL, copy and return size */
    memcpy(lpszFilename, icm, sizeof(icm));
957 958
    return TRUE;
}
959

960 961 962 963 964 965
/**********************************************************************
 * GetLogColorSpaceA [GDI32.@]
 *
 */
BOOL WINAPI GetLogColorSpaceA(HCOLORSPACE hColorSpace, LPLOGCOLORSPACEA lpBuffer, DWORD nSize)
{
966
    FIXME("%p %p 0x%08x: stub!\n", hColorSpace, lpBuffer, nSize);
967 968 969 970 971 972 973 974 975
    return FALSE;
}

/**********************************************************************
 * GetLogColorSpaceW [GDI32.@]
 *
 */
BOOL WINAPI GetLogColorSpaceW(HCOLORSPACE hColorSpace, LPLOGCOLORSPACEW lpBuffer, DWORD nSize)
{
976
    FIXME("%p %p 0x%08x: stub!\n", hColorSpace, lpBuffer, nSize);
977 978 979
    return FALSE;
}

980 981 982 983 984 985
/**********************************************************************
 * SetICMProfileA [GDI32.@]
 *
 */
BOOL WINAPI SetICMProfileA(HDC hDC, LPSTR lpszFilename)
{
986
    FIXME("hDC %p filename %s: stub!\n", hDC, debugstr_a(lpszFilename));
987 988
    return TRUE; /* success */
}
989 990 991 992 993 994 995

/**********************************************************************
 * SetICMProfileA [GDI32.@]
 *
 */
BOOL WINAPI SetICMProfileW(HDC hDC, LPWSTR lpszFilename)
{
996
    FIXME("hDC %p filename %s: stub!\n", hDC, debugstr_w(lpszFilename));
997 998 999 1000 1001 1002 1003 1004 1005
    return TRUE; /* success */
}

/**********************************************************************
 * UpdateICMRegKeyA [GDI32.@]
 *
 */
BOOL WINAPI UpdateICMRegKeyA(DWORD dwReserved, LPSTR lpszCMID, LPSTR lpszFileName, UINT nCommand)
{
1006
    FIXME("(0x%08x, %s, %s, 0x%08x): stub!\n", dwReserved, debugstr_a(lpszCMID),
1007 1008 1009 1010 1011 1012 1013 1014 1015 1016
          debugstr_a(lpszFileName), nCommand);
    return TRUE; /* success */
}

/**********************************************************************
 * UpdateICMRegKeyW [GDI32.@]
 *
 */
BOOL WINAPI UpdateICMRegKeyW(DWORD dwReserved, LPWSTR lpszCMID, LPWSTR lpszFileName, UINT nCommand)
{
1017
    FIXME("(0x%08x, %s, %s, 0x%08x): stub!\n", dwReserved, debugstr_w(lpszCMID),
1018 1019 1020
          debugstr_w(lpszFileName), nCommand);
    return TRUE; /* success */
}