INT FASTCALL IntGdiSetBkMode(HDC hDC, INT Mode) { COLORREF oldMode; PDC dc; PDC_ATTR pdcattr; if (!(dc = DC_LockDc(hDC))) { EngSetLastError(ERROR_INVALID_HANDLE); return CLR_INVALID; } pdcattr = dc->pdcattr; oldMode = pdcattr->lBkMode; pdcattr->jBkMode = Mode; pdcattr->lBkMode = Mode; DC_UnlockDc(dc); return oldMode; }
BOOL NTAPI GreSetDCOwner(HDC hdc, ULONG ulOwner) { PDC pdc; pdc = DC_LockDc(hdc); if (!pdc) { DPRINT1("GreSetDCOwner: Could not lock DC\n"); return FALSE; } /* Call the internal DC function */ DC_vSetOwner(pdc, ulOwner); DC_UnlockDc(pdc); return TRUE; }
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; }
UINT FASTCALL IntGdiSetTextAlign(HDC hDC, UINT Mode) { UINT prevAlign; DC *dc; PDC_ATTR pdcattr; dc = DC_LockDc(hDC); if (!dc) { EngSetLastError(ERROR_INVALID_HANDLE); return GDI_ERROR; } pdcattr = dc->pdcattr; prevAlign = pdcattr->lTextAlign; pdcattr->lTextAlign = Mode; DC_UnlockDc(dc); return prevAlign; }
BOOL APIENTRY NtGdiGetDeviceCapsAll( IN HDC hDC, OUT PDEVCAPS pDevCaps) { PDC pdc; DEVCAPS devcaps; BOOL bResult = TRUE; /* Lock the given DC */ pdc = DC_LockDc(hDC); if (!pdc) { EngSetLastError(ERROR_INVALID_HANDLE); return FALSE; } /* Get the data */ PDEVOBJ_vGetDeviceCaps(pdc->ppdev, &devcaps); /* Unlock the DC */ DC_UnlockDc(pdc); /* Copy data to caller */ _SEH2_TRY { ProbeForWrite(pDevCaps, sizeof(DEVCAPS), 1); RtlCopyMemory(pDevCaps, &devcaps, sizeof(DEVCAPS)); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { SetLastNtError(_SEH2_GetExceptionCode()); bResult = FALSE; } _SEH2_END; return bResult; }
BOOLEAN APIENTRY DxEngSetDCState(HDC hDC, DWORD SetType, DWORD Set) { BOOLEAN Ret = FALSE; PDC pDC = DC_LockDc(hDC); if (pDC) { if (SetType == 1) { if ( Set ) pDC->fs |= DC_FLAG_FULLSCREEN; else pDC->fs &= ~DC_FLAG_FULLSCREEN; Ret = TRUE; } DC_UnlockDc(pDC); return Ret; // Everything else returns FALSE. } return Ret; }
COLORREF FASTCALL IntSetDCPenColor(HDC hdc, COLORREF crColor) { COLORREF OldColor; PDC dc; if (!(dc = DC_LockDc(hdc))) { EngSetLastError(ERROR_INVALID_PARAMETER); return CLR_INVALID; } OldColor = (COLORREF)dc->pdcattr->ulPenClr; dc->pdcattr->ulPenClr = (ULONG)crColor; if (dc->pdcattr->crPenClr != crColor) { dc->pdcattr->ulDirty_ |= DIRTY_LINE; dc->pdcattr->crPenClr = crColor; } DC_UnlockDc(dc); return OldColor; }
VOID NTAPI GreMovePointer( _In_ HDC hdc, _In_ LONG x, _In_ LONG y) { PDC pdc; PRECTL prcl; /* Lock the DC */ pdc = DC_LockDc(hdc); if (!pdc) { DPRINT1("Failed to lock the DC.\n"); return; } ASSERT(pdc->dctype == DCTYPE_DIRECT); /* Acquire PDEV lock */ EngAcquireSemaphore(pdc->ppdev->hsemDevLock); /* Check if we need to move it */ if(pdc->ppdev->SafetyRemoveLevel == 0) { /* Store the cursor exclude position in the PDEV */ prcl = &pdc->ppdev->Pointer.Exclude; /* Call Eng/Drv function */ pdc->ppdev->pfnMovePointer(&pdc->ppdev->pSurface->SurfObj, x, y, prcl); } /* Release PDEV lock */ EngReleaseSemaphore(pdc->ppdev->hsemDevLock); /* Unlock the DC */ DC_UnlockDc(pdc); }
COLORREF APIENTRY NtGdiGetNearestColor(HDC hDC, COLORREF Color) { COLORREF nearest = CLR_INVALID; PDC dc; PPALETTE palGDI; LONG RBits, GBits, BBits; dc = DC_LockDc(hDC); if (NULL != dc) { HPALETTE hpal = dc->dclevel.hpal; palGDI = PALETTE_ShareLockPalette(hpal); if (!palGDI) { DC_UnlockDc(dc); return nearest; } if (palGDI->flFlags & PAL_INDEXED) { ULONG index; index = PALETTE_ulGetNearestPaletteIndex(palGDI, Color); nearest = PALETTE_ulGetRGBColorFromIndex(palGDI, index); } else if (palGDI->flFlags & PAL_RGB || palGDI->flFlags & PAL_BGR) { nearest = Color; } else if (palGDI->flFlags & PAL_BITFIELDS) { RBits = 8 - GetNumberOfBits(palGDI->RedMask); GBits = 8 - GetNumberOfBits(palGDI->GreenMask); BBits = 8 - GetNumberOfBits(palGDI->BlueMask); nearest = RGB( (GetRValue(Color) >> RBits) << RBits, (GetGValue(Color) >> GBits) << GBits, (GetBValue(Color) >> BBits) << BBits); }
COLORREF FASTCALL IntGdiSetBkColor(HDC hDC, COLORREF color) { COLORREF oldColor; PDC dc; PDC_ATTR pdcattr; HBRUSH hBrush; if (!(dc = DC_LockDc(hDC))) { EngSetLastError(ERROR_INVALID_HANDLE); return CLR_INVALID; } pdcattr = dc->pdcattr; oldColor = pdcattr->crBackgroundClr; pdcattr->crBackgroundClr = color; pdcattr->ulBackgroundClr = (ULONG)color; pdcattr->ulDirty_ |= DIRTY_BACKGROUND|DIRTY_LINE|DIRTY_FILL; // Clear Flag if set. hBrush = pdcattr->hbrush; DC_UnlockDc(dc); NtGdiSelectBrush(hDC, hBrush); return oldColor; }
int FASTCALL GreSetStretchBltMode(HDC hDC, int iStretchMode) { PDC pdc; PDC_ATTR pdcattr; INT oSMode = 0; pdc = DC_LockDc(hDC); if (pdc) { pdcattr = pdc->pdcattr; oSMode = pdcattr->lStretchBltMode; pdcattr->lStretchBltMode = iStretchMode; // Wine returns an error here. We set the default. if ((iStretchMode <= 0) || (iStretchMode > MAXSTRETCHBLTMODE)) iStretchMode = WHITEONBLACK; pdcattr->jStretchBltMode = iStretchMode; DC_UnlockDc(pdc); } return oSMode; }
DWORD APIENTRY NtGdiGetBoundsRect( IN HDC hdc, OUT LPRECT prc, IN DWORD flags) { DWORD ret; PDC pdc; /* Lock the DC */ if (!(pdc = DC_LockDc(hdc))) return 0; /* Get the return value */ ret = pdc->fs & DC_ACCUM_APP ? DCB_ENABLE : DCB_DISABLE; ret |= RECTL_bIsEmptyRect(&pdc->erclBoundsApp) ? DCB_RESET : DCB_SET; /* Copy the rect to the caller */ _SEH2_TRY { ProbeForWrite(prc, sizeof(RECT), 1); *prc = pdc->erclBoundsApp; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { ret = 0; } _SEH2_END; if (flags & DCB_RESET) { RECTL_vSetEmptyRect(&pdc->erclBoundsApp); } DC_UnlockDc(pdc); return ret; }
COLORREF FASTCALL IntSetDCBrushColor(HDC hdc, COLORREF crColor) { COLORREF OldColor = CLR_INVALID; PDC dc; if (!(dc = DC_LockDc(hdc))) { EngSetLastError(ERROR_INVALID_HANDLE); return CLR_INVALID; } else { OldColor = (COLORREF) dc->pdcattr->ulBrushClr; dc->pdcattr->ulBrushClr = (ULONG) crColor; if ( dc->pdcattr->crBrushClr != crColor ) { dc->pdcattr->ulDirty_ |= DIRTY_FILL; dc->pdcattr->crBrushClr = crColor; } } DC_UnlockDc(dc); return OldColor; }
VOID FASTCALL GdiSelectVisRgn( HDC hdc, PREGION prgn) { DC *dc; if (!(dc = DC_LockDc(hdc))) { EngSetLastError(ERROR_INVALID_HANDLE); return; } dc->fs |= DC_FLAG_DIRTY_RAO; ASSERT(dc->prgnVis != NULL); ASSERT(prgn != NULL); IntGdiCombineRgn(dc->prgnVis, prgn, NULL, RGN_COPY); REGION_bOffsetRgn(dc->prgnVis, -dc->ptlDCOrig.x, -dc->ptlDCOrig.y); DC_UnlockDc(dc); }
/*++ * @name DxEngGetDCState * @implemented * * The function DxEngGetDCState is capable of returning three * DC states depending on what value is passed in its second parameter: * 1. If the DC is full screen * 2. Get Complexity of visible region * 3. Get Driver hdev, which is ppdev * * @param HDC hdc * The DC handle * * @param DWORD type * value 1 = Is DC fullscreen * value 2 = Get Complexity of visible region. * value 3 = Get Driver hdev, which is a ppdev. * * @return * Return one of the type values * * @remarks. * We do not have type 2 implemented yet * *--*/ DWORD_PTR APIENTRY DxEngGetDCState(HDC hDC, DWORD type) { PDC pDC = DC_LockDc(hDC); DWORD_PTR retVal = 0; DPRINT1("ReactX Calling : DxEngGetDCState type : %lu\n", type); if (pDC) { switch (type) { case 1: retVal = (DWORD_PTR) pDC->fs & DC_FLAG_FULLSCREEN; break; case 2: UNIMPLEMENTED; break; case 3: { /* Return the HDEV of this DC. */ retVal = (DWORD_PTR) pDC->ppdev; break; } default: /* If a valid type is not found, zero is returned */ DPRINT1("Warning: did not find type %lu\n", type); break; } DC_UnlockDc(pDC); } return retVal; }
BOOL NTAPI GreGradientFill( HDC hdc, PTRIVERTEX pVertex, ULONG nVertex, PVOID pMesh, ULONG nMesh, ULONG ulMode) { PDC pdc; SURFACE *psurf; EXLATEOBJ exlo; RECTL rclExtent; POINTL ptlDitherOrg; ULONG i; BOOL bRet; /* Check parameters */ if (ulMode & GRADIENT_FILL_TRIANGLE) { PGRADIENT_TRIANGLE pTriangle = (PGRADIENT_TRIANGLE)pMesh; for (i = 0; i < nMesh; i++, pTriangle++) { if (pTriangle->Vertex1 >= nVertex || pTriangle->Vertex2 >= nVertex || pTriangle->Vertex3 >= nVertex) { EngSetLastError(ERROR_INVALID_PARAMETER); return FALSE; } } } else { PGRADIENT_RECT pRect = (PGRADIENT_RECT)pMesh; for (i = 0; i < nMesh; i++, pRect++) { if (pRect->UpperLeft >= nVertex || pRect->LowerRight >= nVertex) { EngSetLastError(ERROR_INVALID_PARAMETER); return FALSE; } } } /* Lock the output DC */ pdc = DC_LockDc(hdc); if(!pdc) { EngSetLastError(ERROR_INVALID_HANDLE); return FALSE; } if(pdc->dctype == DC_TYPE_INFO) { DC_UnlockDc(pdc); /* Yes, Windows really returns TRUE in this case */ return TRUE; } psurf = pdc->dclevel.pSurface; if(!psurf) { /* Memory DC with no surface selected */ DC_UnlockDc(pdc); return TRUE; // CHECKME } /* Calculate extent */ rclExtent.left = rclExtent.right = pVertex->x; rclExtent.top = rclExtent.bottom = pVertex->y; for (i = 0; i < nVertex; i++) { rclExtent.left = min(rclExtent.left, (pVertex + i)->x); rclExtent.right = max(rclExtent.right, (pVertex + i)->x); rclExtent.top = min(rclExtent.top, (pVertex + i)->y); rclExtent.bottom = max(rclExtent.bottom, (pVertex + i)->y); } IntLPtoDP(pdc, (LPPOINT)&rclExtent, 2); rclExtent.left += pdc->ptlDCOrig.x; rclExtent.right += pdc->ptlDCOrig.x; rclExtent.top += pdc->ptlDCOrig.y; rclExtent.bottom += pdc->ptlDCOrig.y; ptlDitherOrg.x = ptlDitherOrg.y = 0; IntLPtoDP(pdc, (LPPOINT)&ptlDitherOrg, 1); ptlDitherOrg.x += pdc->ptlDCOrig.x; ptlDitherOrg.y += pdc->ptlDCOrig.y; EXLATEOBJ_vInitialize(&exlo, &gpalRGB, psurf->ppal, 0, 0, 0); ASSERT(pdc->rosdc.CombinedClip); DC_vPrepareDCsForBlit(pdc, rclExtent, NULL, rclExtent); bRet = IntEngGradientFill(&psurf->SurfObj, pdc->rosdc.CombinedClip, &exlo.xlo, pVertex, nVertex, pMesh, nMesh, &rclExtent, &ptlDitherOrg, ulMode); EXLATEOBJ_vCleanup(&exlo); DC_vFinishBlit(pdc, NULL); DC_UnlockDc(pdc); return bRet; }
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) { HRGN hRgn; hRgn = IntCreatePolyPolygonRgn(SafePoints, SafeCounts, Count, (INT_PTR)hDC); 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, dc->rosdc.CombinedClip->rclBounds, NULL, dc->rosdc.CombinedClip->rclBounds); 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; }
BOOL APIENTRY NtGdiEllipse( HDC hDC, int Left, int Top, int Right, int Bottom) { PDC dc; PDC_ATTR pdcattr; RECTL RectBounds; PBRUSH pbrush; BOOL ret = TRUE; LONG PenWidth, PenOrigWidth; LONG RadiusX, RadiusY, CenterX, CenterY; PBRUSH pFillBrushObj; BRUSH tmpFillBrushObj; if ((Left == Right) || (Top == Bottom)) return TRUE; dc = DC_LockDc(hDC); if (dc == NULL) { 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 (PATH_IsPathOpen(dc->dclevel)) { ret = PATH_Ellipse(dc, Left, Top, Right, Bottom); DC_UnlockDc(dc); return ret; } if (Right < Left) { INT tmp = Right; Right = Left; Left = tmp; } if (Bottom < Top) { INT tmp = Bottom; Bottom = Top; Top = tmp; } pdcattr = dc->pdcattr; if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY)) DC_vUpdateFillBrush(dc); if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY)) DC_vUpdateLineBrush(dc); pbrush = PEN_ShareLockPen(pdcattr->hpen); if (!pbrush) { DPRINT1("Ellipse Fail 1\n"); DC_UnlockDc(dc); EngSetLastError(ERROR_INTERNAL_ERROR); return FALSE; } PenOrigWidth = PenWidth = pbrush->ptPenWidth.x; if (pbrush->ulPenStyle == PS_NULL) PenWidth = 0; if (pbrush->ulPenStyle == PS_INSIDEFRAME) { if (2*PenWidth > (Right - Left)) PenWidth = (Right -Left + 1)/2; if (2*PenWidth > (Bottom - Top)) PenWidth = (Bottom -Top + 1)/2; Left += PenWidth / 2; Right -= (PenWidth - 1) / 2; Top += PenWidth / 2; Bottom -= (PenWidth - 1) / 2; } if (!PenWidth) PenWidth = 1; pbrush->ptPenWidth.x = PenWidth; RectBounds.left = Left; RectBounds.right = Right; RectBounds.top = Top; RectBounds.bottom = Bottom; IntLPtoDP(dc, (LPPOINT)&RectBounds, 2); RectBounds.left += dc->ptlDCOrig.x; RectBounds.right += dc->ptlDCOrig.x; RectBounds.top += dc->ptlDCOrig.y; RectBounds.bottom += dc->ptlDCOrig.y; // Setup for dynamic width and height. RadiusX = max((RectBounds.right - RectBounds.left) / 2, 2); // Needs room RadiusY = max((RectBounds.bottom - RectBounds.top) / 2, 2); CenterX = (RectBounds.right + RectBounds.left) / 2; CenterY = (RectBounds.bottom + RectBounds.top) / 2; DPRINT("Ellipse 1: Left: %d, Top: %d, Right: %d, Bottom: %d\n", RectBounds.left,RectBounds.top,RectBounds.right,RectBounds.bottom); DPRINT("Ellipse 2: XLeft: %d, YLeft: %d, Width: %d, Height: %d\n", CenterX - RadiusX, CenterY + RadiusY, RadiusX*2, RadiusY*2); pFillBrushObj = BRUSH_ShareLockBrush(pdcattr->hbrush); if (NULL == pFillBrushObj) { DPRINT1("FillEllipse Fail\n"); EngSetLastError(ERROR_INTERNAL_ERROR); ret = FALSE; } else { RtlCopyMemory(&tmpFillBrushObj, pFillBrushObj, sizeof(tmpFillBrushObj)); //tmpFillBrushObj.ptOrigin.x += RectBounds.left - Left; //tmpFillBrushObj.ptOrigin.y += RectBounds.top - Top; tmpFillBrushObj.ptOrigin.x += dc->ptlDCOrig.x; tmpFillBrushObj.ptOrigin.y += dc->ptlDCOrig.y; DC_vPrepareDCsForBlit(dc, RectBounds, NULL, RectBounds); ret = IntFillEllipse( dc, CenterX - RadiusX, CenterY - RadiusY, RadiusX*2, // Width RadiusY*2, // Height &tmpFillBrushObj); BRUSH_ShareUnlockBrush(pFillBrushObj); if (ret) { ret = IntDrawEllipse( dc, CenterX - RadiusX, CenterY - RadiusY, RadiusX*2, // Width RadiusY*2, // Height pbrush); } DC_vFinishBlit(dc, NULL); } pbrush->ptPenWidth.x = PenOrigWidth; PEN_ShareUnlockPen(pbrush); DC_UnlockDc(dc); DPRINT("Ellipse Exit.\n"); return ret; }
BOOL APIENTRY NtGdiExtFloodFill( HDC hDC, INT XStart, INT YStart, COLORREF Color, UINT FillType) { PDC dc; PDC_ATTR pdcattr; SURFACE *psurf = NULL; 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; } pdcattr = dc->pdcattr; if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY)) DC_vUpdateFillBrush(dc); if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY)) DC_vUpdateLineBrush(dc); Pt.x = XStart; Pt.y = YStart; IntLPtoDP(dc, (LPPOINT)&Pt, 1); Ret = NtGdiPtInRegion(dc->rosdc.hGCClipRgn, Pt.x, Pt.y); if (Ret) IntGdiGetRgnBox(dc->rosdc.hGCClipRgn,(LPRECT)&DestRect); else goto cleanup; DC_vPrepareDCsForBlit(dc, DestRect, NULL, DestRect); psurf = dc->dclevel.pSurface; if (!psurf) { Ret = FALSE; goto cleanup; } 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); EXLATEOBJ_vCleanup(&exlo); cleanup: DC_vFinishBlit(dc, NULL); DC_UnlockDc(dc); return Ret; }
BOOL APIENTRY GreStretchBltMask( HDC hDCDest, INT XOriginDest, INT YOriginDest, INT WidthDest, INT HeightDest, HDC hDCSrc, INT XOriginSrc, INT YOriginSrc, INT WidthSrc, INT HeightSrc, DWORD ROP, IN DWORD dwBackColor, HDC hDCMask, INT XOriginMask, INT YOriginMask) { PDC DCDest; PDC DCSrc = NULL; PDC DCMask = NULL; HDC ahDC[3]; PGDIOBJ apObj[3]; PDC_ATTR pdcattr; SURFACE *BitmapDest, *BitmapSrc = NULL; SURFACE *BitmapMask = NULL; RECTL DestRect; RECTL SourceRect; POINTL MaskPoint; BOOL Status = FALSE; EXLATEOBJ exlo; XLATEOBJ *XlateObj = NULL; POINTL BrushOrigin; BOOL UsesSource; BOOL UsesMask; FIXUP_ROP(ROP); UsesSource = ROP_USES_SOURCE(ROP); UsesMask = ROP_USES_MASK(ROP); if (0 == WidthDest || 0 == HeightDest || 0 == WidthSrc || 0 == HeightSrc) { EngSetLastError(ERROR_INVALID_PARAMETER); return TRUE; } if (!hDCDest || (UsesSource && !hDCSrc) || (UsesMask && !hDCMask)) { EngSetLastError(ERROR_INVALID_PARAMETER); return FALSE; } ahDC[0] = hDCDest; ahDC[1] = UsesSource ? hDCSrc : NULL; ahDC[2] = UsesMask ? hDCMask : NULL; if (!GDIOBJ_bLockMultipleObjects(3, (HGDIOBJ*)ahDC, apObj, GDIObjType_DC_TYPE)) { WARN("Invalid dc handle (dest=0x%p, src=0x%p) passed to GreStretchBltMask\n", hDCDest, hDCSrc); EngSetLastError(ERROR_INVALID_HANDLE); return FALSE; } DCDest = apObj[0]; DCSrc = apObj[1]; DCMask = apObj[2]; if (DCDest->dctype == DC_TYPE_INFO) { if(DCSrc) GDIOBJ_vUnlockObject(&DCSrc->BaseObject); if(DCMask) GDIOBJ_vUnlockObject(&DCMask->BaseObject); GDIOBJ_vUnlockObject(&DCDest->BaseObject); /* Yes, Windows really returns TRUE in this case */ return TRUE; } if (UsesSource) { if (DCSrc->dctype == DC_TYPE_INFO) { GDIOBJ_vUnlockObject(&DCDest->BaseObject); GDIOBJ_vUnlockObject(&DCSrc->BaseObject); if(DCMask) GDIOBJ_vUnlockObject(&DCMask->BaseObject); /* Yes, Windows really returns TRUE in this case */ return TRUE; } } pdcattr = DCDest->pdcattr; DestRect.left = XOriginDest; DestRect.top = YOriginDest; DestRect.right = XOriginDest+WidthDest; DestRect.bottom = YOriginDest+HeightDest; IntLPtoDP(DCDest, (LPPOINT)&DestRect, 2); DestRect.left += DCDest->ptlDCOrig.x; DestRect.top += DCDest->ptlDCOrig.y; DestRect.right += DCDest->ptlDCOrig.x; DestRect.bottom += DCDest->ptlDCOrig.y; SourceRect.left = XOriginSrc; SourceRect.top = YOriginSrc; SourceRect.right = XOriginSrc+WidthSrc; SourceRect.bottom = YOriginSrc+HeightSrc; if (UsesSource) { IntLPtoDP(DCSrc, (LPPOINT)&SourceRect, 2); SourceRect.left += DCSrc->ptlDCOrig.x; SourceRect.top += DCSrc->ptlDCOrig.y; SourceRect.right += DCSrc->ptlDCOrig.x; SourceRect.bottom += DCSrc->ptlDCOrig.y; } BrushOrigin.x = 0; BrushOrigin.y = 0; /* Only prepare Source and Dest, hdcMask represents a DIB */ DC_vPrepareDCsForBlit(DCDest, &DestRect, DCSrc, &SourceRect); if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY)) DC_vUpdateFillBrush(DCDest); /* Determine surfaces to be used in the bitblt */ BitmapDest = DCDest->dclevel.pSurface; if (BitmapDest == NULL) goto failed; if (UsesSource) { BitmapSrc = DCSrc->dclevel.pSurface; if (BitmapSrc == NULL) goto failed; /* Create the XLATEOBJ. */ EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest); XlateObj = &exlo.xlo; } /* Offset the brush */ BrushOrigin.x += DCDest->ptlDCOrig.x; BrushOrigin.y += DCDest->ptlDCOrig.y; /* Make mask surface for source surface */ if (BitmapSrc && DCMask) { BitmapMask = DCMask->dclevel.pSurface; if (BitmapMask && (BitmapMask->SurfObj.sizlBitmap.cx < WidthSrc || BitmapMask->SurfObj.sizlBitmap.cy < HeightSrc)) { WARN("%dx%d mask is smaller than %dx%d bitmap\n", BitmapMask->SurfObj.sizlBitmap.cx, BitmapMask->SurfObj.sizlBitmap.cy, WidthSrc, HeightSrc); EXLATEOBJ_vCleanup(&exlo); goto failed; } /* Create mask offset point */ MaskPoint.x = XOriginMask; MaskPoint.y = YOriginMask; IntLPtoDP(DCMask, &MaskPoint, 1); MaskPoint.x += DCMask->ptlDCOrig.x; MaskPoint.y += DCMask->ptlDCOrig.y; } /* Perform the bitblt operation */ Status = IntEngStretchBlt(&BitmapDest->SurfObj, BitmapSrc ? &BitmapSrc->SurfObj : NULL, BitmapMask ? &BitmapMask->SurfObj : NULL, &DCDest->co.ClipObj, XlateObj, &DCDest->dclevel.ca, &DestRect, &SourceRect, BitmapMask ? &MaskPoint : NULL, &DCDest->eboFill.BrushObject, &BrushOrigin, ROP_TO_ROP4(ROP)); if (UsesSource) { EXLATEOBJ_vCleanup(&exlo); } failed: DC_vFinishBlit(DCDest, DCSrc); if (UsesSource) { DC_UnlockDc(DCSrc); } if (DCMask) { DC_UnlockDc(DCMask); } DC_UnlockDc(DCDest); return Status; }
BOOL APIENTRY NtGdiMaskBlt( HDC hdcDest, INT nXDest, INT nYDest, INT nWidth, INT nHeight, HDC hdcSrc, INT nXSrc, INT nYSrc, HBITMAP hbmMask, INT xMask, INT yMask, DWORD dwRop, IN DWORD crBackColor) { PDC DCDest; PDC DCSrc = NULL; HDC ahDC[2]; PGDIOBJ apObj[2]; PDC_ATTR pdcattr = NULL; SURFACE *BitmapDest, *BitmapSrc = NULL, *psurfMask = NULL; RECTL DestRect, SourceRect; POINTL SourcePoint, MaskPoint; BOOL Status = FALSE; EXLATEOBJ exlo; XLATEOBJ *XlateObj = NULL; BOOL UsesSource; FIXUP_ROP(dwRop); // FIXME: why do we need this??? //DPRINT1("dwRop : 0x%08x\n", dwRop); UsesSource = ROP_USES_SOURCE(dwRop); if (!hdcDest || (UsesSource && !hdcSrc)) { EngSetLastError(ERROR_INVALID_PARAMETER); return FALSE; } /* Check if we need a mask and have a mask bitmap */ if (ROP_USES_MASK(dwRop) && (hbmMask != NULL)) { /* Reference the mask bitmap */ psurfMask = SURFACE_ShareLockSurface(hbmMask); if (psurfMask == NULL) { EngSetLastError(ERROR_INVALID_HANDLE); return FALSE; } /* Make sure the mask bitmap is 1 BPP */ if (gajBitsPerFormat[psurfMask->SurfObj.iBitmapFormat] != 1) { EngSetLastError(ERROR_INVALID_PARAMETER); SURFACE_ShareUnlockSurface(psurfMask); return FALSE; } } else { /* We use NULL, if we need a mask, the Eng function will take care of that and use the brushobject to get a mask */ psurfMask = NULL; } MaskPoint.x = xMask; MaskPoint.y = yMask; /* Take care of source and destination bitmap */ TRACE("Locking DCs\n"); ahDC[0] = hdcDest; ahDC[1] = UsesSource ? hdcSrc : NULL; if (!GDIOBJ_bLockMultipleObjects(2, (HGDIOBJ*)ahDC, apObj, GDIObjType_DC_TYPE)) { WARN("Invalid dc handle (dest=0x%p, src=0x%p) passed to NtGdiAlphaBlend\n", hdcDest, hdcSrc); EngSetLastError(ERROR_INVALID_HANDLE); return FALSE; } DCDest = apObj[0]; DCSrc = apObj[1]; ASSERT(DCDest); if (NULL == DCDest) { if(DCSrc) DC_UnlockDc(DCSrc); WARN("Invalid destination dc handle (0x%p) passed to NtGdiBitBlt\n", hdcDest); return FALSE; } if (DCDest->dctype == DC_TYPE_INFO) { if(DCSrc) DC_UnlockDc(DCSrc); DC_UnlockDc(DCDest); /* Yes, Windows really returns TRUE in this case */ return TRUE; } if (UsesSource) { ASSERT(DCSrc); if (DCSrc->dctype == DC_TYPE_INFO) { DC_UnlockDc(DCDest); DC_UnlockDc(DCSrc); /* Yes, Windows really returns TRUE in this case */ return TRUE; } } pdcattr = DCDest->pdcattr; DestRect.left = nXDest; DestRect.top = nYDest; DestRect.right = nXDest + nWidth; DestRect.bottom = nYDest + nHeight; IntLPtoDP(DCDest, (LPPOINT)&DestRect, 2); DestRect.left += DCDest->ptlDCOrig.x; DestRect.top += DCDest->ptlDCOrig.y; DestRect.right += DCDest->ptlDCOrig.x; DestRect.bottom += DCDest->ptlDCOrig.y; SourcePoint.x = nXSrc; SourcePoint.y = nYSrc; if (UsesSource) { IntLPtoDP(DCSrc, (LPPOINT)&SourcePoint, 1); SourcePoint.x += DCSrc->ptlDCOrig.x; SourcePoint.y += DCSrc->ptlDCOrig.y; /* Calculate Source Rect */ SourceRect.left = SourcePoint.x; SourceRect.top = SourcePoint.y; SourceRect.right = SourcePoint.x + DestRect.right - DestRect.left; SourceRect.bottom = SourcePoint.y + DestRect.bottom - DestRect.top ; } else { SourceRect.left = 0; SourceRect.top = 0; SourceRect.right = 0; SourceRect.bottom = 0; } /* Prepare blit */ DC_vPrepareDCsForBlit(DCDest, &DestRect, DCSrc, &SourceRect); if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY)) DC_vUpdateFillBrush(DCDest); /* Determine surfaces to be used in the bitblt */ BitmapDest = DCDest->dclevel.pSurface; if (!BitmapDest) goto cleanup; if (UsesSource) { { BitmapSrc = DCSrc->dclevel.pSurface; if (!BitmapSrc) goto cleanup; } } /* Create the XLATEOBJ. */ if (UsesSource) { EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest); XlateObj = &exlo.xlo; } /* Perform the bitblt operation */ Status = IntEngBitBlt(&BitmapDest->SurfObj, BitmapSrc ? &BitmapSrc->SurfObj : NULL, psurfMask ? &psurfMask->SurfObj : NULL, &DCDest->co.ClipObj, XlateObj, &DestRect, &SourcePoint, &MaskPoint, &DCDest->eboFill.BrushObject, &DCDest->dclevel.pbrFill->ptOrigin, ROP_TO_ROP4(dwRop)); if (UsesSource) EXLATEOBJ_vCleanup(&exlo); cleanup: DC_vFinishBlit(DCDest, DCSrc); if (UsesSource) { DC_UnlockDc(DCSrc); } DC_UnlockDc(DCDest); if(psurfMask) SURFACE_ShareUnlockSurface(psurfMask); return Status; }
HANDLE APIENTRY NtGdiGetDCObject(HDC hDC, INT ObjectType) { HGDIOBJ SelObject; DC *pdc; PDC_ATTR pdcattr; /* From Wine: GetCurrentObject does not SetLastError() on a null object */ if(!hDC) return NULL; if(!(pdc = DC_LockDc(hDC))) { EngSetLastError(ERROR_INVALID_HANDLE); return NULL; } pdcattr = pdc->pdcattr; if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY)) DC_vUpdateFillBrush(pdc); if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY)) DC_vUpdateLineBrush(pdc); switch(ObjectType) { case GDI_OBJECT_TYPE_EXTPEN: case GDI_OBJECT_TYPE_PEN: SelObject = pdcattr->hpen; break; case GDI_OBJECT_TYPE_BRUSH: SelObject = pdcattr->hbrush; break; case GDI_OBJECT_TYPE_PALETTE: SelObject = pdc->dclevel.hpal; break; case GDI_OBJECT_TYPE_FONT: SelObject = pdcattr->hlfntNew; break; case GDI_OBJECT_TYPE_BITMAP: { SURFACE *psurf = pdc->dclevel.pSurface; SelObject = psurf ? psurf->BaseObject.hHmgr : NULL; break; } case GDI_OBJECT_TYPE_COLORSPACE: DPRINT1("FIXME: NtGdiGetCurrentObject() ObjectType OBJ_COLORSPACE not supported yet!\n"); // SelObject = dc->dclevel.pColorSpace.BaseObject.hHmgr; ? SelObject = NULL; break; default: SelObject = NULL; EngSetLastError(ERROR_INVALID_PARAMETER); break; } DC_UnlockDc(pdc); return SelObject; }
/* 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; }
/* 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; }
INT APIENTRY NtGdiDescribePixelFormat(HDC hDC, INT PixelFormat, UINT BufSize, LPPIXELFORMATDESCRIPTOR pfd) { PDC pdc; PPDEVOBJ ppdev; INT Ret = 0; PIXELFORMATDESCRIPTOR pfdSafe; NTSTATUS Status = STATUS_SUCCESS; if (!BufSize) return 0; pdc = DC_LockDc(hDC); if (!pdc) { EngSetLastError(ERROR_INVALID_HANDLE); return 0; } if (!pdc->ipfdDevMax) IntGetipfdDevMax(pdc); if ( BufSize < sizeof(PIXELFORMATDESCRIPTOR) || PixelFormat < 1 || PixelFormat > pdc->ipfdDevMax ) { EngSetLastError(ERROR_INVALID_PARAMETER); goto Exit; } ppdev = pdc->ppdev; if (ppdev->flFlags & PDEV_META_DEVICE) { UNIMPLEMENTED; goto Exit; } if (ppdev->DriverFunctions.DescribePixelFormat) { Ret = ppdev->DriverFunctions.DescribePixelFormat( ppdev->dhpdev, PixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfdSafe); } _SEH2_TRY { ProbeForWrite( pfd, sizeof(PIXELFORMATDESCRIPTOR), 1); RtlCopyMemory(&pfdSafe, pfd, sizeof(PIXELFORMATDESCRIPTOR)); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Status = _SEH2_GetExceptionCode(); } _SEH2_END; if (!NT_SUCCESS(Status)) SetLastNtError(Status); Exit: DC_UnlockDc(pdc); return Ret; }
BOOL APIENTRY NtGdiSetPixelFormat( IN HDC hdc, IN INT ipfd) { PDC pdc; PPDEVOBJ ppdev; HWND hWnd; PWNDOBJ pWndObj; SURFOBJ *pso = NULL; BOOL Ret = FALSE; pdc = DC_LockDc(hdc); if (!pdc) { EngSetLastError(ERROR_INVALID_HANDLE); return FALSE; } if (!pdc->ipfdDevMax) IntGetipfdDevMax(pdc); if ( ipfd < 1 || ipfd > pdc->ipfdDevMax ) { EngSetLastError(ERROR_INVALID_PARAMETER); goto Exit; } UserEnterExclusive(); hWnd = UserGethWnd(hdc, &pWndObj); UserLeave(); if (!hWnd) { EngSetLastError(ERROR_INVALID_WINDOW_STYLE); goto Exit; } ppdev = pdc->ppdev; /* WndObj is needed so exit on NULL pointer. */ if (pWndObj) pso = pWndObj->psoOwner; else { EngSetLastError(ERROR_INVALID_PIXEL_FORMAT); goto Exit; } if (ppdev->flFlags & PDEV_META_DEVICE) { UNIMPLEMENTED; goto Exit; } if (ppdev->DriverFunctions.SetPixelFormat) { Ret = ppdev->DriverFunctions.SetPixelFormat( pso, ipfd, hWnd); } Exit: DC_UnlockDc(pdc); return Ret; }
ULONG NTAPI GreSetPointerShape( _In_ HDC hdc, _In_opt_ HBITMAP hbmMask, _In_opt_ HBITMAP hbmColor, _In_ LONG xHot, _In_ LONG yHot, _In_ LONG x, _In_ LONG y, _In_ FLONG fl) { PDC pdc; PSURFACE psurf, psurfMask, psurfColor; EXLATEOBJ exlo; ULONG ulResult = 0; pdc = DC_LockDc(hdc); if (!pdc) { DPRINT1("Failed to lock the DC.\n"); return 0; } ASSERT(pdc->dctype == DCTYPE_DIRECT); EngAcquireSemaphore(pdc->ppdev->hsemDevLock); /* We're not sure DC surface is the good one */ psurf = pdc->ppdev->pSurface; if (!psurf) { DPRINT1("DC has no surface.\n"); EngReleaseSemaphore(pdc->ppdev->hsemDevLock); DC_UnlockDc(pdc); return 0; } /* Lock the mask bitmap */ if (hbmMask) { psurfMask = SURFACE_ShareLockSurface(hbmMask); } else { //ASSERT(fl & SPS_ALPHA); psurfMask = NULL; } /* Check for color bitmap */ if (hbmColor) { /* We have one, lock it */ psurfColor = SURFACE_ShareLockSurface(hbmColor); if (psurfColor) { /* Create an XLATEOBJ, no mono support */ EXLATEOBJ_vInitialize(&exlo, psurfColor->ppal, psurf->ppal, 0, 0, 0); } } else psurfColor = NULL; /* We must have a valid surface in case of alpha bitmap */ ASSERT(((fl & SPS_ALPHA) && psurfColor) || !(fl & SPS_ALPHA)); /* Call the driver or eng function */ ulResult = IntEngSetPointerShape(&psurf->SurfObj, psurfMask ? &psurfMask->SurfObj : NULL, psurfColor ? &psurfColor->SurfObj : NULL, psurfColor ? &exlo.xlo : NULL, xHot, yHot, x, y, &pdc->ppdev->Pointer.Exclude, fl | SPS_CHANGE); /* Cleanup */ if (psurfColor) { EXLATEOBJ_vCleanup(&exlo); SURFACE_ShareUnlockSurface(psurfColor); } if (psurfMask) SURFACE_ShareUnlockSurface(psurfMask); EngReleaseSemaphore(pdc->ppdev->hsemDevLock); /* Unlock the DC */ DC_UnlockDc(pdc); /* Return result */ return ulResult; }
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; }
/* See wine, msdn, osr and Feng Yuan - Windows Graphics Programming Win32 Gdi And Directdraw 1st: http://www.codeproject.com/gdi/cliprgnguide.asp is wrong! The intersection of the clip with the meta region is not Rao it's API! Go back and read 7.2 Clipping pages 418-19: Rao = API & Vis: 1) The Rao region is the intersection of the API region and the system region, named after the Microsoft engineer who initially proposed it. 2) The Rao region can be calculated from the API region and the system region. API: API region is the intersection of the meta region and the clipping region, clearly named after the fact that it is controlled by GDI API calls. */ INT APIENTRY NtGdiGetRandomRgn( HDC hdc, HRGN hrgnDest, INT iCode) { INT ret = 0; PDC pdc; HRGN hrgnSrc = NULL; POINTL ptlOrg; pdc = DC_LockDc(hdc); if (!pdc) { EngSetLastError(ERROR_INVALID_PARAMETER); return -1; } switch (iCode) { case CLIPRGN: hrgnSrc = pdc->rosdc.hClipRgn; // if (pdc->dclevel.prgnClip) hrgnSrc = pdc->dclevel.prgnClip->BaseObject.hHmgr; break; case METARGN: if (pdc->dclevel.prgnMeta) hrgnSrc = pdc->dclevel.prgnMeta->BaseObject.hHmgr; break; case APIRGN: if (pdc->prgnAPI) hrgnSrc = pdc->prgnAPI->BaseObject.hHmgr; // else if (pdc->dclevel.prgnClip) hrgnSrc = pdc->dclevel.prgnClip->BaseObject.hHmgr; else if (pdc->rosdc.hClipRgn) hrgnSrc = pdc->rosdc.hClipRgn; else if (pdc->dclevel.prgnMeta) hrgnSrc = pdc->dclevel.prgnMeta->BaseObject.hHmgr; break; case SYSRGN: if (pdc->prgnVis) { PREGION prgnDest = REGION_LockRgn(hrgnDest); ret = IntGdiCombineRgn(prgnDest, pdc->prgnVis, 0, RGN_COPY) == ERROR ? -1 : 1; REGION_UnlockRgn(prgnDest); } break; default: hrgnSrc = NULL; } if (hrgnSrc) { ret = NtGdiCombineRgn(hrgnDest, hrgnSrc, 0, RGN_COPY) == ERROR ? -1 : 1; } if (iCode == SYSRGN) { ptlOrg = pdc->ptlDCOrig; NtGdiOffsetRgn(hrgnDest, ptlOrg.x, ptlOrg.y ); } DC_UnlockDc(pdc); return ret; }
/* * @implemented */ HBITMAP APIENTRY NtGdiSelectBitmap( IN HDC hdc, IN HBITMAP hbmp) { PDC pdc; PDC_ATTR pdcattr; HBITMAP hbmpOld; PSURFACE psurfNew; HRGN hVisRgn; SIZEL sizlBitmap = {1, 1}; HDC hdcOld; ASSERT_NOGDILOCKS(); /* Verify parameters */ if (hdc == NULL || hbmp == NULL) return NULL; /* First lock the DC */ pdc = DC_LockDc(hdc); if (!pdc) { return NULL; } pdcattr = pdc->pdcattr; /* Must be a memory dc to select a bitmap */ if (pdc->dctype != DC_TYPE_MEMORY) { DC_UnlockDc(pdc); return NULL; } /* Check if there was a bitmap selected before */ if (pdc->dclevel.pSurface) { /* Return its handle */ hbmpOld = pdc->dclevel.pSurface->BaseObject.hHmgr; } else { /* Return default bitmap */ hbmpOld = StockObjects[DEFAULT_BITMAP]; } /* Check if the default bitmap was passed */ if (hbmp == StockObjects[DEFAULT_BITMAP]) { psurfNew = NULL; // 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; } /* 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; } /* 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; } } /* Select the new surface, release the old */ DC_vSelectSurface(pdc, psurfNew); /* Set the new size */ pdc->dclevel.sizl = sizlBitmap; /* Release one reference we added */ SURFACE_ShareUnlockSurface(psurfNew); /* Mark the dc brushes invalid */ pdcattr->ulDirty_ |= DIRTY_FILL | DIRTY_LINE; /* 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); GreDeleteObject(hVisRgn); } /* Return the old bitmap handle */ return hbmpOld; }