mirror of
https://github.com/reactos/reactos.git
synced 2024-11-01 04:11:30 +00:00
1319 lines
32 KiB
C
1319 lines
32 KiB
C
/*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS Win32k subsystem
|
|
* PURPOSE: GDI Palette Functions
|
|
* FILE: win32ss/gdi/ntgdi/palette.c
|
|
* PROGRAMERS: Jason Filby
|
|
* Timo Kreuzer
|
|
*/
|
|
|
|
#include <win32k.h>
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
#define PAL_SETPOWNER 0x8000
|
|
#define MAX_PALCOLORS 65536
|
|
|
|
static UINT SystemPaletteUse = SYSPAL_NOSTATIC; /* The program need save the pallete and restore it */
|
|
|
|
PALETTE gpalRGB, gpalBGR, gpalRGB555, gpalRGB565, *gppalMono, *gppalDefault;
|
|
PPALETTE appalSurfaceDefault[11];
|
|
|
|
const PALETTEENTRY g_sysPalTemplate[NB_RESERVED_COLORS] =
|
|
{
|
|
// First 10 entries in the system palette
|
|
// Red Green Blue Flags
|
|
{ 0x00, 0x00, 0x00, PC_SYS_USED },
|
|
{ 0x80, 0x00, 0x00, PC_SYS_USED },
|
|
{ 0x00, 0x80, 0x00, PC_SYS_USED },
|
|
{ 0x80, 0x80, 0x00, PC_SYS_USED },
|
|
{ 0x00, 0x00, 0x80, PC_SYS_USED },
|
|
{ 0x80, 0x00, 0x80, PC_SYS_USED },
|
|
{ 0x00, 0x80, 0x80, PC_SYS_USED },
|
|
{ 0xc0, 0xc0, 0xc0, PC_SYS_USED },
|
|
{ 0xc0, 0xdc, 0xc0, PC_SYS_USED },
|
|
{ 0xa6, 0xca, 0xf0, PC_SYS_USED },
|
|
|
|
// ... c_min/2 dynamic colorcells
|
|
// ... gap (for sparse palettes)
|
|
// ... c_min/2 dynamic colorcells
|
|
|
|
{ 0xff, 0xfb, 0xf0, PC_SYS_USED },
|
|
{ 0xa0, 0xa0, 0xa4, PC_SYS_USED },
|
|
{ 0x80, 0x80, 0x80, PC_SYS_USED },
|
|
{ 0xff, 0x00, 0x00, PC_SYS_USED },
|
|
{ 0x00, 0xff, 0x00, PC_SYS_USED },
|
|
{ 0xff, 0xff, 0x00, PC_SYS_USED },
|
|
{ 0x00, 0x00, 0xff, PC_SYS_USED },
|
|
{ 0xff, 0x00, 0xff, PC_SYS_USED },
|
|
{ 0x00, 0xff, 0xff, PC_SYS_USED },
|
|
{ 0xff, 0xff, 0xff, PC_SYS_USED } // Last 10
|
|
};
|
|
|
|
unsigned short GetNumberOfBits(unsigned int dwMask)
|
|
{
|
|
unsigned short wBits;
|
|
for (wBits = 0; dwMask; dwMask = dwMask & (dwMask - 1))
|
|
wBits++;
|
|
return wBits;
|
|
}
|
|
|
|
// Create the system palette
|
|
CODE_SEG("INIT")
|
|
NTSTATUS
|
|
NTAPI
|
|
InitPaletteImpl(VOID)
|
|
{
|
|
// Create default palette (20 system colors)
|
|
gppalDefault = PALETTE_AllocPalWithHandle(PAL_INDEXED,
|
|
20,
|
|
g_sysPalTemplate,
|
|
0, 0, 0);
|
|
GDIOBJ_vReferenceObjectByPointer(&gppalDefault->BaseObject);
|
|
PALETTE_UnlockPalette(gppalDefault);
|
|
|
|
/* palette_size = visual->map_entries; */
|
|
|
|
gpalRGB.flFlags = PAL_RGB;
|
|
gpalRGB.RedMask = RGB(0xFF, 0x00, 0x00);
|
|
gpalRGB.GreenMask = RGB(0x00, 0xFF, 0x00);
|
|
gpalRGB.BlueMask = RGB(0x00, 0x00, 0xFF);
|
|
gpalRGB.BaseObject.ulShareCount = 1;
|
|
gpalRGB.BaseObject.BaseFlags = 0 ;
|
|
|
|
gpalBGR.flFlags = PAL_BGR;
|
|
gpalBGR.RedMask = RGB(0x00, 0x00, 0xFF);
|
|
gpalBGR.GreenMask = RGB(0x00, 0xFF, 0x00);
|
|
gpalBGR.BlueMask = RGB(0xFF, 0x00, 0x00);
|
|
gpalBGR.BaseObject.ulShareCount = 1;
|
|
gpalBGR.BaseObject.BaseFlags = 0 ;
|
|
|
|
gpalRGB555.flFlags = PAL_RGB16_555 | PAL_BITFIELDS;
|
|
gpalRGB555.RedMask = 0x7C00;
|
|
gpalRGB555.GreenMask = 0x3E0;
|
|
gpalRGB555.BlueMask = 0x1F;
|
|
gpalRGB555.BaseObject.ulShareCount = 1;
|
|
gpalRGB555.BaseObject.BaseFlags = 0 ;
|
|
|
|
gpalRGB565.flFlags = PAL_RGB16_565 | PAL_BITFIELDS;
|
|
gpalRGB565.RedMask = 0xF800;
|
|
gpalRGB565.GreenMask = 0x7E0;
|
|
gpalRGB565.BlueMask = 0x1F;
|
|
gpalRGB565.BaseObject.ulShareCount = 1;
|
|
gpalRGB565.BaseObject.BaseFlags = 0 ;
|
|
|
|
gppalMono = PALETTE_AllocPalette(PAL_MONOCHROME|PAL_INDEXED, 2, NULL, 0, 0, 0);
|
|
PALETTE_vSetRGBColorForIndex(gppalMono, 0, 0x000000);
|
|
PALETTE_vSetRGBColorForIndex(gppalMono, 1, 0xffffff);
|
|
|
|
/* Initialize default surface palettes */
|
|
appalSurfaceDefault[BMF_1BPP] = gppalMono;
|
|
appalSurfaceDefault[BMF_4BPP] = gppalDefault;
|
|
appalSurfaceDefault[BMF_8BPP] = gppalDefault;
|
|
appalSurfaceDefault[BMF_16BPP] = &gpalRGB565;
|
|
appalSurfaceDefault[BMF_24BPP] = &gpalBGR;
|
|
appalSurfaceDefault[BMF_32BPP] = &gpalBGR;
|
|
appalSurfaceDefault[BMF_4RLE] = gppalDefault;
|
|
appalSurfaceDefault[BMF_8RLE] = gppalDefault;
|
|
appalSurfaceDefault[BMF_JPEG] = &gpalRGB;
|
|
appalSurfaceDefault[BMF_PNG] = &gpalRGB;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
VOID FASTCALL PALETTE_ValidateFlags(PALETTEENTRY* lpPalE, INT size)
|
|
{
|
|
int i = 0;
|
|
for (; i<size ; i++)
|
|
lpPalE[i].peFlags = PC_SYS_USED | (lpPalE[i].peFlags & 0x07);
|
|
}
|
|
|
|
|
|
PPALETTE
|
|
NTAPI
|
|
PALETTE_AllocPalette(
|
|
_In_ ULONG iMode,
|
|
_In_ ULONG cColors,
|
|
_In_opt_ const PALETTEENTRY* pEntries,
|
|
_In_ FLONG flRed,
|
|
_In_ FLONG flGreen,
|
|
_In_ FLONG flBlue)
|
|
{
|
|
PPALETTE ppal;
|
|
ULONG fl = 0, cjSize = sizeof(PALETTE);
|
|
|
|
/* Check if the palette has entries */
|
|
if (iMode & PAL_INDEXED)
|
|
{
|
|
/* Check color count */
|
|
if ((cColors == 0) || (cColors > 1024)) return NULL;
|
|
|
|
/* Allocate enough space for the palete entries */
|
|
cjSize += cColors * sizeof(PALETTEENTRY);
|
|
}
|
|
else
|
|
{
|
|
/* There are no palette entries */
|
|
cColors = 0;
|
|
|
|
/* We can use the lookaside list */
|
|
fl |= BASEFLAG_LOOKASIDE;
|
|
}
|
|
|
|
/* Allocate the object (without a handle!) */
|
|
ppal = (PPALETTE)GDIOBJ_AllocateObject(GDIObjType_PAL_TYPE, cjSize, fl);
|
|
if (!ppal)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
/* Set mode, color count and entry pointer */
|
|
ppal->flFlags = iMode;
|
|
ppal->NumColors = cColors;
|
|
ppal->IndexedColors = ppal->apalColors;
|
|
|
|
/* Check what kind of palette this is */
|
|
if (iMode & PAL_INDEXED)
|
|
{
|
|
/* Check if we got a color array */
|
|
if (pEntries)
|
|
{
|
|
/* Copy the entries */
|
|
RtlCopyMemory(ppal->IndexedColors, pEntries, cColors * sizeof(pEntries[0]));
|
|
}
|
|
}
|
|
else if (iMode & PAL_BITFIELDS)
|
|
{
|
|
/* Copy the color masks */
|
|
ppal->RedMask = flRed;
|
|
ppal->GreenMask = flGreen;
|
|
ppal->BlueMask = flBlue;
|
|
|
|
/* Check what masks we have and set optimization flags */
|
|
if ((flRed == 0x7c00) && (flGreen == 0x3E0) && (flBlue == 0x1F))
|
|
ppal->flFlags |= PAL_RGB16_555;
|
|
else if ((flRed == 0xF800) && (flGreen == 0x7E0) && (flBlue == 0x1F))
|
|
ppal->flFlags |= PAL_RGB16_565;
|
|
else if ((flRed == 0xFF0000) && (flGreen == 0xFF00) && (flBlue == 0xFF))
|
|
ppal->flFlags |= PAL_BGR;
|
|
else if ((flRed == 0xFF) && (flGreen == 0xFF00) && (flBlue == 0xFF0000))
|
|
ppal->flFlags |= PAL_RGB;
|
|
}
|
|
|
|
return ppal;
|
|
}
|
|
|
|
PPALETTE
|
|
NTAPI
|
|
PALETTE_AllocPalWithHandle(
|
|
_In_ ULONG iMode,
|
|
_In_ ULONG cColors,
|
|
_In_opt_ const PALETTEENTRY* pEntries,
|
|
_In_ FLONG flRed,
|
|
_In_ FLONG flGreen,
|
|
_In_ FLONG flBlue)
|
|
{
|
|
PPALETTE ppal;
|
|
|
|
/* Allocate the palette without a handle */
|
|
ppal = PALETTE_AllocPalette(iMode, cColors, pEntries, flRed, flGreen, flBlue);
|
|
if (!ppal) return NULL;
|
|
|
|
/* Insert the palette into the handle table */
|
|
if (!GDIOBJ_hInsertObject(&ppal->BaseObject, GDI_OBJ_HMGR_POWNED))
|
|
{
|
|
DPRINT1("Could not insert palette into handle table.\n");
|
|
GDIOBJ_vFreeObject(&ppal->BaseObject);
|
|
return NULL;
|
|
}
|
|
|
|
return ppal;
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
PALETTE_vCleanup(PVOID ObjectBody)
|
|
{
|
|
PPALETTE pPal = (PPALETTE)ObjectBody;
|
|
if (pPal->IndexedColors && pPal->IndexedColors != pPal->apalColors)
|
|
{
|
|
ExFreePoolWithTag(pPal->IndexedColors, TAG_PALETTE);
|
|
}
|
|
}
|
|
|
|
INT
|
|
FASTCALL
|
|
PALETTE_GetObject(PPALETTE ppal, INT cbCount, LPLOGBRUSH lpBuffer)
|
|
{
|
|
if (!lpBuffer)
|
|
{
|
|
return sizeof(WORD);
|
|
}
|
|
|
|
if ((UINT)cbCount < sizeof(WORD)) return 0;
|
|
*((WORD*)lpBuffer) = (WORD)ppal->NumColors;
|
|
return sizeof(WORD);
|
|
}
|
|
|
|
ULONG
|
|
NTAPI
|
|
PALETTE_ulGetNearestPaletteIndex(PALETTE* ppal, ULONG iColor)
|
|
{
|
|
ULONG ulDiff, ulColorDiff, ulMinimalDiff = 0xFFFFFF;
|
|
ULONG i, ulBestIndex = 0;
|
|
PALETTEENTRY peColor = *(PPALETTEENTRY)&iColor;
|
|
|
|
/* Loop all palette entries */
|
|
for (i = 0; i < ppal->NumColors; i++)
|
|
{
|
|
/* Calculate distance in the color cube */
|
|
ulDiff = peColor.peRed - ppal->IndexedColors[i].peRed;
|
|
ulColorDiff = ulDiff * ulDiff;
|
|
ulDiff = peColor.peGreen - ppal->IndexedColors[i].peGreen;
|
|
ulColorDiff += ulDiff * ulDiff;
|
|
ulDiff = peColor.peBlue - ppal->IndexedColors[i].peBlue;
|
|
ulColorDiff += ulDiff * ulDiff;
|
|
|
|
/* Check for a better match */
|
|
if (ulColorDiff < ulMinimalDiff)
|
|
{
|
|
ulBestIndex = i;
|
|
ulMinimalDiff = ulColorDiff;
|
|
|
|
/* Break on exact match */
|
|
if (ulMinimalDiff == 0) break;
|
|
}
|
|
}
|
|
|
|
return ulBestIndex;
|
|
}
|
|
|
|
ULONG
|
|
NTAPI
|
|
PALETTE_ulGetNearestBitFieldsIndex(PALETTE* ppal, ULONG ulColor)
|
|
{
|
|
ULONG ulNewColor;
|
|
|
|
// FIXME: HACK, should be stored already
|
|
ppal->ulRedShift = CalculateShift(RGB(0xff,0,0), ppal->RedMask);
|
|
ppal->ulGreenShift = CalculateShift(RGB(0,0xff,0), ppal->GreenMask);
|
|
ppal->ulBlueShift = CalculateShift(RGB(0,0,0xff), ppal->BlueMask);
|
|
|
|
ulNewColor = _rotl(ulColor, ppal->ulRedShift) & ppal->RedMask;
|
|
ulNewColor |= _rotl(ulColor, ppal->ulGreenShift) & ppal->GreenMask;
|
|
ulNewColor |= _rotl(ulColor, ppal->ulBlueShift) & ppal->BlueMask;
|
|
|
|
return ulNewColor;
|
|
}
|
|
|
|
ULONG
|
|
NTAPI
|
|
PALETTE_ulGetNearestIndex(PALETTE* ppal, ULONG ulColor)
|
|
{
|
|
if (ppal->flFlags & PAL_INDEXED) // Use fl & PALINDEXED
|
|
return PALETTE_ulGetNearestPaletteIndex(ppal, ulColor);
|
|
else
|
|
return PALETTE_ulGetNearestBitFieldsIndex(ppal, ulColor);
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
PALETTE_vGetBitMasks(PPALETTE ppal, PULONG pulColors)
|
|
{
|
|
ASSERT(pulColors);
|
|
|
|
if (ppal->flFlags & PAL_INDEXED || ppal->flFlags & PAL_RGB)
|
|
{
|
|
pulColors[0] = RGB(0xFF, 0x00, 0x00);
|
|
pulColors[1] = RGB(0x00, 0xFF, 0x00);
|
|
pulColors[2] = RGB(0x00, 0x00, 0xFF);
|
|
}
|
|
else if (ppal->flFlags & PAL_BGR)
|
|
{
|
|
pulColors[0] = RGB(0x00, 0x00, 0xFF);
|
|
pulColors[1] = RGB(0x00, 0xFF, 0x00);
|
|
pulColors[2] = RGB(0xFF, 0x00, 0x00);
|
|
}
|
|
else if (ppal->flFlags & PAL_BITFIELDS)
|
|
{
|
|
pulColors[0] = ppal->RedMask;
|
|
pulColors[1] = ppal->GreenMask;
|
|
pulColors[2] = ppal->BlueMask;
|
|
}
|
|
}
|
|
|
|
VOID
|
|
FASTCALL
|
|
ColorCorrection(PPALETTE PalGDI, PPALETTEENTRY PaletteEntry, ULONG Colors)
|
|
{
|
|
PPDEVOBJ ppdev = (PPDEVOBJ)PalGDI->hPDev;
|
|
|
|
if (!ppdev) return;
|
|
|
|
if (ppdev->flFlags & PDEV_GAMMARAMP_TABLE)
|
|
{
|
|
ULONG i;
|
|
PGAMMARAMP GammaRamp = (PGAMMARAMP)ppdev->pvGammaRamp;
|
|
for ( i = 0; i < Colors; i++)
|
|
{
|
|
PaletteEntry[i].peRed += GammaRamp->Red[i];
|
|
PaletteEntry[i].peGreen += GammaRamp->Green[i];
|
|
PaletteEntry[i].peBlue += GammaRamp->Blue[i];
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
/** Display Driver Interface **************************************************/
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
HPALETTE
|
|
APIENTRY
|
|
EngCreatePalette(
|
|
ULONG iMode,
|
|
ULONG cColors,
|
|
ULONG *pulColors,
|
|
ULONG flRed,
|
|
ULONG flGreen,
|
|
ULONG flBlue)
|
|
{
|
|
PPALETTE ppal;
|
|
HPALETTE hpal;
|
|
|
|
ppal = PALETTE_AllocPalette(iMode, cColors, (PPALETTEENTRY)pulColors, flRed, flGreen, flBlue);
|
|
if (!ppal) return NULL;
|
|
|
|
hpal = GDIOBJ_hInsertObject(&ppal->BaseObject, GDI_OBJ_HMGR_PUBLIC);
|
|
if (!hpal)
|
|
{
|
|
DPRINT1("Could not insert palette into handle table.\n");
|
|
GDIOBJ_vFreeObject(&ppal->BaseObject);
|
|
return NULL;
|
|
}
|
|
|
|
PALETTE_UnlockPalette(ppal);
|
|
return hpal;
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
BOOL
|
|
APIENTRY
|
|
EngDeletePalette(IN HPALETTE hpal)
|
|
{
|
|
PPALETTE ppal;
|
|
|
|
ppal = PALETTE_ShareLockPalette(hpal);
|
|
if (!ppal) return FALSE;
|
|
|
|
GDIOBJ_vDeleteObject(&ppal->BaseObject);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
ULONG
|
|
APIENTRY
|
|
PALOBJ_cGetColors(PALOBJ *PalObj, ULONG Start, ULONG Colors, ULONG *PaletteEntry)
|
|
{
|
|
PALETTE *PalGDI;
|
|
|
|
PalGDI = (PALETTE*)PalObj;
|
|
|
|
if (Start >= PalGDI->NumColors)
|
|
return 0;
|
|
|
|
Colors = min(Colors, PalGDI->NumColors - Start);
|
|
|
|
/* NOTE: PaletteEntry ULONGs are in the same order as PALETTEENTRY. */
|
|
RtlCopyMemory(PaletteEntry, PalGDI->IndexedColors + Start, sizeof(ULONG) * Colors);
|
|
|
|
if (PalGDI->flFlags & PAL_GAMMACORRECTION)
|
|
ColorCorrection(PalGDI, (PPALETTEENTRY)PaletteEntry, Colors);
|
|
|
|
return Colors;
|
|
}
|
|
|
|
|
|
/** Systemcall Interface ******************************************************/
|
|
|
|
HPALETTE
|
|
NTAPI
|
|
GreCreatePaletteInternal(
|
|
IN LPLOGPALETTE pLogPal,
|
|
IN UINT cEntries)
|
|
{
|
|
HPALETTE hpal = NULL;
|
|
PPALETTE ppal;
|
|
|
|
pLogPal->palNumEntries = cEntries;
|
|
ppal = PALETTE_AllocPalWithHandle(PAL_INDEXED,
|
|
cEntries,
|
|
pLogPal->palPalEntry,
|
|
0, 0, 0);
|
|
|
|
if (ppal != NULL)
|
|
{
|
|
PALETTE_ValidateFlags(ppal->IndexedColors, ppal->NumColors);
|
|
|
|
hpal = ppal->BaseObject.hHmgr;
|
|
PALETTE_UnlockPalette(ppal);
|
|
}
|
|
|
|
return hpal;
|
|
}
|
|
|
|
/*
|
|
* @implemented
|
|
*/
|
|
HPALETTE
|
|
APIENTRY
|
|
NtGdiCreatePaletteInternal(
|
|
IN LPLOGPALETTE plogpalUser,
|
|
IN UINT cEntries)
|
|
{
|
|
HPALETTE hpal = NULL;
|
|
PPALETTE ppal;
|
|
ULONG i, cjSize;
|
|
|
|
ppal = PALETTE_AllocPalWithHandle(PAL_INDEXED, cEntries, NULL, 0, 0, 0);
|
|
if (ppal == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
cjSize = FIELD_OFFSET(LOGPALETTE, palPalEntry[cEntries]);
|
|
|
|
_SEH2_TRY
|
|
{
|
|
ProbeForRead(plogpalUser, cjSize, 1);
|
|
|
|
for (i = 0; i < cEntries; i++)
|
|
{
|
|
ppal->IndexedColors[i] = plogpalUser->palPalEntry[i];
|
|
}
|
|
}
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
GDIOBJ_vDeleteObject(&ppal->BaseObject);
|
|
_SEH2_YIELD(return NULL);
|
|
}
|
|
_SEH2_END;
|
|
|
|
PALETTE_ValidateFlags(ppal->IndexedColors, cEntries);
|
|
hpal = ppal->BaseObject.hHmgr;
|
|
PALETTE_UnlockPalette(ppal);
|
|
|
|
return hpal;
|
|
}
|
|
|
|
HPALETTE
|
|
APIENTRY
|
|
NtGdiCreateHalftonePalette(HDC hDC)
|
|
{
|
|
int i, r, g, b;
|
|
PALETTEENTRY PalEntries[256];
|
|
PPALETTE ppal;
|
|
PDC pdc;
|
|
HPALETTE hpal = NULL;
|
|
|
|
pdc = DC_LockDc(hDC);
|
|
if (!pdc)
|
|
{
|
|
EngSetLastError(ERROR_INVALID_HANDLE);
|
|
return NULL;
|
|
}
|
|
|
|
RtlZeroMemory(PalEntries, sizeof(PalEntries));
|
|
|
|
/* First and last ten entries are default ones */
|
|
for (i = 0; i < 10; i++)
|
|
{
|
|
PalEntries[i].peRed = g_sysPalTemplate[i].peRed;
|
|
PalEntries[i].peGreen = g_sysPalTemplate[i].peGreen;
|
|
PalEntries[i].peBlue = g_sysPalTemplate[i].peBlue;
|
|
|
|
PalEntries[246 + i].peRed = g_sysPalTemplate[10 + i].peRed;
|
|
PalEntries[246 + i].peGreen = g_sysPalTemplate[10 + i].peGreen;
|
|
PalEntries[246 + i].peBlue = g_sysPalTemplate[10 + i].peBlue;
|
|
}
|
|
|
|
ppal = PALETTE_ShareLockPalette(pdc->dclevel.hpal);
|
|
if (ppal && (ppal->flFlags & PAL_INDEXED))
|
|
{
|
|
/* FIXME: optimize the palette for the current palette */
|
|
UNIMPLEMENTED;
|
|
}
|
|
else
|
|
{
|
|
for (r = 0; r < 6; r++)
|
|
{
|
|
for (g = 0; g < 6; g++)
|
|
{
|
|
for (b = 0; b < 6; b++)
|
|
{
|
|
i = r + g*6 + b*36 + 10;
|
|
PalEntries[i].peRed = r * 51;
|
|
PalEntries[i].peGreen = g * 51;
|
|
PalEntries[i].peBlue = b * 51;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (i = 216; i < 246; i++)
|
|
{
|
|
int v = (i - 216) << 3;
|
|
PalEntries[i].peRed = v;
|
|
PalEntries[i].peGreen = v;
|
|
PalEntries[i].peBlue = v;
|
|
}
|
|
}
|
|
|
|
if (ppal)
|
|
PALETTE_ShareUnlockPalette(ppal);
|
|
|
|
DC_UnlockDc(pdc);
|
|
|
|
ppal = PALETTE_AllocPalWithHandle(PAL_INDEXED, 256, PalEntries, 0, 0, 0);
|
|
if (ppal)
|
|
{
|
|
hpal = ppal->BaseObject.hHmgr;
|
|
PALETTE_UnlockPalette(ppal);
|
|
}
|
|
|
|
return hpal;
|
|
}
|
|
|
|
BOOL
|
|
APIENTRY
|
|
NtGdiResizePalette(
|
|
HPALETTE hpal,
|
|
UINT Entries)
|
|
{
|
|
/* PALOBJ *palPtr = (PALOBJ*)AccessUserObject(hPal);
|
|
UINT cPrevEnt, prevVer;
|
|
INT prevsize, size = sizeof(LOGPALETTE) + (cEntries - 1) * sizeof(PALETTEENTRY);
|
|
XLATEOBJ *XlateObj = NULL;
|
|
|
|
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);
|
|
XlateObj = palPtr->logicalToSystem;
|
|
|
|
if (!(palPtr = GDI_ReallocObject(size, hPal, palPtr))) return FALSE;
|
|
|
|
if(XlateObj)
|
|
{
|
|
XLATEOBJ *NewXlateObj = (int*) HeapReAlloc(GetProcessHeap(), 0, XlateObj, cEntries * sizeof(int));
|
|
if(NewXlateObj == NULL)
|
|
{
|
|
ERR("Can not resize logicalToSystem -- out of memory!\n");
|
|
GDI_ReleaseObj( hPal );
|
|
return FALSE;
|
|
}
|
|
palPtr->logicalToSystem = NewXlateObj;
|
|
}
|
|
|
|
if(cEntries > cPrevEnt)
|
|
{
|
|
if(XlateObj) memset(palPtr->logicalToSystem + cPrevEnt, 0, (cEntries - cPrevEnt)*sizeof(int));
|
|
memset( (BYTE*)palPtr + prevsize, 0, size - prevsize );
|
|
PALETTE_ValidateFlags((PALETTEENTRY*)((BYTE*)palPtr + prevsize), cEntries - cPrevEnt );
|
|
}
|
|
palPtr->logpalette->palNumEntries = cEntries;
|
|
palPtr->logpalette->palVersion = prevVer;
|
|
// GDI_ReleaseObj( hPal );
|
|
return TRUE; */
|
|
|
|
UNIMPLEMENTED;
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL
|
|
APIENTRY
|
|
NtGdiGetColorAdjustment(
|
|
HDC hdc,
|
|
LPCOLORADJUSTMENT pca)
|
|
{
|
|
UNIMPLEMENTED;
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL
|
|
APIENTRY
|
|
NtGdiSetColorAdjustment(
|
|
HDC hdc,
|
|
LPCOLORADJUSTMENT pca)
|
|
{
|
|
UNIMPLEMENTED;
|
|
return FALSE;
|
|
}
|
|
|
|
COLORREF
|
|
APIENTRY
|
|
NtGdiGetNearestColor(
|
|
_In_ HDC hDC,
|
|
_In_ COLORREF Color)
|
|
{
|
|
COLORREF nearest = CLR_INVALID;
|
|
PDC dc;
|
|
EXLATEOBJ exlo;
|
|
PPALETTE ppal;
|
|
|
|
dc = DC_LockDc(hDC);
|
|
|
|
if(dc == NULL)
|
|
{
|
|
EngSetLastError(ERROR_INVALID_HANDLE);
|
|
return CLR_INVALID;
|
|
}
|
|
|
|
/// FIXME: shouldn't dereference pSurface while the PDEV is not locked
|
|
if(dc->dclevel.pSurface == NULL)
|
|
ppal = gppalMono;
|
|
else
|
|
ppal = dc->dclevel.pSurface->ppal;
|
|
|
|
/* Translate the color to the DC format */
|
|
Color = TranslateCOLORREF(dc, Color);
|
|
|
|
/* XLATE it back to RGB color space */
|
|
EXLATEOBJ_vInitialize(&exlo,
|
|
ppal,
|
|
&gpalRGB,
|
|
0,
|
|
RGB(0xff, 0xff, 0xff),
|
|
RGB(0, 0, 0));
|
|
|
|
nearest = XLATEOBJ_iXlate(&exlo.xlo, Color);
|
|
|
|
EXLATEOBJ_vCleanup(&exlo);
|
|
|
|
/* We're done */
|
|
DC_UnlockDc(dc);
|
|
|
|
return nearest;
|
|
}
|
|
|
|
UINT
|
|
APIENTRY
|
|
NtGdiGetNearestPaletteIndex(
|
|
HPALETTE hpal,
|
|
COLORREF crColor)
|
|
{
|
|
PPALETTE ppal = PALETTE_ShareLockPalette(hpal);
|
|
UINT index = 0;
|
|
|
|
if (ppal)
|
|
{
|
|
if (ppal->flFlags & PAL_INDEXED)
|
|
{
|
|
/* Return closest match for the given RGB color */
|
|
index = PALETTE_ulGetNearestPaletteIndex(ppal, crColor);
|
|
}
|
|
// else SetLastError ?
|
|
PALETTE_ShareUnlockPalette(ppal);
|
|
}
|
|
|
|
return index;
|
|
}
|
|
|
|
UINT
|
|
FASTCALL
|
|
IntGdiRealizePalette(HDC hDC)
|
|
{
|
|
UINT realize = 0;
|
|
PDC pdc;
|
|
PALETTE *ppalSurf, *ppalDC;
|
|
|
|
pdc = DC_LockDc(hDC);
|
|
if (!pdc)
|
|
{
|
|
EngSetLastError(ERROR_INVALID_HANDLE);
|
|
return 0;
|
|
}
|
|
|
|
if (!pdc->dclevel.pSurface)
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
if (pdc->dctype == DCTYPE_DIRECT)
|
|
{
|
|
static BOOL g_WarnedOnce = FALSE;
|
|
if (!g_WarnedOnce)
|
|
{
|
|
g_WarnedOnce = TRUE;
|
|
UNIMPLEMENTED;
|
|
}
|
|
goto cleanup;
|
|
}
|
|
|
|
/// FIXME: shouldn't dereference pSurface while the PDEV is not locked
|
|
ppalSurf = pdc->dclevel.pSurface->ppal;
|
|
ppalDC = pdc->dclevel.ppal;
|
|
|
|
if (!(ppalSurf->flFlags & PAL_INDEXED))
|
|
{
|
|
// FIXME: Set error?
|
|
goto cleanup;
|
|
}
|
|
|
|
ASSERT(ppalDC->flFlags & PAL_INDEXED);
|
|
|
|
DPRINT1("RealizePalette unimplemented for %s\n",
|
|
(pdc->dctype == DCTYPE_MEMORY ? "memory managed DCs" : "device DCs"));
|
|
|
|
cleanup:
|
|
DC_UnlockDc(pdc);
|
|
return realize;
|
|
}
|
|
|
|
UINT APIENTRY
|
|
IntAnimatePalette(HPALETTE hPal,
|
|
UINT StartIndex,
|
|
UINT NumEntries,
|
|
CONST PPALETTEENTRY PaletteColors)
|
|
{
|
|
UINT ret = 0;
|
|
|
|
if( hPal != NtGdiGetStockObject(DEFAULT_PALETTE) )
|
|
{
|
|
PPALETTE palPtr;
|
|
UINT pal_entries;
|
|
const PALETTEENTRY *pptr = PaletteColors;
|
|
|
|
palPtr = PALETTE_ShareLockPalette(hPal);
|
|
if (!palPtr) return FALSE;
|
|
|
|
pal_entries = palPtr->NumColors;
|
|
if (StartIndex >= pal_entries)
|
|
{
|
|
PALETTE_ShareUnlockPalette(palPtr);
|
|
return FALSE;
|
|
}
|
|
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->IndexedColors[StartIndex].peFlags & PC_RESERVED)
|
|
{
|
|
memcpy( &palPtr->IndexedColors[StartIndex], pptr,
|
|
sizeof(PALETTEENTRY) );
|
|
ret++;
|
|
PALETTE_ValidateFlags(&palPtr->IndexedColors[StartIndex], 1);
|
|
}
|
|
}
|
|
|
|
PALETTE_ShareUnlockPalette(palPtr);
|
|
|
|
#if 0
|
|
/* FIXME: This is completely broken! We cannot call UserGetDesktopWindow
|
|
without first acquiring the USER lock. But the whole process here is
|
|
screwed anyway. Instead of messing with the desktop DC, we need to
|
|
check, whether the palette is associated with a PDEV and whether that
|
|
PDEV supports palette operations. Then we need to call pfnDrvSetPalette.
|
|
But since IntGdiRealizePalette() is not even implemented for direct DCs,
|
|
we can as well just do nothing, that will at least not ASSERT!
|
|
I leave the whole thing here, to scare people away, who want to "fix" it. */
|
|
|
|
/* Immediately apply the new palette if current window uses it */
|
|
Wnd = UserGetDesktopWindow();
|
|
hDC = UserGetWindowDC(Wnd);
|
|
dc = DC_LockDc(hDC);
|
|
if (NULL != dc)
|
|
{
|
|
if (dc->dclevel.hpal == hPal)
|
|
{
|
|
DC_UnlockDc(dc);
|
|
IntGdiRealizePalette(hDC);
|
|
}
|
|
else
|
|
DC_UnlockDc(dc);
|
|
}
|
|
UserReleaseDC(Wnd,hDC, FALSE);
|
|
#endif // 0
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
UINT APIENTRY
|
|
IntGetPaletteEntries(
|
|
HPALETTE hpal,
|
|
UINT StartIndex,
|
|
UINT Entries,
|
|
LPPALETTEENTRY pe)
|
|
{
|
|
PPALETTE palGDI;
|
|
UINT numEntries;
|
|
|
|
palGDI = (PPALETTE) PALETTE_ShareLockPalette(hpal);
|
|
if (NULL == palGDI)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
numEntries = palGDI->NumColors;
|
|
if (NULL != pe)
|
|
{
|
|
if (numEntries < StartIndex + Entries)
|
|
{
|
|
Entries = numEntries - StartIndex;
|
|
}
|
|
if (numEntries <= StartIndex)
|
|
{
|
|
PALETTE_ShareUnlockPalette(palGDI);
|
|
return 0;
|
|
}
|
|
memcpy(pe, palGDI->IndexedColors + StartIndex, Entries * sizeof(PALETTEENTRY));
|
|
}
|
|
else
|
|
{
|
|
Entries = numEntries;
|
|
}
|
|
|
|
PALETTE_ShareUnlockPalette(palGDI);
|
|
return Entries;
|
|
}
|
|
|
|
UINT APIENTRY
|
|
IntGetSystemPaletteEntries(HDC hDC,
|
|
UINT StartIndex,
|
|
UINT Entries,
|
|
LPPALETTEENTRY pe)
|
|
{
|
|
PPALETTE palGDI = NULL;
|
|
PDC dc = NULL;
|
|
UINT EntriesSize = 0;
|
|
UINT Ret = 0;
|
|
|
|
if (Entries == 0)
|
|
{
|
|
EngSetLastError(ERROR_INVALID_PARAMETER);
|
|
return 0;
|
|
}
|
|
|
|
if (pe != NULL)
|
|
{
|
|
EntriesSize = Entries * sizeof(pe[0]);
|
|
if (Entries != EntriesSize / sizeof(pe[0]))
|
|
{
|
|
/* Integer overflow! */
|
|
EngSetLastError(ERROR_INVALID_PARAMETER);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
if (!(dc = DC_LockDc(hDC)))
|
|
{
|
|
EngSetLastError(ERROR_INVALID_HANDLE);
|
|
return 0;
|
|
}
|
|
|
|
palGDI = PALETTE_ShareLockPalette(dc->dclevel.hpal);
|
|
if (palGDI != NULL)
|
|
{
|
|
if (pe != NULL)
|
|
{
|
|
if (StartIndex >= palGDI->NumColors)
|
|
Entries = 0;
|
|
else if (Entries > palGDI->NumColors - StartIndex)
|
|
Entries = palGDI->NumColors - StartIndex;
|
|
|
|
memcpy(pe,
|
|
palGDI->IndexedColors + StartIndex,
|
|
Entries * sizeof(pe[0]));
|
|
|
|
Ret = Entries;
|
|
}
|
|
else
|
|
{
|
|
Ret = dc->ppdev->gdiinfo.ulNumPalReg;
|
|
}
|
|
}
|
|
|
|
if (palGDI != NULL)
|
|
PALETTE_ShareUnlockPalette(palGDI);
|
|
|
|
if (dc != NULL)
|
|
DC_UnlockDc(dc);
|
|
|
|
return Ret;
|
|
}
|
|
|
|
UINT
|
|
APIENTRY
|
|
IntSetPaletteEntries(
|
|
HPALETTE hpal,
|
|
UINT Start,
|
|
UINT Entries,
|
|
CONST LPPALETTEENTRY pe)
|
|
{
|
|
PPALETTE palGDI;
|
|
ULONG numEntries;
|
|
|
|
if (GDI_HANDLE_IS_STOCKOBJ(hpal))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
palGDI = PALETTE_ShareLockPalette(hpal);
|
|
if (!palGDI) return 0;
|
|
|
|
numEntries = palGDI->NumColors;
|
|
if (Start >= numEntries)
|
|
{
|
|
PALETTE_ShareUnlockPalette(palGDI);
|
|
return 0;
|
|
}
|
|
if (numEntries < Start + Entries)
|
|
{
|
|
Entries = numEntries - Start;
|
|
}
|
|
memcpy(palGDI->IndexedColors + Start, pe, Entries * sizeof(PALETTEENTRY));
|
|
PALETTE_ShareUnlockPalette(palGDI);
|
|
|
|
return Entries;
|
|
}
|
|
|
|
ULONG
|
|
APIENTRY
|
|
GreGetSetColorTable(
|
|
HDC hdc,
|
|
ULONG iStartIndex,
|
|
ULONG cEntries,
|
|
RGBQUAD *prgbColors,
|
|
BOOL bSet)
|
|
{
|
|
PDC pdc;
|
|
PSURFACE psurf;
|
|
PPALETTE ppal = NULL;
|
|
ULONG i, iEndIndex, iResult = 0;
|
|
|
|
/* Lock the DC */
|
|
pdc = DC_LockDc(hdc);
|
|
if (!pdc)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
/* Get the surface from the DC */
|
|
psurf = pdc->dclevel.pSurface;
|
|
|
|
/* Check if we have the default surface */
|
|
if (psurf == NULL)
|
|
{
|
|
/* Use a mono palette */
|
|
if (!bSet)
|
|
ppal = gppalMono;
|
|
}
|
|
else if (psurf->SurfObj.iType == STYPE_BITMAP)
|
|
{
|
|
/* Get the palette of the surface */
|
|
ppal = psurf->ppal;
|
|
}
|
|
|
|
/* Check if this is an indexed palette and the range is ok */
|
|
if (ppal && (ppal->flFlags & PAL_INDEXED) &&
|
|
(iStartIndex < ppal->NumColors))
|
|
{
|
|
/* Calculate the end of the operation */
|
|
iEndIndex = min(iStartIndex + cEntries, ppal->NumColors);
|
|
|
|
/* Check what operation to perform */
|
|
if (bSet)
|
|
{
|
|
/* Loop all colors and set the palette entries */
|
|
for (i = iStartIndex; i < iEndIndex; i++, prgbColors++)
|
|
{
|
|
ppal->IndexedColors[i].peRed = prgbColors->rgbRed;
|
|
ppal->IndexedColors[i].peGreen = prgbColors->rgbGreen;
|
|
ppal->IndexedColors[i].peBlue = prgbColors->rgbBlue;
|
|
}
|
|
|
|
/* Mark the dc brushes invalid */
|
|
pdc->pdcattr->ulDirty_ |= DIRTY_FILL|DIRTY_LINE|
|
|
DIRTY_BACKGROUND|DIRTY_TEXT;
|
|
}
|
|
else
|
|
{
|
|
/* Loop all colors and get the palette entries */
|
|
for (i = iStartIndex; i < iEndIndex; i++, prgbColors++)
|
|
{
|
|
prgbColors->rgbRed = ppal->IndexedColors[i].peRed;
|
|
prgbColors->rgbGreen = ppal->IndexedColors[i].peGreen;
|
|
prgbColors->rgbBlue = ppal->IndexedColors[i].peBlue;
|
|
prgbColors->rgbReserved = 0;
|
|
}
|
|
}
|
|
|
|
/* Calculate how many entries were modified */
|
|
iResult = iEndIndex - iStartIndex;
|
|
}
|
|
|
|
/* Unlock the DC */
|
|
DC_UnlockDc(pdc);
|
|
|
|
return iResult;
|
|
}
|
|
|
|
__kernel_entry
|
|
LONG
|
|
APIENTRY
|
|
NtGdiDoPalette(
|
|
_In_ HGDIOBJ hObj,
|
|
_In_ WORD iStart,
|
|
_In_ WORD cEntries,
|
|
_When_(bInbound!=0, _In_reads_bytes_(cEntries*sizeof(PALETTEENTRY)))
|
|
_When_(bInbound==0, _Out_writes_bytes_(cEntries*sizeof(PALETTEENTRY))) LPVOID pUnsafeEntries,
|
|
_In_ DWORD iFunc,
|
|
_In_ BOOL bInbound)
|
|
{
|
|
LONG ret;
|
|
LPVOID pEntries = NULL;
|
|
SIZE_T cjSize;
|
|
|
|
if (pUnsafeEntries)
|
|
{
|
|
if (cEntries == 0)
|
|
return 0;
|
|
|
|
cjSize = cEntries * sizeof(PALETTEENTRY);
|
|
pEntries = ExAllocatePoolWithTag(PagedPool, cjSize, TAG_PALETTE);
|
|
if (!pEntries)
|
|
return 0;
|
|
|
|
if (bInbound)
|
|
{
|
|
_SEH2_TRY
|
|
{
|
|
ProbeForRead(pUnsafeEntries, cjSize, 1);
|
|
memcpy(pEntries, pUnsafeEntries, cjSize);
|
|
}
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
ExFreePoolWithTag(pEntries, TAG_PALETTE);
|
|
_SEH2_YIELD(return 0);
|
|
}
|
|
_SEH2_END
|
|
}
|
|
else
|
|
{
|
|
/* Zero it out, so we don't accidentally leak kernel data */
|
|
RtlZeroMemory(pEntries, cjSize);
|
|
}
|
|
}
|
|
|
|
ret = 0;
|
|
switch(iFunc)
|
|
{
|
|
case GdiPalAnimate:
|
|
if (pEntries)
|
|
ret = IntAnimatePalette((HPALETTE)hObj, iStart, cEntries, (CONST PPALETTEENTRY)pEntries);
|
|
break;
|
|
|
|
case GdiPalSetEntries:
|
|
if (pEntries)
|
|
ret = IntSetPaletteEntries((HPALETTE)hObj, iStart, cEntries, (CONST LPPALETTEENTRY)pEntries);
|
|
break;
|
|
|
|
case GdiPalGetEntries:
|
|
ret = IntGetPaletteEntries((HPALETTE)hObj, iStart, cEntries, (LPPALETTEENTRY)pEntries);
|
|
break;
|
|
|
|
case GdiPalGetSystemEntries:
|
|
ret = IntGetSystemPaletteEntries((HDC)hObj, iStart, cEntries, (LPPALETTEENTRY)pEntries);
|
|
break;
|
|
|
|
case GdiPalSetColorTable:
|
|
if (pEntries)
|
|
ret = GreGetSetColorTable((HDC)hObj, iStart, cEntries, (RGBQUAD*)pEntries, TRUE);
|
|
break;
|
|
|
|
case GdiPalGetColorTable:
|
|
if (pEntries)
|
|
ret = GreGetSetColorTable((HDC)hObj, iStart, cEntries, (RGBQUAD*)pEntries, FALSE);
|
|
break;
|
|
}
|
|
|
|
if (pEntries)
|
|
{
|
|
if (!bInbound && (ret > 0))
|
|
{
|
|
cjSize = min(cEntries, ret) * sizeof(PALETTEENTRY);
|
|
_SEH2_TRY
|
|
{
|
|
ProbeForWrite(pUnsafeEntries, cjSize, 1);
|
|
memcpy(pUnsafeEntries, pEntries, cjSize);
|
|
}
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
ret = 0;
|
|
}
|
|
_SEH2_END
|
|
}
|
|
ExFreePoolWithTag(pEntries, TAG_PALETTE);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
UINT APIENTRY
|
|
NtGdiSetSystemPaletteUse(HDC hDC, UINT Usage)
|
|
{
|
|
UINT old = SystemPaletteUse;
|
|
|
|
/* Device doesn't support colour palettes */
|
|
if (!(NtGdiGetDeviceCaps(hDC, RASTERCAPS) & RC_PALETTE)) {
|
|
return SYSPAL_ERROR;
|
|
}
|
|
|
|
switch (Usage)
|
|
{
|
|
case SYSPAL_NOSTATIC:
|
|
case SYSPAL_NOSTATIC256:
|
|
case SYSPAL_STATIC:
|
|
SystemPaletteUse = Usage;
|
|
break;
|
|
|
|
default:
|
|
old=SYSPAL_ERROR;
|
|
break;
|
|
}
|
|
|
|
return old;
|
|
}
|
|
|
|
UINT
|
|
APIENTRY
|
|
NtGdiGetSystemPaletteUse(HDC hDC)
|
|
{
|
|
return SystemPaletteUse;
|
|
}
|
|
|
|
BOOL
|
|
APIENTRY
|
|
NtGdiUpdateColors(HDC hDC)
|
|
{
|
|
PWND Wnd;
|
|
BOOL calledFromUser, ret;
|
|
USER_REFERENCE_ENTRY Ref;
|
|
|
|
calledFromUser = UserIsEntered();
|
|
|
|
if (!calledFromUser){
|
|
UserEnterExclusive();
|
|
}
|
|
|
|
Wnd = UserGetWindowObject(IntWindowFromDC(hDC));
|
|
if (Wnd == NULL)
|
|
{
|
|
EngSetLastError(ERROR_INVALID_WINDOW_HANDLE);
|
|
|
|
if (!calledFromUser){
|
|
UserLeave();
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
UserRefObjectCo(Wnd, &Ref);
|
|
ret = co_UserRedrawWindow(Wnd, NULL, 0, RDW_INVALIDATE);
|
|
UserDerefObjectCo(Wnd);
|
|
|
|
if (!calledFromUser){
|
|
UserLeave();
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
BOOL
|
|
APIENTRY
|
|
NtGdiUnrealizeObject(HGDIOBJ hgdiobj)
|
|
{
|
|
BOOL Ret = FALSE;
|
|
PPALETTE palGDI;
|
|
|
|
if ( !hgdiobj ||
|
|
GDI_HANDLE_IS_STOCKOBJ(hgdiobj) ||
|
|
!GDI_HANDLE_IS_TYPE(hgdiobj, GDI_OBJECT_TYPE_PALETTE) )
|
|
return Ret;
|
|
|
|
palGDI = PALETTE_ShareLockPalette(hgdiobj);
|
|
if (!palGDI) return FALSE;
|
|
|
|
// FIXME!!
|
|
// Need to do something!!!
|
|
// Zero out Current and Old Translated pointers?
|
|
//
|
|
Ret = TRUE;
|
|
PALETTE_ShareUnlockPalette(palGDI);
|
|
return Ret;
|
|
}
|
|
|
|
__kernel_entry
|
|
HPALETTE
|
|
APIENTRY
|
|
NtGdiEngCreatePalette(
|
|
_In_ ULONG iMode,
|
|
_In_ ULONG cColors,
|
|
_In_ ULONG *pulColors,
|
|
_In_ FLONG flRed,
|
|
_In_ FLONG flGreen,
|
|
_In_ FLONG flBlue)
|
|
{
|
|
HPALETTE hPal = NULL;
|
|
ULONG *pulcSafe, ulColors[WINDDI_MAXSETPALETTECOLORS];
|
|
|
|
if ( cColors > MAX_PALCOLORS ) return NULL;
|
|
|
|
if ( cColors <= WINDDI_MAXSETPALETTECOLORS )
|
|
{
|
|
pulcSafe = ulColors;
|
|
}
|
|
else
|
|
{
|
|
pulcSafe = ExAllocatePoolWithTag(PagedPool, cColors * sizeof(ULONG), GDITAG_UMPD );
|
|
}
|
|
|
|
_SEH2_TRY
|
|
{
|
|
ProbeForRead( pulColors, cColors * sizeof(ULONG), 1);
|
|
RtlCopyMemory( pulcSafe, pulColors, cColors * sizeof(ULONG) );
|
|
}
|
|
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
SetLastNtError(_SEH2_GetExceptionCode());
|
|
if ( cColors > WINDDI_MAXSETPALETTECOLORS ) ExFreePoolWithTag( pulcSafe, GDITAG_UMPD );
|
|
_SEH2_YIELD(return hPal);
|
|
}
|
|
_SEH2_END;
|
|
|
|
hPal = EngCreatePalette( iMode/*|PAL_SETPOWNER*/, cColors, pulcSafe, flRed, flGreen, flBlue );
|
|
|
|
if ( cColors > WINDDI_MAXSETPALETTECOLORS ) ExFreePoolWithTag( pulcSafe, GDITAG_UMPD );
|
|
|
|
return hPal;
|
|
}
|
|
|
|
__kernel_entry
|
|
BOOL
|
|
APIENTRY
|
|
NtGdiEngDeletePalette(
|
|
_In_ HPALETTE hPal)
|
|
{
|
|
return EngDeletePalette(hPal);
|
|
}
|
|
|
|
/* EOF */
|