reactos/reactos/win32ss/gdi/ntgdi/palette.c

1280 lines
31 KiB
C
Raw Normal View History

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS Win32k subsystem
* PURPOSE: GDI Palette Functions
* FILE: subsystems/win32/win32k/objects/palette.c
* PROGRAMERS: Jason Filby
* Timo Kreuzer
*/
#include <win32k.h>
#define NDEBUG
#include <debug.h>
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
INIT_FUNCTION
NTSTATUS
NTAPI
InitPaletteImpl()
{
// Create default palette (20 system colors)
gppalDefault = PALETTE_AllocPalWithHandle(PAL_INDEXED,
20,
(PULONG)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);
XLATEOBJ rewrite. The new XLATEOBJ is not allocated from paged pool anymore, but instead allocated on the stack and Initialized. Only when we habe more than a color table with more than 6 entries, we need to allocate an additional buffer. The new interface: EXLATEOBJ_vInitialize is the main init function. It takes a source and destination palette and back and fore colors for monochome surfaces. EXLATEOBJ_vInitXlateFromDCs takes the source and dest DC and is for color translation between 2 surfaces represented by 2 DCs. EXLATEOBJ_vInitBrushXlate initializes an XLATEOBJ for a pattern brush. Finally EXLATEOBJ_vCleanup needs to be called when the XLATEOBJ is not needed anymore. Implement individual iXlate functions for certain cases and store a function pointer in the EXLATEOBJ structure for quick access. Change the usage of the PALETTE.Mode member to be a flag instead of an enum, add usage of PAL_MONOCHOME, PAL_RGB16_555 and PAL_RGB16_565. Add gpalMono, which *should* be used as palette for 1bpp DDBs. Currently there's a hack in the XLATEOBJ init code, to hack around the fact that this is missing. Fix the Hatch brush patterns, as they were inverted. Implement PALETTE_ulGetNearestBitFieldsIndex and PALETTE_ulGetNearestIndex. Get rid of the XLATEOBJ for the mouse pointer instead realize the pointer before usage. Get rid of logicalToSystem PALETTE member. NtGdiGetDIBitsInternal: Don't create a DIBBrush from the BITMAPINFO, when pvBits is NULL, as the function might be uninitualized. This fixes a crash of gdi_regtest. The whole function is quite ugly and needs to be rewritten (like probably the rest of the DIB code). This fixes the problem of artifacts in the selected desktop icons and some color problems. svn path=/trunk/; revision=42391
2009-08-04 20:37:10 +00:00
/* 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);
}
[WIN32K] Rewrite of the GDI handle manager - The old handle manager used a completely retarded spinlock in combination with KeDelayExecutionThread() for both exclusive and shared locks. This is probably the most uneffective algorithm possible. It was also duplicating code everywhere and it was a overall mess It is now replaced with a lock-free reference counter for shared locks and a pushlock for exclusive locks. -> Better performance and scalability. - Allocate user mode object attributes from the new gdi pool. This way, we don't need any caching, since the pool serves as a cache. Its also much faster and uses much less memory. - Allow object allocations of different size, instead of fixed size from a table. This way a single allocation can take care of actual needs. - Allow allcoating objects without a handle and insert them into the handle table later - Properly synchronize the process GDIHandleCount. Now gdiview and taskmanager show the correct number of gdi handles. - Implement a new event tracking system, that is capable of tracking all reverences and locks of objects and pool allocations to help track possible leaks - Make sure that all objects of a process are deleted in cleanup - Make sure all usermode memory allocations are freed, when cleaning up the process pool. - Make sure that each object type is using the correct type of lock (either shared or exclusive, not a mixture) - Fix some object / reference leaks - Lots of inferface improvements - Use global variables for certain things instead of members in the mapped gdi handle table - Make IntSysCreateRectpRgn create a region without a handle - Fix detection od source and mask use in GreStretchBltMask - Use GDIOBJ_bLockMultipleObjects in NtGdiCombineRegion to avoid possible deadlocks - Fix NtGdiAbortPath to reset DCPATH_ACTIVE flag in the dc and only bail out on error, instead of always - Replace DC_AllocateDcAttr and DC_AllocDcAttr with DC_bAllocDcAttr using the new user mode pool - Remove DCU_SyncDcAttrtoUser and DCU_SynchDcAttrtoUser. Those functions were unused and didn't do anything useful anyway, - Replace IntGdiSetDCOwnerEx and DC_SetOwnership with GreSetDCOwner, remove unused NoSetBrush parameter - Replace GDIOBJ_bValidateHandle and IsObjectDead with GreIsHandleValid - Chage GDIOBJ_bLockMultipleObjects: pass object type, return a BOOL, whether all objects could be locked, cleanup on failure svn path=/trunk/; revision=51470
2011-04-28 08:26:46 +00:00
PPALETTE
NTAPI
PALETTE_AllocPalette(
_In_ ULONG iMode,
_In_ ULONG cColors,
_In_opt_ PULONG pulColors,
_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 (pulColors)
{
/* Copy the entries */
RtlCopyMemory(ppal->IndexedColors,
pulColors,
cColors * sizeof(ULONG));
}
}
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;
[WIN32K] Rewrite of the GDI handle manager - The old handle manager used a completely retarded spinlock in combination with KeDelayExecutionThread() for both exclusive and shared locks. This is probably the most uneffective algorithm possible. It was also duplicating code everywhere and it was a overall mess It is now replaced with a lock-free reference counter for shared locks and a pushlock for exclusive locks. -> Better performance and scalability. - Allocate user mode object attributes from the new gdi pool. This way, we don't need any caching, since the pool serves as a cache. Its also much faster and uses much less memory. - Allow object allocations of different size, instead of fixed size from a table. This way a single allocation can take care of actual needs. - Allow allcoating objects without a handle and insert them into the handle table later - Properly synchronize the process GDIHandleCount. Now gdiview and taskmanager show the correct number of gdi handles. - Implement a new event tracking system, that is capable of tracking all reverences and locks of objects and pool allocations to help track possible leaks - Make sure that all objects of a process are deleted in cleanup - Make sure all usermode memory allocations are freed, when cleaning up the process pool. - Make sure that each object type is using the correct type of lock (either shared or exclusive, not a mixture) - Fix some object / reference leaks - Lots of inferface improvements - Use global variables for certain things instead of members in the mapped gdi handle table - Make IntSysCreateRectpRgn create a region without a handle - Fix detection od source and mask use in GreStretchBltMask - Use GDIOBJ_bLockMultipleObjects in NtGdiCombineRegion to avoid possible deadlocks - Fix NtGdiAbortPath to reset DCPATH_ACTIVE flag in the dc and only bail out on error, instead of always - Replace DC_AllocateDcAttr and DC_AllocDcAttr with DC_bAllocDcAttr using the new user mode pool - Remove DCU_SyncDcAttrtoUser and DCU_SynchDcAttrtoUser. Those functions were unused and didn't do anything useful anyway, - Replace IntGdiSetDCOwnerEx and DC_SetOwnership with GreSetDCOwner, remove unused NoSetBrush parameter - Replace GDIOBJ_bValidateHandle and IsObjectDead with GreIsHandleValid - Chage GDIOBJ_bLockMultipleObjects: pass object type, return a BOOL, whether all objects could be locked, cleanup on failure svn path=/trunk/; revision=51470
2011-04-28 08:26:46 +00:00
}
PPALETTE
NTAPI
PALETTE_AllocPalWithHandle(
_In_ ULONG iMode,
_In_ ULONG cColors,
_In_opt_ PULONG pulColors,
_In_ FLONG flRed,
_In_ FLONG flGreen,
_In_ FLONG flBlue)
{
PPALETTE ppal;
/* Allocate the palette without a handle */
ppal = PALETTE_AllocPalette(iMode, cColors, pulColors, 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;
}
XLATEOBJ rewrite. The new XLATEOBJ is not allocated from paged pool anymore, but instead allocated on the stack and Initialized. Only when we habe more than a color table with more than 6 entries, we need to allocate an additional buffer. The new interface: EXLATEOBJ_vInitialize is the main init function. It takes a source and destination palette and back and fore colors for monochome surfaces. EXLATEOBJ_vInitXlateFromDCs takes the source and dest DC and is for color translation between 2 surfaces represented by 2 DCs. EXLATEOBJ_vInitBrushXlate initializes an XLATEOBJ for a pattern brush. Finally EXLATEOBJ_vCleanup needs to be called when the XLATEOBJ is not needed anymore. Implement individual iXlate functions for certain cases and store a function pointer in the EXLATEOBJ structure for quick access. Change the usage of the PALETTE.Mode member to be a flag instead of an enum, add usage of PAL_MONOCHOME, PAL_RGB16_555 and PAL_RGB16_565. Add gpalMono, which *should* be used as palette for 1bpp DDBs. Currently there's a hack in the XLATEOBJ init code, to hack around the fact that this is missing. Fix the Hatch brush patterns, as they were inverted. Implement PALETTE_ulGetNearestBitFieldsIndex and PALETTE_ulGetNearestIndex. Get rid of the XLATEOBJ for the mouse pointer instead realize the pointer before usage. Get rid of logicalToSystem PALETTE member. NtGdiGetDIBitsInternal: Don't create a DIBBrush from the BITMAPINFO, when pvBits is NULL, as the function might be uninitualized. This fixes a crash of gdi_regtest. The whole function is quite ugly and needs to be rewritten (like probably the rest of the DIB code). This fixes the problem of artifacts in the selected desktop icons and some color problems. svn path=/trunk/; revision=42391
2009-08-04 20:37:10 +00:00
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
XLATEOBJ rewrite. The new XLATEOBJ is not allocated from paged pool anymore, but instead allocated on the stack and Initialized. Only when we habe more than a color table with more than 6 entries, we need to allocate an additional buffer. The new interface: EXLATEOBJ_vInitialize is the main init function. It takes a source and destination palette and back and fore colors for monochome surfaces. EXLATEOBJ_vInitXlateFromDCs takes the source and dest DC and is for color translation between 2 surfaces represented by 2 DCs. EXLATEOBJ_vInitBrushXlate initializes an XLATEOBJ for a pattern brush. Finally EXLATEOBJ_vCleanup needs to be called when the XLATEOBJ is not needed anymore. Implement individual iXlate functions for certain cases and store a function pointer in the EXLATEOBJ structure for quick access. Change the usage of the PALETTE.Mode member to be a flag instead of an enum, add usage of PAL_MONOCHOME, PAL_RGB16_555 and PAL_RGB16_565. Add gpalMono, which *should* be used as palette for 1bpp DDBs. Currently there's a hack in the XLATEOBJ init code, to hack around the fact that this is missing. Fix the Hatch brush patterns, as they were inverted. Implement PALETTE_ulGetNearestBitFieldsIndex and PALETTE_ulGetNearestIndex. Get rid of the XLATEOBJ for the mouse pointer instead realize the pointer before usage. Get rid of logicalToSystem PALETTE member. NtGdiGetDIBitsInternal: Don't create a DIBBrush from the BITMAPINFO, when pvBits is NULL, as the function might be uninitualized. This fixes a crash of gdi_regtest. The whole function is quite ugly and needs to be rewritten (like probably the rest of the DIB code). This fixes the problem of artifacts in the selected desktop icons and some color problems. svn path=/trunk/; revision=42391
2009-08-04 20:37:10 +00:00
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)
{
XLATEOBJ rewrite. The new XLATEOBJ is not allocated from paged pool anymore, but instead allocated on the stack and Initialized. Only when we habe more than a color table with more than 6 entries, we need to allocate an additional buffer. The new interface: EXLATEOBJ_vInitialize is the main init function. It takes a source and destination palette and back and fore colors for monochome surfaces. EXLATEOBJ_vInitXlateFromDCs takes the source and dest DC and is for color translation between 2 surfaces represented by 2 DCs. EXLATEOBJ_vInitBrushXlate initializes an XLATEOBJ for a pattern brush. Finally EXLATEOBJ_vCleanup needs to be called when the XLATEOBJ is not needed anymore. Implement individual iXlate functions for certain cases and store a function pointer in the EXLATEOBJ structure for quick access. Change the usage of the PALETTE.Mode member to be a flag instead of an enum, add usage of PAL_MONOCHOME, PAL_RGB16_555 and PAL_RGB16_565. Add gpalMono, which *should* be used as palette for 1bpp DDBs. Currently there's a hack in the XLATEOBJ init code, to hack around the fact that this is missing. Fix the Hatch brush patterns, as they were inverted. Implement PALETTE_ulGetNearestBitFieldsIndex and PALETTE_ulGetNearestIndex. Get rid of the XLATEOBJ for the mouse pointer instead realize the pointer before usage. Get rid of logicalToSystem PALETTE member. NtGdiGetDIBitsInternal: Don't create a DIBBrush from the BITMAPINFO, when pvBits is NULL, as the function might be uninitualized. This fixes a crash of gdi_regtest. The whole function is quite ugly and needs to be rewritten (like probably the rest of the DIB code). This fixes the problem of artifacts in the selected desktop icons and some color problems. svn path=/trunk/; revision=42391
2009-08-04 20:37:10 +00:00
pulColors[0] = RGB(0xFF, 0x00, 0x00);
pulColors[1] = RGB(0x00, 0xFF, 0x00);
pulColors[2] = RGB(0x00, 0x00, 0xFF);
}
else if (ppal->flFlags & PAL_BGR)
XLATEOBJ rewrite. The new XLATEOBJ is not allocated from paged pool anymore, but instead allocated on the stack and Initialized. Only when we habe more than a color table with more than 6 entries, we need to allocate an additional buffer. The new interface: EXLATEOBJ_vInitialize is the main init function. It takes a source and destination palette and back and fore colors for monochome surfaces. EXLATEOBJ_vInitXlateFromDCs takes the source and dest DC and is for color translation between 2 surfaces represented by 2 DCs. EXLATEOBJ_vInitBrushXlate initializes an XLATEOBJ for a pattern brush. Finally EXLATEOBJ_vCleanup needs to be called when the XLATEOBJ is not needed anymore. Implement individual iXlate functions for certain cases and store a function pointer in the EXLATEOBJ structure for quick access. Change the usage of the PALETTE.Mode member to be a flag instead of an enum, add usage of PAL_MONOCHOME, PAL_RGB16_555 and PAL_RGB16_565. Add gpalMono, which *should* be used as palette for 1bpp DDBs. Currently there's a hack in the XLATEOBJ init code, to hack around the fact that this is missing. Fix the Hatch brush patterns, as they were inverted. Implement PALETTE_ulGetNearestBitFieldsIndex and PALETTE_ulGetNearestIndex. Get rid of the XLATEOBJ for the mouse pointer instead realize the pointer before usage. Get rid of logicalToSystem PALETTE member. NtGdiGetDIBitsInternal: Don't create a DIBBrush from the BITMAPINFO, when pvBits is NULL, as the function might be uninitualized. This fixes a crash of gdi_regtest. The whole function is quite ugly and needs to be rewritten (like probably the rest of the DIB code). This fixes the problem of artifacts in the selected desktop icons and some color problems. svn path=/trunk/; revision=42391
2009-08-04 20:37:10 +00:00
{
pulColors[0] = RGB(0x00, 0x00, 0xFF);
pulColors[1] = RGB(0x00, 0xFF, 0x00);
pulColors[2] = RGB(0xFF, 0x00, 0x00);
}
else if (ppal->flFlags & PAL_BITFIELDS)
XLATEOBJ rewrite. The new XLATEOBJ is not allocated from paged pool anymore, but instead allocated on the stack and Initialized. Only when we habe more than a color table with more than 6 entries, we need to allocate an additional buffer. The new interface: EXLATEOBJ_vInitialize is the main init function. It takes a source and destination palette and back and fore colors for monochome surfaces. EXLATEOBJ_vInitXlateFromDCs takes the source and dest DC and is for color translation between 2 surfaces represented by 2 DCs. EXLATEOBJ_vInitBrushXlate initializes an XLATEOBJ for a pattern brush. Finally EXLATEOBJ_vCleanup needs to be called when the XLATEOBJ is not needed anymore. Implement individual iXlate functions for certain cases and store a function pointer in the EXLATEOBJ structure for quick access. Change the usage of the PALETTE.Mode member to be a flag instead of an enum, add usage of PAL_MONOCHOME, PAL_RGB16_555 and PAL_RGB16_565. Add gpalMono, which *should* be used as palette for 1bpp DDBs. Currently there's a hack in the XLATEOBJ init code, to hack around the fact that this is missing. Fix the Hatch brush patterns, as they were inverted. Implement PALETTE_ulGetNearestBitFieldsIndex and PALETTE_ulGetNearestIndex. Get rid of the XLATEOBJ for the mouse pointer instead realize the pointer before usage. Get rid of logicalToSystem PALETTE member. NtGdiGetDIBitsInternal: Don't create a DIBBrush from the BITMAPINFO, when pvBits is NULL, as the function might be uninitualized. This fixes a crash of gdi_regtest. The whole function is quite ugly and needs to be rewritten (like probably the rest of the DIB code). This fixes the problem of artifacts in the selected desktop icons and some color problems. svn path=/trunk/; revision=42391
2009-08-04 20:37:10 +00:00
{
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(
[WIN32K] Rewrite of the GDI handle manager - The old handle manager used a completely retarded spinlock in combination with KeDelayExecutionThread() for both exclusive and shared locks. This is probably the most uneffective algorithm possible. It was also duplicating code everywhere and it was a overall mess It is now replaced with a lock-free reference counter for shared locks and a pushlock for exclusive locks. -> Better performance and scalability. - Allocate user mode object attributes from the new gdi pool. This way, we don't need any caching, since the pool serves as a cache. Its also much faster and uses much less memory. - Allow object allocations of different size, instead of fixed size from a table. This way a single allocation can take care of actual needs. - Allow allcoating objects without a handle and insert them into the handle table later - Properly synchronize the process GDIHandleCount. Now gdiview and taskmanager show the correct number of gdi handles. - Implement a new event tracking system, that is capable of tracking all reverences and locks of objects and pool allocations to help track possible leaks - Make sure that all objects of a process are deleted in cleanup - Make sure all usermode memory allocations are freed, when cleaning up the process pool. - Make sure that each object type is using the correct type of lock (either shared or exclusive, not a mixture) - Fix some object / reference leaks - Lots of inferface improvements - Use global variables for certain things instead of members in the mapped gdi handle table - Make IntSysCreateRectpRgn create a region without a handle - Fix detection od source and mask use in GreStretchBltMask - Use GDIOBJ_bLockMultipleObjects in NtGdiCombineRegion to avoid possible deadlocks - Fix NtGdiAbortPath to reset DCPATH_ACTIVE flag in the dc and only bail out on error, instead of always - Replace DC_AllocateDcAttr and DC_AllocDcAttr with DC_bAllocDcAttr using the new user mode pool - Remove DCU_SyncDcAttrtoUser and DCU_SynchDcAttrtoUser. Those functions were unused and didn't do anything useful anyway, - Replace IntGdiSetDCOwnerEx and DC_SetOwnership with GreSetDCOwner, remove unused NoSetBrush parameter - Replace GDIOBJ_bValidateHandle and IsObjectDead with GreIsHandleValid - Chage GDIOBJ_bLockMultipleObjects: pass object type, return a BOOL, whether all objects could be locked, cleanup on failure svn path=/trunk/; revision=51470
2011-04-28 08:26:46 +00:00
ULONG iMode,
ULONG cColors,
ULONG *pulColors,
ULONG flRed,
ULONG flGreen,
ULONG flBlue)
{
[WIN32K] Rewrite of the GDI handle manager - The old handle manager used a completely retarded spinlock in combination with KeDelayExecutionThread() for both exclusive and shared locks. This is probably the most uneffective algorithm possible. It was also duplicating code everywhere and it was a overall mess It is now replaced with a lock-free reference counter for shared locks and a pushlock for exclusive locks. -> Better performance and scalability. - Allocate user mode object attributes from the new gdi pool. This way, we don't need any caching, since the pool serves as a cache. Its also much faster and uses much less memory. - Allow object allocations of different size, instead of fixed size from a table. This way a single allocation can take care of actual needs. - Allow allcoating objects without a handle and insert them into the handle table later - Properly synchronize the process GDIHandleCount. Now gdiview and taskmanager show the correct number of gdi handles. - Implement a new event tracking system, that is capable of tracking all reverences and locks of objects and pool allocations to help track possible leaks - Make sure that all objects of a process are deleted in cleanup - Make sure all usermode memory allocations are freed, when cleaning up the process pool. - Make sure that each object type is using the correct type of lock (either shared or exclusive, not a mixture) - Fix some object / reference leaks - Lots of inferface improvements - Use global variables for certain things instead of members in the mapped gdi handle table - Make IntSysCreateRectpRgn create a region without a handle - Fix detection od source and mask use in GreStretchBltMask - Use GDIOBJ_bLockMultipleObjects in NtGdiCombineRegion to avoid possible deadlocks - Fix NtGdiAbortPath to reset DCPATH_ACTIVE flag in the dc and only bail out on error, instead of always - Replace DC_AllocateDcAttr and DC_AllocDcAttr with DC_bAllocDcAttr using the new user mode pool - Remove DCU_SyncDcAttrtoUser and DCU_SynchDcAttrtoUser. Those functions were unused and didn't do anything useful anyway, - Replace IntGdiSetDCOwnerEx and DC_SetOwnership with GreSetDCOwner, remove unused NoSetBrush parameter - Replace GDIOBJ_bValidateHandle and IsObjectDead with GreIsHandleValid - Chage GDIOBJ_bLockMultipleObjects: pass object type, return a BOOL, whether all objects could be locked, cleanup on failure svn path=/trunk/; revision=51470
2011-04-28 08:26:46 +00:00
PPALETTE ppal;
HPALETTE hpal;
ppal = PALETTE_AllocPalette(iMode, cColors, pulColors, flRed, flGreen, flBlue);
[WIN32K] Rewrite of the GDI handle manager - The old handle manager used a completely retarded spinlock in combination with KeDelayExecutionThread() for both exclusive and shared locks. This is probably the most uneffective algorithm possible. It was also duplicating code everywhere and it was a overall mess It is now replaced with a lock-free reference counter for shared locks and a pushlock for exclusive locks. -> Better performance and scalability. - Allocate user mode object attributes from the new gdi pool. This way, we don't need any caching, since the pool serves as a cache. Its also much faster and uses much less memory. - Allow object allocations of different size, instead of fixed size from a table. This way a single allocation can take care of actual needs. - Allow allcoating objects without a handle and insert them into the handle table later - Properly synchronize the process GDIHandleCount. Now gdiview and taskmanager show the correct number of gdi handles. - Implement a new event tracking system, that is capable of tracking all reverences and locks of objects and pool allocations to help track possible leaks - Make sure that all objects of a process are deleted in cleanup - Make sure all usermode memory allocations are freed, when cleaning up the process pool. - Make sure that each object type is using the correct type of lock (either shared or exclusive, not a mixture) - Fix some object / reference leaks - Lots of inferface improvements - Use global variables for certain things instead of members in the mapped gdi handle table - Make IntSysCreateRectpRgn create a region without a handle - Fix detection od source and mask use in GreStretchBltMask - Use GDIOBJ_bLockMultipleObjects in NtGdiCombineRegion to avoid possible deadlocks - Fix NtGdiAbortPath to reset DCPATH_ACTIVE flag in the dc and only bail out on error, instead of always - Replace DC_AllocateDcAttr and DC_AllocDcAttr with DC_bAllocDcAttr using the new user mode pool - Remove DCU_SyncDcAttrtoUser and DCU_SynchDcAttrtoUser. Those functions were unused and didn't do anything useful anyway, - Replace IntGdiSetDCOwnerEx and DC_SetOwnership with GreSetDCOwner, remove unused NoSetBrush parameter - Replace GDIOBJ_bValidateHandle and IsObjectDead with GreIsHandleValid - Chage GDIOBJ_bLockMultipleObjects: pass object type, return a BOOL, whether all objects could be locked, cleanup on failure svn path=/trunk/; revision=51470
2011-04-28 08:26:46 +00:00
if (!ppal) return NULL;
[WIN32K] Rewrite of the GDI handle manager - The old handle manager used a completely retarded spinlock in combination with KeDelayExecutionThread() for both exclusive and shared locks. This is probably the most uneffective algorithm possible. It was also duplicating code everywhere and it was a overall mess It is now replaced with a lock-free reference counter for shared locks and a pushlock for exclusive locks. -> Better performance and scalability. - Allocate user mode object attributes from the new gdi pool. This way, we don't need any caching, since the pool serves as a cache. Its also much faster and uses much less memory. - Allow object allocations of different size, instead of fixed size from a table. This way a single allocation can take care of actual needs. - Allow allcoating objects without a handle and insert them into the handle table later - Properly synchronize the process GDIHandleCount. Now gdiview and taskmanager show the correct number of gdi handles. - Implement a new event tracking system, that is capable of tracking all reverences and locks of objects and pool allocations to help track possible leaks - Make sure that all objects of a process are deleted in cleanup - Make sure all usermode memory allocations are freed, when cleaning up the process pool. - Make sure that each object type is using the correct type of lock (either shared or exclusive, not a mixture) - Fix some object / reference leaks - Lots of inferface improvements - Use global variables for certain things instead of members in the mapped gdi handle table - Make IntSysCreateRectpRgn create a region without a handle - Fix detection od source and mask use in GreStretchBltMask - Use GDIOBJ_bLockMultipleObjects in NtGdiCombineRegion to avoid possible deadlocks - Fix NtGdiAbortPath to reset DCPATH_ACTIVE flag in the dc and only bail out on error, instead of always - Replace DC_AllocateDcAttr and DC_AllocDcAttr with DC_bAllocDcAttr using the new user mode pool - Remove DCU_SyncDcAttrtoUser and DCU_SynchDcAttrtoUser. Those functions were unused and didn't do anything useful anyway, - Replace IntGdiSetDCOwnerEx and DC_SetOwnership with GreSetDCOwner, remove unused NoSetBrush parameter - Replace GDIOBJ_bValidateHandle and IsObjectDead with GreIsHandleValid - Chage GDIOBJ_bLockMultipleObjects: pass object type, return a BOOL, whether all objects could be locked, cleanup on failure svn path=/trunk/; revision=51470
2011-04-28 08:26:46 +00:00
hpal = GDIOBJ_hInsertObject(&ppal->BaseObject, GDI_OBJ_HMGR_PUBLIC);
if (!hpal)
{
[WIN32K] Rewrite of the GDI handle manager - The old handle manager used a completely retarded spinlock in combination with KeDelayExecutionThread() for both exclusive and shared locks. This is probably the most uneffective algorithm possible. It was also duplicating code everywhere and it was a overall mess It is now replaced with a lock-free reference counter for shared locks and a pushlock for exclusive locks. -> Better performance and scalability. - Allocate user mode object attributes from the new gdi pool. This way, we don't need any caching, since the pool serves as a cache. Its also much faster and uses much less memory. - Allow object allocations of different size, instead of fixed size from a table. This way a single allocation can take care of actual needs. - Allow allcoating objects without a handle and insert them into the handle table later - Properly synchronize the process GDIHandleCount. Now gdiview and taskmanager show the correct number of gdi handles. - Implement a new event tracking system, that is capable of tracking all reverences and locks of objects and pool allocations to help track possible leaks - Make sure that all objects of a process are deleted in cleanup - Make sure all usermode memory allocations are freed, when cleaning up the process pool. - Make sure that each object type is using the correct type of lock (either shared or exclusive, not a mixture) - Fix some object / reference leaks - Lots of inferface improvements - Use global variables for certain things instead of members in the mapped gdi handle table - Make IntSysCreateRectpRgn create a region without a handle - Fix detection od source and mask use in GreStretchBltMask - Use GDIOBJ_bLockMultipleObjects in NtGdiCombineRegion to avoid possible deadlocks - Fix NtGdiAbortPath to reset DCPATH_ACTIVE flag in the dc and only bail out on error, instead of always - Replace DC_AllocateDcAttr and DC_AllocDcAttr with DC_bAllocDcAttr using the new user mode pool - Remove DCU_SyncDcAttrtoUser and DCU_SynchDcAttrtoUser. Those functions were unused and didn't do anything useful anyway, - Replace IntGdiSetDCOwnerEx and DC_SetOwnership with GreSetDCOwner, remove unused NoSetBrush parameter - Replace GDIOBJ_bValidateHandle and IsObjectDead with GreIsHandleValid - Chage GDIOBJ_bLockMultipleObjects: pass object type, return a BOOL, whether all objects could be locked, cleanup on failure svn path=/trunk/; revision=51470
2011-04-28 08:26:46 +00:00
DPRINT1("Could not insert palette into handle table.\n");
GDIOBJ_vFreeObject(&ppal->BaseObject);
return NULL;
}
[WIN32K] Rewrite of the GDI handle manager - The old handle manager used a completely retarded spinlock in combination with KeDelayExecutionThread() for both exclusive and shared locks. This is probably the most uneffective algorithm possible. It was also duplicating code everywhere and it was a overall mess It is now replaced with a lock-free reference counter for shared locks and a pushlock for exclusive locks. -> Better performance and scalability. - Allocate user mode object attributes from the new gdi pool. This way, we don't need any caching, since the pool serves as a cache. Its also much faster and uses much less memory. - Allow object allocations of different size, instead of fixed size from a table. This way a single allocation can take care of actual needs. - Allow allcoating objects without a handle and insert them into the handle table later - Properly synchronize the process GDIHandleCount. Now gdiview and taskmanager show the correct number of gdi handles. - Implement a new event tracking system, that is capable of tracking all reverences and locks of objects and pool allocations to help track possible leaks - Make sure that all objects of a process are deleted in cleanup - Make sure all usermode memory allocations are freed, when cleaning up the process pool. - Make sure that each object type is using the correct type of lock (either shared or exclusive, not a mixture) - Fix some object / reference leaks - Lots of inferface improvements - Use global variables for certain things instead of members in the mapped gdi handle table - Make IntSysCreateRectpRgn create a region without a handle - Fix detection od source and mask use in GreStretchBltMask - Use GDIOBJ_bLockMultipleObjects in NtGdiCombineRegion to avoid possible deadlocks - Fix NtGdiAbortPath to reset DCPATH_ACTIVE flag in the dc and only bail out on error, instead of always - Replace DC_AllocateDcAttr and DC_AllocDcAttr with DC_bAllocDcAttr using the new user mode pool - Remove DCU_SyncDcAttrtoUser and DCU_SynchDcAttrtoUser. Those functions were unused and didn't do anything useful anyway, - Replace IntGdiSetDCOwnerEx and DC_SetOwnership with GreSetDCOwner, remove unused NoSetBrush parameter - Replace GDIOBJ_bValidateHandle and IsObjectDead with GreIsHandleValid - Chage GDIOBJ_bLockMultipleObjects: pass object type, return a BOOL, whether all objects could be locked, cleanup on failure svn path=/trunk/; revision=51470
2011-04-28 08:26:46 +00:00
PALETTE_UnlockPalette(ppal);
return hpal;
}
/*
* @implemented
*/
BOOL
APIENTRY
[WIN32K] Rewrite of the GDI handle manager - The old handle manager used a completely retarded spinlock in combination with KeDelayExecutionThread() for both exclusive and shared locks. This is probably the most uneffective algorithm possible. It was also duplicating code everywhere and it was a overall mess It is now replaced with a lock-free reference counter for shared locks and a pushlock for exclusive locks. -> Better performance and scalability. - Allocate user mode object attributes from the new gdi pool. This way, we don't need any caching, since the pool serves as a cache. Its also much faster and uses much less memory. - Allow object allocations of different size, instead of fixed size from a table. This way a single allocation can take care of actual needs. - Allow allcoating objects without a handle and insert them into the handle table later - Properly synchronize the process GDIHandleCount. Now gdiview and taskmanager show the correct number of gdi handles. - Implement a new event tracking system, that is capable of tracking all reverences and locks of objects and pool allocations to help track possible leaks - Make sure that all objects of a process are deleted in cleanup - Make sure all usermode memory allocations are freed, when cleaning up the process pool. - Make sure that each object type is using the correct type of lock (either shared or exclusive, not a mixture) - Fix some object / reference leaks - Lots of inferface improvements - Use global variables for certain things instead of members in the mapped gdi handle table - Make IntSysCreateRectpRgn create a region without a handle - Fix detection od source and mask use in GreStretchBltMask - Use GDIOBJ_bLockMultipleObjects in NtGdiCombineRegion to avoid possible deadlocks - Fix NtGdiAbortPath to reset DCPATH_ACTIVE flag in the dc and only bail out on error, instead of always - Replace DC_AllocateDcAttr and DC_AllocDcAttr with DC_bAllocDcAttr using the new user mode pool - Remove DCU_SyncDcAttrtoUser and DCU_SynchDcAttrtoUser. Those functions were unused and didn't do anything useful anyway, - Replace IntGdiSetDCOwnerEx and DC_SetOwnership with GreSetDCOwner, remove unused NoSetBrush parameter - Replace GDIOBJ_bValidateHandle and IsObjectDead with GreIsHandleValid - Chage GDIOBJ_bLockMultipleObjects: pass object type, return a BOOL, whether all objects could be locked, cleanup on failure svn path=/trunk/; revision=51470
2011-04-28 08:26:46 +00:00
EngDeletePalette(IN HPALETTE hpal)
{
[WIN32K] Rewrite of the GDI handle manager - The old handle manager used a completely retarded spinlock in combination with KeDelayExecutionThread() for both exclusive and shared locks. This is probably the most uneffective algorithm possible. It was also duplicating code everywhere and it was a overall mess It is now replaced with a lock-free reference counter for shared locks and a pushlock for exclusive locks. -> Better performance and scalability. - Allocate user mode object attributes from the new gdi pool. This way, we don't need any caching, since the pool serves as a cache. Its also much faster and uses much less memory. - Allow object allocations of different size, instead of fixed size from a table. This way a single allocation can take care of actual needs. - Allow allcoating objects without a handle and insert them into the handle table later - Properly synchronize the process GDIHandleCount. Now gdiview and taskmanager show the correct number of gdi handles. - Implement a new event tracking system, that is capable of tracking all reverences and locks of objects and pool allocations to help track possible leaks - Make sure that all objects of a process are deleted in cleanup - Make sure all usermode memory allocations are freed, when cleaning up the process pool. - Make sure that each object type is using the correct type of lock (either shared or exclusive, not a mixture) - Fix some object / reference leaks - Lots of inferface improvements - Use global variables for certain things instead of members in the mapped gdi handle table - Make IntSysCreateRectpRgn create a region without a handle - Fix detection od source and mask use in GreStretchBltMask - Use GDIOBJ_bLockMultipleObjects in NtGdiCombineRegion to avoid possible deadlocks - Fix NtGdiAbortPath to reset DCPATH_ACTIVE flag in the dc and only bail out on error, instead of always - Replace DC_AllocateDcAttr and DC_AllocDcAttr with DC_bAllocDcAttr using the new user mode pool - Remove DCU_SyncDcAttrtoUser and DCU_SynchDcAttrtoUser. Those functions were unused and didn't do anything useful anyway, - Replace IntGdiSetDCOwnerEx and DC_SetOwnership with GreSetDCOwner, remove unused NoSetBrush parameter - Replace GDIOBJ_bValidateHandle and IsObjectDead with GreIsHandleValid - Chage GDIOBJ_bLockMultipleObjects: pass object type, return a BOOL, whether all objects could be locked, cleanup on failure svn path=/trunk/; revision=51470
2011-04-28 08:26:46 +00:00
PPALETTE ppal;
ppal = PALETTE_ShareLockPalette(hpal);
if (!ppal) return FALSE;
[WIN32K] Rewrite of the GDI handle manager - The old handle manager used a completely retarded spinlock in combination with KeDelayExecutionThread() for both exclusive and shared locks. This is probably the most uneffective algorithm possible. It was also duplicating code everywhere and it was a overall mess It is now replaced with a lock-free reference counter for shared locks and a pushlock for exclusive locks. -> Better performance and scalability. - Allocate user mode object attributes from the new gdi pool. This way, we don't need any caching, since the pool serves as a cache. Its also much faster and uses much less memory. - Allow object allocations of different size, instead of fixed size from a table. This way a single allocation can take care of actual needs. - Allow allcoating objects without a handle and insert them into the handle table later - Properly synchronize the process GDIHandleCount. Now gdiview and taskmanager show the correct number of gdi handles. - Implement a new event tracking system, that is capable of tracking all reverences and locks of objects and pool allocations to help track possible leaks - Make sure that all objects of a process are deleted in cleanup - Make sure all usermode memory allocations are freed, when cleaning up the process pool. - Make sure that each object type is using the correct type of lock (either shared or exclusive, not a mixture) - Fix some object / reference leaks - Lots of inferface improvements - Use global variables for certain things instead of members in the mapped gdi handle table - Make IntSysCreateRectpRgn create a region without a handle - Fix detection od source and mask use in GreStretchBltMask - Use GDIOBJ_bLockMultipleObjects in NtGdiCombineRegion to avoid possible deadlocks - Fix NtGdiAbortPath to reset DCPATH_ACTIVE flag in the dc and only bail out on error, instead of always - Replace DC_AllocateDcAttr and DC_AllocDcAttr with DC_bAllocDcAttr using the new user mode pool - Remove DCU_SyncDcAttrtoUser and DCU_SynchDcAttrtoUser. Those functions were unused and didn't do anything useful anyway, - Replace IntGdiSetDCOwnerEx and DC_SetOwnership with GreSetDCOwner, remove unused NoSetBrush parameter - Replace GDIOBJ_bValidateHandle and IsObjectDead with GreIsHandleValid - Chage GDIOBJ_bLockMultipleObjects: pass object type, return a BOOL, whether all objects could be locked, cleanup on failure svn path=/trunk/; revision=51470
2011-04-28 08:26:46 +00:00
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,
(PULONG)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;
struct {
WORD Version;
WORD NumberOfEntries;
PALETTEENTRY aEntries[256];
} Palette;
Palette.Version = 0x300;
Palette.NumberOfEntries = 256;
if (IntGetSystemPaletteEntries(hDC, 0, 256, Palette.aEntries) == 0)
{
/* From WINE, more that 256 color math */
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;
}
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;
case 10:
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;
}
}
else
{
/* 256 color table */
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;
Palette.aEntries[i].peRed = r * 51;
Palette.aEntries[i].peGreen = g * 51;
Palette.aEntries[i].peBlue = b * 51;
}
for (i = 216; i < 246; i++)
{
int v = (i - 216) << 3;
Palette.aEntries[i].peRed = v;
Palette.aEntries[i].peGreen = v;
Palette.aEntries[i].peBlue = v;
}
}
return GreCreatePaletteInternal((LOGPALETTE *)&Palette, Palette.NumberOfEntries);
}
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!");
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;
}
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)
XLATEOBJ rewrite. The new XLATEOBJ is not allocated from paged pool anymore, but instead allocated on the stack and Initialized. Only when we habe more than a color table with more than 6 entries, we need to allocate an additional buffer. The new interface: EXLATEOBJ_vInitialize is the main init function. It takes a source and destination palette and back and fore colors for monochome surfaces. EXLATEOBJ_vInitXlateFromDCs takes the source and dest DC and is for color translation between 2 surfaces represented by 2 DCs. EXLATEOBJ_vInitBrushXlate initializes an XLATEOBJ for a pattern brush. Finally EXLATEOBJ_vCleanup needs to be called when the XLATEOBJ is not needed anymore. Implement individual iXlate functions for certain cases and store a function pointer in the EXLATEOBJ structure for quick access. Change the usage of the PALETTE.Mode member to be a flag instead of an enum, add usage of PAL_MONOCHOME, PAL_RGB16_555 and PAL_RGB16_565. Add gpalMono, which *should* be used as palette for 1bpp DDBs. Currently there's a hack in the XLATEOBJ init code, to hack around the fact that this is missing. Fix the Hatch brush patterns, as they were inverted. Implement PALETTE_ulGetNearestBitFieldsIndex and PALETTE_ulGetNearestIndex. Get rid of the XLATEOBJ for the mouse pointer instead realize the pointer before usage. Get rid of logicalToSystem PALETTE member. NtGdiGetDIBitsInternal: Don't create a DIBBrush from the BITMAPINFO, when pvBits is NULL, as the function might be uninitualized. This fixes a crash of gdi_regtest. The whole function is quite ugly and needs to be rewritten (like probably the rest of the DIB code). This fixes the problem of artifacts in the selected desktop icons and some color problems. svn path=/trunk/; revision=42391
2009-08-04 20:37:10 +00:00
{
/* 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 i, 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)
{
UNIMPLEMENTED;
goto cleanup;
}
ppalSurf = pdc->dclevel.pSurface->ppal;
ppalDC = pdc->dclevel.ppal;
if(!(ppalSurf->flFlags & PAL_INDEXED))
{
// FIXME: Set error?
goto cleanup;
}
ASSERT(ppalDC->flFlags & PAL_INDEXED);
// FIXME: Should we resize ppalSurf if it's too small?
realize = (ppalDC->NumColors < ppalSurf->NumColors) ? ppalDC->NumColors : ppalSurf->NumColors;
for(i=0; i<realize; i++)
{
InterlockedExchange((LONG*)&ppalSurf->IndexedColors[i], *(LONG*)&ppalDC->IndexedColors[i]);
}
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;
HDC hDC;
PDC dc;
PWND Wnd;
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);
/* 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);
}
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 ((UINT)hpal & GDI_HANDLE_STOCK_MASK)
{
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 surace 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;
}
W32KAPI
LONG
APIENTRY
NtGdiDoPalette(
IN HGDIOBJ hObj,
IN WORD iStart,
IN WORD cEntries,
IN LPVOID pUnsafeEntries,
IN DWORD iFunc,
IN BOOL bInbound)
{
LONG ret;
LPVOID pEntries = NULL;
/* FIXME: Handle bInbound correctly */
if (bInbound &&
(pUnsafeEntries == NULL || cEntries == 0))
{
return 0;
}
if (pUnsafeEntries)
{
pEntries = ExAllocatePoolWithTag(PagedPool, cEntries * sizeof(PALETTEENTRY), TAG_PALETTE);
if (!pEntries)
return 0;
if (bInbound)
{
_SEH2_TRY
{
ProbeForRead(pUnsafeEntries, cEntries * sizeof(PALETTEENTRY), 1);
memcpy(pEntries, pUnsafeEntries, cEntries * sizeof(PALETTEENTRY));
}
_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, cEntries * sizeof(PALETTEENTRY));
}
}
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)
{
_SEH2_TRY
{
ProbeForWrite(pUnsafeEntries, cEntries * sizeof(PALETTEENTRY), 1);
memcpy(pUnsafeEntries, pEntries, cEntries * sizeof(PALETTEENTRY));
}
_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 ||
((UINT)hgdiobj & GDI_HANDLE_STOCK_MASK) ||
!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;
}
/* EOF */