BOOL APIENTRY NtUserSBGetParms( HWND hWnd, int fnBar, PSBDATA pSBData, LPSCROLLINFO lpsi) { NTSTATUS Status; PWND Window; SCROLLINFO psi; DWORD sz; BOOL Ret; DECLARE_RETURN(BOOL); USER_REFERENCE_ENTRY Ref; TRACE("Enter NtUserGetScrollInfo\n"); UserEnterExclusive(); Status = MmCopyFromCaller(&psi.cbSize, &(lpsi->cbSize), sizeof(UINT)); if(!NT_SUCCESS(Status) || !((psi.cbSize == sizeof(SCROLLINFO)) || (psi.cbSize == sizeof(SCROLLINFO) - sizeof(psi.nTrackPos)))) { SetLastNtError(Status); RETURN(FALSE); } sz = psi.cbSize; Status = MmCopyFromCaller(&psi, lpsi, sz); if (!NT_SUCCESS(Status)) { SetLastNtError(Status); RETURN(FALSE); } if(!(Window = UserGetWindowObject(hWnd))) { RETURN(FALSE); } UserRefObjectCo(Window, &Ref); Ret = co_IntGetScrollInfo(Window, fnBar, &psi); UserDerefObjectCo(Window); Status = MmCopyToCaller(lpsi, &psi, sz); if(!NT_SUCCESS(Status)) { SetLastNtError(Status); RETURN( FALSE); } RETURN( Ret); CLEANUP: TRACE("Leave NtUserGetScrollInfo, ret=%i\n",_ret_); UserLeave(); END_CLEANUP; }
NTSTATUS FASTCALL IntSafeCopyUnicodeStringTerminateNULL(PUNICODE_STRING Dest, PUNICODE_STRING Source) { NTSTATUS Status; PWSTR Src; Status = MmCopyFromCaller(Dest, Source, sizeof(UNICODE_STRING)); if(!NT_SUCCESS(Status)) { return Status; } if(Dest->Length > 0x4000) { return STATUS_UNSUCCESSFUL; } Src = Dest->Buffer; Dest->Buffer = NULL; Dest->MaximumLength = 0; if(Dest->Length > 0 && Src) { Dest->MaximumLength = Dest->Length + sizeof(WCHAR); Dest->Buffer = ExAllocatePoolWithTag(PagedPool, Dest->MaximumLength, TAG_STRING); if(!Dest->Buffer) { return STATUS_NO_MEMORY; } Status = MmCopyFromCaller(Dest->Buffer, Src, Dest->Length); if(!NT_SUCCESS(Status)) { ExFreePoolWithTag(Dest->Buffer, TAG_STRING); Dest->Buffer = NULL; return Status; } /* Make sure the string is null-terminated */ Src = (PWSTR)((PBYTE)Dest->Buffer + Dest->Length); *Src = L'\0'; return STATUS_SUCCESS; } /* String is empty */ return STATUS_SUCCESS; }
NTSTATUS FASTCALL IntSafeCopyUnicodeString(PUNICODE_STRING Dest, PUNICODE_STRING Source) { NTSTATUS Status; PWSTR Src; Status = MmCopyFromCaller(Dest, Source, sizeof(UNICODE_STRING)); if(!NT_SUCCESS(Status)) { return Status; } if(Dest->Length > 0x4000) { return STATUS_UNSUCCESSFUL; } Src = Dest->Buffer; Dest->Buffer = NULL; Dest->MaximumLength = Dest->Length; if(Dest->Length > 0 && Src) { Dest->Buffer = ExAllocatePoolWithTag(PagedPool, Dest->MaximumLength, TAG_STRING); if(!Dest->Buffer) { return STATUS_NO_MEMORY; } Status = MmCopyFromCaller(Dest->Buffer, Src, Dest->Length); if(!NT_SUCCESS(Status)) { ExFreePoolWithTag(Dest->Buffer, TAG_STRING); Dest->Buffer = NULL; return Status; } return STATUS_SUCCESS; } /* String is empty */ return STATUS_SUCCESS; }
BOOL APIENTRY NtUserGetScrollBarInfo(HWND hWnd, LONG idObject, PSCROLLBARINFO psbi) { NTSTATUS Status; SCROLLBARINFO sbi; PWND Window; BOOL Ret; DECLARE_RETURN(BOOL); USER_REFERENCE_ENTRY Ref; TRACE("Enter NtUserGetScrollBarInfo\n"); UserEnterExclusive(); Status = MmCopyFromCaller(&sbi, psbi, sizeof(SCROLLBARINFO)); if(!NT_SUCCESS(Status) || (sbi.cbSize != sizeof(SCROLLBARINFO))) { SetLastNtError(Status); RETURN(FALSE); } if(!(Window = UserGetWindowObject(hWnd))) { RETURN(FALSE); } UserRefObjectCo(Window, &Ref); Ret = co_IntGetScrollBarInfo(Window, idObject, &sbi); UserDerefObjectCo(Window); Status = MmCopyToCaller(psbi, &sbi, sizeof(SCROLLBARINFO)); if(!NT_SUCCESS(Status)) { SetLastNtError(Status); Ret = FALSE; } RETURN( Ret); CLEANUP: TRACE("Leave NtUserGetScrollBarInfo, ret=%i\n",_ret_); UserLeave(); END_CLEANUP; }
DWORD APIENTRY NtUserSetScrollInfo( HWND hWnd, int fnBar, LPCSCROLLINFO lpsi, BOOL bRedraw) { PWND Window = NULL; NTSTATUS Status; SCROLLINFO ScrollInfo; DECLARE_RETURN(DWORD); USER_REFERENCE_ENTRY Ref; TRACE("Enter NtUserSetScrollInfo\n"); UserEnterExclusive(); if(!(Window = UserGetWindowObject(hWnd)) || // FIXME: Window == UserGetDesktopWindow() || // pWnd->fnid == FNID_DESKTOP Window == UserGetMessageWindow() ) // pWnd->fnid == FNID_MESSAGEWND { RETURN( 0); } UserRefObjectCo(Window, &Ref); Status = MmCopyFromCaller(&ScrollInfo, lpsi, sizeof(SCROLLINFO) - sizeof(ScrollInfo.nTrackPos)); if(!NT_SUCCESS(Status)) { SetLastNtError(Status); RETURN( 0); } RETURN(co_IntSetScrollInfo(Window, fnBar, &ScrollInfo, bRedraw)); CLEANUP: if (Window) UserDerefObjectCo(Window); TRACE("Leave NtUserSetScrollInfo, ret=%lu\n", _ret_); UserLeave(); END_CLEANUP; }
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; }
// this is highly hacked from W32kPolygon... BOOL Polygon ( CONST PPOINT UnsafePoints, int Count, int polyFillMode ) { BOOL ret; RECTL DestRect; int CurrentPoint; PPOINT Points; SURFOBJ* SurfObj = 0; DC dc; PBRUSHOBJ OutBrushObj = 0; dc.CombinedClip = 0; dc.w.polyFillMode = polyFillMode; DPRINT1("In W32kPolygon()\n"); if ( NULL == UnsafePoints || Count < 2) { DPRINT1("ERROR_INVALID_PARAMETER\n"); return FALSE; } /* Copy points from userspace to kernelspace */ Points = (PPOINT)EngAllocMem(0, Count * sizeof(POINT)); if (NULL == Points) { DPRINT1("ERROR_NOT_ENOUGH_MEMORY\n"); return FALSE; } MmCopyFromCaller(Points, UnsafePoints, Count * sizeof(POINT)); if ( memcmp ( Points, UnsafePoints, Count * sizeof(POINT) ) ) { free(Points); return FALSE; } 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); } // Draw the Polygon Edges with the current pen for (CurrentPoint = 0; CurrentPoint < Count; ++CurrentPoint) { POINT To, From; //, Next; /* Let CurrentPoint be i * if i+1 > Count, Draw a line from Points[i] to Points[0] * Draw a line from Points[i] to Points[i+1] */ From = Points[CurrentPoint]; if ( CurrentPoint + 1 >= Count) { To = Points[0]; } else { To = Points[CurrentPoint + 1]; } DPRINT1("Polygon Making line from (%ld,%ld) to (%ld,%ld)\n", From.x, From.y, To.x, To.y ); IntEngLineTo(SurfObj, dc.CombinedClip, OutBrushObj, From.x, From.y, To.x, To.y, &DestRect, EDGE_CHAR); /* MIX */ } /* determine the fill mode to fill the polygon. */ ret = FillPolygon(&dc, SurfObj, OutBrushObj, FILL_CHAR, Points, Count, DestRect ); free(Points); return ret; }
/* NtUserMonitorFromRect * * Returns a handle to the monitor having the largest intersection with a * given rectangle * * Arguments * * pRect * Pointer to a RECT for which to find monitor * * dwFlags * Specifies the behaviour if no monitor intersects the given rect * * Return value * If a monitor intersects the rect a handle to it is returned; if not the * return value depends on dwFlags */ HMONITOR APIENTRY NtUserMonitorFromRect( IN LPCRECTL pRect, IN DWORD dwFlags) { ULONG numMonitors, iLargestArea = 0, i; PRECTL rectList; HMONITOR *hMonitorList; HMONITOR hMonitor = NULL; RECTL rect; NTSTATUS status; /* get rect */ status = MmCopyFromCaller(&rect, pRect, sizeof (RECT)); if (!NT_SUCCESS(status)) { SetLastNtError(status); return (HMONITOR)NULL; } /* find intersecting monitors */ numMonitors = IntGetMonitorsFromRect(&rect, &hMonitor, NULL, 1, dwFlags); if (numMonitors <= 1) { return hMonitor; } hMonitorList = ExAllocatePoolWithTag(PagedPool, sizeof(HMONITOR) * numMonitors, USERTAG_MONITORRECTS); if (hMonitorList == NULL) { /* FIXME: EngSetLastError? */ return (HMONITOR)NULL; } rectList = ExAllocatePoolWithTag(PagedPool, sizeof(RECT) * numMonitors, USERTAG_MONITORRECTS); if (rectList == NULL) { ExFreePoolWithTag(hMonitorList, USERTAG_MONITORRECTS); /* FIXME: EngSetLastError? */ return (HMONITOR)NULL; } /* get intersecting monitors */ numMonitors = IntGetMonitorsFromRect(&rect, hMonitorList, rectList, numMonitors, 0); if (numMonitors == 0) { ExFreePoolWithTag(hMonitorList, USERTAG_MONITORRECTS); ExFreePoolWithTag(rectList, USERTAG_MONITORRECTS); return (HMONITOR)NULL; } /* find largest intersection */ for (i = 0; i < numMonitors; i++) { ULONG area = (rectList[i].right - rectList[i].left) * (rectList[i].bottom - rectList[i].top); if (area >= iLargestArea) { hMonitor = hMonitorList[i]; } } ExFreePoolWithTag(hMonitorList, USERTAG_MONITORRECTS); ExFreePoolWithTag(rectList, USERTAG_MONITORRECTS); return hMonitor; }
/* NtUserGetMonitorInfo * * Retrieves information about a given monitor * * Arguments * * hMonitor * Handle to a monitor for which to get information * * pMonitorInfo * Pointer to a MONITORINFO struct which is filled with the information. * The cbSize member must be set to sizeof(MONITORINFO) or * sizeof(MONITORINFOEX). Even if set to sizeof(MONITORINFOEX) only parts * from MONITORINFO will be filled. * * pDevice * Pointer to a UNICODE_STRING which will recieve the device's name. The * length should be CCHDEVICENAME * Can be NULL * * Return value * TRUE on success; FALSE on failure (calls SetLastNtError()) * */ BOOL APIENTRY NtUserGetMonitorInfo( IN HMONITOR hMonitor, OUT LPMONITORINFO pMonitorInfo) { PMONITOR Monitor; MONITORINFOEXW MonitorInfo; NTSTATUS Status; DECLARE_RETURN(BOOL); TRACE("Enter NtUserGetMonitorInfo\n"); UserEnterShared(); /* get monitor object */ if (!(Monitor = UserGetMonitorObject(hMonitor))) { TRACE("Couldnt find monitor 0x%lx\n", hMonitor); RETURN(FALSE); } if(pMonitorInfo == NULL) { SetLastNtError(STATUS_INVALID_PARAMETER); RETURN(FALSE); } /* get size of pMonitorInfo */ Status = MmCopyFromCaller(&MonitorInfo.cbSize, &pMonitorInfo->cbSize, sizeof (MonitorInfo.cbSize)); if (!NT_SUCCESS(Status)) { SetLastNtError(Status); RETURN(FALSE); } if ((MonitorInfo.cbSize != sizeof (MONITORINFO)) && (MonitorInfo.cbSize != sizeof (MONITORINFOEXW))) { SetLastNtError(STATUS_INVALID_PARAMETER); RETURN(FALSE); } /* fill monitor info */ MonitorInfo.rcMonitor = Monitor->rcMonitor; MonitorInfo.rcWork = Monitor->rcWork; MonitorInfo.dwFlags = 0; if (Monitor->IsPrimary) MonitorInfo.dwFlags |= MONITORINFOF_PRIMARY; /* fill device name */ if (MonitorInfo.cbSize == sizeof (MONITORINFOEXW)) { RtlStringCbCopyNW(MonitorInfo.szDevice, sizeof(MonitorInfo.szDevice), Monitor->DeviceName.Buffer, Monitor->DeviceName.Length); } /* output data */ Status = MmCopyToCaller(pMonitorInfo, &MonitorInfo, MonitorInfo.cbSize); if (!NT_SUCCESS(Status)) { TRACE("GetMonitorInfo: MmCopyToCaller failed\n"); SetLastNtError(Status); RETURN(FALSE); } TRACE("GetMonitorInfo: success\n"); RETURN(TRUE); CLEANUP: TRACE("Leave NtUserGetMonitorInfo, ret=%i\n",_ret_); UserLeave(); END_CLEANUP; }
/* 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; }
/* NtUserMonitorFromRect * * Returns a handle to the monitor having the largest intersection with a * given rectangle * * Arguments * * pRectUnsafe * Pointer to a RECT for which to find monitor * * dwFlags * Specifies the behaviour if no monitor intersects the given rect * * Return value * If a monitor intersects the rect a handle to it is returned; if not the * return value depends on dwFlags */ HMONITOR APIENTRY NtUserMonitorFromRect( IN LPCRECTL pRectUnsafe, IN DWORD dwFlags) { ULONG cMonitors, LargestArea = 0, i; PRECTL prcMonitorList = NULL; HMONITOR *phMonitorList = NULL; HMONITOR hMonitor = NULL; RECTL Rect; NTSTATUS Status; /* Check if flags are valid */ if (dwFlags != MONITOR_DEFAULTTONULL && dwFlags != MONITOR_DEFAULTTOPRIMARY && dwFlags != MONITOR_DEFAULTTONEAREST) { EngSetLastError(ERROR_INVALID_FLAGS); return NULL; } /* Copy rectangle to safe buffer */ Status = MmCopyFromCaller(&Rect, pRectUnsafe, sizeof (RECT)); if (!NT_SUCCESS(Status)) { SetLastNtError(Status); return NULL; } UserEnterShared(); /* Find intersecting monitors */ cMonitors = IntGetMonitorsFromRect(&Rect, &hMonitor, NULL, 1, dwFlags); if (cMonitors <= 1) { /* No or one monitor found. Just return handle. */ goto cleanup; } /* There is more than one monitor. Find monitor with largest intersection. Temporary reset hMonitor */ hMonitor = NULL; /* Allocate helper buffers */ phMonitorList = ExAllocatePoolWithTag(PagedPool, sizeof(HMONITOR) * cMonitors, USERTAG_MONITORRECTS); if (phMonitorList == NULL) { EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); goto cleanup; } prcMonitorList = ExAllocatePoolWithTag(PagedPool, sizeof(RECT) * cMonitors, USERTAG_MONITORRECTS); if (prcMonitorList == NULL) { EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); goto cleanup; } /* Get intersecting monitors again but now with rectangle list */ cMonitors = IntGetMonitorsFromRect(&Rect, phMonitorList, prcMonitorList, cMonitors, 0); /* Find largest intersection */ for (i = 0; i < cMonitors; i++) { ULONG Area = (prcMonitorList[i].right - prcMonitorList[i].left) * (prcMonitorList[i].bottom - prcMonitorList[i].top); if (Area >= LargestArea) { hMonitor = phMonitorList[i]; LargestArea = Area; } } cleanup: if (phMonitorList) ExFreePoolWithTag(phMonitorList, USERTAG_MONITORRECTS); if (prcMonitorList) ExFreePoolWithTag(prcMonitorList, USERTAG_MONITORRECTS); UserLeave(); return hMonitor; }
/* NtUserGetMonitorInfo * * Retrieves information about a given monitor * * Arguments * * hMonitor * Handle to a monitor for which to get information * * pMonitorInfoUnsafe * Pointer to a MONITORINFO struct which is filled with the information. * The cbSize member must be set to sizeof(MONITORINFO) or * sizeof(MONITORINFOEX). Even if set to sizeof(MONITORINFOEX) only parts * from MONITORINFO will be filled. * * pDevice * Pointer to a UNICODE_STRING which will receive the device's name. The * length should be CCHDEVICENAME * Can be NULL * * Return value * TRUE on success; FALSE on failure (calls SetLastNtError()) * */ BOOL APIENTRY NtUserGetMonitorInfo( IN HMONITOR hMonitor, OUT LPMONITORINFO pMonitorInfoUnsafe) { PMONITOR pMonitor; MONITORINFOEXW MonitorInfo; NTSTATUS Status; BOOL bRet = FALSE; PWCHAR pwstrDeviceName; TRACE("Enter NtUserGetMonitorInfo\n"); UserEnterShared(); /* Get monitor object */ pMonitor = UserGetMonitorObject(hMonitor); if (!pMonitor) { TRACE("Couldnt find monitor %p\n", hMonitor); goto cleanup; } /* Check if pMonitorInfoUnsafe is valid */ if(pMonitorInfoUnsafe == NULL) { SetLastNtError(STATUS_INVALID_PARAMETER); goto cleanup; } pwstrDeviceName = ((PPDEVOBJ)(pMonitor->hDev))->pGraphicsDevice->szWinDeviceName; /* Get size of pMonitorInfoUnsafe */ Status = MmCopyFromCaller(&MonitorInfo.cbSize, &pMonitorInfoUnsafe->cbSize, sizeof(MonitorInfo.cbSize)); if (!NT_SUCCESS(Status)) { SetLastNtError(Status); goto cleanup; } /* Check if size of struct is valid */ if (MonitorInfo.cbSize != sizeof(MONITORINFO) && MonitorInfo.cbSize != sizeof(MONITORINFOEXW)) { SetLastNtError(STATUS_INVALID_PARAMETER); goto cleanup; } /* Fill monitor info */ MonitorInfo.rcMonitor = pMonitor->rcMonitor; MonitorInfo.rcWork = pMonitor->rcWork; MonitorInfo.dwFlags = 0; if (pMonitor->IsPrimary) MonitorInfo.dwFlags |= MONITORINFOF_PRIMARY; /* Fill device name */ if (MonitorInfo.cbSize == sizeof(MONITORINFOEXW)) { RtlStringCbCopyNExW(MonitorInfo.szDevice, sizeof(MonitorInfo.szDevice), pwstrDeviceName, (wcslen(pwstrDeviceName)+1) * sizeof(WCHAR), NULL, NULL, STRSAFE_FILL_BEHIND_NULL); } /* Output data */ Status = MmCopyToCaller(pMonitorInfoUnsafe, &MonitorInfo, MonitorInfo.cbSize); if (!NT_SUCCESS(Status)) { TRACE("GetMonitorInfo: MmCopyToCaller failed\n"); SetLastNtError(Status); goto cleanup; } TRACE("GetMonitorInfo: success\n"); bRet = TRUE; cleanup: TRACE("Leave NtUserGetMonitorInfo, ret=%i\n", bRet); UserLeave(); return bRet; }
/* 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; }
/* * NtUserSendInput * * Generates input events from software */ UINT APIENTRY NtUserSendInput( UINT nInputs, LPINPUT pInput, INT cbSize) { PTHREADINFO pti; UINT uRet = 0; TRACE("Enter NtUserSendInput\n"); UserEnterExclusive(); pti = PsGetCurrentThreadWin32Thread(); ASSERT(pti); if (!pti->rpdesk) { goto cleanup; } if (!nInputs || !pInput || cbSize != sizeof(INPUT)) { EngSetLastError(ERROR_INVALID_PARAMETER); goto cleanup; } /* * FIXME: Check access rights of the window station * e.g. services running in the service window station cannot block input */ if (!ThreadHasInputAccess(pti) || !IntIsActiveDesktop(pti->rpdesk)) { EngSetLastError(ERROR_ACCESS_DENIED); goto cleanup; } while (nInputs--) { INPUT SafeInput; NTSTATUS Status; Status = MmCopyFromCaller(&SafeInput, pInput++, sizeof(INPUT)); if (!NT_SUCCESS(Status)) { SetLastNtError(Status); goto cleanup; } switch (SafeInput.type) { case INPUT_MOUSE: if (UserSendMouseInput(&SafeInput.mi, TRUE)) uRet++; break; case INPUT_KEYBOARD: if (UserSendKeyboardInput(&SafeInput.ki, TRUE)) uRet++; break; case INPUT_HARDWARE: FIXME("INPUT_HARDWARE not supported!"); break; default: ERR("SendInput(): Invalid input type: 0x%x\n", SafeInput.type); break; } } cleanup: TRACE("Leave NtUserSendInput, ret=%u\n", uRet); UserLeave(); return uRet; }
BOOL APIENTRY NtUserSetScrollBarInfo( HWND hWnd, LONG idObject, SETSCROLLBARINFO *info) { PWND Window = NULL; SETSCROLLBARINFO Safeinfo; PSCROLLBARINFO sbi; LPSCROLLINFO psi; NTSTATUS Status; LONG Obj; DECLARE_RETURN(BOOL); USER_REFERENCE_ENTRY Ref; TRACE("Enter NtUserSetScrollBarInfo\n"); UserEnterExclusive(); if(!(Window = UserGetWindowObject(hWnd))) { RETURN( FALSE); } UserRefObjectCo(Window, &Ref); Obj = SBOBJ_TO_SBID(idObject); if(!SBID_IS_VALID(Obj)) { EngSetLastError(ERROR_INVALID_PARAMETER); ERR("Trying to set scrollinfo for unknown scrollbar type %d\n", Obj); RETURN( FALSE); } if(!co_IntCreateScrollBars(Window)) { RETURN(FALSE); } Status = MmCopyFromCaller(&Safeinfo, info, sizeof(SETSCROLLBARINFO)); if(!NT_SUCCESS(Status)) { SetLastNtError(Status); RETURN(FALSE); } sbi = IntGetScrollbarInfoFromWindow(Window, Obj); psi = IntGetScrollInfoFromWindow(Window, Obj); psi->nTrackPos = Safeinfo.nTrackPos; sbi->reserved = Safeinfo.reserved; RtlCopyMemory(&sbi->rgstate, &Safeinfo.rgstate, sizeof(Safeinfo.rgstate)); RETURN(TRUE); CLEANUP: if (Window) UserDerefObjectCo(Window); TRACE("Leave NtUserSetScrollBarInfo, ret=%i\n",_ret_); UserLeave(); END_CLEANUP; }