Author: rharabien Date: Wed Oct 19 15:40:17 2011 New Revision: 54197
URL: http://svn.reactos.org/svn/reactos?rev=54197&view=rev Log: [WIN32K] - Simplify monitors code - fix few minor bugs (ie. not updating last error) - Make monitor object more compatible to windows
Modified: trunk/reactos/subsystems/win32/win32k/include/monitor.h trunk/reactos/subsystems/win32/win32k/ntuser/monitor.c
Modified: trunk/reactos/subsystems/win32/win32k/include/monitor.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/inc... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/include/monitor.h [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/include/monitor.h [iso-8859-1] Wed Oct 19 15:40:17 2011 @@ -4,30 +4,28 @@ typedef struct _MONITOR { HEAD head; -// - UNICODE_STRING DeviceName; /* name of the monitor */ - PDEVOBJ *GdiDevice; /* pointer to the GDI device to - which this monitor is attached */ -// This is the structure Windows uses: -// struct _MONITOR* pMonitorNext; - union { - DWORD dwMONFlags; - struct { - DWORD IsVisible:1; - DWORD IsPalette:1; - DWORD IsPrimary:1; /* wether this is the primary monitor */ - };}; + struct _MONITOR* pMonitorNext; + union + { + DWORD dwMONFlags; + struct + { + DWORD IsVisible: 1; + DWORD IsPalette: 1; + DWORD IsPrimary: 1; /* wether this is the primary monitor */ + }; + }; RECT rcMonitor; RECT rcWork; HRGN hrgnMonitor; SHORT cFullScreen; SHORT cWndStack; HDEV hDev; - HDEV hDevReal; -// BYTE DockTargets[4][7]; -// Use LIST_ENTRY - struct _MONITOR* Next; //Flink; - struct _MONITOR* Prev; //Blink; + + // ReactOS specific fields: + UNICODE_STRING DeviceName; /* name of the monitor */ + PDEVOBJ *GdiDevice; /* pointer to the GDI device to + which this monitor is attached */ } MONITOR, *PMONITOR;
NTSTATUS IntAttachMonitor(PDEVOBJ *pGdiDevice, ULONG DisplayNumber);
Modified: trunk/reactos/subsystems/win32/win32k/ntuser/monitor.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntu... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/monitor.c [iso-8859-1] (original) +++ trunk/reactos/subsystems/win32/win32k/ntuser/monitor.c [iso-8859-1] Wed Oct 19 15:40:17 2011 @@ -1,9 +1,10 @@ /* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel - * PURPOSE: Monitor support + * PURPOSE: pMonitor support * FILE: subsys/win32k/ntuser/monitor.c - * PROGRAMER: Anich Gregor (blight@blight.eu.org) + * PROGRAMERS: Anich Gregor (blight@blight.eu.org) + * Rafal Harabien (rafalh@reactos.org) */
#include <win32k.h> @@ -20,7 +21,7 @@
/* GLOBALS *******************************************************************/
-/* list of monitors */ +/* List of monitors */ static PMONITOR gMonitorList = NULL;
/* PRIVATE FUNCTIONS **********************************************************/ @@ -37,16 +38,7 @@ PMONITOR IntCreateMonitorObject() { - HANDLE Handle; - PMONITOR Monitor; - - Monitor = UserCreateObject(gHandleTable, NULL, &Handle, otMonitor, sizeof (MONITOR)); - if (Monitor == NULL) - { - return NULL; - } - - return Monitor; + return UserCreateObject(gHandleTable, NULL, NULL, otMonitor, sizeof(MONITOR)); }
/* IntDestroyMonitorObject @@ -63,15 +55,34 @@ void IntDestroyMonitorObject(IN PMONITOR pMonitor) { + /* Free monitor name */ RtlFreeUnicodeString(&pMonitor->DeviceName); + + /* Remove monitor region */ + if (pMonitor->hrgnMonitor) + { + GreSetObjectOwner(pMonitor->hrgnMonitor, GDI_OBJ_HMGR_POWNED); + GreDeleteObject(pMonitor->hrgnMonitor); + } + + /* Destroy monitor object */ UserDereferenceObject(pMonitor); -} - - + UserDeleteObject(UserHMGetHandle(pMonitor), otMonitor); +} + +/* UserGetMonitorObject + * + * Returns monitor object from handle or sets last error if handle is invalid + * + * Arguments + * + * hMonitor + * Handle of MONITOR object + */ PMONITOR FASTCALL UserGetMonitorObject(IN HMONITOR hMonitor) { - PMONITOR Monitor; + PMONITOR pMonitor;
if (!hMonitor) { @@ -79,16 +90,38 @@ return NULL; }
- Monitor = (PMONITOR)UserGetObject(gHandleTable, hMonitor, otMonitor); - if (!Monitor) + pMonitor = (PMONITOR)UserGetObject(gHandleTable, hMonitor, otMonitor); + if (!pMonitor) { EngSetLastError(ERROR_INVALID_MONITOR_HANDLE); return NULL; }
- return Monitor; -} - + return pMonitor; +} + +/* IntGetPrimaryMonitor + * + * Returns a PMONITOR for the primary monitor + * + * Return value + * PMONITOR + */ +PMONITOR +FASTCALL +IntGetPrimaryMonitor() +{ + PMONITOR pMonitor; + + /* Find primary monitor */ + for (pMonitor = gMonitorList; pMonitor != NULL; pMonitor = pMonitor->pMonitorNext) + { + if (pMonitor->IsPrimary) + break; + } + + return pMonitor; +}
/* IntAttachMonitor * @@ -106,46 +139,45 @@ IntAttachMonitor(IN PDEVOBJ *pGdiDevice, IN ULONG DisplayNumber) { - PMONITOR Monitor; + PMONITOR pMonitor; WCHAR Buffer[CCHDEVICENAME];
TRACE("Attaching monitor...\n");
/* create new monitor object */ - Monitor = IntCreateMonitorObject(); - if (Monitor == NULL) + pMonitor = IntCreateMonitorObject(); + if (pMonitor == NULL) { TRACE("Couldnt create monitor object\n"); return STATUS_INSUFFICIENT_RESOURCES; }
_snwprintf(Buffer, CCHDEVICENAME, L"\\.\DISPLAY%d", DisplayNumber + 1); - if (!RtlCreateUnicodeString(&Monitor->DeviceName, Buffer)) + if (!RtlCreateUnicodeString(&pMonitor->DeviceName, Buffer)) { TRACE("Couldn't duplicate monitor name!\n"); - UserDereferenceObject(Monitor); - UserDeleteObject(UserHMGetHandle(Monitor), otMonitor); + UserDereferenceObject(pMonitor); + UserDeleteObject(UserHMGetHandle(pMonitor), otMonitor); return STATUS_INSUFFICIENT_RESOURCES; }
- Monitor->GdiDevice = pGdiDevice; - Monitor->cWndStack = 0; + pMonitor->GdiDevice = pGdiDevice; + pMonitor->cWndStack = 0;
if (gMonitorList == NULL) { TRACE("Primary monitor is beeing attached\n"); - Monitor->IsPrimary = TRUE; - gMonitorList = Monitor; + pMonitor->IsPrimary = TRUE; + gMonitorList = pMonitor; } else { - PMONITOR p; + PMONITOR pmonLast = gMonitorList; TRACE("Additional monitor is beeing attached\n"); - for (p = gMonitorList; p->Next != NULL; p = p->Next) - { - p->Next = Monitor; - } - Monitor->Prev = p; + while (pmonLast->pMonitorNext != NULL) + pmonLast = pmonLast->pMonitorNext; + + pmonLast->pMonitorNext = pMonitor; }
IntUpdateMonitorSize(pGdiDevice); @@ -167,44 +199,33 @@ NTSTATUS IntDetachMonitor(IN PDEVOBJ *pGdiDevice) { - PMONITOR Monitor; - - for (Monitor = gMonitorList; Monitor != NULL; Monitor = Monitor->Next) - { - if (Monitor->GdiDevice == pGdiDevice) + PMONITOR pMonitor = gMonitorList, *pLink = &gMonitorList; + + /* Find monitor attached to given device */ + while (pMonitor != NULL) + { + if (pMonitor->GdiDevice == pGdiDevice) break; - } - - if (Monitor == NULL) - { - /* no monitor for given device found */ + + pLink = &pMonitor->pMonitorNext; + pMonitor = pMonitor->pMonitorNext; + } + + if (pMonitor == NULL) + { + /* No monitor has been found */ return STATUS_INVALID_PARAMETER; }
- if (Monitor->IsPrimary && (Monitor->Next != NULL || Monitor->Prev != NULL)) - { - PMONITOR NewPrimaryMonitor = (Monitor->Prev != NULL) ? (Monitor->Prev) : (Monitor->Next); - - NewPrimaryMonitor->IsPrimary = TRUE; - } - - if (gMonitorList == Monitor) - { - gMonitorList = Monitor->Next; - if (Monitor->Next != NULL) - Monitor->Next->Prev = NULL; - } - else - { - Monitor->Prev->Next = Monitor->Next; - if (Monitor->Next != NULL) - Monitor->Next->Prev = Monitor->Prev; - } - - if (Monitor->hrgnMonitor) - GreDeleteObject(Monitor->hrgnMonitor); - - IntDestroyMonitorObject(Monitor); + /* We destroy primary monitor - set next as primary */ + if (pMonitor->IsPrimary && pMonitor->pMonitorNext != NULL) + pMonitor->pMonitorNext->IsPrimary = TRUE; + + /* Update Next ptr in previous monitor */ + *pLink = pMonitor->pMonitorNext; + + /* Finally destroy monitor */ + IntDestroyMonitorObject(pMonitor);
return STATUS_SUCCESS; } @@ -224,60 +245,41 @@ NTSTATUS IntUpdateMonitorSize(IN PDEVOBJ *pGdiDevice) { - PMONITOR Monitor; - - for (Monitor = gMonitorList; Monitor != NULL; Monitor = Monitor->Next) - { - if (Monitor->GdiDevice == pGdiDevice) + PMONITOR pMonitor; + + /* Find monitor attached to given device */ + for (pMonitor = gMonitorList; pMonitor != NULL; pMonitor = pMonitor->pMonitorNext) + { + if (pMonitor->GdiDevice == pGdiDevice) break; }
- if (Monitor == NULL) - { - /* no monitor for given device found */ + if (pMonitor == NULL) + { + /* No monitor has been found */ return STATUS_INVALID_PARAMETER; }
- Monitor->rcMonitor.left = 0; - Monitor->rcMonitor.top = 0; - Monitor->rcMonitor.right = Monitor->rcMonitor.left + Monitor->GdiDevice->gdiinfo.ulHorzRes; - Monitor->rcMonitor.bottom = Monitor->rcMonitor.top + Monitor->GdiDevice->gdiinfo.ulVertRes; - Monitor->rcWork = Monitor->rcMonitor; - - if (Monitor->hrgnMonitor) - { - GreSetObjectOwner(Monitor->hrgnMonitor, GDI_OBJ_HMGR_POWNED); - GreDeleteObject(Monitor->hrgnMonitor); - } - - Monitor->hrgnMonitor = IntSysCreateRectRgnIndirect( &Monitor->rcMonitor ); - - IntGdiSetRegionOwner(Monitor->hrgnMonitor, GDI_OBJ_HMGR_PUBLIC); + /* Update monitor size */ + pMonitor->rcMonitor.left = 0; + pMonitor->rcMonitor.top = 0; + pMonitor->rcMonitor.right = pMonitor->rcMonitor.left + pMonitor->GdiDevice->gdiinfo.ulHorzRes; + pMonitor->rcMonitor.bottom = pMonitor->rcMonitor.top + pMonitor->GdiDevice->gdiinfo.ulVertRes; + pMonitor->rcWork = pMonitor->rcMonitor; + + /* Destroy monitor region... */ + if (pMonitor->hrgnMonitor) + { + GreSetObjectOwner(pMonitor->hrgnMonitor, GDI_OBJ_HMGR_POWNED); + GreDeleteObject(pMonitor->hrgnMonitor); + } + + /* ...and create new one */ + pMonitor->hrgnMonitor = IntSysCreateRectRgnIndirect(&pMonitor->rcMonitor); + if (pMonitor->hrgnMonitor) + IntGdiSetRegionOwner(pMonitor->hrgnMonitor, GDI_OBJ_HMGR_PUBLIC);
return STATUS_SUCCESS; -} - -/* IntGetPrimaryMonitor - * - * Returns a PMONITOR for the primary monitor - * - * Return value - * PMONITOR - */ -PMONITOR -FASTCALL -IntGetPrimaryMonitor() -{ - PMONITOR Monitor; - - for (Monitor = gMonitorList; Monitor != NULL; Monitor = Monitor->Next) - { - /* FIXME: I guess locking the monitor is not neccessary to read 1 int */ - if (Monitor->IsPrimary) - break; - } - - return Monitor; }
/* IntGetMonitorsFromRect @@ -291,21 +293,21 @@ * Rectangle in desktop coordinates. If this is NULL all monitors are * returned and the rect list is filled with the sizes of the monitors. * - * hMonitorList + * phMonitorList * Pointer to an array of HMONITOR which is filled with monitor handles. * Can be NULL * - * monitorRectList + * prcMonitorList * Pointer to an array of RECT which is filled with intersection rects in * desktop coordinates. * Can be NULL, will be ignored if no intersecting monitor is found and * flags is MONITOR_DEFAULTTONEAREST * - * listSize - * Size of the hMonitorList and monitorRectList arguments. If this is zero - * hMonitorList and monitorRectList are ignored. - * - * flags + * dwListSize + * Size of the phMonitorList and prcMonitorList arguments. If this is zero + * phMonitorList and prcMonitorList are ignored. + * + * dwFlags * Either 0 or MONITOR_DEFAULTTONEAREST (ignored if rect is NULL) * * Returns @@ -314,29 +316,28 @@ static UINT IntGetMonitorsFromRect(OPTIONAL IN LPCRECTL pRect, - OPTIONAL OUT HMONITOR *hMonitorList, - OPTIONAL OUT PRECTL monitorRectList, - OPTIONAL IN DWORD listSize, - OPTIONAL IN DWORD flags) -{ - PMONITOR Monitor, NearestMonitor = NULL, PrimaryMonitor = NULL; - UINT iCount = 0; + OPTIONAL OUT HMONITOR *phMonitorList, + OPTIONAL OUT PRECTL prcMonitorList, + OPTIONAL IN DWORD dwListSize, + OPTIONAL IN DWORD dwFlags) +{ + PMONITOR pMonitor, pNearestMonitor = NULL, pPrimaryMonitor = NULL; + UINT cMonitors = 0; ULONG iNearestDistance = 0xffffffff;
- /* Find monitors which intersect the rectangle */ - for (Monitor = gMonitorList; Monitor != NULL; Monitor = Monitor->Next) + /* Find monitors which intersects the rectangle */ + for (pMonitor = gMonitorList; pMonitor != NULL; pMonitor = pMonitor->pMonitorNext) { RECTL MonitorRect, IntersectionRect;
- MonitorRect = Monitor->rcMonitor; + MonitorRect = pMonitor->rcMonitor;
TRACE("MonitorRect: left = %d, top = %d, right = %d, bottom = %d\n", MonitorRect.left, MonitorRect.top, MonitorRect.right, MonitorRect.bottom);
- if (flags == MONITOR_DEFAULTTOPRIMARY && Monitor->IsPrimary) - { - PrimaryMonitor = Monitor; - } + /* Save primary monitor for later usage */ + if (dwFlags == MONITOR_DEFAULTTOPRIMARY && pMonitor->IsPrimary) + pPrimaryMonitor = pMonitor;
/* Check if a rect is given */ if (pRect == NULL) @@ -344,12 +345,11 @@ /* No rect given, so use the full monitor rect */ IntersectionRect = MonitorRect; } - /* We have a rect, calculate intersection */ else if (!RECTL_bIntersectRect(&IntersectionRect, &MonitorRect, pRect)) { /* Rects did not intersect */ - if (flags == MONITOR_DEFAULTTONEAREST) + if (dwFlags == MONITOR_DEFAULTTONEAREST) { ULONG cx, cy, iDistance;
@@ -366,7 +366,7 @@ if (iDistance < iNearestDistance) { iNearestDistance = iDistance; - NearestMonitor = Monitor; + pNearestMonitor = pMonitor; } }
@@ -374,38 +374,39 @@ }
/* Check if there's space in the buffer */ - if (iCount < listSize) - { - if (hMonitorList != NULL) - hMonitorList[iCount] = UserHMGetHandle(Monitor); - if (monitorRectList != NULL) - monitorRectList[iCount] = IntersectionRect; + if (cMonitors < dwListSize) + { + /* Save monitor data */ + if (phMonitorList != NULL) + phMonitorList[cMonitors] = UserHMGetHandle(pMonitor); + if (prcMonitorList != NULL) + prcMonitorList[cMonitors] = IntersectionRect; }
/* Increase count of found monitors */ - iCount++; - } - - /* Found nothing intersecting? */ - if (iCount == 0) + cMonitors++; + } + + /* Nothing has been found? */ + if (cMonitors == 0) { /* Check if we shall default to the nearest monitor */ - if (flags == MONITOR_DEFAULTTONEAREST && NearestMonitor) - { - if (hMonitorList && listSize > 0) - hMonitorList[iCount] = UserHMGetHandle(NearestMonitor); - iCount++; + if (dwFlags == MONITOR_DEFAULTTONEAREST && pNearestMonitor) + { + if (phMonitorList && dwListSize > 0) + phMonitorList[cMonitors] = UserHMGetHandle(pNearestMonitor); + cMonitors++; } /* Check if we shall default to the primary monitor */ - else if (flags == MONITOR_DEFAULTTOPRIMARY && PrimaryMonitor) - { - if (hMonitorList != NULL && listSize > 0) - hMonitorList[iCount] = UserHMGetHandle(PrimaryMonitor); - iCount++; - } - } - - return iCount; + else if (dwFlags == MONITOR_DEFAULTTOPRIMARY && pPrimaryMonitor) + { + if (phMonitorList != NULL && dwListSize > 0) + phMonitorList[cMonitors] = UserHMGetHandle(pPrimaryMonitor); + cMonitors++; + } + } + + return cMonitors; }
/* PUBLIC FUNCTIONS ***********************************************************/ @@ -416,24 +417,24 @@ * * Arguments * - * hDC + * 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 + * 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 * - * hMonitorList + * phUnsafeMonitorList * Pointer to an array of HMONITOR which is filled with monitor handles. * Can be NULL * - * monitorRectList + * prcUnsafeMonitorList * Pointer to an array of RECT which is filled with intersection rectangles. * Can be NULL * - * listSize + * dwListSize * Size of the hMonitorList and monitorRectList arguments. If this is zero * hMonitorList and monitorRectList are ignored. * @@ -443,154 +444,158 @@ 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)) + 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); + SetLastNtError(Status); return -1; } }
- if (hDC != NULL) - { - PDC dc; - INT regionType; - - /* get visible region bounding rect */ - dc = DC_LockDc(hDC); - if (dc == NULL) + 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; } - regionType = REGION_GetRgnBox(dc->prgnVis, &dcRect); - DC_UnlockDc(dc); - - if (regionType == 0) + iRgnType = REGION_GetRgnBox(pDc->prgnVis, &DcRect); + DC_UnlockDc(pDc); + + if (iRgnType == 0) { TRACE("NtGdiGetRgnBox() failed!\n"); return -1; } - if (regionType == NULLREGION) + if (iRgnType == NULLREGION) return 0; - if (regionType == COMPLEXREGION) + if (iRgnType == COMPLEXREGION) { /* TODO: warning */ }
- /* if hDC and pRect are given the area of interest is pRect with + /* 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 */ + 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 { - rect = dcRect; - } - } - - if (hDC == NULL && pRect == NULL) - myRect = NULL; + rc = DcRect; + } + } + + if (hdc == NULL && pUnsafeRect == NULL) + pRect = NULL; else - myRect = ▭ + pRect = &rc;
UserEnterShared();
- /* find intersecting monitors */ - numMonitors = IntGetMonitorsFromRect(myRect, NULL, NULL, 0, 0); - if (numMonitors == 0 || listSize == 0 || - (hMonitorList == NULL && monitorRectList == NULL)) - { - TRACE("numMonitors = %d\n", numMonitors); + /* 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; }
- if (hMonitorList != NULL && listSize != 0) - { - safeHMonitorList = ExAllocatePoolWithTag(PagedPool, sizeof (HMONITOR) * listSize, USERTAG_MONITORRECTS); - if (safeHMonitorList == NULL) + /* Allocate safe buffers */ + if (phUnsafeMonitorList != NULL && dwListSize != 0) + { + phMonitorList = ExAllocatePoolWithTag(PagedPool, sizeof (HMONITOR) * dwListSize, USERTAG_MONITORRECTS); + if (phMonitorList == NULL) { EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); - numMonitors = -1; goto cleanup; } } - if (monitorRectList != NULL && listSize != 0) - { - safeRectList = ExAllocatePoolWithTag(PagedPool, sizeof (RECT) * listSize, USERTAG_MONITORRECTS); - if (safeRectList == NULL) - { - ExFreePoolWithTag(safeHMonitorList, USERTAG_MONITORRECTS); + if (prcUnsafeMonitorList != NULL && dwListSize != 0) + { + prcMonitorList = ExAllocatePoolWithTag(PagedPool, sizeof (RECT) * dwListSize, USERTAG_MONITORRECTS); + if (prcMonitorList == NULL) + { EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); - numMonitors = -1; goto cleanup; } }
- /* 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); - ExFreePoolWithTag(safeHMonitorList, USERTAG_MONITORRECTS); - if (!NT_SUCCESS(status)) - { - ExFreePoolWithTag(safeRectList, USERTAG_MONITORRECTS); - SetLastNtError(status); - numMonitors = -1; + /* 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 (monitorRectList != NULL && listSize != 0) - { - status = MmCopyToCaller(monitorRectList, safeRectList, sizeof (RECT) * listSize); - ExFreePoolWithTag(safeRectList, USERTAG_MONITORRECTS); - if (!NT_SUCCESS(status)) - { - SetLastNtError(status); - numMonitors = -1; - } - } + 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 numMonitors; + return iRet; }
/* NtUserGetMonitorInfo @@ -602,7 +607,7 @@ * hMonitor * Handle to a monitor for which to get information * - * pMonitorInfo + * 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 @@ -621,77 +626,80 @@ APIENTRY NtUserGetMonitorInfo( IN HMONITOR hMonitor, - OUT LPMONITORINFO pMonitorInfo) -{ - PMONITOR Monitor; + OUT LPMONITORINFO pMonitorInfoUnsafe) +{ + PMONITOR pMonitor; MONITORINFOEXW MonitorInfo; NTSTATUS Status; - DECLARE_RETURN(BOOL); + BOOL bRet = FALSE;
TRACE("Enter NtUserGetMonitorInfo\n"); UserEnterShared();
- /* get monitor object */ - if (!(Monitor = UserGetMonitorObject(hMonitor))) + /* Get monitor object */ + pMonitor = UserGetMonitorObject(hMonitor); + if (!pMonitor) { TRACE("Couldnt find monitor 0x%lx\n", hMonitor); - RETURN(FALSE); - } - - if(pMonitorInfo == NULL) + goto cleanup; + } + + /* Check if pMonitorInfoUnsafe is valid */ + if(pMonitorInfoUnsafe == NULL) { SetLastNtError(STATUS_INVALID_PARAMETER); - RETURN(FALSE); - } - - /* get size of pMonitorInfo */ - Status = MmCopyFromCaller(&MonitorInfo.cbSize, &pMonitorInfo->cbSize, sizeof (MonitorInfo.cbSize)); + goto cleanup; + } + + /* Get size of pMonitorInfoUnsafe */ + Status = MmCopyFromCaller(&MonitorInfo.cbSize, &pMonitorInfoUnsafe->cbSize, sizeof(MonitorInfo.cbSize)); if (!NT_SUCCESS(Status)) { SetLastNtError(Status); - RETURN(FALSE); - } - if ((MonitorInfo.cbSize != sizeof (MONITORINFO)) && - (MonitorInfo.cbSize != sizeof (MONITORINFOEXW))) + goto cleanup; + } + + /* Check if size of struct is valid */ + 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; + goto cleanup; + } + + /* Fill monitor info */ + MonitorInfo.rcMonitor = pMonitor->rcMonitor; + MonitorInfo.rcWork = pMonitor->rcWork; MonitorInfo.dwFlags = 0; - - if (Monitor->IsPrimary) + if (pMonitor->IsPrimary) MonitorInfo.dwFlags |= MONITORINFOF_PRIMARY;
- /* fill device name */ - if (MonitorInfo.cbSize == sizeof (MONITORINFOEXW)) - { - RtlStringCbCopyNW(MonitorInfo.szDevice, + /* Fill device name */ + if (MonitorInfo.cbSize == sizeof(MONITORINFOEXW)) + { + RtlStringCbCopyNExW(MonitorInfo.szDevice, sizeof(MonitorInfo.szDevice), - Monitor->DeviceName.Buffer, - Monitor->DeviceName.Length); - } - - /* output data */ - Status = MmCopyToCaller(pMonitorInfo, &MonitorInfo, MonitorInfo.cbSize); + pMonitor->DeviceName.Buffer, + pMonitor->DeviceName.Length, + 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); - RETURN(FALSE); + goto cleanup; }
TRACE("GetMonitorInfo: success\n"); - - RETURN(TRUE); - -CLEANUP: - TRACE("Leave NtUserGetMonitorInfo, ret=%i\n",_ret_); + bRet = TRUE; + +cleanup: + TRACE("Leave NtUserGetMonitorInfo, ret=%i\n", bRet); UserLeave(); - END_CLEANUP; + return bRet; }
/* NtUserMonitorFromPoint @@ -700,7 +708,7 @@ * * Arguments * - * point + * pt * Point for which to find monitor * * dwFlags @@ -713,25 +721,32 @@ HMONITOR APIENTRY NtUserMonitorFromPoint( - IN POINT point, + IN POINT pt, IN DWORD dwFlags) { - INT NumMonitors; - RECTL InRect; + INT cMonitors; + RECTL rc; HMONITOR hMonitor = NULL;
- /* fill inRect (bottom-right exclusive) */ - InRect.left = point.x; - InRect.right = point.x + 1; - InRect.top = point.y; - InRect.bottom = point.y + 1; + /* Check if flags are valid */ + if (dwFlags != MONITOR_DEFAULTTONULL && + dwFlags != MONITOR_DEFAULTTOPRIMARY && + dwFlags != MONITOR_DEFAULTTONEAREST) + { + EngSetLastError(ERROR_INVALID_FLAGS); + return NULL; + } + + /* Fill rect (bottom-right exclusive) */ + rc.left = pt.x; + rc.right = pt.x + 1; + rc.top = pt.y; + rc.bottom = pt.y + 1;
UserEnterShared();
- /* find intersecting monitor */ - NumMonitors = IntGetMonitorsFromRect(&InRect, &hMonitor, NULL, 1, dwFlags); - if (NumMonitors < 0) - hMonitor = NULL; + /* Find intersecting monitor */ + cMonitors = IntGetMonitorsFromRect(&rc, &hMonitor, NULL, 1, dwFlags);
UserLeave(); return hMonitor; @@ -744,7 +759,7 @@ * * Arguments * - * pRect + * pRectUnsafe * Pointer to a RECT for which to find monitor * * dwFlags @@ -757,78 +772,87 @@ HMONITOR APIENTRY NtUserMonitorFromRect( - IN LPCRECTL pRect, + IN LPCRECTL pRectUnsafe, IN DWORD dwFlags) { - ULONG numMonitors, iLargestArea = 0, i; - PRECTL rectList = NULL; - HMONITOR *hMonitorList = NULL; + ULONG cMonitors, LargestArea = 0, i; + PRECTL prcMonitorList = NULL; + HMONITOR *phMonitorList = NULL; HMONITOR hMonitor = NULL; - RECTL rect; - NTSTATUS status; - - /* get rect */ - status = MmCopyFromCaller(&rect, pRect, sizeof (RECT)); - if (!NT_SUCCESS(status)) - { - SetLastNtError(status); - return (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 */ - numMonitors = IntGetMonitorsFromRect(&rect, &hMonitor, NULL, 1, dwFlags); - if (numMonitors <= 1) - { + /* Find intersecting monitors */ + cMonitors = IntGetMonitorsFromRect(&Rect, &hMonitor, NULL, 1, dwFlags); + if (cMonitors <= 1) + { + /* No or one monitor found. Just return handle. */ goto cleanup; }
- hMonitorList = ExAllocatePoolWithTag(PagedPool, - sizeof(HMONITOR) * numMonitors, - USERTAG_MONITORRECTS); - if (hMonitorList == NULL) + /* 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); - hMonitor = NULL; goto cleanup; }
- rectList = ExAllocatePoolWithTag(PagedPool, - sizeof(RECT) * numMonitors, - USERTAG_MONITORRECTS); - if (rectList == NULL) + prcMonitorList = ExAllocatePoolWithTag(PagedPool, + sizeof(RECT) * cMonitors, + USERTAG_MONITORRECTS); + if (prcMonitorList == NULL) { EngSetLastError(ERROR_NOT_ENOUGH_MEMORY); - hMonitor = NULL; goto cleanup; }
- /* get intersecting monitors */ - numMonitors = IntGetMonitorsFromRect(&rect, hMonitorList, rectList, - numMonitors, 0); - if (numMonitors == 0) - { - hMonitor = NULL; - goto cleanup; - } - - /* 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]; + /* 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 (hMonitorList) - ExFreePoolWithTag(hMonitorList, USERTAG_MONITORRECTS); - if (rectList) - ExFreePoolWithTag(rectList, USERTAG_MONITORRECTS); + if (phMonitorList) + ExFreePoolWithTag(phMonitorList, USERTAG_MONITORRECTS); + if (prcMonitorList) + ExFreePoolWithTag(prcMonitorList, USERTAG_MONITORRECTS); UserLeave();
return hMonitor; @@ -841,33 +865,41 @@ IN HWND hWnd, IN DWORD dwFlags) { - PWND Window; + PWND pWnd; HMONITOR hMonitor = NULL; - RECTL Rect; - DECLARE_RETURN(HMONITOR); + RECTL Rect = {0, 0, 0, 0};
TRACE("Enter NtUserMonitorFromWindow\n"); + + /* Check if flags are valid */ + if (dwFlags != MONITOR_DEFAULTTONULL && + dwFlags != MONITOR_DEFAULTTOPRIMARY && + dwFlags != MONITOR_DEFAULTTONEAREST) + { + EngSetLastError(ERROR_INVALID_FLAGS); + return NULL; + } + UserEnterShared();
- if (!(Window = UserGetWindowObject(hWnd))) - { - if (dwFlags == MONITOR_DEFAULTTONULL) - { - RETURN(hMonitor); - } - IntGetMonitorsFromRect(NULL, &hMonitor, NULL, 1, dwFlags); - RETURN(hMonitor); - } - - Rect.left = Rect.right = Window->rcWindow.left; - Rect.top = Rect.bottom = Window->rcWindow.bottom; - + /* If window is given, use it first */ + if (hWnd) + { + /* Get window object */ + pWnd = UserGetWindowObject(hWnd); + if (!pWnd) + goto cleanup; + + /* Find only monitors which have intersection with given window */ + Rect.left = Rect.right = pWnd->rcWindow.left; + Rect.top = Rect.bottom = pWnd->rcWindow.bottom; + } + + /* Find monitors now */ IntGetMonitorsFromRect(&Rect, &hMonitor, NULL, 1, dwFlags);
- RETURN(hMonitor); - -CLEANUP: - TRACE("Leave NtUserMonitorFromWindow, ret=%i\n",_ret_); +cleanup: + TRACE("Leave NtUserMonitorFromWindow, ret=%p\n", hMonitor); UserLeave(); - END_CLEANUP; -} + return hMonitor; +}