BOOL FASTCALL co_IntRegisterLogonProcess(HANDLE ProcessId, BOOL Register) { NTSTATUS Status; PEPROCESS Process; Status = PsLookupProcessByProcessId(ProcessId, &Process); if (!NT_SUCCESS(Status)) { EngSetLastError(RtlNtStatusToDosError(Status)); return FALSE; } ProcessId = Process->UniqueProcessId; ObDereferenceObject(Process); if (Register) { /* Register the logon process */ if (gpidLogon != 0) return FALSE; gpidLogon = ProcessId; } else { /* Deregister the logon process */ if (gpidLogon != ProcessId) return FALSE; gpidLogon = 0; } return TRUE; }
HWND APIENTRY NtUserSetClipboardViewer(HWND hWndNewViewer) { HWND hWndNext = NULL; PWINSTATION_OBJECT pWinStaObj = NULL; PWND pWindow; UserEnterExclusive(); pWinStaObj = IntGetWinStaForCbAccess(); if (!pWinStaObj) goto cleanup; pWindow = UserGetWindowObject(hWndNewViewer); if (!pWindow) { EngSetLastError(ERROR_INVALID_WINDOW_HANDLE); goto cleanup; } /* Return previous viewer. New viever window should send messages to rest of the chain */ if (pWinStaObj->spwndClipViewer) hWndNext = pWinStaObj->spwndClipViewer->head.h; /* Set new viewer window */ pWinStaObj->spwndClipViewer = pWindow; cleanup: if(pWinStaObj) ObDereferenceObject(pWinStaObj); UserLeave(); return hWndNext; }
BOOL APIENTRY NtUserUnlockWindowStation(HWINSTA hWindowStation) { PWINSTATION_OBJECT Object; NTSTATUS Status; BOOL Ret; TRACE("About to set process window station with handle (%p)\n", hWindowStation); if (gpidLogon != PsGetCurrentProcessId()) { ERR("Unauthorized process attempted to unlock the window station!\n"); EngSetLastError(ERROR_ACCESS_DENIED); return FALSE; } Status = IntValidateWindowStationHandle(hWindowStation, UserMode, 0, &Object, 0); if (!NT_SUCCESS(Status)) { TRACE("Validation of window station handle (%p) failed\n", hWindowStation); SetLastNtError(Status); return FALSE; } Ret = (Object->Flags & WSS_LOCKED) == WSS_LOCKED; Object->Flags &= ~WSS_LOCKED; ObDereferenceObject(Object); 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; }
HANDLE IntCreateCurIconHandle(BOOLEAN Animated) { PCURICON_OBJECT CurIcon; HANDLE hCurIcon; CurIcon = UserCreateObject( gHandleTable, NULL, NULL, &hCurIcon, TYPE_CURSOR, Animated ? sizeof(ACON) : sizeof(CURICON_OBJECT)); if (!CurIcon) { EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); return FALSE; } UserDereferenceObject(CurIcon); return hCurIcon; }
BOOL APIENTRY NtUserGetGUIThreadInfo( DWORD idThread, /* If NULL use foreground thread */ LPGUITHREADINFO lpgui) { NTSTATUS Status; PTHRDCARETINFO CaretInfo; GUITHREADINFO SafeGui; PDESKTOP Desktop; PUSER_MESSAGE_QUEUE MsgQueue; PTHREADINFO W32Thread; PETHREAD Thread = NULL; DECLARE_RETURN(BOOLEAN); TRACE("Enter NtUserGetGUIThreadInfo\n"); UserEnterShared(); Status = MmCopyFromCaller(&SafeGui, lpgui, sizeof(DWORD)); if(!NT_SUCCESS(Status)) { SetLastNtError(Status); RETURN( FALSE); } if(SafeGui.cbSize != sizeof(GUITHREADINFO)) { EngSetLastError(ERROR_INVALID_PARAMETER); RETURN( FALSE); } if (idThread) { Status = PsLookupThreadByThreadId((HANDLE)(DWORD_PTR)idThread, &Thread); if(!NT_SUCCESS(Status)) { EngSetLastError(ERROR_ACCESS_DENIED); RETURN( FALSE); } W32Thread = (PTHREADINFO)Thread->Tcb.Win32Thread; Desktop = W32Thread->rpdesk; if (!Thread || !Desktop ) { if(Thread) ObDereferenceObject(Thread); EngSetLastError(ERROR_ACCESS_DENIED); RETURN( FALSE); } if ( W32Thread->MessageQueue ) MsgQueue = W32Thread->MessageQueue; else { if ( Desktop ) MsgQueue = Desktop->ActiveMessageQueue; } } else { /* Get the foreground thread */ /* FIXME: Handle NULL queue properly? */ MsgQueue = IntGetFocusMessageQueue(); if(!MsgQueue) { EngSetLastError(ERROR_ACCESS_DENIED); RETURN( FALSE); } } CaretInfo = &MsgQueue->CaretInfo; SafeGui.flags = (CaretInfo->Visible ? GUI_CARETBLINKING : 0); /* if (W32Thread->pMenuState->pGlobalPopupMenu) { SafeGui.flags |= GUI_INMENUMODE; if (W32Thread->pMenuState->pGlobalPopupMenu->spwndNotify) SafeGui.hwndMenuOwner = UserHMGetHandle(W32Thread->pMenuState->pGlobalPopupMenu->spwndNotify); if (W32Thread->pMenuState->pGlobalPopupMenu->fHasMenuBar) { if (W32Thread->pMenuState->pGlobalPopupMenu->fIsSysMenu) { SafeGui.flags |= GUI_SYSTEMMENUMODE; } } else { SafeGui.flags |= GUI_POPUPMENUMODE; } } */ SafeGui.hwndMenuOwner = MsgQueue->MenuOwner; if (MsgQueue->MenuOwner) SafeGui.flags |= GUI_INMENUMODE | MsgQueue->MenuState; if (MsgQueue->MoveSize) SafeGui.flags |= GUI_INMOVESIZE; /* FIXME: Add flag GUI_16BITTASK */ SafeGui.hwndActive = MsgQueue->spwndActive ? UserHMGetHandle(MsgQueue->spwndActive) : 0; SafeGui.hwndFocus = MsgQueue->spwndFocus ? UserHMGetHandle(MsgQueue->spwndFocus) : 0; SafeGui.hwndCapture = MsgQueue->spwndCapture ? UserHMGetHandle(MsgQueue->spwndCapture) : 0; SafeGui.hwndMoveSize = MsgQueue->MoveSize; SafeGui.hwndCaret = CaretInfo->hWnd; SafeGui.rcCaret.left = CaretInfo->Pos.x; SafeGui.rcCaret.top = CaretInfo->Pos.y; SafeGui.rcCaret.right = SafeGui.rcCaret.left + CaretInfo->Size.cx; SafeGui.rcCaret.bottom = SafeGui.rcCaret.top + CaretInfo->Size.cy; if (idThread) ObDereferenceObject(Thread); Status = MmCopyToCaller(lpgui, &SafeGui, sizeof(GUITHREADINFO)); if(!NT_SUCCESS(Status)) { SetLastNtError(Status); RETURN( FALSE); } RETURN( TRUE); CLEANUP: TRACE("Leave NtUserGetGUIThreadInfo, ret=%u\n",_ret_); UserLeave(); END_CLEANUP; }
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 FASTCALL IntGdiPolygon(PDC dc, PPOINT Points, int Count) { SURFACE *psurf; PBRUSH pbrLine, pbrFill; BOOL ret = FALSE; // Default to failure RECTL DestRect; int CurrentPoint; PDC_ATTR pdcattr; POINTL BrushOrigin; // int Left; // int Top; ASSERT(dc); // Caller's responsibility to pass a valid dc if (!Points || Count < 2 ) { EngSetLastError(ERROR_INVALID_PARAMETER); return FALSE; } /* // Find start x, y Left = Points[0].x; Top = Points[0].y; for (CurrentPoint = 1; CurrentPoint < Count; ++CurrentPoint) { Left = min(Left, Points[CurrentPoint].x); Top = min(Top, Points[CurrentPoint].y); } */ pdcattr = dc->pdcattr; /* Convert to screen coordinates */ IntLPtoDP(dc, Points, Count); for (CurrentPoint = 0; CurrentPoint < Count; CurrentPoint++) { Points[CurrentPoint].x += dc->ptlDCOrig.x; Points[CurrentPoint].y += dc->ptlDCOrig.y; } // No need to have path here. { DestRect.left = Points[0].x; DestRect.right = Points[0].x; DestRect.top = Points[0].y; DestRect.bottom = Points[0].y; for (CurrentPoint = 1; CurrentPoint < Count; ++CurrentPoint) { DestRect.left = min(DestRect.left, Points[CurrentPoint].x); DestRect.right = max(DestRect.right, Points[CurrentPoint].x); DestRect.top = min(DestRect.top, Points[CurrentPoint].y); DestRect.bottom = max(DestRect.bottom, Points[CurrentPoint].y); } if (pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY)) DC_vUpdateFillBrush(dc); if (pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY)) DC_vUpdateLineBrush(dc); /* Special locking order to avoid lock-ups */ pbrFill = dc->dclevel.pbrFill; pbrLine = dc->dclevel.pbrLine; psurf = dc->dclevel.pSurface; /* FIXME: psurf can be NULL!!!! don't assert but handle this case gracefully! */ ASSERT(psurf); /* Now fill the polygon with the current fill brush. */ if (!(pbrFill->flAttrs & BR_IS_NULL)) { BrushOrigin = *((PPOINTL)&pbrFill->ptOrigin); BrushOrigin.x += dc->ptlDCOrig.x; BrushOrigin.y += dc->ptlDCOrig.y; ret = IntFillPolygon (dc, psurf, &dc->eboFill.BrushObject, Points, Count, DestRect, &BrushOrigin); } // Draw the Polygon Edges with the current pen ( if not a NULL pen ) if (!(pbrLine->flAttrs & BR_IS_NULL)) { int i; for (i = 0; i < Count-1; i++) { // DPRINT1("Polygon Making line from (%d,%d) to (%d,%d)\n", // Points[0].x, Points[0].y, // Points[1].x, Points[1].y ); ret = IntEngLineTo(&psurf->SurfObj, dc->rosdc.CombinedClip, &dc->eboLine.BrushObject, Points[i].x, /* From */ Points[i].y, Points[i+1].x, /* To */ Points[i+1].y, &DestRect, ROP2_TO_MIX(pdcattr->jROP2)); /* MIX */ if (!ret) break; } /* Close the polygon */ if (ret) { ret = IntEngLineTo(&psurf->SurfObj, dc->rosdc.CombinedClip, &dc->eboLine.BrushObject, Points[Count-1].x, /* From */ Points[Count-1].y, Points[0].x, /* To */ Points[0].y, &DestRect, ROP2_TO_MIX(pdcattr->jROP2)); /* MIX */ } } } 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 NtGdiTransparentBlt( HDC hdcDst, INT xDst, INT yDst, INT cxDst, INT cyDst, HDC hdcSrc, INT xSrc, INT ySrc, INT cxSrc, INT cySrc, COLORREF TransColor) { PDC DCDest, DCSrc; HDC ahDC[2]; PGDIOBJ apObj[2]; RECTL rcDest, rcSrc; SURFACE *BitmapDest, *BitmapSrc = NULL; ULONG TransparentColor = 0; BOOL Ret = FALSE; EXLATEOBJ exlo; if ((hdcDst == NULL) || (hdcSrc == NULL)) { EngSetLastError(ERROR_INVALID_PARAMETER); return FALSE; } TRACE("Locking DCs\n"); ahDC[0] = hdcDst; ahDC[1] = hdcSrc ; if (!GDIOBJ_bLockMultipleObjects(2, (HGDIOBJ*)ahDC, apObj, GDIObjType_DC_TYPE)) { WARN("Invalid dc handle (dest=0x%p, src=0x%p) passed to NtGdiAlphaBlend\n", hdcDst, hdcSrc); EngSetLastError(ERROR_INVALID_HANDLE); return FALSE; } DCDest = apObj[0]; DCSrc = apObj[1]; if (DCDest->dctype == DC_TYPE_INFO || DCDest->dctype == DCTYPE_INFO) { GDIOBJ_vUnlockObject(&DCSrc->BaseObject); GDIOBJ_vUnlockObject(&DCDest->BaseObject); /* Yes, Windows really returns TRUE in this case */ return TRUE; } rcDest.left = xDst; rcDest.top = yDst; rcDest.right = rcDest.left + cxDst; rcDest.bottom = rcDest.top + cyDst; IntLPtoDP(DCDest, (LPPOINT)&rcDest, 2); rcDest.left += DCDest->ptlDCOrig.x; rcDest.top += DCDest->ptlDCOrig.y; rcDest.right += DCDest->ptlDCOrig.x; rcDest.bottom += DCDest->ptlDCOrig.y; rcSrc.left = xSrc; rcSrc.top = ySrc; rcSrc.right = rcSrc.left + cxSrc; rcSrc.bottom = rcSrc.top + cySrc; IntLPtoDP(DCSrc, (LPPOINT)&rcSrc, 2); rcSrc.left += DCSrc->ptlDCOrig.x; rcSrc.top += DCSrc->ptlDCOrig.y; rcSrc.right += DCSrc->ptlDCOrig.x; rcSrc.bottom += DCSrc->ptlDCOrig.y; /* Prepare for blit */ DC_vPrepareDCsForBlit(DCDest, &rcDest, DCSrc, &rcSrc); BitmapDest = DCDest->dclevel.pSurface; if (!BitmapDest) { goto done; } BitmapSrc = DCSrc->dclevel.pSurface; if (!BitmapSrc) { goto done; } /* Translate Transparent (RGB) Color to the source palette */ EXLATEOBJ_vInitialize(&exlo, &gpalRGB, BitmapSrc->ppal, 0, 0, 0); TransparentColor = XLATEOBJ_iXlate(&exlo.xlo, (ULONG)TransColor); EXLATEOBJ_vCleanup(&exlo); EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest); Ret = IntEngTransparentBlt(&BitmapDest->SurfObj, &BitmapSrc->SurfObj, &DCDest->co.ClipObj, &exlo.xlo, &rcDest, &rcSrc, TransparentColor, 0); EXLATEOBJ_vCleanup(&exlo); done: DC_vFinishBlit(DCDest, DCSrc); GDIOBJ_vUnlockObject(&DCDest->BaseObject); GDIOBJ_vUnlockObject(&DCSrc->BaseObject); return Ret; }
HPEN APIENTRY IntGdiExtCreatePen( DWORD dwPenStyle, DWORD dwWidth, IN ULONG ulBrushStyle, IN ULONG ulColor, IN ULONG_PTR ulClientHatch, IN ULONG_PTR ulHatch, DWORD dwStyleCount, PULONG pStyle, IN ULONG cjDIB, IN BOOL bOldStylePen, IN OPTIONAL HBRUSH hbrush) { HPEN hPen; PBRUSH pbrushPen; static const BYTE PatternAlternate[] = {0x55, 0x55, 0x55, 0}; static const BYTE PatternDash[] = {0xFF, 0xFF, 0xC0, 0}; static const BYTE PatternDot[] = {0xE3, 0x8E, 0x38, 0}; static const BYTE PatternDashDot[] = {0xFF, 0x81, 0xC0, 0}; static const BYTE PatternDashDotDot[] = {0xFF, 0x8E, 0x38, 0}; dwWidth = abs(dwWidth); if ( (dwPenStyle & PS_STYLE_MASK) == PS_NULL) { return StockObjects[NULL_PEN]; } if (bOldStylePen) { pbrushPen = PEN_AllocPenWithHandle(); } else { pbrushPen = PEN_AllocExtPenWithHandle(); } if (!pbrushPen) { EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); DPRINT("Can't allocate pen\n"); return 0; } hPen = pbrushPen->BaseObject.hHmgr; // If nWidth is zero, the pen is a single pixel wide, regardless of the current transformation. if ((bOldStylePen) && (!dwWidth) && ((dwPenStyle & PS_STYLE_MASK) != PS_SOLID)) dwWidth = 1; pbrushPen->lWidth = dwWidth; pbrushPen->eWidth = (FLOAT)pbrushPen->lWidth; pbrushPen->ulPenStyle = dwPenStyle; pbrushPen->BrushAttr.lbColor = ulColor; pbrushPen->iBrushStyle = ulBrushStyle; // FIXME: Copy the bitmap first ? pbrushPen->hbmClient = (HANDLE)ulClientHatch; pbrushPen->dwStyleCount = dwStyleCount; pbrushPen->pStyle = pStyle; pbrushPen->flAttrs = bOldStylePen ? BR_IS_OLDSTYLEPEN : BR_IS_PEN; // If dwPenStyle is PS_COSMETIC, the width must be set to 1. if ( !(bOldStylePen) && ((dwPenStyle & PS_TYPE_MASK) == PS_COSMETIC) && ( dwWidth != 1) ) goto ExitCleanup; switch (dwPenStyle & PS_STYLE_MASK) { case PS_NULL: pbrushPen->flAttrs |= BR_IS_NULL; break; case PS_SOLID: pbrushPen->flAttrs |= BR_IS_SOLID; break; case PS_ALTERNATE: pbrushPen->flAttrs |= BR_IS_BITMAP; pbrushPen->hbmPattern = GreCreateBitmap(24, 1, 1, 1, (LPBYTE)PatternAlternate); break; case PS_DOT: pbrushPen->flAttrs |= BR_IS_BITMAP; pbrushPen->hbmPattern = GreCreateBitmap(24, 1, 1, 1, (LPBYTE)PatternDot); break; case PS_DASH: pbrushPen->flAttrs |= BR_IS_BITMAP; pbrushPen->hbmPattern = GreCreateBitmap(24, 1, 1, 1, (LPBYTE)PatternDash); break; case PS_DASHDOT: pbrushPen->flAttrs |= BR_IS_BITMAP; pbrushPen->hbmPattern = GreCreateBitmap(24, 1, 1, 1, (LPBYTE)PatternDashDot); break; case PS_DASHDOTDOT: pbrushPen->flAttrs |= BR_IS_BITMAP; pbrushPen->hbmPattern = GreCreateBitmap(24, 1, 1, 1, (LPBYTE)PatternDashDotDot); break; case PS_INSIDEFRAME: pbrushPen->flAttrs |= (BR_IS_SOLID | BR_IS_INSIDEFRAME); break; case PS_USERSTYLE: if ((dwPenStyle & PS_TYPE_MASK) == PS_COSMETIC) { /* FIXME: PS_USERSTYLE workaround */ DPRINT1("PS_COSMETIC | PS_USERSTYLE not handled\n"); pbrushPen->flAttrs |= BR_IS_SOLID; break; } else { UINT i; BOOL has_neg = FALSE, all_zero = TRUE; for(i = 0; (i < dwStyleCount) && !has_neg; i++) { has_neg = has_neg || (((INT)(pStyle[i])) < 0); all_zero = all_zero && (pStyle[i] == 0); } if(all_zero || has_neg) { goto ExitCleanup; } } /* FIXME: What style here? */ pbrushPen->flAttrs |= 0; break; default: DPRINT1("IntGdiExtCreatePen unknown penstyle %x\n", dwPenStyle); } PEN_UnlockPen(pbrushPen); return hPen; ExitCleanup: EngSetLastError(ERROR_INVALID_PARAMETER); pbrushPen->pStyle = NULL; GDIOBJ_vDeleteObject(&pbrushPen->BaseObject); return NULL; }
HPEN APIENTRY NtGdiExtCreatePen( DWORD dwPenStyle, DWORD ulWidth, IN ULONG ulBrushStyle, IN ULONG ulColor, IN ULONG_PTR ulClientHatch, IN ULONG_PTR ulHatch, DWORD dwStyleCount, PULONG pUnsafeStyle, IN ULONG cjDIB, IN BOOL bOldStylePen, IN OPTIONAL HBRUSH hBrush) { NTSTATUS Status = STATUS_SUCCESS; DWORD* pSafeStyle = NULL; HPEN hPen; if ((int)dwStyleCount < 0) return 0; if (dwStyleCount > 16) { EngSetLastError(ERROR_INVALID_PARAMETER); return 0; } if (dwStyleCount > 0) { if (pUnsafeStyle == NULL) { EngSetLastError(ERROR_INVALID_PARAMETER); return 0; } pSafeStyle = ExAllocatePoolWithTag(NonPagedPool, dwStyleCount * sizeof(DWORD), GDITAG_PENSTYLE); if (!pSafeStyle) { SetLastNtError(ERROR_NOT_ENOUGH_MEMORY); return 0; } _SEH2_TRY { ProbeForRead(pUnsafeStyle, dwStyleCount * sizeof(DWORD), 1); RtlCopyMemory(pSafeStyle, pUnsafeStyle, dwStyleCount * sizeof(DWORD)); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Status = _SEH2_GetExceptionCode(); } _SEH2_END if(!NT_SUCCESS(Status)) { SetLastNtError(Status); ExFreePoolWithTag(pSafeStyle, GDITAG_PENSTYLE); return 0; } } if (ulBrushStyle == BS_PATTERN) { _SEH2_TRY { ProbeForRead((PVOID)ulHatch, cjDIB, 1); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Status = _SEH2_GetExceptionCode(); } _SEH2_END if(!NT_SUCCESS(Status)) { SetLastNtError(Status); if (pSafeStyle) ExFreePoolWithTag(pSafeStyle, GDITAG_PENSTYLE); return 0; } }
HANDLE APIENTRY NtUserGetClipboardData(UINT fmt, PGETCLIPBDATA pgcd) { HANDLE hRet = NULL; PCLIP pElement; PWINSTATION_OBJECT pWinStaObj = NULL; TRACE("NtUserGetClipboardData(%x, %p)\n", fmt, pgcd); UserEnterShared(); pWinStaObj = IntGetWinStaForCbAccess(); if (!pWinStaObj) goto cleanup; if (!IntIsClipboardOpenByMe(pWinStaObj)) { EngSetLastError(ERROR_CLIPBOARD_NOT_OPEN); goto cleanup; } pElement = IntIsFormatAvailable(pWinStaObj, fmt); if (pElement && IS_DATA_DELAYED(pElement) && pWinStaObj->spwndClipOwner) { /* Send WM_RENDERFORMAT message */ pWinStaObj->fInDelayedRendering = TRUE; co_IntSendMessage(pWinStaObj->spwndClipOwner->head.h, WM_RENDERFORMAT, (WPARAM)fmt, 0); pWinStaObj->fInDelayedRendering = FALSE; /* Data should be in clipboard now */ pElement = IntIsFormatAvailable(pWinStaObj, fmt); } if (!pElement || IS_DATA_DELAYED(pElement)) goto cleanup; if (IS_DATA_SYNTHESIZED(pElement)) { /* Note: Data is synthesized in usermode */ /* TODO: Add more formats */ switch (fmt) { case CF_UNICODETEXT: case CF_TEXT: case CF_OEMTEXT: pElement = IntIsFormatAvailable(pWinStaObj, CF_UNICODETEXT); if (IS_DATA_SYNTHESIZED(pElement)) pElement = IntIsFormatAvailable(pWinStaObj, CF_TEXT); if (IS_DATA_SYNTHESIZED(pElement)) pElement = IntIsFormatAvailable(pWinStaObj, CF_OEMTEXT); break; case CF_BITMAP: IntSynthesizeBitmap(pWinStaObj, pElement); break; default: ASSERT(FALSE); } } _SEH2_TRY { ProbeForWrite(pgcd, sizeof(*pgcd), 1); pgcd->uFmtRet = pElement->fmt; pgcd->fGlobalHandle = pElement->fGlobalHandle; /* Text and bitmap needs more data */ if (fmt == CF_TEXT) { PCLIP pLocaleEl; pLocaleEl = IntIsFormatAvailable(pWinStaObj, CF_LOCALE); if (pLocaleEl && !IS_DATA_DELAYED(pLocaleEl)) pgcd->hLocale = pLocaleEl->hData; } else if (fmt == CF_BITMAP) { PCLIP pPaletteEl; pPaletteEl = IntIsFormatAvailable(pWinStaObj, CF_PALETTE); if (pPaletteEl && !IS_DATA_DELAYED(pPaletteEl)) pgcd->hPalette = pPaletteEl->hData; } hRet = pElement->hData; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { SetLastNtError(_SEH2_GetExceptionCode()); } _SEH2_END; cleanup: if(pWinStaObj) ObDereferenceObject(pWinStaObj); UserLeave(); TRACE("NtUserGetClipboardData returns %p\n", hRet); return hRet; }
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 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; }
BOOL APIENTRY NtGdiAlphaBlend( HDC hDCDest, LONG XOriginDest, LONG YOriginDest, LONG WidthDest, LONG HeightDest, HDC hDCSrc, LONG XOriginSrc, LONG YOriginSrc, LONG WidthSrc, LONG HeightSrc, BLENDFUNCTION BlendFunc, HANDLE hcmXform) { PDC DCDest; PDC DCSrc; HDC ahDC[2]; PGDIOBJ apObj[2]; SURFACE *BitmapDest, *BitmapSrc; RECTL DestRect, SourceRect; BOOL bResult; EXLATEOBJ exlo; BLENDOBJ BlendObj; BlendObj.BlendFunction = BlendFunc; if (WidthDest < 0 || HeightDest < 0 || WidthSrc < 0 || HeightSrc < 0) { EngSetLastError(ERROR_INVALID_PARAMETER); return FALSE; } if ((hDCDest == NULL) || (hDCSrc == NULL)) { EngSetLastError(ERROR_INVALID_PARAMETER); return FALSE; } TRACE("Locking DCs\n"); ahDC[0] = hDCDest; ahDC[1] = hDCSrc ; 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]; if (DCDest->dctype == DC_TYPE_INFO || DCDest->dctype == DCTYPE_INFO) { GDIOBJ_vUnlockObject(&DCSrc->BaseObject); GDIOBJ_vUnlockObject(&DCDest->BaseObject); /* Yes, Windows really returns TRUE in this case */ return TRUE; } 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; 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; if (!DestRect.right || !DestRect.bottom || !SourceRect.right || !SourceRect.bottom) { GDIOBJ_vUnlockObject(&DCSrc->BaseObject); GDIOBJ_vUnlockObject(&DCDest->BaseObject); return TRUE; } /* Prepare DCs for blit */ TRACE("Preparing DCs for blit\n"); DC_vPrepareDCsForBlit(DCDest, &DestRect, DCSrc, &SourceRect); /* Determine surfaces to be used in the bitblt */ BitmapDest = DCDest->dclevel.pSurface; if (!BitmapDest) { bResult = FALSE ; goto leave ; } BitmapSrc = DCSrc->dclevel.pSurface; if (!BitmapSrc) { bResult = FALSE; goto leave; } /* Create the XLATEOBJ. */ EXLATEOBJ_vInitXlateFromDCs(&exlo, DCSrc, DCDest); /* Perform the alpha blend operation */ TRACE("Performing the alpha blend\n"); bResult = IntEngAlphaBlend(&BitmapDest->SurfObj, &BitmapSrc->SurfObj, &DCDest->co.ClipObj, &exlo.xlo, &DestRect, &SourceRect, &BlendObj); EXLATEOBJ_vCleanup(&exlo); leave : TRACE("Finishing blit\n"); DC_vFinishBlit(DCDest, DCSrc); GDIOBJ_vUnlockObject(&DCSrc->BaseObject); GDIOBJ_vUnlockObject(&DCDest->BaseObject); return bResult; }
/* * @unimplemented */ DWORD_PTR APIENTRY NtUserCallNoParam(DWORD Routine) { DWORD_PTR Result = 0; DECLARE_RETURN(DWORD_PTR); TRACE("Enter NtUserCallNoParam\n"); UserEnterExclusive(); switch(Routine) { case NOPARAM_ROUTINE_CREATEMENU: Result = (DWORD_PTR)UserCreateMenu(FALSE); break; case NOPARAM_ROUTINE_CREATEMENUPOPUP: Result = (DWORD_PTR)UserCreateMenu(TRUE); break; case NOPARAM_ROUTINE_DESTROY_CARET: Result = (DWORD_PTR)co_IntDestroyCaret(PsGetCurrentThread()->Tcb.Win32Thread); break; case NOPARAM_ROUTINE_INIT_MESSAGE_PUMP: Result = (DWORD_PTR)IntInitMessagePumpHook(); break; case NOPARAM_ROUTINE_UNINIT_MESSAGE_PUMP: Result = (DWORD_PTR)IntUninitMessagePumpHook(); break; case NOPARAM_ROUTINE_GETMESSAGEEXTRAINFO: Result = (DWORD_PTR)MsqGetMessageExtraInfo(); break; case NOPARAM_ROUTINE_MSQCLEARWAKEMASK: RETURN( (DWORD_PTR)IntMsqClearWakeMask()); case NOPARAM_ROUTINE_GETMSESSAGEPOS: { PTHREADINFO pti = PsGetCurrentThreadWin32Thread(); RETURN( (DWORD_PTR)MAKELONG(pti->ptLast.x, pti->ptLast.y)); } case NOPARAM_ROUTINE_RELEASECAPTURE: RETURN( (DWORD_PTR)IntReleaseCapture()); case NOPARAM_ROUTINE_LOADUSERAPIHOOK: RETURN(UserLoadApiHook()); case NOPARAM_ROUTINE_ZAPACTIVEANDFOUS: { PTHREADINFO pti = PsGetCurrentThreadWin32Thread(); TRACE("Zapping the Active and Focus window out of the Queue!\n"); pti->MessageQueue->spwndFocus = NULL; pti->MessageQueue->spwndActive = NULL; RETURN(0); } /* this is a Reactos only case and is needed for gui-on-demand */ case NOPARAM_ROUTINE_ISCONSOLEMODE: RETURN( ScreenDeviceContext == NULL ); default: ERR("Calling invalid routine number 0x%x in NtUserCallNoParam\n", Routine); EngSetLastError(ERROR_INVALID_PARAMETER); break; } RETURN(Result); CLEANUP: TRACE("Leave NtUserCallNoParam, ret=%p\n",(PVOID)_ret_); UserLeave(); END_CLEANUP; }
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; }
HBITMAP APIENTRY NtGdiCreateBitmap( IN INT nWidth, IN INT nHeight, IN UINT cPlanes, IN UINT cBitsPixel, IN OPTIONAL LPBYTE pUnsafeBits) { HBITMAP hbmp; ULONG cRealBpp, cjWidthBytes, iFormat; ULONGLONG cjSize; PSURFACE psurf; /* Calculate bitmap format and real bits per pixel. */ iFormat = BitmapFormat(cBitsPixel * cPlanes, BI_RGB); cRealBpp = gajBitsPerFormat[iFormat]; /* Calculate width and image size in bytes */ cjWidthBytes = WIDTH_BYTES_ALIGN16(nWidth, cRealBpp); cjSize = (ULONGLONG)cjWidthBytes * nHeight; /* Check parameters (possible overflow of cjSize!) */ if ((iFormat == 0) || (nWidth <= 0) || (nWidth >= 0x8000000) || (nHeight <= 0) || (cBitsPixel > 32) || (cPlanes > 32) || (cjSize >= 0x100000000ULL)) { DPRINT1("Invalid bitmap format! Width=%d, Height=%d, Bpp=%u, Planes=%u\n", nWidth, nHeight, cBitsPixel, cPlanes); EngSetLastError(ERROR_INVALID_PARAMETER); return NULL; } /* Allocate the surface (but don't set the bits) */ psurf = SURFACE_AllocSurface(STYPE_BITMAP, nWidth, nHeight, iFormat, 0, 0, NULL); if (!psurf) { DPRINT1("SURFACE_AllocSurface failed.\n"); return NULL; } /* Mark as API and DDB bitmap */ psurf->flags |= (API_BITMAP | DDB_SURFACE); /* Check if we have bits to set */ if (pUnsafeBits) { /* Protect with SEH and copy the bits */ _SEH2_TRY { ProbeForRead(pUnsafeBits, (SIZE_T)cjSize, 1); UnsafeSetBitmapBits(psurf, 0, pUnsafeBits); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { GDIOBJ_vDeleteObject(&psurf->BaseObject); _SEH2_YIELD(return NULL;) } _SEH2_END } else {
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; }
LONG APIENTRY NtUserChangeDisplaySettings( PUNICODE_STRING pustrDevice, LPDEVMODEW lpDevMode, HWND hwnd, DWORD dwflags, LPVOID lParam) { WCHAR awcDevice[CCHDEVICENAME]; UNICODE_STRING ustrDevice; DEVMODEW dmLocal; LONG lRet; /* Check arguments */ if ((dwflags != CDS_VIDEOPARAMETERS && lParam != NULL) || (hwnd != NULL)) { EngSetLastError(ERROR_INVALID_PARAMETER); return DISP_CHANGE_BADPARAM; } /* Check flags */ if ((dwflags & (CDS_GLOBAL|CDS_NORESET)) && !(dwflags & CDS_UPDATEREGISTRY)) { return DISP_CHANGE_BADFLAGS; } /* Copy the device name */ if (pustrDevice) { /* Initialize destination string */ RtlInitEmptyUnicodeString(&ustrDevice, awcDevice, sizeof(awcDevice)); _SEH2_TRY { /* Probe the UNICODE_STRING and the buffer */ ProbeForRead(pustrDevice, sizeof(UNICODE_STRING), 1); ProbeForRead(pustrDevice->Buffer, pustrDevice->Length, 1); /* Copy the string */ RtlCopyUnicodeString(&ustrDevice, pustrDevice); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { /* Set and return error */ SetLastNtError(_SEH2_GetExceptionCode()); _SEH2_YIELD(return DISP_CHANGE_BADPARAM); } _SEH2_END pustrDevice = &ustrDevice; } /* Copy devmode */ if (lpDevMode) { _SEH2_TRY { /* Probe the size field of the structure */ ProbeForRead(lpDevMode, sizeof(dmLocal.dmSize), 1); /* Calculate usable size */ dmLocal.dmSize = min(sizeof(dmLocal), lpDevMode->dmSize); /* Probe and copy the full DEVMODE */ ProbeForRead(lpDevMode, dmLocal.dmSize, 1); RtlCopyMemory(&dmLocal, lpDevMode, dmLocal.dmSize); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { /* Set and return error */ SetLastNtError(_SEH2_GetExceptionCode()); _SEH2_YIELD(return DISP_CHANGE_BADPARAM); } _SEH2_END /* Check for extra parameters */ if (dmLocal.dmDriverExtra > 0) { /* FIXME: TODO */ ERR("lpDevMode->dmDriverExtra is IGNORED!\n"); dmLocal.dmDriverExtra = 0; } /* Use the local structure */ lpDevMode = &dmLocal; } // FIXME: Copy videoparameters /* Acquire global USER lock */ UserEnterExclusive(); /* Call internal function */ lRet = UserChangeDisplaySettings(pustrDevice, lpDevMode, hwnd, dwflags, NULL); /* Release lock */ UserLeave(); return lRet; }
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 NtUserCreateCaret( HWND hWnd, HBITMAP hBitmap, int nWidth, int nHeight) { PWND Window; PTHREADINFO pti; PUSER_MESSAGE_QUEUE ThreadQueue; DECLARE_RETURN(BOOL); TRACE("Enter NtUserCreateCaret\n"); UserEnterExclusive(); if(!(Window = UserGetWindowObject(hWnd))) { RETURN(FALSE); } if(Window->head.pti->pEThread != PsGetCurrentThread()) { EngSetLastError(ERROR_ACCESS_DENIED); RETURN(FALSE); } pti = PsGetCurrentThreadWin32Thread(); ThreadQueue = pti->MessageQueue; if (ThreadQueue->CaretInfo->Visible) { IntKillTimer(Window, IDCARETTIMER, TRUE); co_IntHideCaret(ThreadQueue->CaretInfo); } ThreadQueue->CaretInfo->hWnd = hWnd; if(hBitmap) { ThreadQueue->CaretInfo->Bitmap = hBitmap; ThreadQueue->CaretInfo->Size.cx = ThreadQueue->CaretInfo->Size.cy = 0; } else { if (nWidth == 0) { nWidth = UserGetSystemMetrics(SM_CXBORDER); } if (nHeight == 0) { nHeight = UserGetSystemMetrics(SM_CYBORDER); } ThreadQueue->CaretInfo->Bitmap = (HBITMAP)0; ThreadQueue->CaretInfo->Size.cx = nWidth; ThreadQueue->CaretInfo->Size.cy = nHeight; } ThreadQueue->CaretInfo->Visible = 0; ThreadQueue->CaretInfo->Showing = 0; IntSetTimer( Window, IDCARETTIMER, gpsi->dtCaretBlink, CaretSystemTimerProc, TMRF_SYSTEM ); IntNotifyWinEvent(EVENT_OBJECT_CREATE, Window, OBJID_CARET, CHILDID_SELF, 0); RETURN(TRUE); CLEANUP: TRACE("Leave NtUserCreateCaret, ret=%i\n",_ret_); UserLeave(); END_CLEANUP; }
BOOL FASTCALL IntRoundRect( PDC dc, int Left, int Top, int Right, int Bottom, int xCurveDiameter, int yCurveDiameter) { PDC_ATTR pdcattr; PBRUSH pbrLine, pbrFill; RECTL RectBounds; LONG PenWidth, PenOrigWidth; BOOL ret = TRUE; // Default to success BRUSH brushTemp; ASSERT ( dc ); // Caller's responsibility to set this up if ( PATH_IsPathOpen(dc->dclevel) ) return PATH_RoundRect ( dc, Left, Top, Right, Bottom, xCurveDiameter, yCurveDiameter ); if ((Left == Right) || (Top == Bottom)) return TRUE; xCurveDiameter = max(abs( xCurveDiameter ), 1); yCurveDiameter = max(abs( yCurveDiameter ), 1); 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); pbrLine = PEN_ShareLockPen(pdcattr->hpen); if (!pbrLine) { /* Nothing to do, as we don't have a bitmap */ EngSetLastError(ERROR_INTERNAL_ERROR); return FALSE; } PenOrigWidth = PenWidth = pbrLine->ptPenWidth.x; if (pbrLine->ulPenStyle == PS_NULL) PenWidth = 0; if (pbrLine->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; pbrLine->ptPenWidth.x = PenWidth; RectBounds.left = Left; RectBounds.top = Top; RectBounds.right = Right; RectBounds.bottom = Bottom; IntLPtoDP(dc, (LPPOINT)&RectBounds, 2); RectBounds.left += dc->ptlDCOrig.x; RectBounds.top += dc->ptlDCOrig.y; RectBounds.right += dc->ptlDCOrig.x; RectBounds.bottom += dc->ptlDCOrig.y; pbrFill = BRUSH_ShareLockBrush(pdcattr->hbrush); if (!pbrFill) { DPRINT1("FillRound Fail\n"); EngSetLastError(ERROR_INTERNAL_ERROR); ret = FALSE; } else { DC_vPrepareDCsForBlit(dc, RectBounds, NULL, RectBounds); RtlCopyMemory(&brushTemp, pbrFill, sizeof(brushTemp)); brushTemp.ptOrigin.x += RectBounds.left - Left; brushTemp.ptOrigin.y += RectBounds.top - Top; ret = IntFillRoundRect( dc, RectBounds.left, RectBounds.top, RectBounds.right, RectBounds.bottom, xCurveDiameter, yCurveDiameter, &brushTemp); BRUSH_ShareUnlockBrush(pbrFill); if (ret) { ret = IntDrawRoundRect( dc, RectBounds.left, RectBounds.top, RectBounds.right, RectBounds.bottom, xCurveDiameter, yCurveDiameter, pbrLine); } DC_vFinishBlit(dc, NULL); } pbrLine->ptPenWidth.x = PenOrigWidth; PEN_ShareUnlockPen(pbrLine); return ret; }
/* * @implemented */ DWORD_PTR APIENTRY NtUserCallOneParam( DWORD_PTR Param, DWORD Routine) { DECLARE_RETURN(DWORD_PTR); TRACE("Enter NtUserCallOneParam\n"); UserEnterExclusive(); switch(Routine) { case ONEPARAM_ROUTINE_POSTQUITMESSAGE: { PTHREADINFO pti; pti = PsGetCurrentThreadWin32Thread(); MsqPostQuitMessage(pti->MessageQueue, Param); RETURN(TRUE); } case ONEPARAM_ROUTINE_BEGINDEFERWNDPOS: { PSMWP psmwp; HDWP hDwp = NULL; INT count = (INT)Param; if (count < 0) { EngSetLastError(ERROR_INVALID_PARAMETER); RETURN(0); } /* Windows allows zero count, in which case it allocates context for 8 moves */ if (count == 0) count = 8; psmwp = (PSMWP) UserCreateObject( gHandleTable, NULL, (PHANDLE)&hDwp, otSMWP, sizeof(SMWP)); if (!psmwp) RETURN(0); psmwp->acvr = ExAllocatePoolWithTag(PagedPool, count * sizeof(CVR), USERTAG_SWP); if (!psmwp->acvr) { UserDeleteObject(hDwp, otSMWP); RETURN(0); } RtlZeroMemory(psmwp->acvr, count * sizeof(CVR)); psmwp->bHandle = TRUE; psmwp->ccvr = 0; // actualCount psmwp->ccvrAlloc = count; // suggestedCount RETURN((DWORD_PTR)hDwp); } case ONEPARAM_ROUTINE_SHOWCURSOR: RETURN( (DWORD_PTR)UserShowCursor((BOOL)Param) ); case ONEPARAM_ROUTINE_GETDESKTOPMAPPING: { PTHREADINFO ti; ti = GetW32ThreadInfo(); if (ti != NULL) { /* Try convert the pointer to a user mode pointer if the desktop is mapped into the process */ RETURN((DWORD_PTR)DesktopHeapAddressToUser((PVOID)Param)); } else { RETURN(0); } } case ONEPARAM_ROUTINE_WINDOWFROMDC: RETURN( (DWORD_PTR)IntWindowFromDC((HDC)Param)); case ONEPARAM_ROUTINE_SWAPMOUSEBUTTON: { DWORD_PTR Result; Result = gspv.bMouseBtnSwap; gspv.bMouseBtnSwap = Param ? TRUE : FALSE; gpsi->aiSysMet[SM_SWAPBUTTON] = gspv.bMouseBtnSwap; RETURN(Result); } case ONEPARAM_ROUTINE_SWITCHCARETSHOWING: RETURN( (DWORD_PTR)IntSwitchCaretShowing((PVOID)Param)); case ONEPARAM_ROUTINE_SETCARETBLINKTIME: RETURN( (DWORD_PTR)IntSetCaretBlinkTime((UINT)Param)); case ONEPARAM_ROUTINE_SETMESSAGEEXTRAINFO: RETURN( (DWORD_PTR)MsqSetMessageExtraInfo((LPARAM)Param)); case ONEPARAM_ROUTINE_CREATEEMPTYCUROBJECT: { PCURICON_OBJECT CurIcon; DWORD_PTR Result ; if (!(CurIcon = IntCreateCurIconHandle())) { EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); RETURN(0); } Result = (DWORD_PTR)CurIcon->Self; UserDereferenceObject(CurIcon); RETURN(Result); } case ONEPARAM_ROUTINE_GETCURSORPOSITION: { BOOL ret = TRUE; _SEH2_TRY { ProbeForWrite((POINT*)Param,sizeof(POINT),1); RtlCopyMemory((POINT*)Param,&gpsi->ptCursor,sizeof(POINT)); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { SetLastNtError(_SEH2_GetExceptionCode()); ret = FALSE; } _SEH2_END; RETURN (ret); } case ONEPARAM_ROUTINE_ENABLEPROCWNDGHSTING: { BOOL Enable; PPROCESSINFO Process = PsGetCurrentProcessWin32Process(); if(Process != NULL) { Enable = (BOOL)(Param != 0); if(Enable) { Process->W32PF_flags &= ~W32PF_NOWINDOWGHOSTING; } else { Process->W32PF_flags |= W32PF_NOWINDOWGHOSTING; } RETURN( TRUE); } RETURN( FALSE); } case ONEPARAM_ROUTINE_GETINPUTEVENT: RETURN( (DWORD_PTR)IntMsqSetWakeMask(Param)); case ONEPARAM_ROUTINE_GETKEYBOARDTYPE: RETURN( UserGetKeyboardType(Param)); case ONEPARAM_ROUTINE_GETKEYBOARDLAYOUT: RETURN( (DWORD_PTR)UserGetKeyboardLayout(Param)); case ONEPARAM_ROUTINE_RELEASEDC: RETURN (UserReleaseDC(NULL, (HDC) Param, FALSE)); case ONEPARAM_ROUTINE_REALIZEPALETTE: RETURN (UserRealizePalette((HDC) Param)); case ONEPARAM_ROUTINE_GETQUEUESTATUS: { RETURN (IntGetQueueStatus((DWORD)Param)); } case ONEPARAM_ROUTINE_ENUMCLIPBOARDFORMATS: /* FIXME: Should use UserEnterShared */ RETURN(IntEnumClipboardFormats(Param)); case ONEPARAM_ROUTINE_CSRSS_GUICHECK: IntUserManualGuiCheck(Param); RETURN(TRUE); case ONEPARAM_ROUTINE_GETCURSORPOS: { BOOL Ret = TRUE; PPOINTL pptl; PTHREADINFO pti = PsGetCurrentThreadWin32Thread(); if (pti->hdesk != InputDesktopHandle) RETURN(FALSE); _SEH2_TRY { pptl = (PPOINTL)Param; *pptl = gpsi->ptCursor; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { Ret = FALSE; } _SEH2_END; RETURN(Ret); } case ONEPARAM_ROUTINE_SETPROCDEFLAYOUT: { PPROCESSINFO ppi; if (Param & LAYOUT_ORIENTATIONMASK) { ppi = PsGetCurrentProcessWin32Process(); ppi->dwLayout = Param; RETURN(TRUE); } EngSetLastError(ERROR_INVALID_PARAMETER); RETURN(FALSE); } case ONEPARAM_ROUTINE_GETPROCDEFLAYOUT: { BOOL Ret = TRUE; PPROCESSINFO ppi; PDWORD pdwLayout; if ( PsGetCurrentProcess() == CsrProcess) { EngSetLastError(ERROR_INVALID_ACCESS); RETURN(FALSE); } ppi = PsGetCurrentProcessWin32Process(); _SEH2_TRY { pdwLayout = (PDWORD)Param; *pdwLayout = ppi->dwLayout; } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { SetLastNtError(_SEH2_GetExceptionCode()); Ret = FALSE; } _SEH2_END; RETURN(Ret); } case ONEPARAM_ROUTINE_REPLYMESSAGE: RETURN (co_MsqReplyMessage((LRESULT) Param)); case ONEPARAM_ROUTINE_MESSAGEBEEP: RETURN ( UserPostMessage(hwndSAS, WM_LOGONNOTIFY, LN_MESSAGE_BEEP, Param) ); /* TODO: Implement sound sentry */ } ERR("Calling invalid routine number 0x%x in NtUserCallOneParam(), Param=0x%x\n", Routine, Param); EngSetLastError(ERROR_INVALID_PARAMETER); RETURN( 0); CLEANUP: TRACE("Leave NtUserCallOneParam, ret=%i\n",_ret_); UserLeave(); END_CLEANUP; }
BOOL APIENTRY NtGdiGradientFill( HDC hdc, PTRIVERTEX pVertex, ULONG nVertex, PVOID pMesh, ULONG nMesh, ULONG ulMode) { BOOL bRet; PTRIVERTEX SafeVertex; PVOID SafeMesh; ULONG cbVertex, cbMesh; /* Validate parameters */ if (!pVertex || !nVertex || !pMesh || !nMesh) { EngSetLastError(ERROR_INVALID_PARAMETER); return FALSE; } switch (ulMode) { case GRADIENT_FILL_RECT_H: case GRADIENT_FILL_RECT_V: cbMesh = nMesh * sizeof(GRADIENT_RECT); break; case GRADIENT_FILL_TRIANGLE: cbMesh = nMesh * sizeof(GRADIENT_TRIANGLE); break; default: EngSetLastError(ERROR_INVALID_PARAMETER); return FALSE; } cbVertex = nVertex * sizeof(TRIVERTEX) ; if(cbVertex + cbMesh <= cbVertex) { /* Overflow */ return FALSE ; } /* Allocate a kernel mode buffer */ SafeVertex = ExAllocatePoolWithTag(PagedPool, cbVertex + cbMesh, TAG_SHAPE); if(!SafeVertex) { EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); return FALSE; } SafeMesh = (PVOID)((ULONG_PTR)SafeVertex + cbVertex); /* Copy the parameters to kernel mode */ _SEH2_TRY { ProbeForRead(pVertex, cbVertex, 1); ProbeForRead(pMesh, cbMesh, 1); RtlCopyMemory(SafeVertex, pVertex, cbVertex); RtlCopyMemory(SafeMesh, pMesh, cbMesh); } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { ExFreePoolWithTag(SafeVertex, TAG_SHAPE); SetLastNtError(_SEH2_GetExceptionCode()); _SEH2_YIELD(return FALSE;) } _SEH2_END; /* Call the internal function */ bRet = GreGradientFill(hdc, SafeVertex, nVertex, SafeMesh, nMesh, ulMode); /* Cleanup and return result */ ExFreePoolWithTag(SafeVertex, TAG_SHAPE); return bRet; }
/* * @implemented */ DWORD_PTR APIENTRY NtUserCallTwoParam( DWORD_PTR Param1, DWORD_PTR Param2, DWORD Routine) { PWND Window; DECLARE_RETURN(DWORD_PTR); TRACE("Enter NtUserCallTwoParam\n"); UserEnterExclusive(); switch(Routine) { case TWOPARAM_ROUTINE_SETMENUBARHEIGHT: { DWORD_PTR Ret; PMENU_OBJECT MenuObject = IntGetMenuObject((HMENU)Param1); if(!MenuObject) RETURN( 0); if(Param2 > 0) { Ret = (MenuObject->MenuInfo.Height == (int)Param2); MenuObject->MenuInfo.Height = (int)Param2; } else Ret = (DWORD_PTR)MenuObject->MenuInfo.Height; IntReleaseMenuObject(MenuObject); RETURN( Ret); } case TWOPARAM_ROUTINE_SETGUITHRDHANDLE: { PUSER_MESSAGE_QUEUE MsgQueue = ((PTHREADINFO)PsGetCurrentThread()->Tcb.Win32Thread)->MessageQueue; ASSERT(MsgQueue); RETURN( (DWORD_PTR)MsqSetStateWindow(MsgQueue, (ULONG)Param1, (HWND)Param2)); } case TWOPARAM_ROUTINE_ENABLEWINDOW: RETURN( IntEnableWindow((HWND)Param1, (BOOL)Param2)); case TWOPARAM_ROUTINE_SHOWOWNEDPOPUPS: { Window = UserGetWindowObject((HWND)Param1); if (!Window) RETURN(0); RETURN( (DWORD_PTR)IntShowOwnedPopups(Window, (BOOL) Param2)); } case TWOPARAM_ROUTINE_ROS_UPDATEUISTATE: { WPARAM wParam; Window = UserGetWindowObject((HWND)Param1); if (!Window) RETURN(0); /* Unpack wParam */ wParam = MAKEWPARAM((Param2 >> 3) & 0x3, Param2 & (UISF_HIDEFOCUS | UISF_HIDEACCEL | UISF_ACTIVE)); RETURN( UserUpdateUiState(Window, wParam) ); } case TWOPARAM_ROUTINE_SWITCHTOTHISWINDOW: STUB RETURN( 0); case TWOPARAM_ROUTINE_SETCARETPOS: RETURN( (DWORD_PTR)co_IntSetCaretPos((int)Param1, (int)Param2)); case TWOPARAM_ROUTINE_REGISTERLOGONPROCESS: RETURN( (DWORD_PTR)co_IntRegisterLogonProcess((HANDLE)Param1, (BOOL)Param2)); case TWOPARAM_ROUTINE_SETCURSORPOS: RETURN( (DWORD_PTR)UserSetCursorPos((int)Param1, (int)Param2, 0, 0, FALSE)); case TWOPARAM_ROUTINE_UNHOOKWINDOWSHOOK: RETURN( IntUnhookWindowsHook((int)Param1, (HOOKPROC)Param2)); } ERR("Calling invalid routine number 0x%x in NtUserCallTwoParam(), Param1=0x%x Parm2=0x%x\n", Routine, Param1, Param2); EngSetLastError(ERROR_INVALID_PARAMETER); RETURN( 0); CLEANUP: TRACE("Leave NtUserCallTwoParam, ret=%i\n",_ret_); UserLeave(); END_CLEANUP; }
DWORD APIENTRY NtUserGetGuiResources( HANDLE hProcess, DWORD uiFlags) { PEPROCESS Process; PPROCESSINFO W32Process; NTSTATUS Status; DWORD Ret = 0; DECLARE_RETURN(DWORD); TRACE("Enter NtUserGetGuiResources\n"); UserEnterShared(); Status = ObReferenceObjectByHandle(hProcess, PROCESS_QUERY_INFORMATION, *PsProcessType, ExGetPreviousMode(), (PVOID*)&Process, NULL); if(!NT_SUCCESS(Status)) { SetLastNtError(Status); RETURN( 0); } W32Process = (PPROCESSINFO)Process->Win32Process; if(!W32Process) { ObDereferenceObject(Process); EngSetLastError(ERROR_INVALID_PARAMETER); RETURN( 0); } switch(uiFlags) { case GR_GDIOBJECTS: { Ret = (DWORD)W32Process->GDIHandleCount; break; } case GR_USEROBJECTS: { Ret = (DWORD)W32Process->UserHandleCount; break; } default: { EngSetLastError(ERROR_INVALID_PARAMETER); break; } } ObDereferenceObject(Process); RETURN( Ret); CLEANUP: TRACE("Leave NtUserGetGuiResources, ret=%lu\n",_ret_); UserLeave(); END_CLEANUP; }
/* * @implemented */ BOOL APIENTRY EngAlphaBlend(IN SURFOBJ *psoDest, IN SURFOBJ *psoSource, IN CLIPOBJ *ClipRegion, IN XLATEOBJ *ColorTranslation, IN PRECTL DestRect, IN PRECTL SourceRect, IN BLENDOBJ *BlendObj) { RECTL InputRect; RECTL OutputRect; RECTL ClipRect; RECTL CombinedRect; RECTL Rect; POINTL Translate; INTENG_ENTER_LEAVE EnterLeaveSource; INTENG_ENTER_LEAVE EnterLeaveDest; SURFOBJ* InputObj; SURFOBJ* OutputObj; LONG ClippingType; RECT_ENUM RectEnum; BOOL EnumMore; INT i; BOOLEAN Ret; DPRINT("EngAlphaBlend(psoDest:0x%p, psoSource:0x%p, ClipRegion:0x%p, ColorTranslation:0x%p,\n", psoDest, psoSource, ClipRegion, ColorTranslation); DPRINT(" DestRect:{0x%x, 0x%x, 0x%x, 0x%x}, SourceRect:{0x%x, 0x%x, 0x%x, 0x%x},\n", DestRect->left, DestRect->top, DestRect->right, DestRect->bottom, SourceRect->left, SourceRect->top, SourceRect->right, SourceRect->bottom); DPRINT(" BlendObj:{0x%x, 0x%x, 0x%x, 0x%x}\n", BlendObj->BlendFunction.BlendOp, BlendObj->BlendFunction.BlendFlags, BlendObj->BlendFunction.SourceConstantAlpha, BlendObj->BlendFunction.AlphaFormat); /* Validate output */ OutputRect = *DestRect; if (OutputRect.right < OutputRect.left) { OutputRect.left = DestRect->right; OutputRect.right = DestRect->left; } if (OutputRect.bottom < OutputRect.top) { OutputRect.left = DestRect->right; OutputRect.right = DestRect->left; } /* Validate input */ InputRect = *SourceRect; if ( (InputRect.top < 0) || (InputRect.bottom < 0) || (InputRect.left < 0) || (InputRect.right < 0) || InputRect.right > psoSource->sizlBitmap.cx || InputRect.bottom > psoSource->sizlBitmap.cy ) { EngSetLastError(ERROR_INVALID_PARAMETER); return FALSE; } if (psoDest == psoSource && !(OutputRect.left >= SourceRect->right || InputRect.left >= OutputRect.right || OutputRect.top >= SourceRect->bottom || InputRect.top >= OutputRect.bottom)) { DPRINT1("Source and destination rectangles overlap!\n"); return FALSE; } if (BlendObj->BlendFunction.BlendOp != AC_SRC_OVER) { DPRINT1("BlendOp != AC_SRC_OVER (0x%x)\n", BlendObj->BlendFunction.BlendOp); return FALSE; } if (BlendObj->BlendFunction.BlendFlags != 0) { DPRINT1("BlendFlags != 0 (0x%x)\n", BlendObj->BlendFunction.BlendFlags); return FALSE; } if ((BlendObj->BlendFunction.AlphaFormat & ~AC_SRC_ALPHA) != 0) { DPRINT1("Unsupported AlphaFormat (0x%x)\n", BlendObj->BlendFunction.AlphaFormat); return FALSE; } /* Check if there is anything to draw */ if (ClipRegion != NULL && (ClipRegion->rclBounds.left >= ClipRegion->rclBounds.right || ClipRegion->rclBounds.top >= ClipRegion->rclBounds.bottom)) { /* Nothing to do */ return TRUE; } /* Now call the DIB function */ if (!IntEngEnter(&EnterLeaveSource, psoSource, &InputRect, TRUE, &Translate, &InputObj)) { return FALSE; } InputRect.left += Translate.x; InputRect.right += Translate.x; InputRect.top += Translate.y; InputRect.bottom += Translate.y; if (!IntEngEnter(&EnterLeaveDest, psoDest, &OutputRect, FALSE, &Translate, &OutputObj)) { return FALSE; } OutputRect.left += Translate.x; OutputRect.right += Translate.x; OutputRect.top += Translate.y; OutputRect.bottom += Translate.y; Ret = FALSE; ClippingType = (ClipRegion == NULL) ? DC_TRIVIAL : ClipRegion->iDComplexity; switch (ClippingType) { case DC_TRIVIAL: Ret = DibFunctionsForBitmapFormat[OutputObj->iBitmapFormat].DIB_AlphaBlend( OutputObj, InputObj, &OutputRect, &InputRect, ClipRegion, ColorTranslation, BlendObj); break; case DC_RECT: ClipRect.left = ClipRegion->rclBounds.left + Translate.x; ClipRect.right = ClipRegion->rclBounds.right + Translate.x; ClipRect.top = ClipRegion->rclBounds.top + Translate.y; ClipRect.bottom = ClipRegion->rclBounds.bottom + Translate.y; if (RECTL_bIntersectRect(&CombinedRect, &OutputRect, &ClipRect)) { Rect.left = InputRect.left + CombinedRect.left - OutputRect.left; Rect.right = InputRect.right + CombinedRect.right - OutputRect.right; Rect.top = InputRect.top + CombinedRect.top - OutputRect.top; Rect.bottom = InputRect.bottom + CombinedRect.bottom - OutputRect.bottom; Ret = DibFunctionsForBitmapFormat[OutputObj->iBitmapFormat].DIB_AlphaBlend( OutputObj, InputObj, &CombinedRect, &Rect, ClipRegion, ColorTranslation, BlendObj); } break; case DC_COMPLEX: Ret = TRUE; CLIPOBJ_cEnumStart(ClipRegion, FALSE, CT_RECTANGLES, CD_ANY, 0); do { EnumMore = CLIPOBJ_bEnum(ClipRegion,(ULONG) sizeof(RectEnum), (PVOID) &RectEnum); for (i = 0; i < RectEnum.c; i++) { ClipRect.left = RectEnum.arcl[i].left + Translate.x; ClipRect.right = RectEnum.arcl[i].right + Translate.x; ClipRect.top = RectEnum.arcl[i].top + Translate.y; ClipRect.bottom = RectEnum.arcl[i].bottom + Translate.y; if (RECTL_bIntersectRect(&CombinedRect, &OutputRect, &ClipRect)) { Rect.left = InputRect.left + CombinedRect.left - OutputRect.left; Rect.right = InputRect.right + CombinedRect.right - OutputRect.right; Rect.top = InputRect.top + CombinedRect.top - OutputRect.top; Rect.bottom = InputRect.bottom + CombinedRect.bottom - OutputRect.bottom; Ret = DibFunctionsForBitmapFormat[OutputObj->iBitmapFormat].DIB_AlphaBlend( OutputObj, InputObj, &CombinedRect, &Rect, ClipRegion, ColorTranslation, BlendObj) && Ret; } } } while (EnumMore); break; default: UNIMPLEMENTED; ASSERT(FALSE); break; } IntEngLeave(&EnterLeaveDest); IntEngLeave(&EnterLeaveSource); return Ret; }