2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Win32k subsystem
4 * PURPOSE: GDI Palette Functions
5 * FILE: win32ss/gdi/ntgdi/palette.c
6 * PROGRAMERS: Jason Filby
15 #define PAL_SETPOWNER 0x8000
16 #define MAX_PALCOLORS 65536
18 static UINT SystemPaletteUse
= SYSPAL_NOSTATIC
; /* The program need save the pallete and restore it */
20 PALETTE gpalRGB
, gpalBGR
, gpalRGB555
, gpalRGB565
, *gppalMono
, *gppalDefault
;
21 PPALETTE appalSurfaceDefault
[11];
23 const PALETTEENTRY g_sysPalTemplate
[NB_RESERVED_COLORS
] =
25 // First 10 entries in the system palette
26 // Red Green Blue Flags
27 { 0x00, 0x00, 0x00, PC_SYS_USED
},
28 { 0x80, 0x00, 0x00, PC_SYS_USED
},
29 { 0x00, 0x80, 0x00, PC_SYS_USED
},
30 { 0x80, 0x80, 0x00, PC_SYS_USED
},
31 { 0x00, 0x00, 0x80, PC_SYS_USED
},
32 { 0x80, 0x00, 0x80, PC_SYS_USED
},
33 { 0x00, 0x80, 0x80, PC_SYS_USED
},
34 { 0xc0, 0xc0, 0xc0, PC_SYS_USED
},
35 { 0xc0, 0xdc, 0xc0, PC_SYS_USED
},
36 { 0xa6, 0xca, 0xf0, PC_SYS_USED
},
38 // ... c_min/2 dynamic colorcells
39 // ... gap (for sparse palettes)
40 // ... c_min/2 dynamic colorcells
42 { 0xff, 0xfb, 0xf0, PC_SYS_USED
},
43 { 0xa0, 0xa0, 0xa4, PC_SYS_USED
},
44 { 0x80, 0x80, 0x80, PC_SYS_USED
},
45 { 0xff, 0x00, 0x00, PC_SYS_USED
},
46 { 0x00, 0xff, 0x00, PC_SYS_USED
},
47 { 0xff, 0xff, 0x00, PC_SYS_USED
},
48 { 0x00, 0x00, 0xff, PC_SYS_USED
},
49 { 0xff, 0x00, 0xff, PC_SYS_USED
},
50 { 0x00, 0xff, 0xff, PC_SYS_USED
},
51 { 0xff, 0xff, 0xff, PC_SYS_USED
} // Last 10
54 unsigned short GetNumberOfBits(unsigned int dwMask
)
57 for (wBits
= 0; dwMask
; dwMask
= dwMask
& (dwMask
- 1))
62 // Create the system palette
68 // Create default palette (20 system colors)
69 gppalDefault
= PALETTE_AllocPalWithHandle(PAL_INDEXED
,
73 GDIOBJ_vReferenceObjectByPointer(&gppalDefault
->BaseObject
);
74 PALETTE_UnlockPalette(gppalDefault
);
76 /* palette_size = visual->map_entries; */
78 gpalRGB
.flFlags
= PAL_RGB
;
79 gpalRGB
.RedMask
= RGB(0xFF, 0x00, 0x00);
80 gpalRGB
.GreenMask
= RGB(0x00, 0xFF, 0x00);
81 gpalRGB
.BlueMask
= RGB(0x00, 0x00, 0xFF);
82 gpalRGB
.BaseObject
.ulShareCount
= 1;
83 gpalRGB
.BaseObject
.BaseFlags
= 0 ;
85 gpalBGR
.flFlags
= PAL_BGR
;
86 gpalBGR
.RedMask
= RGB(0x00, 0x00, 0xFF);
87 gpalBGR
.GreenMask
= RGB(0x00, 0xFF, 0x00);
88 gpalBGR
.BlueMask
= RGB(0xFF, 0x00, 0x00);
89 gpalBGR
.BaseObject
.ulShareCount
= 1;
90 gpalBGR
.BaseObject
.BaseFlags
= 0 ;
92 gpalRGB555
.flFlags
= PAL_RGB16_555
| PAL_BITFIELDS
;
93 gpalRGB555
.RedMask
= 0x7C00;
94 gpalRGB555
.GreenMask
= 0x3E0;
95 gpalRGB555
.BlueMask
= 0x1F;
96 gpalRGB555
.BaseObject
.ulShareCount
= 1;
97 gpalRGB555
.BaseObject
.BaseFlags
= 0 ;
99 gpalRGB565
.flFlags
= PAL_RGB16_565
| PAL_BITFIELDS
;
100 gpalRGB565
.RedMask
= 0xF800;
101 gpalRGB565
.GreenMask
= 0x7E0;
102 gpalRGB565
.BlueMask
= 0x1F;
103 gpalRGB565
.BaseObject
.ulShareCount
= 1;
104 gpalRGB565
.BaseObject
.BaseFlags
= 0 ;
106 gppalMono
= PALETTE_AllocPalette(PAL_MONOCHROME
|PAL_INDEXED
, 2, NULL
, 0, 0, 0);
107 PALETTE_vSetRGBColorForIndex(gppalMono
, 0, 0x000000);
108 PALETTE_vSetRGBColorForIndex(gppalMono
, 1, 0xffffff);
110 /* Initialize default surface palettes */
111 appalSurfaceDefault
[BMF_1BPP
] = gppalMono
;
112 appalSurfaceDefault
[BMF_4BPP
] = gppalDefault
;
113 appalSurfaceDefault
[BMF_8BPP
] = gppalDefault
;
114 appalSurfaceDefault
[BMF_16BPP
] = &gpalRGB565
;
115 appalSurfaceDefault
[BMF_24BPP
] = &gpalBGR
;
116 appalSurfaceDefault
[BMF_32BPP
] = &gpalBGR
;
117 appalSurfaceDefault
[BMF_4RLE
] = gppalDefault
;
118 appalSurfaceDefault
[BMF_8RLE
] = gppalDefault
;
119 appalSurfaceDefault
[BMF_JPEG
] = &gpalRGB
;
120 appalSurfaceDefault
[BMF_PNG
] = &gpalRGB
;
122 return STATUS_SUCCESS
;
125 VOID FASTCALL
PALETTE_ValidateFlags(PALETTEENTRY
* lpPalE
, INT size
)
129 lpPalE
[i
].peFlags
= PC_SYS_USED
| (lpPalE
[i
].peFlags
& 0x07);
135 PALETTE_AllocPalette(
138 _In_opt_
const PALETTEENTRY
* pEntries
,
144 ULONG fl
= 0, cjSize
= sizeof(PALETTE
);
146 /* Check if the palette has entries */
147 if (iMode
& PAL_INDEXED
)
149 /* Check color count */
150 if ((cColors
== 0) || (cColors
> 1024)) return NULL
;
152 /* Allocate enough space for the palete entries */
153 cjSize
+= cColors
* sizeof(PALETTEENTRY
);
157 /* There are no palette entries */
160 /* We can use the lookaside list */
161 fl
|= BASEFLAG_LOOKASIDE
;
164 /* Allocate the object (without a handle!) */
165 ppal
= (PPALETTE
)GDIOBJ_AllocateObject(GDIObjType_PAL_TYPE
, cjSize
, fl
);
171 /* Set mode, color count and entry pointer */
172 ppal
->flFlags
= iMode
;
173 ppal
->NumColors
= cColors
;
174 ppal
->IndexedColors
= ppal
->apalColors
;
176 /* Check what kind of palette this is */
177 if (iMode
& PAL_INDEXED
)
179 /* Check if we got a color array */
182 /* Copy the entries */
183 RtlCopyMemory(ppal
->IndexedColors
, pEntries
, cColors
* sizeof(pEntries
[0]));
186 else if (iMode
& PAL_BITFIELDS
)
188 /* Copy the color masks */
189 ppal
->RedMask
= flRed
;
190 ppal
->GreenMask
= flGreen
;
191 ppal
->BlueMask
= flBlue
;
193 /* Check what masks we have and set optimization flags */
194 if ((flRed
== 0x7c00) && (flGreen
== 0x3E0) && (flBlue
== 0x1F))
195 ppal
->flFlags
|= PAL_RGB16_555
;
196 else if ((flRed
== 0xF800) && (flGreen
== 0x7E0) && (flBlue
== 0x1F))
197 ppal
->flFlags
|= PAL_RGB16_565
;
198 else if ((flRed
== 0xFF0000) && (flGreen
== 0xFF00) && (flBlue
== 0xFF))
199 ppal
->flFlags
|= PAL_BGR
;
200 else if ((flRed
== 0xFF) && (flGreen
== 0xFF00) && (flBlue
== 0xFF0000))
201 ppal
->flFlags
|= PAL_RGB
;
209 PALETTE_AllocPalWithHandle(
212 _In_opt_
const PALETTEENTRY
* pEntries
,
219 /* Allocate the palette without a handle */
220 ppal
= PALETTE_AllocPalette(iMode
, cColors
, pEntries
, flRed
, flGreen
, flBlue
);
221 if (!ppal
) return NULL
;
223 /* Insert the palette into the handle table */
224 if (!GDIOBJ_hInsertObject(&ppal
->BaseObject
, GDI_OBJ_HMGR_POWNED
))
226 DPRINT1("Could not insert palette into handle table.\n");
227 GDIOBJ_vFreeObject(&ppal
->BaseObject
);
236 PALETTE_vCleanup(PVOID ObjectBody
)
238 PPALETTE pPal
= (PPALETTE
)ObjectBody
;
239 if (pPal
->IndexedColors
&& pPal
->IndexedColors
!= pPal
->apalColors
)
241 ExFreePoolWithTag(pPal
->IndexedColors
, TAG_PALETTE
);
247 PALETTE_GetObject(PPALETTE ppal
, INT cbCount
, LPLOGBRUSH lpBuffer
)
254 if ((UINT
)cbCount
< sizeof(WORD
)) return 0;
255 *((WORD
*)lpBuffer
) = (WORD
)ppal
->NumColors
;
261 PALETTE_ulGetNearestPaletteIndex(PALETTE
* ppal
, ULONG iColor
)
263 ULONG ulDiff
, ulColorDiff
, ulMinimalDiff
= 0xFFFFFF;
264 ULONG i
, ulBestIndex
= 0;
265 PALETTEENTRY peColor
= *(PPALETTEENTRY
)&iColor
;
267 /* Loop all palette entries */
268 for (i
= 0; i
< ppal
->NumColors
; i
++)
270 /* Calculate distance in the color cube */
271 ulDiff
= peColor
.peRed
- ppal
->IndexedColors
[i
].peRed
;
272 ulColorDiff
= ulDiff
* ulDiff
;
273 ulDiff
= peColor
.peGreen
- ppal
->IndexedColors
[i
].peGreen
;
274 ulColorDiff
+= ulDiff
* ulDiff
;
275 ulDiff
= peColor
.peBlue
- ppal
->IndexedColors
[i
].peBlue
;
276 ulColorDiff
+= ulDiff
* ulDiff
;
278 /* Check for a better match */
279 if (ulColorDiff
< ulMinimalDiff
)
282 ulMinimalDiff
= ulColorDiff
;
284 /* Break on exact match */
285 if (ulMinimalDiff
== 0) break;
294 PALETTE_ulGetNearestBitFieldsIndex(PALETTE
* ppal
, ULONG ulColor
)
298 // FIXME: HACK, should be stored already
299 ppal
->ulRedShift
= CalculateShift(RGB(0xff,0,0), ppal
->RedMask
);
300 ppal
->ulGreenShift
= CalculateShift(RGB(0,0xff,0), ppal
->GreenMask
);
301 ppal
->ulBlueShift
= CalculateShift(RGB(0,0,0xff), ppal
->BlueMask
);
303 ulNewColor
= _rotl(ulColor
, ppal
->ulRedShift
) & ppal
->RedMask
;
304 ulNewColor
|= _rotl(ulColor
, ppal
->ulGreenShift
) & ppal
->GreenMask
;
305 ulNewColor
|= _rotl(ulColor
, ppal
->ulBlueShift
) & ppal
->BlueMask
;
312 PALETTE_ulGetNearestIndex(PALETTE
* ppal
, ULONG ulColor
)
314 if (ppal
->flFlags
& PAL_INDEXED
) // Use fl & PALINDEXED
315 return PALETTE_ulGetNearestPaletteIndex(ppal
, ulColor
);
317 return PALETTE_ulGetNearestBitFieldsIndex(ppal
, ulColor
);
322 PALETTE_vGetBitMasks(PPALETTE ppal
, PULONG pulColors
)
326 if (ppal
->flFlags
& PAL_INDEXED
|| ppal
->flFlags
& PAL_RGB
)
328 pulColors
[0] = RGB(0xFF, 0x00, 0x00);
329 pulColors
[1] = RGB(0x00, 0xFF, 0x00);
330 pulColors
[2] = RGB(0x00, 0x00, 0xFF);
332 else if (ppal
->flFlags
& PAL_BGR
)
334 pulColors
[0] = RGB(0x00, 0x00, 0xFF);
335 pulColors
[1] = RGB(0x00, 0xFF, 0x00);
336 pulColors
[2] = RGB(0xFF, 0x00, 0x00);
338 else if (ppal
->flFlags
& PAL_BITFIELDS
)
340 pulColors
[0] = ppal
->RedMask
;
341 pulColors
[1] = ppal
->GreenMask
;
342 pulColors
[2] = ppal
->BlueMask
;
348 ColorCorrection(PPALETTE PalGDI
, PPALETTEENTRY PaletteEntry
, ULONG Colors
)
350 PPDEVOBJ ppdev
= (PPDEVOBJ
)PalGDI
->hPDev
;
354 if (ppdev
->flFlags
& PDEV_GAMMARAMP_TABLE
)
357 PGAMMARAMP GammaRamp
= (PGAMMARAMP
)ppdev
->pvGammaRamp
;
358 for ( i
= 0; i
< Colors
; i
++)
360 PaletteEntry
[i
].peRed
+= GammaRamp
->Red
[i
];
361 PaletteEntry
[i
].peGreen
+= GammaRamp
->Green
[i
];
362 PaletteEntry
[i
].peBlue
+= GammaRamp
->Blue
[i
];
368 /** Display Driver Interface **************************************************/
386 ppal
= PALETTE_AllocPalette(iMode
, cColors
, (PPALETTEENTRY
)pulColors
, flRed
, flGreen
, flBlue
);
387 if (!ppal
) return NULL
;
389 hpal
= GDIOBJ_hInsertObject(&ppal
->BaseObject
, GDI_OBJ_HMGR_PUBLIC
);
392 DPRINT1("Could not insert palette into handle table.\n");
393 GDIOBJ_vFreeObject(&ppal
->BaseObject
);
397 PALETTE_UnlockPalette(ppal
);
406 EngDeletePalette(IN HPALETTE hpal
)
410 ppal
= PALETTE_ShareLockPalette(hpal
);
411 if (!ppal
) return FALSE
;
413 GDIOBJ_vDeleteObject(&ppal
->BaseObject
);
423 PALOBJ_cGetColors(PALOBJ
*PalObj
, ULONG Start
, ULONG Colors
, ULONG
*PaletteEntry
)
427 PalGDI
= (PALETTE
*)PalObj
;
429 if (Start
>= PalGDI
->NumColors
)
432 Colors
= min(Colors
, PalGDI
->NumColors
- Start
);
434 /* NOTE: PaletteEntry ULONGs are in the same order as PALETTEENTRY. */
435 RtlCopyMemory(PaletteEntry
, PalGDI
->IndexedColors
+ Start
, sizeof(ULONG
) * Colors
);
437 if (PalGDI
->flFlags
& PAL_GAMMACORRECTION
)
438 ColorCorrection(PalGDI
, (PPALETTEENTRY
)PaletteEntry
, Colors
);
444 /** Systemcall Interface ******************************************************/
448 GreCreatePaletteInternal(
449 IN LPLOGPALETTE pLogPal
,
452 HPALETTE hpal
= NULL
;
455 pLogPal
->palNumEntries
= cEntries
;
456 ppal
= PALETTE_AllocPalWithHandle(PAL_INDEXED
,
458 pLogPal
->palPalEntry
,
463 PALETTE_ValidateFlags(ppal
->IndexedColors
, ppal
->NumColors
);
465 hpal
= ppal
->BaseObject
.hHmgr
;
466 PALETTE_UnlockPalette(ppal
);
477 NtGdiCreatePaletteInternal(
478 IN LPLOGPALETTE plogpalUser
,
481 HPALETTE hpal
= NULL
;
485 ppal
= PALETTE_AllocPalWithHandle(PAL_INDEXED
, cEntries
, NULL
, 0, 0, 0);
491 cjSize
= FIELD_OFFSET(LOGPALETTE
, palPalEntry
[cEntries
]);
495 ProbeForRead(plogpalUser
, cjSize
, 1);
497 for (i
= 0; i
< cEntries
; i
++)
499 ppal
->IndexedColors
[i
] = plogpalUser
->palPalEntry
[i
];
502 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
504 GDIOBJ_vDeleteObject(&ppal
->BaseObject
);
505 _SEH2_YIELD(return NULL
);
509 PALETTE_ValidateFlags(ppal
->IndexedColors
, cEntries
);
510 hpal
= ppal
->BaseObject
.hHmgr
;
511 PALETTE_UnlockPalette(ppal
);
518 NtGdiCreateHalftonePalette(HDC hDC
)
521 PALETTEENTRY PalEntries
[256];
524 HPALETTE hpal
= NULL
;
526 pdc
= DC_LockDc(hDC
);
529 EngSetLastError(ERROR_INVALID_HANDLE
);
533 RtlZeroMemory(PalEntries
, sizeof(PalEntries
));
535 /* First and last ten entries are default ones */
536 for (i
= 0; i
< 10; i
++)
538 PalEntries
[i
].peRed
= g_sysPalTemplate
[i
].peRed
;
539 PalEntries
[i
].peGreen
= g_sysPalTemplate
[i
].peGreen
;
540 PalEntries
[i
].peBlue
= g_sysPalTemplate
[i
].peBlue
;
542 PalEntries
[246 + i
].peRed
= g_sysPalTemplate
[10 + i
].peRed
;
543 PalEntries
[246 + i
].peGreen
= g_sysPalTemplate
[10 + i
].peGreen
;
544 PalEntries
[246 + i
].peBlue
= g_sysPalTemplate
[10 + i
].peBlue
;
547 ppal
= PALETTE_ShareLockPalette(pdc
->dclevel
.hpal
);
548 if (ppal
&& (ppal
->flFlags
& PAL_INDEXED
))
550 /* FIXME: optimize the palette for the current palette */
555 for (r
= 0; r
< 6; r
++)
557 for (g
= 0; g
< 6; g
++)
559 for (b
= 0; b
< 6; b
++)
561 i
= r
+ g
*6 + b
*36 + 10;
562 PalEntries
[i
].peRed
= r
* 51;
563 PalEntries
[i
].peGreen
= g
* 51;
564 PalEntries
[i
].peBlue
= b
* 51;
569 for (i
= 216; i
< 246; i
++)
571 int v
= (i
- 216) << 3;
572 PalEntries
[i
].peRed
= v
;
573 PalEntries
[i
].peGreen
= v
;
574 PalEntries
[i
].peBlue
= v
;
579 PALETTE_ShareUnlockPalette(ppal
);
583 ppal
= PALETTE_AllocPalWithHandle(PAL_INDEXED
, 256, PalEntries
, 0, 0, 0);
586 hpal
= ppal
->BaseObject
.hHmgr
;
587 PALETTE_UnlockPalette(ppal
);
599 /* PALOBJ *palPtr = (PALOBJ*)AccessUserObject(hPal);
600 UINT cPrevEnt, prevVer;
601 INT prevsize, size = sizeof(LOGPALETTE) + (cEntries - 1) * sizeof(PALETTEENTRY);
602 XLATEOBJ *XlateObj = NULL;
604 if(!palPtr) return FALSE;
605 cPrevEnt = palPtr->logpalette->palNumEntries;
606 prevVer = palPtr->logpalette->palVersion;
607 prevsize = sizeof(LOGPALETTE) + (cPrevEnt - 1) * sizeof(PALETTEENTRY) + sizeof(int*) + sizeof(GDIOBJHDR);
608 size += sizeof(int*) + sizeof(GDIOBJHDR);
609 XlateObj = palPtr->logicalToSystem;
611 if (!(palPtr = GDI_ReallocObject(size, hPal, palPtr))) return FALSE;
615 XLATEOBJ *NewXlateObj = (int*) HeapReAlloc(GetProcessHeap(), 0, XlateObj, cEntries * sizeof(int));
616 if(NewXlateObj == NULL)
618 ERR("Can not resize logicalToSystem -- out of memory!");
619 GDI_ReleaseObj( hPal );
622 palPtr->logicalToSystem = NewXlateObj;
625 if(cEntries > cPrevEnt)
627 if(XlateObj) memset(palPtr->logicalToSystem + cPrevEnt, 0, (cEntries - cPrevEnt)*sizeof(int));
628 memset( (BYTE*)palPtr + prevsize, 0, size - prevsize );
629 PALETTE_ValidateFlags((PALETTEENTRY*)((BYTE*)palPtr + prevsize), cEntries - cPrevEnt );
631 palPtr->logpalette->palNumEntries = cEntries;
632 palPtr->logpalette->palVersion = prevVer;
633 // GDI_ReleaseObj( hPal );
642 NtGdiGetColorAdjustment(
644 LPCOLORADJUSTMENT pca
)
652 NtGdiSetColorAdjustment(
654 LPCOLORADJUSTMENT pca
)
662 NtGdiGetNearestColor(
666 COLORREF nearest
= CLR_INVALID
;
675 EngSetLastError(ERROR_INVALID_HANDLE
);
679 /// FIXME: shouldn't dereference pSurface while the PDEV is not locked
680 if(dc
->dclevel
.pSurface
== NULL
)
683 ppal
= dc
->dclevel
.pSurface
->ppal
;
685 /* Translate the color to the DC format */
686 Color
= TranslateCOLORREF(dc
, Color
);
688 /* XLATE it back to RGB color space */
689 EXLATEOBJ_vInitialize(&exlo
,
693 RGB(0xff, 0xff, 0xff),
696 nearest
= XLATEOBJ_iXlate(&exlo
.xlo
, Color
);
698 EXLATEOBJ_vCleanup(&exlo
);
708 NtGdiGetNearestPaletteIndex(
712 PPALETTE ppal
= PALETTE_ShareLockPalette(hpal
);
717 if (ppal
->flFlags
& PAL_INDEXED
)
719 /* Return closest match for the given RGB color */
720 index
= PALETTE_ulGetNearestPaletteIndex(ppal
, crColor
);
722 // else SetLastError ?
723 PALETTE_ShareUnlockPalette(ppal
);
731 IntGdiRealizePalette(HDC hDC
)
735 PALETTE
*ppalSurf
, *ppalDC
;
737 pdc
= DC_LockDc(hDC
);
740 EngSetLastError(ERROR_INVALID_HANDLE
);
744 if (!pdc
->dclevel
.pSurface
)
749 if (pdc
->dctype
== DCTYPE_DIRECT
)
751 static BOOL g_WarnedOnce
= FALSE
;
760 /// FIXME: shouldn't dereference pSurface while the PDEV is not locked
761 ppalSurf
= pdc
->dclevel
.pSurface
->ppal
;
762 ppalDC
= pdc
->dclevel
.ppal
;
764 if (!(ppalSurf
->flFlags
& PAL_INDEXED
))
770 ASSERT(ppalDC
->flFlags
& PAL_INDEXED
);
772 // FIXME: Should we resize ppalSurf if it's too small?
773 realize
= (ppalDC
->NumColors
< ppalSurf
->NumColors
) ? ppalDC
->NumColors
: ppalSurf
->NumColors
;
775 for (i
=0; i
<realize
; i
++)
777 InterlockedExchange((LONG
*)&ppalSurf
->IndexedColors
[i
], *(LONG
*)&ppalDC
->IndexedColors
[i
]);
786 IntAnimatePalette(HPALETTE hPal
,
789 CONST PPALETTEENTRY PaletteColors
)
793 if( hPal
!= NtGdiGetStockObject(DEFAULT_PALETTE
) )
797 const PALETTEENTRY
*pptr
= PaletteColors
;
799 palPtr
= PALETTE_ShareLockPalette(hPal
);
800 if (!palPtr
) return FALSE
;
802 pal_entries
= palPtr
->NumColors
;
803 if (StartIndex
>= pal_entries
)
805 PALETTE_ShareUnlockPalette(palPtr
);
808 if (StartIndex
+NumEntries
> pal_entries
) NumEntries
= pal_entries
- StartIndex
;
810 for (NumEntries
+= StartIndex
; StartIndex
< NumEntries
; StartIndex
++, pptr
++)
812 /* According to MSDN, only animate PC_RESERVED colours */
813 if (palPtr
->IndexedColors
[StartIndex
].peFlags
& PC_RESERVED
)
815 memcpy( &palPtr
->IndexedColors
[StartIndex
], pptr
,
816 sizeof(PALETTEENTRY
) );
818 PALETTE_ValidateFlags(&palPtr
->IndexedColors
[StartIndex
], 1);
822 PALETTE_ShareUnlockPalette(palPtr
);
825 /* FIXME: This is completely broken! We cannot call UserGetDesktopWindow
826 without first acquiring the USER lock. But the whole process here is
827 screwed anyway. Instead of messing with the desktop DC, we need to
828 check, whether the palette is associated with a PDEV and whether that
829 PDEV supports palette operations. Then we need to call pfnDrvSetPalette.
830 But since IntGdiRealizePalette() is not even implemented for direct DCs,
831 we can as well just do nothing, that will at least not ASSERT!
832 I leave the whole thing here, to scare people away, who want to "fix" it. */
834 /* Immediately apply the new palette if current window uses it */
835 Wnd
= UserGetDesktopWindow();
836 hDC
= UserGetWindowDC(Wnd
);
840 if (dc
->dclevel
.hpal
== hPal
)
843 IntGdiRealizePalette(hDC
);
848 UserReleaseDC(Wnd
,hDC
, FALSE
);
855 IntGetPaletteEntries(
864 palGDI
= (PPALETTE
) PALETTE_ShareLockPalette(hpal
);
870 numEntries
= palGDI
->NumColors
;
873 if (numEntries
< StartIndex
+ Entries
)
875 Entries
= numEntries
- StartIndex
;
877 if (numEntries
<= StartIndex
)
879 PALETTE_ShareUnlockPalette(palGDI
);
882 memcpy(pe
, palGDI
->IndexedColors
+ StartIndex
, Entries
* sizeof(PALETTEENTRY
));
886 Entries
= numEntries
;
889 PALETTE_ShareUnlockPalette(palGDI
);
894 IntGetSystemPaletteEntries(HDC hDC
,
899 PPALETTE palGDI
= NULL
;
901 UINT EntriesSize
= 0;
906 EngSetLastError(ERROR_INVALID_PARAMETER
);
912 EntriesSize
= Entries
* sizeof(pe
[0]);
913 if (Entries
!= EntriesSize
/ sizeof(pe
[0]))
915 /* Integer overflow! */
916 EngSetLastError(ERROR_INVALID_PARAMETER
);
921 if (!(dc
= DC_LockDc(hDC
)))
923 EngSetLastError(ERROR_INVALID_HANDLE
);
927 palGDI
= PALETTE_ShareLockPalette(dc
->dclevel
.hpal
);
932 if (StartIndex
>= palGDI
->NumColors
)
934 else if (Entries
> palGDI
->NumColors
- StartIndex
)
935 Entries
= palGDI
->NumColors
- StartIndex
;
938 palGDI
->IndexedColors
+ StartIndex
,
939 Entries
* sizeof(pe
[0]));
945 Ret
= dc
->ppdev
->gdiinfo
.ulNumPalReg
;
950 PALETTE_ShareUnlockPalette(palGDI
);
960 IntSetPaletteEntries(
964 CONST LPPALETTEENTRY pe
)
969 if ((UINT_PTR
)hpal
& GDI_HANDLE_STOCK_MASK
)
974 palGDI
= PALETTE_ShareLockPalette(hpal
);
975 if (!palGDI
) return 0;
977 numEntries
= palGDI
->NumColors
;
978 if (Start
>= numEntries
)
980 PALETTE_ShareUnlockPalette(palGDI
);
983 if (numEntries
< Start
+ Entries
)
985 Entries
= numEntries
- Start
;
987 memcpy(palGDI
->IndexedColors
+ Start
, pe
, Entries
* sizeof(PALETTEENTRY
));
988 PALETTE_ShareUnlockPalette(palGDI
);
1004 PPALETTE ppal
= NULL
;
1005 ULONG i
, iEndIndex
, iResult
= 0;
1008 pdc
= DC_LockDc(hdc
);
1014 /* Get the surface from the DC */
1015 psurf
= pdc
->dclevel
.pSurface
;
1017 /* Check if we have the default surface */
1020 /* Use a mono palette */
1024 else if (psurf
->SurfObj
.iType
== STYPE_BITMAP
)
1026 /* Get the palette of the surface */
1030 /* Check if this is an indexed palette and the range is ok */
1031 if (ppal
&& (ppal
->flFlags
& PAL_INDEXED
) &&
1032 (iStartIndex
< ppal
->NumColors
))
1034 /* Calculate the end of the operation */
1035 iEndIndex
= min(iStartIndex
+ cEntries
, ppal
->NumColors
);
1037 /* Check what operation to perform */
1040 /* Loop all colors and set the palette entries */
1041 for (i
= iStartIndex
; i
< iEndIndex
; i
++, prgbColors
++)
1043 ppal
->IndexedColors
[i
].peRed
= prgbColors
->rgbRed
;
1044 ppal
->IndexedColors
[i
].peGreen
= prgbColors
->rgbGreen
;
1045 ppal
->IndexedColors
[i
].peBlue
= prgbColors
->rgbBlue
;
1048 /* Mark the dc brushes invalid */
1049 pdc
->pdcattr
->ulDirty_
|= DIRTY_FILL
|DIRTY_LINE
|
1050 DIRTY_BACKGROUND
|DIRTY_TEXT
;
1054 /* Loop all colors and get the palette entries */
1055 for (i
= iStartIndex
; i
< iEndIndex
; i
++, prgbColors
++)
1057 prgbColors
->rgbRed
= ppal
->IndexedColors
[i
].peRed
;
1058 prgbColors
->rgbGreen
= ppal
->IndexedColors
[i
].peGreen
;
1059 prgbColors
->rgbBlue
= ppal
->IndexedColors
[i
].peBlue
;
1060 prgbColors
->rgbReserved
= 0;
1064 /* Calculate how many entries were modified */
1065 iResult
= iEndIndex
- iStartIndex
;
1081 _When_(bInbound
!=0, _In_reads_bytes_(cEntries
*sizeof(PALETTEENTRY
)))
1082 _When_(bInbound
==0, _Out_writes_bytes_(cEntries
*sizeof(PALETTEENTRY
))) LPVOID pUnsafeEntries
,
1087 LPVOID pEntries
= NULL
;
1095 cjSize
= cEntries
* sizeof(PALETTEENTRY
);
1096 pEntries
= ExAllocatePoolWithTag(PagedPool
, cjSize
, TAG_PALETTE
);
1104 ProbeForRead(pUnsafeEntries
, cjSize
, 1);
1105 memcpy(pEntries
, pUnsafeEntries
, cjSize
);
1107 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1109 ExFreePoolWithTag(pEntries
, TAG_PALETTE
);
1110 _SEH2_YIELD(return 0);
1116 /* Zero it out, so we don't accidentally leak kernel data */
1117 RtlZeroMemory(pEntries
, cjSize
);
1126 ret
= IntAnimatePalette((HPALETTE
)hObj
, iStart
, cEntries
, (CONST PPALETTEENTRY
)pEntries
);
1129 case GdiPalSetEntries
:
1131 ret
= IntSetPaletteEntries((HPALETTE
)hObj
, iStart
, cEntries
, (CONST LPPALETTEENTRY
)pEntries
);
1134 case GdiPalGetEntries
:
1135 ret
= IntGetPaletteEntries((HPALETTE
)hObj
, iStart
, cEntries
, (LPPALETTEENTRY
)pEntries
);
1138 case GdiPalGetSystemEntries
:
1139 ret
= IntGetSystemPaletteEntries((HDC
)hObj
, iStart
, cEntries
, (LPPALETTEENTRY
)pEntries
);
1142 case GdiPalSetColorTable
:
1144 ret
= GreGetSetColorTable((HDC
)hObj
, iStart
, cEntries
, (RGBQUAD
*)pEntries
, TRUE
);
1147 case GdiPalGetColorTable
:
1149 ret
= GreGetSetColorTable((HDC
)hObj
, iStart
, cEntries
, (RGBQUAD
*)pEntries
, FALSE
);
1155 if (!bInbound
&& (ret
> 0))
1157 cjSize
= min(cEntries
, ret
) * sizeof(PALETTEENTRY
);
1160 ProbeForWrite(pUnsafeEntries
, cjSize
, 1);
1161 memcpy(pUnsafeEntries
, pEntries
, cjSize
);
1163 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1169 ExFreePoolWithTag(pEntries
, TAG_PALETTE
);
1176 NtGdiSetSystemPaletteUse(HDC hDC
, UINT Usage
)
1178 UINT old
= SystemPaletteUse
;
1180 /* Device doesn't support colour palettes */
1181 if (!(NtGdiGetDeviceCaps(hDC
, RASTERCAPS
) & RC_PALETTE
)) {
1182 return SYSPAL_ERROR
;
1187 case SYSPAL_NOSTATIC
:
1188 case SYSPAL_NOSTATIC256
:
1190 SystemPaletteUse
= Usage
;
1203 NtGdiGetSystemPaletteUse(HDC hDC
)
1205 return SystemPaletteUse
;
1210 NtGdiUpdateColors(HDC hDC
)
1213 BOOL calledFromUser
, ret
;
1214 USER_REFERENCE_ENTRY Ref
;
1216 calledFromUser
= UserIsEntered();
1218 if (!calledFromUser
){
1219 UserEnterExclusive();
1222 Wnd
= UserGetWindowObject(IntWindowFromDC(hDC
));
1225 EngSetLastError(ERROR_INVALID_WINDOW_HANDLE
);
1227 if (!calledFromUser
){
1234 UserRefObjectCo(Wnd
, &Ref
);
1235 ret
= co_UserRedrawWindow(Wnd
, NULL
, 0, RDW_INVALIDATE
);
1236 UserDerefObjectCo(Wnd
);
1238 if (!calledFromUser
){
1247 NtGdiUnrealizeObject(HGDIOBJ hgdiobj
)
1253 ((UINT_PTR
)hgdiobj
& GDI_HANDLE_STOCK_MASK
) ||
1254 !GDI_HANDLE_IS_TYPE(hgdiobj
, GDI_OBJECT_TYPE_PALETTE
) )
1257 palGDI
= PALETTE_ShareLockPalette(hgdiobj
);
1258 if (!palGDI
) return FALSE
;
1261 // Need to do something!!!
1262 // Zero out Current and Old Translated pointers?
1265 PALETTE_ShareUnlockPalette(palGDI
);
1272 NtGdiEngCreatePalette(
1275 _In_ ULONG
*pulColors
,
1280 HPALETTE hPal
= NULL
;
1281 ULONG
*pulcSafe
, ulColors
[WINDDI_MAXSETPALETTECOLORS
];
1283 if ( cColors
> MAX_PALCOLORS
) return NULL
;
1285 if ( cColors
<= WINDDI_MAXSETPALETTECOLORS
)
1287 pulcSafe
= ulColors
;
1291 pulcSafe
= ExAllocatePoolWithTag(PagedPool
, cColors
* sizeof(ULONG
), GDITAG_UMPD
);
1296 ProbeForRead( pulColors
, cColors
* sizeof(ULONG
), 1);
1297 RtlCopyMemory( pulcSafe
, pulColors
, cColors
* sizeof(ULONG
) );
1299 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
1301 SetLastNtError(_SEH2_GetExceptionCode());
1302 if ( cColors
> WINDDI_MAXSETPALETTECOLORS
) ExFreePoolWithTag( pulcSafe
, GDITAG_UMPD
);
1303 _SEH2_YIELD(return hPal
);
1307 hPal
= EngCreatePalette( iMode
/*|PAL_SETPOWNER*/, cColors
, pulcSafe
, flRed
, flGreen
, flBlue
);
1309 if ( cColors
> WINDDI_MAXSETPALETTECOLORS
) ExFreePoolWithTag( pulcSafe
, GDITAG_UMPD
);
1317 NtGdiEngDeletePalette(
1320 return EngDeletePalette(hPal
);