HBITMAP
APIENTRY
NtGdiSelectBitmap(
- IN HDC hDC,
- IN HBITMAP hBmp)
+ IN HDC hdc,
+ IN HBITMAP hbmp)
{
- PDC pDC;
+ PDC pdc;
PDC_ATTR pdcattr;
- HBITMAP hOrgBmp;
- PSURFACE psurfBmp, psurfOld;
+ HBITMAP hbmpOld;
+ PSURFACE psurfNew;
HRGN hVisRgn;
+ SIZEL sizlBitmap = {1, 1};
+ HDC hdcOld;
+ ASSERT_NOGDILOCKS();
- if (hDC == NULL || hBmp == NULL) return NULL;
+ /* Verify parameters */
+ if (hdc == NULL || hbmp == NULL) return NULL;
- pDC = DC_LockDc(hDC);
- if (!pDC)
+ /* First lock the DC */
+ pdc = DC_LockDc(hdc);
+ if (!pdc)
{
return NULL;
}
- pdcattr = pDC->pdcattr;
+ pdcattr = pdc->pdcattr;
- /* must be memory dc to select bitmap */
- if (pDC->dctype != DC_TYPE_MEMORY)
+ /* Must be a memory dc to select a bitmap */
+ if (pdc->dctype != DC_TYPE_MEMORY)
{
- DC_UnlockDc(pDC);
+ DC_UnlockDc(pdc);
return NULL;
}
- psurfBmp = SURFACE_LockSurface(hBmp);
- if (!psurfBmp)
+ /* Check if there was a bitmap selected before */
+ if (pdc->dclevel.pSurface)
{
- DC_UnlockDc(pDC);
- return NULL;
+ /* Return its handle */
+ hbmpOld = pdc->dclevel.pSurface->BaseObject.hHmgr;
+ }
+ else
+ {
+ /* Return default bitmap */
+ hbmpOld = StockObjects[DEFAULT_BITMAP];
}
- /* Get the handle for the old bitmap */
- ASSERT(pDC->dclevel.pSurface);
- hOrgBmp = pDC->dclevel.pSurface->BaseObject.hHmgr;
-
- /* Lock it, to be sure while we mess with it*/
- psurfOld = SURFACE_LockSurface(hOrgBmp);
-
- /* Reset hdc, this surface isn't selected anymore */
- psurfOld->hdc = NULL;
+ /* Check if the default bitmap was passed */
+ if (hbmp == StockObjects[DEFAULT_BITMAP])
+ {
+ psurfNew = NULL;
- /* Release the old bitmap, reference the new */
- DC_vSelectSurface(pDC, psurfBmp);
+ // HACK
+ psurfNew = SURFACE_ShareLockSurface(hbmp);
+ }
+ else
+ {
+ /* Reference the new bitmap and check if it's valid */
+ psurfNew = SURFACE_ShareLockSurface(hbmp);
+ if (!psurfNew)
+ {
+ DC_UnlockDc(pdc);
+ return NULL;
+ }
- /* And unlock it, now we're done */
- SURFACE_UnlockSurface(psurfOld);
+ /* Set the bitmp's hdc */
+ hdcOld = InterlockedCompareExchangePointer((PVOID*)&psurfNew->hdc, hdc, 0);
+ if (hdcOld != NULL && hdcOld != hdc)
+ {
+ /* The bitmap is already selected, fail */
+ SURFACE_ShareUnlockSurface(psurfNew);
+ DC_UnlockDc(pdc);
+ return NULL;
+ }
- // If Info DC this is zero and pSurface is moved to DC->pSurfInfo.
- psurfBmp->hdc = hDC;
+ /* Get the bitmap size */
+ sizlBitmap = psurfNew->SurfObj.sizlBitmap;
+ /* Check if the bitmap is a dibsection */
+ if(psurfNew->hSecure)
+ {
+ /* Set DIBSECTION attribute */
+ pdcattr->ulDirty_ |= DC_DIBSECTION;
+ }
+ else
+ {
+ pdcattr->ulDirty_ &= ~DC_DIBSECTION;
+ }
+ }
- /* FIXME; improve by using a region without a handle and selecting it */
- hVisRgn = IntSysCreateRectRgn( 0,
- 0,
- psurfBmp->SurfObj.sizlBitmap.cx,
- psurfBmp->SurfObj.sizlBitmap.cy);
+ /* Select the new surface, release the old */
+ DC_vSelectSurface(pdc, psurfNew);
- if(psurfBmp->hSecure)
- {
- /* Set DIBSECTION attribute */
- pdcattr->ulDirty_ |= DC_DIBSECTION;
- }
- else
- {
- pdcattr->ulDirty_ &= ~DC_DIBSECTION;
- }
+ /* Set the new size */
+ pdc->dclevel.sizl = sizlBitmap;
- /* Release the exclusive lock */
- SURFACE_UnlockSurface(psurfBmp);
+ /* Release one reference we added */
+ SURFACE_ShareUnlockSurface(psurfNew);
- /* Mark the brushes invalid */
+ /* Mark the dc brushes invalid */
pdcattr->ulDirty_ |= DIRTY_FILL | DIRTY_LINE;
- DC_UnlockDc(pDC);
+ /* Unlock the DC */
+ DC_UnlockDc(pdc);
+ /* FIXME; improve by using a region without a handle and selecting it */
+ hVisRgn = IntSysCreateRectRgn( 0,
+ 0,
+ sizlBitmap.cx,
+ sizlBitmap.cy);
if (hVisRgn)
{
- GdiSelectVisRgn(hDC, hVisRgn);
+ GdiSelectVisRgn(hdc, hVisRgn);
REGION_FreeRgnByHandle(hVisRgn);
}
- return hOrgBmp;
+ /* Return the old bitmp handle */
+ return hbmpOld;
}