Fix another bug in NtGdiSelectBitmap, where selecting the same bitmap a second time, would release the bitmap

svn path=/trunk/; revision=55671
This commit is contained in:
Timo Kreuzer 2012-02-17 15:51:13 +00:00
parent 04135b7ce4
commit 4c5e2c71ec

View file

@ -261,11 +261,9 @@ NtGdiSelectBitmap(
IN HBITMAP hbmp) IN HBITMAP hbmp)
{ {
PDC pdc; PDC pdc;
PDC_ATTR pdcattr;
HBITMAP hbmpOld; HBITMAP hbmpOld;
PSURFACE psurfNew, psurfOld; PSURFACE psurfNew, psurfOld;
HRGN hVisRgn; HRGN hVisRgn;
SIZEL sizlBitmap = {1, 1};
HDC hdcOld; HDC hdcOld;
ASSERT_NOGDILOCKS(); ASSERT_NOGDILOCKS();
@ -278,7 +276,6 @@ NtGdiSelectBitmap(
{ {
return NULL; return NULL;
} }
pdcattr = pdc->pdcattr;
/* Must be a memory dc to select a bitmap */ /* Must be a memory dc to select a bitmap */
if (pdc->dctype != DC_TYPE_MEMORY) if (pdc->dctype != DC_TYPE_MEMORY)
@ -290,11 +287,35 @@ NtGdiSelectBitmap(
/* Save the old bitmap */ /* Save the old bitmap */
psurfOld = pdc->dclevel.pSurface; psurfOld = pdc->dclevel.pSurface;
/* Check if there is a bitmap selected */
if (psurfOld)
{
/* Get the old bitmap's handle */
hbmpOld = psurfOld->BaseObject.hHmgr;
}
else
{
/* Use the default bitmap */
hbmpOld = StockObjects[DEFAULT_BITMAP];
}
/* Check if the new bitmap is already selected */
if (hbmp == hbmpOld)
{
/* Unlock the DC and return the old bitmap */
DC_UnlockDc(pdc);
return hbmpOld;
}
/* Check if the default bitmap was passed */ /* Check if the default bitmap was passed */
if (hbmp == StockObjects[DEFAULT_BITMAP]) if (hbmp == StockObjects[DEFAULT_BITMAP])
{ {
psurfNew = NULL; psurfNew = NULL;
/* Default bitmap is 1x1 pixel */
pdc->dclevel.sizl.cx = 1;
pdc->dclevel.sizl.cy = 1;
// HACK // HACK
psurfNew = SURFACE_ShareLockSurface(hbmp); psurfNew = SURFACE_ShareLockSurface(hbmp);
} }
@ -308,28 +329,32 @@ NtGdiSelectBitmap(
return NULL; return NULL;
} }
/* Set the bitmp's hdc */ /* Set the bitmap's hdc and check if it was set before */
hdcOld = InterlockedCompareExchangePointer((PVOID*)&psurfNew->hdc, hdc, 0); hdcOld = InterlockedCompareExchangePointer((PVOID*)&psurfNew->hdc, hdc, 0);
if (hdcOld != NULL && hdcOld != hdc) if (hdcOld != NULL)
{ {
/* The bitmap is already selected, fail */ /* The bitmap is already selected into a different DC */
ASSERT(hdcOld != hdc);
/* Dereference the bitmap, unlock the DC and fail. */
SURFACE_ShareUnlockSurface(psurfNew); SURFACE_ShareUnlockSurface(psurfNew);
DC_UnlockDc(pdc); DC_UnlockDc(pdc);
return NULL; return NULL;
} }
/* Get the bitmap size */ /* Copy the bitmap size */
sizlBitmap = psurfNew->SurfObj.sizlBitmap; pdc->dclevel.sizl = psurfNew->SurfObj.sizlBitmap;
/* Check if the bitmap is a dibsection */ /* Check if the bitmap is a dibsection */
if(psurfNew->hSecure) if(psurfNew->hSecure)
{ {
/* Set DIBSECTION attribute */ /* Set DIBSECTION attribute */
pdcattr->ulDirty_ |= DC_DIBSECTION; pdc->pdcattr->ulDirty_ |= DC_DIBSECTION;
} }
else else
{ {
pdcattr->ulDirty_ &= ~DC_DIBSECTION; /* Remove DIBSECTION attribute */
pdc->pdcattr->ulDirty_ &= ~DC_DIBSECTION;
} }
} }
@ -339,38 +364,31 @@ NtGdiSelectBitmap(
/* Check if there was a bitmap selected before */ /* Check if there was a bitmap selected before */
if (psurfOld) if (psurfOld)
{ {
/* Get the old bitmap's handle */ /* Reset hdc of the old bitmap, it isn't selected anymore */
hbmpOld = psurfOld->BaseObject.hHmgr;
/* Reset hdc of the old bitmap,it isn't selected anymore */
psurfOld->hdc = NULL; psurfOld->hdc = NULL;
/* Dereference the old bitmap */ /* Dereference the old bitmap */
SURFACE_ShareUnlockSurface(psurfOld); SURFACE_ShareUnlockSurface(psurfOld);
} }
else
{
/* Return default bitmap */
hbmpOld = StockObjects[DEFAULT_BITMAP];
}
/* Mark the dc brushes invalid */ /* Mark the dc brushes invalid */
pdcattr->ulDirty_ |= DIRTY_FILL | DIRTY_LINE; pdc->pdcattr->ulDirty_ |= DIRTY_FILL | DIRTY_LINE;
/* Unlock the DC */
DC_UnlockDc(pdc);
/* FIXME: Improve by using a region without a handle and selecting it */ /* FIXME: Improve by using a region without a handle and selecting it */
hVisRgn = IntSysCreateRectRgn( 0, hVisRgn = IntSysCreateRectRgn( 0,
0, 0,
sizlBitmap.cx, pdc->dclevel.sizl.cx,
sizlBitmap.cy); pdc->dclevel.sizl.cy);
if (hVisRgn) if (hVisRgn)
{ {
GdiSelectVisRgn(hdc, hVisRgn); GdiSelectVisRgn(hdc, hVisRgn);
GreDeleteObject(hVisRgn); GreDeleteObject(hVisRgn);
} }
/* Unlock the DC */
DC_UnlockDc(pdc);
/* Return the old bitmap handle */ /* Return the old bitmap handle */
return hbmpOld; return hbmpOld;
} }