INT FASTCALL GdiSelectVisRgn(HDC hdc, HRGN hrgn) { int retval; DC *dc; PREGION prgn; if (!hrgn) { EngSetLastError(ERROR_INVALID_PARAMETER); return ERROR; } if (!(dc = DC_LockDc(hdc))) { EngSetLastError(ERROR_INVALID_HANDLE); return ERROR; } dc->fs &= ~DC_FLAG_DIRTY_RAO; ASSERT (dc->prgnVis != NULL); prgn = RGNOBJAPI_Lock(hrgn, NULL); retval = prgn ? IntGdiCombineRgn(dc->prgnVis, prgn, NULL, RGN_COPY) : ERROR; RGNOBJAPI_Unlock(prgn); if ( retval != ERROR ) { IntGdiOffsetRgn(dc->prgnVis, -dc->ptlDCOrig.x, -dc->ptlDCOrig.y); CLIPPING_UpdateGCRegion(dc); } DC_UnlockDc(dc); return retval; }
int FASTCALL CLIPPING_UpdateGCRegion(DC* Dc) { PROSRGNDATA CombinedRegion; HRGN hRgnVis; PREGION prgnClip, prgnGCClip; // would prefer this, but the rest of the code sucks // ASSERT(Dc->rosdc.hGCClipRgn); // ASSERT(Dc->rosdc.hClipRgn); ASSERT(Dc->prgnVis); hRgnVis = Dc->prgnVis->BaseObject.hHmgr; if (Dc->rosdc.hGCClipRgn == NULL) Dc->rosdc.hGCClipRgn = IntSysCreateRectRgn(0, 0, 0, 0); prgnGCClip = REGION_LockRgn(Dc->rosdc.hGCClipRgn); ASSERT(prgnGCClip); if (Dc->rosdc.hClipRgn == NULL) IntGdiCombineRgn(prgnGCClip, Dc->prgnVis, NULL, RGN_COPY); else { prgnClip = REGION_LockRgn(Dc->rosdc.hClipRgn); // FIXME: locking order, ugh IntGdiCombineRgn(prgnGCClip, Dc->prgnVis, prgnClip, RGN_AND); REGION_UnlockRgn(prgnClip); } REGION_UnlockRgn(prgnGCClip); NtGdiOffsetRgn(Dc->rosdc.hGCClipRgn, Dc->ptlDCOrig.x, Dc->ptlDCOrig.y); if((CombinedRegion = RGNOBJAPI_Lock(Dc->rosdc.hGCClipRgn, NULL))) { CLIPOBJ *CombinedClip; CombinedClip = IntEngCreateClipRegion(CombinedRegion->rdh.nCount, CombinedRegion->Buffer, &CombinedRegion->rdh.rcBound); RGNOBJAPI_Unlock(CombinedRegion); if ( !CombinedClip ) { DPRINT1("IntEngCreateClipRegion() failed\n"); return ERROR; } if(Dc->rosdc.CombinedClip != NULL) IntEngDeleteClipRegion(Dc->rosdc.CombinedClip); Dc->rosdc.CombinedClip = CombinedClip ; } return NtGdiOffsetRgn(Dc->rosdc.hGCClipRgn, -Dc->ptlDCOrig.x, -Dc->ptlDCOrig.y); }
BOOL APIENTRY NtGdiRectVisible(HDC hDC, LPRECT UnsafeRect) { NTSTATUS Status = STATUS_SUCCESS; PROSRGNDATA Rgn; PDC dc = DC_LockDc(hDC); BOOL Result = FALSE; RECTL Rect; if (!dc) { EngSetLastError(ERROR_INVALID_HANDLE); return FALSE; } _SEH2_TRY { ProbeForRead(UnsafeRect, sizeof(RECT), 1); Rect = *UnsafeRect; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Status = _SEH2_GetExceptionCode(); } _SEH2_END; if(!NT_SUCCESS(Status)) { DC_UnlockDc(dc); SetLastNtError(Status); return FALSE; } if (dc->rosdc.hGCClipRgn) { if((Rgn = (PROSRGNDATA)RGNOBJAPI_Lock(dc->rosdc.hGCClipRgn, NULL))) { IntLPtoDP(dc, (LPPOINT)&Rect, 2); Result = REGION_RectInRegion(Rgn, &Rect); RGNOBJAPI_Unlock(Rgn); } } DC_UnlockDc(dc); return Result; }
ULONG_PTR APIENTRY NtGdiPolyPolyDraw( IN HDC hDC, IN PPOINT UnsafePoints, IN PULONG UnsafeCounts, IN ULONG Count, IN INT iFunc ) { DC *dc; PVOID pTemp; LPPOINT SafePoints; PULONG SafeCounts; NTSTATUS Status = STATUS_SUCCESS; BOOL Ret = TRUE; ULONG nPoints = 0, nMaxPoints = 0, nInvalid = 0, i; if (!UnsafePoints || !UnsafeCounts || Count == 0 || iFunc == 0 || iFunc > GdiPolyPolyRgn) { /* Windows doesn't set last error */ return FALSE; } _SEH2_TRY { ProbeForRead(UnsafePoints, Count * sizeof(POINT), 1); ProbeForRead(UnsafeCounts, Count * sizeof(ULONG), 1); /* Count points and validate poligons */ for (i = 0; i < Count; i++) { if (UnsafeCounts[i] < 2) { nInvalid++; } nPoints += UnsafeCounts[i]; nMaxPoints = max(nMaxPoints, UnsafeCounts[i]); } } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Status = _SEH2_GetExceptionCode(); } _SEH2_END; if (!NT_SUCCESS(Status)) { /* Windows doesn't set last error */ return FALSE; } if (nPoints == 0 || nPoints < nMaxPoints) { /* If all polygon counts are zero, or we have overflow, return without setting a last error code. */ return FALSE; } if (nInvalid != 0) { /* If at least one poly count is 0 or 1, fail */ EngSetLastError(ERROR_INVALID_PARAMETER); return FALSE; } /* Allocate one buffer for both counts and points */ pTemp = ExAllocatePoolWithTag(PagedPool, Count * sizeof(ULONG) + nPoints * sizeof(POINT), TAG_SHAPE); if (!pTemp) { EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); return FALSE; } SafeCounts = pTemp; SafePoints = (PVOID)(SafeCounts + Count); _SEH2_TRY { /* Pointers already probed! */ RtlCopyMemory(SafeCounts, UnsafeCounts, Count * sizeof(ULONG)); RtlCopyMemory(SafePoints, UnsafePoints, nPoints * sizeof(POINT)); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Status = _SEH2_GetExceptionCode(); } _SEH2_END; if (!NT_SUCCESS(Status)) { ExFreePoolWithTag(pTemp, TAG_SHAPE); return FALSE; } /* Special handling for GdiPolyPolyRgn */ if (iFunc == GdiPolyPolyRgn) { PREGION Rgn; HRGN hRgn; Rgn = REGION_AllocUserRgnWithHandle(0); if (!Rgn) { EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); ExFreePoolWithTag(pTemp, TAG_SHAPE); return 0; } hRgn = Rgn->BaseObject.hHmgr; if (!IntSetPolyPolygonRgn(SafePoints, SafeCounts, Count, hDC ? 1 : 2, Rgn)) { /* EngSetLastError ? */ GreDeleteObject(hRgn); hRgn = NULL; } RGNOBJAPI_Unlock(Rgn); ExFreePoolWithTag(pTemp, TAG_SHAPE); return (ULONG_PTR)hRgn; } dc = DC_LockDc(hDC); if (!dc) { EngSetLastError(ERROR_INVALID_HANDLE); ExFreePoolWithTag(pTemp, TAG_SHAPE); return FALSE; } if (dc->dctype == DC_TYPE_INFO) { DC_UnlockDc(dc); ExFreePoolWithTag(pTemp, TAG_SHAPE); /* Yes, Windows really returns TRUE in this case */ return TRUE; } DC_vPrepareDCsForBlit(dc, NULL, NULL, NULL); if (dc->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY)) DC_vUpdateFillBrush(dc); if (dc->pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY)) DC_vUpdateLineBrush(dc); /* Perform the actual work */ switch (iFunc) { case GdiPolyPolygon: Ret = IntGdiPolyPolygon(dc, SafePoints, SafeCounts, Count); break; case GdiPolyPolyLine: Ret = IntGdiPolyPolyline(dc, SafePoints, SafeCounts, Count); break; case GdiPolyBezier: Ret = IntGdiPolyBezier(dc, SafePoints, *SafeCounts); break; case GdiPolyLineTo: Ret = IntGdiPolylineTo(dc, SafePoints, *SafeCounts); break; case GdiPolyBezierTo: Ret = IntGdiPolyBezierTo(dc, SafePoints, *SafeCounts); break; default: EngSetLastError(ERROR_INVALID_PARAMETER); Ret = FALSE; } /* Cleanup and return */ DC_vFinishBlit(dc, NULL); DC_UnlockDc(dc); ExFreePoolWithTag(pTemp, TAG_SHAPE); return (ULONG_PTR)Ret; }
/* * Fills the CLIPOBJ and client rect of the WNDOBJ with the data from the given WND */ BOOLEAN FASTCALL IntEngWndUpdateClipObj( WNDGDI *WndObjInt, PWND Window) { HRGN hVisRgn; PROSRGNDATA visRgn; CLIPOBJ *ClipObj = NULL; CLIPOBJ *OldClipObj; DPRINT("IntEngWndUpdateClipObj\n"); hVisRgn = VIS_ComputeVisibleRegion(Window, TRUE, TRUE, TRUE); if (hVisRgn != NULL) { NtGdiOffsetRgn(hVisRgn, Window->rcClient.left, Window->rcClient.top); visRgn = RGNOBJAPI_Lock(hVisRgn, NULL); if (visRgn != NULL) { if (visRgn->rdh.nCount > 0) { ClipObj = IntEngCreateClipRegion(visRgn->rdh.nCount, visRgn->Buffer, &visRgn->rdh.rcBound); DPRINT("Created visible region with %lu rects\n", visRgn->rdh.nCount); DPRINT(" BoundingRect: %d, %d %d, %d\n", visRgn->rdh.rcBound.left, visRgn->rdh.rcBound.top, visRgn->rdh.rcBound.right, visRgn->rdh.rcBound.bottom); { ULONG i; for (i = 0; i < visRgn->rdh.nCount; i++) { DPRINT(" Rect #%lu: %ld,%ld %ld,%ld\n", i+1, visRgn->Buffer[i].left, visRgn->Buffer[i].top, visRgn->Buffer[i].right, visRgn->Buffer[i].bottom); } } } RGNOBJAPI_Unlock(visRgn); } else { DPRINT1("Warning: Couldn't lock visible region of window DC\n"); } GreDeleteObject(hVisRgn); } else { DPRINT1("Warning: VIS_ComputeVisibleRegion failed!\n"); } if (ClipObj == NULL) { /* Fall back to client rect */ ClipObj = IntEngCreateClipRegion(1, &Window->rcClient, &Window->rcClient); } if (ClipObj == NULL) { DPRINT1("Warning: IntEngCreateClipRegion() failed!\n"); return FALSE; } RtlCopyMemory(&WndObjInt->WndObj.coClient, ClipObj, sizeof (CLIPOBJ)); RtlCopyMemory(&WndObjInt->WndObj.rclClient, &Window->rcClient, sizeof (RECT)); OldClipObj = InterlockedExchangePointer((PVOID*)&WndObjInt->ClientClipObj, ClipObj); if (OldClipObj != NULL) IntEngDeleteClipRegion(OldClipObj); return TRUE; }