advapi32: Close hTemp on error (Coverity).
[wine] / dlls / gdi32 / palette.c
1 /*
2  * GDI palette objects
3  *
4  * Copyright 1993,1994 Alexandre Julliard
5  * Copyright 1996 Alex Korobka
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * 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:
22  * PALETTEOBJ is documented in the Dr. Dobbs Journal May 1993.
23  * Information in the "Undocumented Windows" is incorrect.
24  */
25
26 #include <stdarg.h>
27 #include <stdlib.h>
28 #include <string.h>
29
30 #include "windef.h"
31 #include "winbase.h"
32 #include "winerror.h"
33 #include "wingdi.h"
34 #include "winuser.h"
35
36 #include "gdi_private.h"
37 #include "wine/debug.h"
38
39 WINE_DEFAULT_DEBUG_CHANNEL(palette);
40
41 typedef BOOL (*unrealize_function)(HPALETTE);
42
43 typedef struct tagPALETTEOBJ
44 {
45     unrealize_function  unrealize;
46     WORD                version;    /* palette version */
47     WORD                count;      /* count of palette entries */
48     PALETTEENTRY       *entries;
49 } PALETTEOBJ;
50
51 static INT PALETTE_GetObject( HGDIOBJ handle, INT count, LPVOID buffer );
52 static BOOL PALETTE_UnrealizeObject( HGDIOBJ handle );
53 static BOOL PALETTE_DeleteObject( HGDIOBJ handle );
54
55 static const struct gdi_obj_funcs palette_funcs =
56 {
57     NULL,                     /* pSelectObject */
58     PALETTE_GetObject,        /* pGetObjectA */
59     PALETTE_GetObject,        /* pGetObjectW */
60     PALETTE_UnrealizeObject,  /* pUnrealizeObject */
61     PALETTE_DeleteObject      /* pDeleteObject */
62 };
63
64 /* Pointers to USER implementation of SelectPalette/RealizePalette */
65 /* they will be patched by USER on startup */
66 HPALETTE (WINAPI *pfnSelectPalette)(HDC hdc, HPALETTE hpal, WORD bkgnd ) = GDISelectPalette;
67 UINT (WINAPI *pfnRealizePalette)(HDC hdc) = GDIRealizePalette;
68
69 static UINT SystemPaletteUse = SYSPAL_STATIC;  /* currently not considered */
70
71 static HPALETTE hPrimaryPalette = 0; /* used for WM_PALETTECHANGED */
72 static HPALETTE hLastRealizedPalette = 0; /* UnrealizeObject() needs it */
73
74
75 /***********************************************************************
76  *           PALETTE_Init
77  *
78  * Create the system palette.
79  */
80 HPALETTE PALETTE_Init(void)
81 {
82     const RGBQUAD *entries = get_default_color_table( 8 );
83     char buffer[FIELD_OFFSET( LOGPALETTE, palPalEntry[20] )];
84     LOGPALETTE *palPtr = (LOGPALETTE *)buffer;
85     int i;
86
87     /* create default palette (20 system colors) */
88
89     palPtr->palVersion = 0x300;
90     palPtr->palNumEntries = 20;
91     for (i = 0; i < 20; i++)
92     {
93         palPtr->palPalEntry[i].peRed   = entries[i < 10 ? i : 236 + i].rgbRed;
94         palPtr->palPalEntry[i].peGreen = entries[i < 10 ? i : 236 + i].rgbGreen;
95         palPtr->palPalEntry[i].peBlue  = entries[i < 10 ? i : 236 + i].rgbBlue;
96         palPtr->palPalEntry[i].peFlags = 0;
97     }
98     return CreatePalette( palPtr );
99 }
100
101
102 /***********************************************************************
103  * CreatePalette [GDI32.@]
104  *
105  * Creates a logical color palette.
106  *
107  * RETURNS
108  *    Success: Handle to logical palette
109  *    Failure: NULL
110  */
111 HPALETTE WINAPI CreatePalette(
112     const LOGPALETTE* palette) /* [in] Pointer to logical color palette */
113 {
114     PALETTEOBJ * palettePtr;
115     HPALETTE hpalette;
116     int size;
117
118     if (!palette) return 0;
119     TRACE("entries=%i\n", palette->palNumEntries);
120
121     if (!(palettePtr = HeapAlloc( GetProcessHeap(), 0, sizeof(*palettePtr) ))) return 0;
122     palettePtr->unrealize = NULL;
123     palettePtr->version = palette->palVersion;
124     palettePtr->count   = palette->palNumEntries;
125     size = palettePtr->count * sizeof(*palettePtr->entries);
126     if (!(palettePtr->entries = HeapAlloc( GetProcessHeap(), 0, size )))
127     {
128         HeapFree( GetProcessHeap(), 0, palettePtr );
129         return 0;
130     }
131     memcpy( palettePtr->entries, palette->palPalEntry, size );
132     if (!(hpalette = alloc_gdi_handle( palettePtr, OBJ_PAL, &palette_funcs )))
133     {
134         HeapFree( GetProcessHeap(), 0, palettePtr->entries );
135         HeapFree( GetProcessHeap(), 0, palettePtr );
136     }
137     TRACE("   returning %p\n", hpalette);
138     return hpalette;
139 }
140
141
142 /***********************************************************************
143  * CreateHalftonePalette [GDI32.@]
144  *
145  * Creates a halftone palette.
146  *
147  * RETURNS
148  *    Success: Handle to logical halftone palette
149  *    Failure: 0
150  *
151  * FIXME: This simply creates the halftone palette derived from running
152  *        tests on a windows NT machine. This is assuming a color depth
153  *        of greater that 256 color. On a 256 color device the halftone
154  *        palette will be different and this function will be incorrect
155  */
156 HPALETTE WINAPI CreateHalftonePalette(
157     HDC hdc) /* [in] Handle to device context */
158 {
159     const RGBQUAD *entries = get_default_color_table( 8 );
160     char buffer[FIELD_OFFSET( LOGPALETTE, palPalEntry[256] )];
161     LOGPALETTE *pal = (LOGPALETTE *)buffer;
162     int i;
163
164     pal->palVersion = 0x300;
165     pal->palNumEntries = 256;
166     for (i = 0; i < 256; i++)
167     {
168         pal->palPalEntry[i].peRed   = entries[i].rgbRed;
169         pal->palPalEntry[i].peGreen = entries[i].rgbGreen;
170         pal->palPalEntry[i].peBlue  = entries[i].rgbBlue;
171         pal->palPalEntry[i].peFlags = 0;
172     }
173     return CreatePalette( pal );
174 }
175
176
177 /***********************************************************************
178  * GetPaletteEntries [GDI32.@]
179  *
180  * Retrieves palette entries.
181  *
182  * RETURNS
183  *    Success: Number of entries from logical palette
184  *    Failure: 0
185  */
186 UINT WINAPI GetPaletteEntries(
187     HPALETTE hpalette,    /* [in]  Handle of logical palette */
188     UINT start,           /* [in]  First entry to receive */
189     UINT count,           /* [in]  Number of entries to receive */
190     LPPALETTEENTRY entries) /* [out] Address of array receiving entries */
191 {
192     PALETTEOBJ * palPtr;
193     UINT numEntries;
194
195     TRACE("hpal = %p, count=%i\n", hpalette, count );
196
197     palPtr = GDI_GetObjPtr( hpalette, OBJ_PAL );
198     if (!palPtr) return 0;
199
200     /* NOTE: not documented but test show this to be the case */
201     if (count == 0)
202     {
203         count = palPtr->count;
204     }
205     else
206     {
207         numEntries = palPtr->count;
208         if (start+count > numEntries) count = numEntries - start;
209         if (entries)
210         {
211             if (start >= numEntries) count = 0;
212             else memcpy( entries, &palPtr->entries[start], count * sizeof(PALETTEENTRY) );
213         }
214     }
215
216     GDI_ReleaseObj( hpalette );
217     return count;
218 }
219
220
221 /***********************************************************************
222  * SetPaletteEntries [GDI32.@]
223  *
224  * Sets color values for range in palette.
225  *
226  * RETURNS
227  *    Success: Number of entries that were set
228  *    Failure: 0
229  */
230 UINT WINAPI SetPaletteEntries(
231     HPALETTE hpalette,    /* [in] Handle of logical palette */
232     UINT start,           /* [in] Index of first entry to set */
233     UINT count,           /* [in] Number of entries to set */
234     const PALETTEENTRY *entries) /* [in] Address of array of structures */
235 {
236     PALETTEOBJ * palPtr;
237     UINT numEntries;
238
239     TRACE("hpal=%p,start=%i,count=%i\n",hpalette,start,count );
240
241     hpalette = get_full_gdi_handle( hpalette );
242     if (hpalette == GetStockObject(DEFAULT_PALETTE)) return 0;
243     palPtr = GDI_GetObjPtr( hpalette, OBJ_PAL );
244     if (!palPtr) return 0;
245
246     numEntries = palPtr->count;
247     if (start >= numEntries)
248     {
249       GDI_ReleaseObj( hpalette );
250       return 0;
251     }
252     if (start+count > numEntries) count = numEntries - start;
253     memcpy( &palPtr->entries[start], entries, count * sizeof(PALETTEENTRY) );
254     GDI_ReleaseObj( hpalette );
255     UnrealizeObject( hpalette );
256     return count;
257 }
258
259
260 /***********************************************************************
261  * ResizePalette [GDI32.@]
262  *
263  * Resizes logical palette.
264  *
265  * RETURNS
266  *    Success: TRUE
267  *    Failure: FALSE
268  */
269 BOOL WINAPI ResizePalette(
270     HPALETTE hPal, /* [in] Handle of logical palette */
271     UINT cEntries) /* [in] Number of entries in logical palette */
272 {
273     PALETTEOBJ * palPtr = GDI_GetObjPtr( hPal, OBJ_PAL );
274     PALETTEENTRY *entries;
275
276     if( !palPtr ) return FALSE;
277     TRACE("hpal = %p, prev = %i, new = %i\n", hPal, palPtr->count, cEntries );
278
279     if (!(entries = HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
280                                  palPtr->entries, cEntries * sizeof(*palPtr->entries) )))
281     {
282         GDI_ReleaseObj( hPal );
283         return FALSE;
284     }
285     palPtr->entries = entries;
286     palPtr->count = cEntries;
287
288     GDI_ReleaseObj( hPal );
289     PALETTE_UnrealizeObject( hPal );
290     return TRUE;
291 }
292
293
294 /***********************************************************************
295  * AnimatePalette [GDI32.@]
296  *
297  * Replaces entries in logical palette.
298  *
299  * RETURNS
300  *    Success: TRUE
301  *    Failure: FALSE
302  *
303  * FIXME
304  *    Should use existing mapping when animating a primary palette
305  */
306 BOOL WINAPI AnimatePalette(
307     HPALETTE hPal,              /* [in] Handle to logical palette */
308     UINT StartIndex,            /* [in] First entry in palette */
309     UINT NumEntries,            /* [in] Count of entries in palette */
310     const PALETTEENTRY* PaletteColors) /* [in] Pointer to first replacement */
311 {
312     TRACE("%p (%i - %i)\n", hPal, StartIndex,StartIndex+NumEntries);
313
314     hPal = get_full_gdi_handle( hPal );
315     if( hPal != GetStockObject(DEFAULT_PALETTE) )
316     {
317         PALETTEOBJ * palPtr;
318         UINT pal_entries;
319         const PALETTEENTRY *pptr = PaletteColors;
320
321         palPtr = GDI_GetObjPtr( hPal, OBJ_PAL );
322         if (!palPtr) return 0;
323
324         pal_entries = palPtr->count;
325         if (StartIndex >= pal_entries)
326         {
327           GDI_ReleaseObj( hPal );
328           return 0;
329         }
330         if (StartIndex+NumEntries > pal_entries) NumEntries = pal_entries - StartIndex;
331         
332         for (NumEntries += StartIndex; StartIndex < NumEntries; StartIndex++, pptr++) {
333           /* According to MSDN, only animate PC_RESERVED colours */
334           if (palPtr->entries[StartIndex].peFlags & PC_RESERVED) {
335             TRACE("Animating colour (%d,%d,%d) to (%d,%d,%d)\n",
336               palPtr->entries[StartIndex].peRed,
337               palPtr->entries[StartIndex].peGreen,
338               palPtr->entries[StartIndex].peBlue,
339               pptr->peRed, pptr->peGreen, pptr->peBlue);
340             palPtr->entries[StartIndex] = *pptr;
341           } else {
342             TRACE("Not animating entry %d -- not PC_RESERVED\n", StartIndex);
343           }
344         }
345         GDI_ReleaseObj( hPal );
346         /* FIXME: check for palette selected in active window */
347     }
348     return TRUE;
349 }
350
351
352 /***********************************************************************
353  * SetSystemPaletteUse [GDI32.@]
354  *
355  * Specify whether the system palette contains 2 or 20 static colors.
356  *
357  * RETURNS
358  *    Success: Previous system palette
359  *    Failure: SYSPAL_ERROR
360  */
361 UINT WINAPI SetSystemPaletteUse(
362     HDC hdc,  /* [in] Handle of device context */
363     UINT use) /* [in] Palette-usage flag */
364 {
365     UINT old = SystemPaletteUse;
366
367     /* Device doesn't support colour palettes */
368     if (!(GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE)) {
369         return SYSPAL_ERROR;
370     }
371
372     switch (use) {
373         case SYSPAL_NOSTATIC:
374         case SYSPAL_NOSTATIC256:        /* WINVER >= 0x0500 */
375         case SYSPAL_STATIC:
376             SystemPaletteUse = use;
377             return old;
378         default:
379             return SYSPAL_ERROR;
380     }
381 }
382
383
384 /***********************************************************************
385  * GetSystemPaletteUse [GDI32.@]
386  *
387  * Gets state of system palette.
388  *
389  * RETURNS
390  *    Current state of system palette
391  */
392 UINT WINAPI GetSystemPaletteUse(
393     HDC hdc) /* [in] Handle of device context */
394 {
395     return SystemPaletteUse;
396 }
397
398
399 /***********************************************************************
400  * GetSystemPaletteEntries [GDI32.@]
401  *
402  * Gets range of palette entries.
403  *
404  * RETURNS
405  *    Success: Number of entries retrieved from palette
406  *    Failure: 0
407  */
408 UINT WINAPI GetSystemPaletteEntries(
409     HDC hdc,              /* [in]  Handle of device context */
410     UINT start,           /* [in]  Index of first entry to be retrieved */
411     UINT count,           /* [in]  Number of entries to be retrieved */
412     LPPALETTEENTRY entries) /* [out] Array receiving system-palette entries */
413 {
414     UINT ret = 0;
415     DC *dc;
416
417     TRACE("hdc=%p,start=%i,count=%i\n", hdc,start,count);
418
419     if ((dc = get_dc_ptr( hdc )))
420     {
421         PHYSDEV physdev = GET_DC_PHYSDEV( dc, pGetSystemPaletteEntries );
422         ret = physdev->funcs->pGetSystemPaletteEntries( physdev, start, count, entries );
423         release_dc_ptr( dc );
424     }
425     return ret;
426 }
427
428
429 /***********************************************************************
430  * GetNearestPaletteIndex [GDI32.@]
431  *
432  * Gets palette index for color.
433  *
434  * NOTES
435  *    Should index be initialized to CLR_INVALID instead of 0?
436  *
437  * RETURNS
438  *    Success: Index of entry in logical palette
439  *    Failure: CLR_INVALID
440  */
441 UINT WINAPI GetNearestPaletteIndex(
442     HPALETTE hpalette, /* [in] Handle of logical color palette */
443     COLORREF color)      /* [in] Color to be matched */
444 {
445     PALETTEOBJ* palObj = GDI_GetObjPtr( hpalette, OBJ_PAL );
446     UINT index  = 0;
447
448     if( palObj )
449     {
450         int i, diff = 0x7fffffff;
451         int r,g,b;
452         PALETTEENTRY* entry = palObj->entries;
453
454         for( i = 0; i < palObj->count && diff ; i++, entry++)
455         {
456             r = entry->peRed - GetRValue(color);
457             g = entry->peGreen - GetGValue(color);
458             b = entry->peBlue - GetBValue(color);
459
460             r = r*r + g*g + b*b;
461
462             if( r < diff ) { index = i; diff = r; }
463         }
464         GDI_ReleaseObj( hpalette );
465     }
466     TRACE("(%p,%06x): returning %d\n", hpalette, color, index );
467     return index;
468 }
469
470
471 /* null driver fallback implementation for GetNearestColor */
472 COLORREF nulldrv_GetNearestColor( PHYSDEV dev, COLORREF color )
473 {
474     unsigned char spec_type;
475
476     if (!(GetDeviceCaps( dev->hdc, RASTERCAPS ) & RC_PALETTE)) return color;
477
478     spec_type = color >> 24;
479     if (spec_type == 1 || spec_type == 2)
480     {
481         /* we need logical palette for PALETTERGB and PALETTEINDEX colorrefs */
482         UINT index;
483         PALETTEENTRY entry;
484         HPALETTE hpal = GetCurrentObject( dev->hdc, OBJ_PAL );
485
486         if (!hpal) hpal = GetStockObject( DEFAULT_PALETTE );
487         if (spec_type == 2) /* PALETTERGB */
488             index = GetNearestPaletteIndex( hpal, color );
489         else  /* PALETTEINDEX */
490             index = LOWORD(color);
491
492         if (!GetPaletteEntries( hpal, index, 1, &entry ))
493         {
494             WARN("RGB(%x) : idx %d is out of bounds, assuming NULL\n", color, index );
495             if (!GetPaletteEntries( hpal, 0, 1, &entry )) return CLR_INVALID;
496         }
497         color = RGB( entry.peRed, entry.peGreen, entry.peBlue );
498     }
499     return color & 0x00ffffff;
500 }
501
502
503 /***********************************************************************
504  * GetNearestColor [GDI32.@]
505  *
506  * Gets a system color to match.
507  *
508  * RETURNS
509  *    Success: Color from system palette that corresponds to given color
510  *    Failure: CLR_INVALID
511  */
512 COLORREF WINAPI GetNearestColor(
513     HDC hdc,      /* [in] Handle of device context */
514     COLORREF color) /* [in] Color to be matched */
515 {
516     COLORREF nearest = CLR_INVALID;
517     DC *dc;
518
519     if ((dc = get_dc_ptr( hdc )))
520     {
521         PHYSDEV physdev = GET_DC_PHYSDEV( dc, pGetNearestColor );
522         nearest = physdev->funcs->pGetNearestColor( physdev, color );
523         release_dc_ptr( dc );
524     }
525     return nearest;
526 }
527
528
529 /***********************************************************************
530  *           PALETTE_GetObject
531  */
532 static INT PALETTE_GetObject( HGDIOBJ handle, INT count, LPVOID buffer )
533 {
534     PALETTEOBJ *palette = GDI_GetObjPtr( handle, OBJ_PAL );
535
536     if (!palette) return 0;
537
538     if (buffer)
539     {
540         if (count > sizeof(WORD)) count = sizeof(WORD);
541         memcpy( buffer, &palette->count, count );
542     }
543     else count = sizeof(WORD);
544     GDI_ReleaseObj( handle );
545     return count;
546 }
547
548
549 /***********************************************************************
550  *           PALETTE_UnrealizeObject
551  */
552 static BOOL PALETTE_UnrealizeObject( HGDIOBJ handle )
553 {
554     PALETTEOBJ *palette = GDI_GetObjPtr( handle, OBJ_PAL );
555
556     if (palette)
557     {
558         unrealize_function unrealize = palette->unrealize;
559         palette->unrealize = NULL;
560         GDI_ReleaseObj( handle );
561         if (unrealize) unrealize( handle );
562     }
563
564     if (InterlockedCompareExchangePointer( (void **)&hLastRealizedPalette, 0, handle ) == handle)
565         TRACE("unrealizing palette %p\n", handle);
566
567     return TRUE;
568 }
569
570
571 /***********************************************************************
572  *           PALETTE_DeleteObject
573  */
574 static BOOL PALETTE_DeleteObject( HGDIOBJ handle )
575 {
576     PALETTEOBJ *obj;
577
578     PALETTE_UnrealizeObject( handle );
579     if (!(obj = free_gdi_handle( handle ))) return FALSE;
580     HeapFree( GetProcessHeap(), 0, obj->entries );
581     return HeapFree( GetProcessHeap(), 0, obj );
582 }
583
584
585 /***********************************************************************
586  *           GDISelectPalette    (Not a Windows API)
587  */
588 HPALETTE WINAPI GDISelectPalette( HDC hdc, HPALETTE hpal, WORD wBkg)
589 {
590     HPALETTE ret = 0;
591     DC *dc;
592
593     TRACE("%p %p\n", hdc, hpal );
594
595     hpal = get_full_gdi_handle( hpal );
596     if (GetObjectType(hpal) != OBJ_PAL)
597     {
598       WARN("invalid selected palette %p\n",hpal);
599       return 0;
600     }
601     if ((dc = get_dc_ptr( hdc )))
602     {
603         PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSelectPalette );
604         ret = dc->hPalette;
605         if (physdev->funcs->pSelectPalette( physdev, hpal, FALSE ))
606         {
607             dc->hPalette = hpal;
608             if (!wBkg) hPrimaryPalette = hpal;
609         }
610         else ret = 0;
611         release_dc_ptr( dc );
612     }
613     return ret;
614 }
615
616
617 /***********************************************************************
618  *           GDIRealizePalette    (Not a Windows API)
619  */
620 UINT WINAPI GDIRealizePalette( HDC hdc )
621 {
622     UINT realized = 0;
623     DC* dc = get_dc_ptr( hdc );
624
625     if (!dc) return 0;
626
627     TRACE("%p...\n", hdc );
628
629     if( dc->hPalette == GetStockObject( DEFAULT_PALETTE ))
630     {
631         PHYSDEV physdev = GET_DC_PHYSDEV( dc, pRealizeDefaultPalette );
632         realized = physdev->funcs->pRealizeDefaultPalette( physdev );
633     }
634     else if (InterlockedExchangePointer( (void **)&hLastRealizedPalette, dc->hPalette ) != dc->hPalette)
635     {
636         PHYSDEV physdev = GET_DC_PHYSDEV( dc, pRealizePalette );
637         PALETTEOBJ *palPtr = GDI_GetObjPtr( dc->hPalette, OBJ_PAL );
638         if (palPtr)
639         {
640             realized = physdev->funcs->pRealizePalette( physdev, dc->hPalette,
641                                                         (dc->hPalette == hPrimaryPalette) );
642             palPtr->unrealize = physdev->funcs->pUnrealizePalette;
643             GDI_ReleaseObj( dc->hPalette );
644         }
645     }
646     else TRACE("  skipping (hLastRealizedPalette = %p)\n", hLastRealizedPalette);
647
648     release_dc_ptr( dc );
649     TRACE("   realized %i colors.\n", realized );
650     return realized;
651 }
652
653
654 /***********************************************************************
655  * SelectPalette [GDI32.@]
656  *
657  * Selects logical palette into DC.
658  *
659  * RETURNS
660  *    Success: Previous logical palette
661  *    Failure: NULL
662  */
663 HPALETTE WINAPI SelectPalette(
664     HDC hDC,               /* [in] Handle of device context */
665     HPALETTE hPal,         /* [in] Handle of logical color palette */
666     BOOL bForceBackground) /* [in] Foreground/background mode */
667 {
668     return pfnSelectPalette( hDC, hPal, bForceBackground );
669 }
670
671
672 /***********************************************************************
673  * RealizePalette [GDI32.@]
674  *
675  * Maps palette entries to system palette.
676  *
677  * RETURNS
678  *    Success: Number of entries in logical palette
679  *    Failure: GDI_ERROR
680  */
681 UINT WINAPI RealizePalette(
682     HDC hDC) /* [in] Handle of device context */
683 {
684     return pfnRealizePalette( hDC );
685 }
686
687
688 typedef HWND (WINAPI *WindowFromDC_funcptr)( HDC );
689 typedef BOOL (WINAPI *RedrawWindow_funcptr)( HWND, const RECT *, HRGN, UINT );
690
691 /**********************************************************************
692  * UpdateColors [GDI32.@]
693  *
694  * Remaps current colors to logical palette.
695  *
696  * RETURNS
697  *    Success: TRUE
698  *    Failure: FALSE
699  */
700 BOOL WINAPI UpdateColors(
701     HDC hDC) /* [in] Handle of device context */
702 {
703     HMODULE mod;
704     int size = GetDeviceCaps( hDC, SIZEPALETTE );
705
706     if (!size) return 0;
707
708     mod = GetModuleHandleA("user32.dll");
709     if (mod)
710     {
711         WindowFromDC_funcptr pWindowFromDC = (WindowFromDC_funcptr)GetProcAddress(mod,"WindowFromDC");
712         if (pWindowFromDC)
713         {
714             HWND hWnd = pWindowFromDC( hDC );
715
716             /* Docs say that we have to remap current drawable pixel by pixel
717              * but it would take forever given the speed of XGet/PutPixel.
718              */
719             if (hWnd && size)
720             {
721                 RedrawWindow_funcptr pRedrawWindow = (void *)GetProcAddress( mod, "RedrawWindow" );
722                 if (pRedrawWindow) pRedrawWindow( hWnd, NULL, 0, RDW_INVALIDATE );
723             }
724         }
725     }
726     return 0x666;
727 }
728
729 /*********************************************************************
730  *           SetMagicColors   (GDI32.@)
731  */
732 BOOL WINAPI SetMagicColors(HDC hdc, ULONG u1, ULONG u2)
733 {
734     FIXME("(%p 0x%08x 0x%08x): stub\n", hdc, u1, u2);
735     return TRUE;
736 }