INT FASTCALL GdiGetClipBox(HDC hDC, PRECTL rc) { INT retval; PDC dc; PROSRGNDATA pRgnNew, pRgn = NULL; BOOL Unlock = FALSE; //Small hack if (!(dc = DC_LockDc(hDC))) { return ERROR; } /* FIXME! Rao and Vis only! */ if (dc->prgnAPI) // APIRGN { pRgn = dc->prgnAPI; } else if (dc->dclevel.prgnMeta) // METARGN { pRgn = dc->dclevel.prgnMeta; } else if (dc->rosdc.hClipRgn) { Unlock = TRUE ; pRgn = REGION_LockRgn(dc->rosdc.hClipRgn); // CLIPRGN } if (pRgn) { pRgnNew = IntSysCreateRectpRgn( 0, 0, 0, 0 ); if (!pRgnNew) { DC_UnlockDc(dc); if(Unlock) REGION_UnlockRgn(pRgn); return ERROR; } IntGdiCombineRgn(pRgnNew, dc->prgnVis, pRgn, RGN_AND); retval = REGION_GetRgnBox(pRgnNew, rc); REGION_Delete(pRgnNew); DC_UnlockDc(dc); if(Unlock) REGION_UnlockRgn(pRgn); return retval; } retval = REGION_GetRgnBox(dc->prgnVis, rc); IntDPtoLP(dc, (LPPOINT)rc, 2); DC_UnlockDc(dc); return retval; }
INT FASTCALL GdiGetClipBox( _In_ HDC hdc, _Out_ LPRECT prc) { PDC pdc; INT iComplexity; /* Lock the DC */ pdc = DC_LockDc(hdc); if (!pdc) { return ERROR; } /* Update RAO region if necessary */ if (pdc->fs & DC_FLAG_DIRTY_RAO) CLIPPING_UpdateGCRegion(pdc); /* Check if we have a RAO region (intersection of API and VIS region) */ if (pdc->prgnRao) { /* We have a RAO region, use it */ iComplexity = REGION_GetRgnBox(pdc->prgnRao, prc); } else { /* No RAO region means no API region, so use the VIS region */ ASSERT(pdc->prgnVis); iComplexity = REGION_GetRgnBox(pdc->prgnVis, prc); } /* Unlock the DC */ DC_UnlockDc(pdc); /* Convert the rect to logical coordinates */ IntDPtoLP(pdc, (LPPOINT)prc, 2); /* Return the complexity */ return iComplexity; }
int FASTCALL GdiExtSelectClipRgn(PDC dc, HRGN hrgn, int fnMode) { // dc->fs &= ~DC_FLAG_DIRTY_RAO; if (!hrgn) { if (fnMode == RGN_COPY) { if (dc->rosdc.hClipRgn != NULL) { GreDeleteObject(dc->rosdc.hClipRgn); dc->rosdc.hClipRgn = NULL; } } else { EngSetLastError(ERROR_INVALID_PARAMETER); return ERROR; } } else { if (!dc->rosdc.hClipRgn) { RECTL rect; if(dc->prgnVis) { REGION_GetRgnBox(dc->prgnVis, &rect); dc->rosdc.hClipRgn = IntSysCreateRectRgnIndirect(&rect); } else { dc->rosdc.hClipRgn = IntSysCreateRectRgn(0, 0, 0, 0); } } if(fnMode == RGN_COPY) { NtGdiCombineRgn(dc->rosdc.hClipRgn, hrgn, 0, fnMode); } else NtGdiCombineRgn(dc->rosdc.hClipRgn, dc->rosdc.hClipRgn, hrgn, fnMode); } return CLIPPING_UpdateGCRegion(dc); }
int FASTCALL IntGdiExtSelectClipRgn( PDC dc, PREGION prgn, int fnMode) { if (fnMode == RGN_COPY) { if (!prgn) { if (dc->dclevel.prgnClip != NULL) { REGION_Delete(dc->dclevel.prgnClip); dc->dclevel.prgnClip = NULL; dc->fs |= DC_FLAG_DIRTY_RAO; } return SIMPLEREGION; } if (!dc->dclevel.prgnClip) dc->dclevel.prgnClip = IntSysCreateRectpRgn(0, 0, 0, 0); dc->fs |= DC_FLAG_DIRTY_RAO; return IntGdiCombineRgn(dc->dclevel.prgnClip, prgn, NULL, RGN_COPY); } ASSERT(prgn != NULL); if (!dc->dclevel.prgnClip) { RECTL rect; REGION_GetRgnBox(dc->prgnVis, &rect); dc->dclevel.prgnClip = IntSysCreateRectpRgnIndirect(&rect); } dc->fs |= DC_FLAG_DIRTY_RAO; return IntGdiCombineRgn(dc->dclevel.prgnClip, dc->dclevel.prgnClip, prgn, fnMode); }
BOOL APIENTRY NtGdiExtFloodFill( HDC hDC, INT XStart, INT YStart, COLORREF Color, UINT FillType) { PDC dc; #if 0 PDC_ATTR pdcattr; #endif SURFACE *psurf; EXLATEOBJ exlo; BOOL Ret = FALSE; RECTL DestRect; POINTL Pt; ULONG ConvColor; dc = DC_LockDc(hDC); if (!dc) { EngSetLastError(ERROR_INVALID_HANDLE); return FALSE; } if (dc->dctype == DC_TYPE_INFO) { DC_UnlockDc(dc); /* Yes, Windows really returns TRUE in this case */ return TRUE; } if (!dc->dclevel.pSurface) { Ret = FALSE; goto cleanup; } #if 0 pdcattr = dc->pdcattr; #endif Pt.x = XStart; Pt.y = YStart; IntLPtoDP(dc, (LPPOINT)&Pt, 1); DC_vPrepareDCsForBlit(dc, &DestRect, NULL, NULL); /// FIXME: what about prgnVIS? And what about REAL clipping? psurf = dc->dclevel.pSurface; if (dc->prgnRao) { Ret = REGION_PtInRegion(dc->prgnRao, Pt.x, Pt.y); if (Ret) REGION_GetRgnBox(dc->prgnRao, (LPRECT)&DestRect); else { DC_vFinishBlit(dc, NULL); goto cleanup; } } else { RECTL_vSetRect(&DestRect, 0, 0, psurf->SurfObj.sizlBitmap.cx, psurf->SurfObj.sizlBitmap.cy); } EXLATEOBJ_vInitialize(&exlo, &gpalRGB, psurf->ppal, 0, 0xffffff, 0); /* Only solid fills supported for now * How to support pattern brushes and non standard surfaces (not offering dib functions): * Version a (most likely slow): call DrvPatBlt for every pixel * Version b: create a flood mask and let MaskBlt blit a masked brush */ ConvColor = XLATEOBJ_iXlate(&exlo.xlo, Color); Ret = DIB_XXBPP_FloodFillSolid(&psurf->SurfObj, &dc->eboFill.BrushObject, &DestRect, &Pt, ConvColor, FillType); DC_vFinishBlit(dc, NULL); EXLATEOBJ_vCleanup(&exlo); cleanup: DC_UnlockDc(dc); return Ret; }
/* NtUserEnumDisplayMonitors * * Enumerates display monitors which intersect the given HDC/cliprect * * Arguments * * hDC * Handle to a DC for which to enum intersecting monitors. If this is NULL * it returns all monitors which are part of the current virtual screen. * * pRect * Clipping rectangle with coordinate system origin at the DCs origin if the * given HDC is not NULL or in virtual screen coordinated if it is NULL. * Can be NULL * * hMonitorList * Pointer to an array of HMONITOR which is filled with monitor handles. * Can be NULL * * monitorRectList * Pointer to an array of RECT which is filled with intersection rectangles. * Can be NULL * * listSize * Size of the hMonitorList and monitorRectList arguments. If this is zero * hMonitorList and monitorRectList are ignored. * * Returns * The number of monitors which intersect the specified region or -1 on failure. */ INT APIENTRY NtUserEnumDisplayMonitors( OPTIONAL IN HDC hDC, OPTIONAL IN LPCRECTL pRect, OPTIONAL OUT HMONITOR *hMonitorList, OPTIONAL OUT PRECTL monitorRectList, OPTIONAL IN DWORD listSize) { INT numMonitors, i; HMONITOR *safeHMonitorList = NULL; PRECTL safeRectList = NULL; RECTL rect, *myRect; RECTL dcRect; NTSTATUS status; /* get rect */ if (pRect != NULL) { status = MmCopyFromCaller(&rect, pRect, sizeof (RECT)); if (!NT_SUCCESS(status)) { TRACE("MmCopyFromCaller() failed!\n"); SetLastNtError(status); return -1; } } if (hDC != NULL) { PDC dc; INT regionType; /* get visible region bounding rect */ dc = DC_LockDc(hDC); if (dc == NULL) { TRACE("DC_LockDc() failed!\n"); /* FIXME: setlasterror? */ return -1; } regionType = REGION_GetRgnBox(dc->prgnVis, &dcRect); DC_UnlockDc(dc); if (regionType == 0) { TRACE("NtGdiGetRgnBox() failed!\n"); return -1; } if (regionType == NULLREGION) return 0; if (regionType == COMPLEXREGION) { /* TODO: warning */ } /* if hDC and pRect are given the area of interest is pRect with coordinate origin at the DC position */ if (pRect != NULL) { rect.left += dcRect.left; rect.right += dcRect.left; rect.top += dcRect.top; rect.bottom += dcRect.top; } /* if hDC is given and pRect is not the area of interest is the bounding rect of hDC */ else { rect = dcRect; } } if (hDC == NULL && pRect == NULL) myRect = NULL; else myRect = ▭ /* find intersecting monitors */ numMonitors = IntGetMonitorsFromRect(myRect, NULL, NULL, 0, 0); if (numMonitors == 0 || listSize == 0 || (hMonitorList == NULL && monitorRectList == NULL)) { TRACE("numMonitors = %d\n", numMonitors); return numMonitors; } if (hMonitorList != NULL && listSize != 0) { safeHMonitorList = ExAllocatePoolWithTag(PagedPool, sizeof (HMONITOR) * listSize, USERTAG_MONITORRECTS); if (safeHMonitorList == NULL) { /* FIXME: EngSetLastError? */ return -1; } } if (monitorRectList != NULL && listSize != 0) { safeRectList = ExAllocatePoolWithTag(PagedPool, sizeof (RECT) * listSize, USERTAG_MONITORRECTS); if (safeRectList == NULL) { ExFreePoolWithTag(safeHMonitorList, USERTAG_MONITORRECTS); /* FIXME: EngSetLastError? */ return -1; } } /* get intersecting monitors */ numMonitors = IntGetMonitorsFromRect(myRect, safeHMonitorList, safeRectList, listSize, 0 ); if (hDC != NULL && pRect != NULL && safeRectList != NULL) for (i = 0; i < numMonitors; i++) { safeRectList[i].left -= dcRect.left; safeRectList[i].right -= dcRect.left; safeRectList[i].top -= dcRect.top; safeRectList[i].bottom -= dcRect.top; } /* output result */ if (hMonitorList != NULL && listSize != 0) { status = MmCopyToCaller(hMonitorList, safeHMonitorList, sizeof (HMONITOR) * listSize); ExFreePool(safeHMonitorList); if (!NT_SUCCESS(status)) { ExFreePoolWithTag(safeRectList, USERTAG_MONITORRECTS); SetLastNtError(status); return -1; } } if (monitorRectList != NULL && listSize != 0) { status = MmCopyToCaller(monitorRectList, safeRectList, sizeof (RECT) * listSize); ExFreePoolWithTag(safeRectList, USERTAG_MONITORRECTS); if (!NT_SUCCESS(status)) { SetLastNtError(status); return -1; } } return numMonitors; }
/* NtUserEnumDisplayMonitors * * Enumerates display monitors which intersect the given HDC/cliprect * * Arguments * * hdc * Handle to a DC for which to enum intersecting monitors. If this is NULL * it returns all monitors which are part of the current virtual screen. * * pUnsafeRect * Clipping rectangle with coordinate system origin at the DCs origin if the * given HDC is not NULL or in virtual screen coordinated if it is NULL. * Can be NULL * * phUnsafeMonitorList * Pointer to an array of HMONITOR which is filled with monitor handles. * Can be NULL * * prcUnsafeMonitorList * Pointer to an array of RECT which is filled with intersection rectangles. * Can be NULL * * dwListSize * Size of the hMonitorList and monitorRectList arguments. If this is zero * hMonitorList and monitorRectList are ignored. * * Returns * The number of monitors which intersect the specified region or -1 on failure. */ INT APIENTRY NtUserEnumDisplayMonitors( OPTIONAL IN HDC hdc, OPTIONAL IN LPCRECTL pUnsafeRect, OPTIONAL OUT HMONITOR *phUnsafeMonitorList, OPTIONAL OUT PRECTL prcUnsafeMonitorList, OPTIONAL IN DWORD dwListSize) { INT cMonitors, iRet = -1, i; HMONITOR *phMonitorList = NULL; PRECTL prcMonitorList = NULL; RECTL rc, *pRect; RECTL DcRect = {0}; NTSTATUS Status; /* Get rectangle */ if (pUnsafeRect != NULL) { Status = MmCopyFromCaller(&rc, pUnsafeRect, sizeof(RECT)); if (!NT_SUCCESS(Status)) { TRACE("MmCopyFromCaller() failed!\n"); SetLastNtError(Status); return -1; } } if (hdc != NULL) { PDC pDc; INT iRgnType; /* Get visible region bounding rect */ pDc = DC_LockDc(hdc); if (pDc == NULL) { TRACE("DC_LockDc() failed!\n"); /* FIXME: setlasterror? */ return -1; } iRgnType = REGION_GetRgnBox(pDc->prgnVis, &DcRect); DC_UnlockDc(pDc); if (iRgnType == 0) { TRACE("NtGdiGetRgnBox() failed!\n"); return -1; } if (iRgnType == NULLREGION) return 0; if (iRgnType == COMPLEXREGION) { /* TODO: Warning */ } /* If hdc and pRect are given the area of interest is pRect with coordinate origin at the DC position */ if (pUnsafeRect != NULL) { rc.left += DcRect.left; rc.right += DcRect.left; rc.top += DcRect.top; rc.bottom += DcRect.top; } /* If hdc is given and pRect is not the area of interest is the bounding rect of hdc */ else { rc = DcRect; } } if (hdc == NULL && pUnsafeRect == NULL) pRect = NULL; else pRect = &rc; UserEnterShared(); /* Find intersecting monitors */ cMonitors = IntGetMonitorsFromRect(pRect, NULL, NULL, 0, MONITOR_DEFAULTTONULL); if (cMonitors == 0 || dwListSize == 0 || (phUnsafeMonitorList == NULL && prcUnsafeMonitorList == NULL)) { /* Simple case - just return monitors count */ TRACE("cMonitors = %d\n", cMonitors); iRet = cMonitors; goto cleanup; } /* Allocate safe buffers */ if (phUnsafeMonitorList != NULL && dwListSize != 0) { phMonitorList = ExAllocatePoolWithTag(PagedPool, sizeof (HMONITOR) * dwListSize, USERTAG_MONITORRECTS); if (phMonitorList == NULL) { EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); goto cleanup; } } if (prcUnsafeMonitorList != NULL && dwListSize != 0) { prcMonitorList = ExAllocatePoolWithTag(PagedPool, sizeof (RECT) * dwListSize, USERTAG_MONITORRECTS); if (prcMonitorList == NULL) { EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); goto cleanup; } } /* Get intersecting monitors */ cMonitors = IntGetMonitorsFromRect(pRect, phMonitorList, prcMonitorList, dwListSize, MONITOR_DEFAULTTONULL); if (hdc != NULL && pRect != NULL && prcMonitorList != NULL) for (i = 0; i < cMonitors; i++) { prcMonitorList[i].left -= DcRect.left; prcMonitorList[i].right -= DcRect.left; prcMonitorList[i].top -= DcRect.top; prcMonitorList[i].bottom -= DcRect.top; } /* Output result */ if (phUnsafeMonitorList != NULL && dwListSize != 0) { Status = MmCopyToCaller(phUnsafeMonitorList, phMonitorList, sizeof(HMONITOR) * dwListSize); if (!NT_SUCCESS(Status)) { SetLastNtError(Status); goto cleanup; } } if (prcUnsafeMonitorList != NULL && dwListSize != 0) { Status = MmCopyToCaller(prcUnsafeMonitorList, prcMonitorList, sizeof(RECT) * dwListSize); if (!NT_SUCCESS(Status)) { SetLastNtError(Status); goto cleanup; } } /* Return monitors count on success */ iRet = cMonitors; cleanup: if (phMonitorList) ExFreePoolWithTag(phMonitorList, USERTAG_MONITORRECTS); if (prcMonitorList) ExFreePoolWithTag(prcMonitorList, USERTAG_MONITORRECTS); UserLeave(); return iRet; }
DWORD APIENTRY NtGdiGetBoundsRect( IN HDC hdc, OUT LPRECT prc, IN DWORD flags) { DWORD ret; PDC pdc; RECT rc; /* Lock the DC */ if (!(pdc = DC_LockDc(hdc))) return 0; if (!(flags & DCB_WINDOWMGR)) { rc = pdc->erclBoundsApp; if (RECTL_bIsEmptyRect(&rc)) { rc.left = rc.top = rc.right = rc.bottom = 0; ret = DCB_RESET; } else { RECTL rcRgn; if (pdc->fs & DC_FLAG_DIRTY_RAO) CLIPPING_UpdateGCRegion(pdc); if(!REGION_GetRgnBox(pdc->prgnRao, &rcRgn)) { REGION_GetRgnBox(pdc->prgnVis, &rcRgn); } rc.left = max( rc.left, 0 ); rc.top = max( rc.top, 0 ); rc.right = min( rc.right, rcRgn.right - rcRgn.left ); rc.bottom = min( rc.bottom, rcRgn.bottom - rcRgn.top ); DPRINT("Rao dc %p r %d b %d\n",pdc,rcRgn.right - rcRgn.left, rcRgn.bottom - rcRgn.top); DPRINT("rc l %d t %d\n",rc.left,rc.top); DPRINT(" r %d b %d\n",rc.right,rc.bottom); ret = DCB_SET; } IntDPtoLP( pdc, &rc, 2 ); DPRINT("rc1 l %d t %d\n",rc.left,rc.top); DPRINT(" r %d b %d\n",rc.right,rc.bottom); } else { rc = pdc->erclBounds; ret = DCB_SET; } /* Copy the rect to the caller */ _SEH2_TRY { ProbeForWrite(prc, sizeof(RECT), 1); *prc = rc; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { ret = 0; } _SEH2_END; if (flags & DCB_RESET) { if (!(flags & DCB_WINDOWMGR)) { pdc->erclBoundsApp.left = pdc->erclBoundsApp.top = INT_MAX; pdc->erclBoundsApp.right = pdc->erclBoundsApp.bottom = INT_MIN; } else { pdc->erclBounds.left = pdc->erclBounds.top = INT_MAX; pdc->erclBounds.right = pdc->erclBounds.bottom = INT_MIN; } } DC_UnlockDc(pdc); return ret; }