2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: pMonitor support
5 * FILE: subsys/win32k/ntuser/monitor.c
6 * PROGRAMERS: Anich Gregor (blight@blight.eu.org)
7 * Rafal Harabien (rafalh@reactos.org)
11 DBG_DEFAULT_CHANNEL(UserMonitor
);
16 /* GLOBALS *******************************************************************/
18 /* List of monitors */
19 static PMONITOR gMonitorList
= NULL
;
21 /* PRIVATE FUNCTIONS **********************************************************/
23 /* IntCreateMonitorObject
28 * If the function succeeds a pointer to a MONITOR is returned. On failure
33 IntCreateMonitorObject()
35 return UserCreateObject(gHandleTable
, NULL
, NULL
, NULL
, TYPE_MONITOR
, sizeof(MONITOR
));
38 /* IntDestroyMonitorObject
41 * You have to be the owner of the monitors lock to safely destroy it.
46 * Pointer to the MONITOR which shall be deleted
50 IntDestroyMonitorObject(IN PMONITOR pMonitor
)
52 /* Remove monitor region */
53 if (pMonitor
->hrgnMonitor
)
55 GreSetObjectOwner(pMonitor
->hrgnMonitor
, GDI_OBJ_HMGR_POWNED
);
56 GreDeleteObject(pMonitor
->hrgnMonitor
);
59 /* Destroy monitor object */
60 UserDereferenceObject(pMonitor
);
61 UserDeleteObject(UserHMGetHandle(pMonitor
), TYPE_MONITOR
);
64 /* UserGetMonitorObject
66 * Returns monitor object from handle or sets last error if handle is invalid
71 * Handle of MONITOR object
74 UserGetMonitorObject(IN HMONITOR hMonitor
)
80 EngSetLastError(ERROR_INVALID_MONITOR_HANDLE
);
84 pMonitor
= (PMONITOR
)UserGetObject(gHandleTable
, hMonitor
, TYPE_MONITOR
);
87 EngSetLastError(ERROR_INVALID_MONITOR_HANDLE
);
94 /* UserGetPrimaryMonitor
96 * Returns a PMONITOR for the primary monitor
102 UserGetPrimaryMonitor()
106 /* Find primary monitor */
107 for (pMonitor
= gMonitorList
; pMonitor
!= NULL
; pMonitor
= pMonitor
->pMonitorNext
)
109 if (pMonitor
->IsPrimary
)
118 * Creates a new MONITOR and appends it to the list of monitors.
122 * pGdiDevice Pointer to the PDEVOBJ onto which the monitor was attached
123 * DisplayNumber Display Number (starting with 0)
129 UserAttachMonitor(IN HDEV hDev
)
133 TRACE("Attaching monitor...\n");
135 /* Create new monitor object */
136 pMonitor
= IntCreateMonitorObject();
137 if (pMonitor
== NULL
)
139 TRACE("Couldnt create monitor object\n");
140 return STATUS_INSUFFICIENT_RESOURCES
;
143 pMonitor
->hDev
= hDev
;
144 pMonitor
->cWndStack
= 0;
146 if (gMonitorList
== NULL
)
148 TRACE("Primary monitor is beeing attached\n");
149 pMonitor
->IsPrimary
= TRUE
;
150 gMonitorList
= pMonitor
;
154 PMONITOR pmonLast
= gMonitorList
;
155 TRACE("Additional monitor is beeing attached\n");
156 while (pmonLast
->pMonitorNext
!= NULL
)
157 pmonLast
= pmonLast
->pMonitorNext
;
159 pmonLast
->pMonitorNext
= pMonitor
;
162 UserUpdateMonitorSize(hDev
);
164 return STATUS_SUCCESS
;
169 * Deletes a MONITOR and removes it from the list of monitors.
173 * pGdiDevice Pointer to the PDEVOBJ from which the monitor was detached
179 UserDetachMonitor(IN HDEV hDev
)
181 PMONITOR pMonitor
= gMonitorList
, *pLink
= &gMonitorList
;
183 /* Find monitor attached to given device */
184 while (pMonitor
!= NULL
)
186 if (pMonitor
->hDev
== hDev
)
189 pLink
= &pMonitor
->pMonitorNext
;
190 pMonitor
= pMonitor
->pMonitorNext
;
193 if (pMonitor
== NULL
)
195 /* No monitor has been found */
196 return STATUS_INVALID_PARAMETER
;
199 /* We destroy primary monitor - set next as primary */
200 if (pMonitor
->IsPrimary
&& pMonitor
->pMonitorNext
!= NULL
)
201 pMonitor
->pMonitorNext
->IsPrimary
= TRUE
;
203 /* Update Next ptr in previous monitor */
204 *pLink
= pMonitor
->pMonitorNext
;
206 /* Finally destroy monitor */
207 IntDestroyMonitorObject(pMonitor
);
209 return STATUS_SUCCESS
;
212 /* UserUpdateMonitorSize
214 * Reset size of the monitor using atached device
219 * pGdiDevice Pointer to the PDEVOBJ, which size has changed
225 UserUpdateMonitorSize(IN HDEV hDev
)
230 /* Find monitor attached to given device */
231 for (pMonitor
= gMonitorList
; pMonitor
!= NULL
; pMonitor
= pMonitor
->pMonitorNext
)
233 if (pMonitor
->hDev
== hDev
)
237 if (pMonitor
== NULL
)
239 /* No monitor has been found */
240 return STATUS_INVALID_PARAMETER
;
243 /* Get the size of the hdev */
244 PDEVOBJ_sizl((PPDEVOBJ
)hDev
, &DeviceSize
);
246 /* Update monitor size */
247 pMonitor
->rcMonitor
.left
= 0;
248 pMonitor
->rcMonitor
.top
= 0;
249 pMonitor
->rcMonitor
.right
= pMonitor
->rcMonitor
.left
+ DeviceSize
.cx
;
250 pMonitor
->rcMonitor
.bottom
= pMonitor
->rcMonitor
.top
+ DeviceSize
.cy
;
251 pMonitor
->rcWork
= pMonitor
->rcMonitor
;
253 /* Destroy monitor region... */
254 if (pMonitor
->hrgnMonitor
)
256 GreSetObjectOwner(pMonitor
->hrgnMonitor
, GDI_OBJ_HMGR_POWNED
);
257 GreDeleteObject(pMonitor
->hrgnMonitor
);
260 /* ...and create new one */
261 pMonitor
->hrgnMonitor
= IntSysCreateRectRgnIndirect(&pMonitor
->rcMonitor
);
262 if (pMonitor
->hrgnMonitor
)
263 IntGdiSetRegionOwner(pMonitor
->hrgnMonitor
, GDI_OBJ_HMGR_PUBLIC
);
265 return STATUS_SUCCESS
;
268 /* IntGetMonitorsFromRect
270 * Returns a list of monitor handles/rectangles. The rectangles in the list are
271 * the areas of intersection with the monitors.
276 * Rectangle in desktop coordinates. If this is NULL all monitors are
277 * returned and the rect list is filled with the sizes of the monitors.
280 * Pointer to an array of HMONITOR which is filled with monitor handles.
284 * Pointer to an array of RECT which is filled with intersection rects in
285 * desktop coordinates.
286 * Can be NULL, will be ignored if no intersecting monitor is found and
287 * flags is MONITOR_DEFAULTTONEAREST
290 * Size of the phMonitorList and prcMonitorList arguments. If this is zero
291 * phMonitorList and prcMonitorList are ignored.
294 * Either 0 or MONITOR_DEFAULTTONEAREST (ignored if rect is NULL)
297 * The number of monitors which intersect the specified region.
301 IntGetMonitorsFromRect(OPTIONAL IN LPCRECTL pRect
,
302 OPTIONAL OUT HMONITOR
*phMonitorList
,
303 OPTIONAL OUT PRECTL prcMonitorList
,
304 OPTIONAL IN DWORD dwListSize
,
305 OPTIONAL IN DWORD dwFlags
)
307 PMONITOR pMonitor
, pNearestMonitor
= NULL
, pPrimaryMonitor
= NULL
;
309 ULONG iNearestDistance
= 0xffffffff;
311 /* Find monitors which intersects the rectangle */
312 for (pMonitor
= gMonitorList
; pMonitor
!= NULL
; pMonitor
= pMonitor
->pMonitorNext
)
314 RECTL MonitorRect
, IntersectionRect
;
316 MonitorRect
= pMonitor
->rcMonitor
;
318 TRACE("MonitorRect: left = %d, top = %d, right = %d, bottom = %d\n",
319 MonitorRect
.left
, MonitorRect
.top
, MonitorRect
.right
, MonitorRect
.bottom
);
321 /* Save primary monitor for later usage */
322 if (dwFlags
== MONITOR_DEFAULTTOPRIMARY
&& pMonitor
->IsPrimary
)
323 pPrimaryMonitor
= pMonitor
;
325 /* Check if a rect is given */
328 /* No rect given, so use the full monitor rect */
329 IntersectionRect
= MonitorRect
;
331 /* We have a rect, calculate intersection */
332 else if (!RECTL_bIntersectRect(&IntersectionRect
, &MonitorRect
, pRect
))
334 /* Rects did not intersect */
335 if (dwFlags
== MONITOR_DEFAULTTONEAREST
)
337 ULONG cx
, cy
, iDistance
;
339 /* Get x and y distance */
340 cx
= min(abs(MonitorRect
.left
- pRect
->right
),
341 abs(pRect
->left
- MonitorRect
.right
));
342 cy
= min(abs(MonitorRect
.top
- pRect
->bottom
),
343 abs(pRect
->top
- MonitorRect
.bottom
));
345 /* Calculate distance square */
346 iDistance
= cx
* cx
+ cy
* cy
;
348 /* Check if this is the new nearest monitor */
349 if (iDistance
< iNearestDistance
)
351 iNearestDistance
= iDistance
;
352 pNearestMonitor
= pMonitor
;
359 /* Check if there's space in the buffer */
360 if (cMonitors
< dwListSize
)
362 /* Save monitor data */
363 if (phMonitorList
!= NULL
)
364 phMonitorList
[cMonitors
] = UserHMGetHandle(pMonitor
);
365 if (prcMonitorList
!= NULL
)
366 prcMonitorList
[cMonitors
] = IntersectionRect
;
369 /* Increase count of found monitors */
373 /* Nothing has been found? */
376 /* Check if we shall default to the nearest monitor */
377 if (dwFlags
== MONITOR_DEFAULTTONEAREST
&& pNearestMonitor
)
379 if (phMonitorList
&& dwListSize
> 0)
380 phMonitorList
[cMonitors
] = UserHMGetHandle(pNearestMonitor
);
383 /* Check if we shall default to the primary monitor */
384 else if (dwFlags
== MONITOR_DEFAULTTOPRIMARY
&& pPrimaryMonitor
)
386 if (phMonitorList
!= NULL
&& dwListSize
> 0)
387 phMonitorList
[cMonitors
] = UserHMGetHandle(pPrimaryMonitor
);
400 ULONG cMonitors
, LargestArea
= 0, i
;
401 PRECTL prcMonitorList
= NULL
;
402 HMONITOR
*phMonitorList
= NULL
;
403 HMONITOR hMonitor
= NULL
;
405 /* Check if flags are valid */
406 if (dwFlags
!= MONITOR_DEFAULTTONULL
&&
407 dwFlags
!= MONITOR_DEFAULTTOPRIMARY
&&
408 dwFlags
!= MONITOR_DEFAULTTONEAREST
)
410 EngSetLastError(ERROR_INVALID_FLAGS
);
414 /* Find intersecting monitors */
415 cMonitors
= IntGetMonitorsFromRect(pRect
, &hMonitor
, NULL
, 1, dwFlags
);
418 /* No or one monitor found. Just return handle. */
422 /* There is more than one monitor. Find monitor with largest intersection.
423 Temporary reset hMonitor */
426 /* Allocate helper buffers */
427 phMonitorList
= ExAllocatePoolWithTag(PagedPool
,
428 sizeof(HMONITOR
) * cMonitors
,
429 USERTAG_MONITORRECTS
);
430 if (phMonitorList
== NULL
)
432 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
436 prcMonitorList
= ExAllocatePoolWithTag(PagedPool
,
437 sizeof(RECT
) * cMonitors
,
438 USERTAG_MONITORRECTS
);
439 if (prcMonitorList
== NULL
)
441 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
445 /* Get intersecting monitors again but now with rectangle list */
446 cMonitors
= IntGetMonitorsFromRect(pRect
, phMonitorList
, prcMonitorList
,
449 /* Find largest intersection */
450 for (i
= 0; i
< cMonitors
; i
++)
452 ULONG Area
= (prcMonitorList
[i
].right
- prcMonitorList
[i
].left
) *
453 (prcMonitorList
[i
].bottom
- prcMonitorList
[i
].top
);
454 if (Area
>= LargestArea
)
456 hMonitor
= phMonitorList
[i
];
463 ExFreePoolWithTag(phMonitorList
, USERTAG_MONITORRECTS
);
465 ExFreePoolWithTag(prcMonitorList
, USERTAG_MONITORRECTS
);
467 return UserGetMonitorObject(hMonitor
);
472 UserMonitorFromPoint(
477 HMONITOR hMonitor
= NULL
;
479 /* Check if flags are valid */
480 if (dwFlags
!= MONITOR_DEFAULTTONULL
&&
481 dwFlags
!= MONITOR_DEFAULTTOPRIMARY
&&
482 dwFlags
!= MONITOR_DEFAULTTONEAREST
)
484 EngSetLastError(ERROR_INVALID_FLAGS
);
488 /* Fill rect (bottom-right exclusive) */
492 rc
.bottom
= pt
.y
+ 1;
494 /* Find intersecting monitor */
495 IntGetMonitorsFromRect(&rc
, &hMonitor
, NULL
, 1, dwFlags
);
497 return UserGetMonitorObject(hMonitor
);
500 /* PUBLIC FUNCTIONS ***********************************************************/
502 /* NtUserEnumDisplayMonitors
504 * Enumerates display monitors which intersect the given HDC/cliprect
509 * Handle to a DC for which to enum intersecting monitors. If this is NULL
510 * it returns all monitors which are part of the current virtual screen.
513 * Clipping rectangle with coordinate system origin at the DCs origin if the
514 * given HDC is not NULL or in virtual screen coordinated if it is NULL.
517 * phUnsafeMonitorList
518 * Pointer to an array of HMONITOR which is filled with monitor handles.
521 * prcUnsafeMonitorList
522 * Pointer to an array of RECT which is filled with intersection rectangles.
526 * Size of the hMonitorList and monitorRectList arguments. If this is zero
527 * hMonitorList and monitorRectList are ignored.
530 * The number of monitors which intersect the specified region or -1 on failure.
534 NtUserEnumDisplayMonitors(
536 OPTIONAL IN LPCRECTL pUnsafeRect
,
537 OPTIONAL OUT HMONITOR
*phUnsafeMonitorList
,
538 OPTIONAL OUT PRECTL prcUnsafeMonitorList
,
539 OPTIONAL IN DWORD dwListSize
)
541 INT cMonitors
, iRet
= -1, i
;
542 HMONITOR
*phMonitorList
= NULL
;
543 PRECTL prcMonitorList
= NULL
;
549 if (pUnsafeRect
!= NULL
)
551 Status
= MmCopyFromCaller(&rc
, pUnsafeRect
, sizeof(RECT
));
552 if (!NT_SUCCESS(Status
))
554 TRACE("MmCopyFromCaller() failed!\n");
555 SetLastNtError(Status
);
565 /* Get visible region bounding rect */
566 pDc
= DC_LockDc(hdc
);
569 TRACE("DC_LockDc() failed!\n");
570 /* FIXME: setlasterror? */
573 iRgnType
= REGION_GetRgnBox(pDc
->prgnVis
, &DcRect
);
578 TRACE("NtGdiGetRgnBox() failed!\n");
581 if (iRgnType
== NULLREGION
)
583 if (iRgnType
== COMPLEXREGION
)
588 /* If hdc and pRect are given the area of interest is pRect with
589 coordinate origin at the DC position */
590 if (pUnsafeRect
!= NULL
)
592 rc
.left
+= DcRect
.left
;
593 rc
.right
+= DcRect
.left
;
594 rc
.top
+= DcRect
.top
;
595 rc
.bottom
+= DcRect
.top
;
597 /* If hdc is given and pRect is not the area of interest is the
598 bounding rect of hdc */
605 if (hdc
== NULL
&& pUnsafeRect
== NULL
)
612 /* Find intersecting monitors */
613 cMonitors
= IntGetMonitorsFromRect(pRect
, NULL
, NULL
, 0, MONITOR_DEFAULTTONULL
);
614 if (cMonitors
== 0 || dwListSize
== 0 ||
615 (phUnsafeMonitorList
== NULL
&& prcUnsafeMonitorList
== NULL
))
617 /* Simple case - just return monitors count */
618 TRACE("cMonitors = %d\n", cMonitors
);
623 /* Allocate safe buffers */
624 if (phUnsafeMonitorList
!= NULL
&& dwListSize
!= 0)
626 phMonitorList
= ExAllocatePoolWithTag(PagedPool
, sizeof (HMONITOR
) * dwListSize
, USERTAG_MONITORRECTS
);
627 if (phMonitorList
== NULL
)
629 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
633 if (prcUnsafeMonitorList
!= NULL
&& dwListSize
!= 0)
635 prcMonitorList
= ExAllocatePoolWithTag(PagedPool
, sizeof (RECT
) * dwListSize
, USERTAG_MONITORRECTS
);
636 if (prcMonitorList
== NULL
)
638 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
643 /* Get intersecting monitors */
644 cMonitors
= IntGetMonitorsFromRect(pRect
, phMonitorList
, prcMonitorList
,
645 dwListSize
, MONITOR_DEFAULTTONULL
);
647 if (hdc
!= NULL
&& pRect
!= NULL
&& prcMonitorList
!= NULL
)
648 for (i
= 0; i
< cMonitors
; i
++)
650 prcMonitorList
[i
].left
-= DcRect
.left
;
651 prcMonitorList
[i
].right
-= DcRect
.left
;
652 prcMonitorList
[i
].top
-= DcRect
.top
;
653 prcMonitorList
[i
].bottom
-= DcRect
.top
;
657 if (phUnsafeMonitorList
!= NULL
&& dwListSize
!= 0)
659 Status
= MmCopyToCaller(phUnsafeMonitorList
, phMonitorList
, sizeof(HMONITOR
) * dwListSize
);
660 if (!NT_SUCCESS(Status
))
662 SetLastNtError(Status
);
666 if (prcUnsafeMonitorList
!= NULL
&& dwListSize
!= 0)
668 Status
= MmCopyToCaller(prcUnsafeMonitorList
, prcMonitorList
, sizeof(RECT
) * dwListSize
);
669 if (!NT_SUCCESS(Status
))
671 SetLastNtError(Status
);
676 /* Return monitors count on success */
681 ExFreePoolWithTag(phMonitorList
, USERTAG_MONITORRECTS
);
683 ExFreePoolWithTag(prcMonitorList
, USERTAG_MONITORRECTS
);
689 /* NtUserGetMonitorInfo
691 * Retrieves information about a given monitor
696 * Handle to a monitor for which to get information
699 * Pointer to a MONITORINFO struct which is filled with the information.
700 * The cbSize member must be set to sizeof(MONITORINFO) or
701 * sizeof(MONITORINFOEX). Even if set to sizeof(MONITORINFOEX) only parts
702 * from MONITORINFO will be filled.
705 * Pointer to a UNICODE_STRING which will receive the device's name. The
706 * length should be CCHDEVICENAME
710 * TRUE on success; FALSE on failure (calls SetLastNtError())
715 NtUserGetMonitorInfo(
716 IN HMONITOR hMonitor
,
717 OUT LPMONITORINFO pMonitorInfoUnsafe
)
720 MONITORINFOEXW MonitorInfo
;
723 PWCHAR pwstrDeviceName
;
725 TRACE("Enter NtUserGetMonitorInfo\n");
728 /* Get monitor object */
729 pMonitor
= UserGetMonitorObject(hMonitor
);
732 TRACE("Couldnt find monitor %p\n", hMonitor
);
736 /* Check if pMonitorInfoUnsafe is valid */
737 if(pMonitorInfoUnsafe
== NULL
)
739 SetLastNtError(STATUS_INVALID_PARAMETER
);
743 pwstrDeviceName
= ((PPDEVOBJ
)(pMonitor
->hDev
))->pGraphicsDevice
->szWinDeviceName
;
745 /* Get size of pMonitorInfoUnsafe */
746 Status
= MmCopyFromCaller(&MonitorInfo
.cbSize
, &pMonitorInfoUnsafe
->cbSize
, sizeof(MonitorInfo
.cbSize
));
747 if (!NT_SUCCESS(Status
))
749 SetLastNtError(Status
);
753 /* Check if size of struct is valid */
754 if (MonitorInfo
.cbSize
!= sizeof(MONITORINFO
) &&
755 MonitorInfo
.cbSize
!= sizeof(MONITORINFOEXW
))
757 SetLastNtError(STATUS_INVALID_PARAMETER
);
761 /* Fill monitor info */
762 MonitorInfo
.rcMonitor
= pMonitor
->rcMonitor
;
763 MonitorInfo
.rcWork
= pMonitor
->rcWork
;
764 MonitorInfo
.dwFlags
= 0;
765 if (pMonitor
->IsPrimary
)
766 MonitorInfo
.dwFlags
|= MONITORINFOF_PRIMARY
;
768 /* Fill device name */
769 if (MonitorInfo
.cbSize
== sizeof(MONITORINFOEXW
))
771 RtlStringCbCopyNExW(MonitorInfo
.szDevice
,
772 sizeof(MonitorInfo
.szDevice
),
774 (wcslen(pwstrDeviceName
)+1) * sizeof(WCHAR
),
775 NULL
, NULL
, STRSAFE_FILL_BEHIND_NULL
);
779 Status
= MmCopyToCaller(pMonitorInfoUnsafe
, &MonitorInfo
, MonitorInfo
.cbSize
);
780 if (!NT_SUCCESS(Status
))
782 TRACE("GetMonitorInfo: MmCopyToCaller failed\n");
783 SetLastNtError(Status
);
787 TRACE("GetMonitorInfo: success\n");
791 TRACE("Leave NtUserGetMonitorInfo, ret=%i\n", bRet
);
796 /* NtUserMonitorFromPoint
798 * Returns a handle to the monitor containing the given point.
803 * Point for which to find monitor
806 * Specifies the behaviour if the point isn't on any of the monitors.
809 * If the point is found a handle to the monitor is returned; if not the
810 * return value depends on dwFlags
814 NtUserMonitorFromPoint(
819 HMONITOR hMonitor
= NULL
;
821 /* Check if flags are valid */
822 if (dwFlags
!= MONITOR_DEFAULTTONULL
&&
823 dwFlags
!= MONITOR_DEFAULTTOPRIMARY
&&
824 dwFlags
!= MONITOR_DEFAULTTONEAREST
)
826 EngSetLastError(ERROR_INVALID_FLAGS
);
830 /* Fill rect (bottom-right exclusive) */
834 rc
.bottom
= pt
.y
+ 1;
838 /* Find intersecting monitor */
839 IntGetMonitorsFromRect(&rc
, &hMonitor
, NULL
, 1, dwFlags
);
845 /* NtUserMonitorFromRect
847 * Returns a handle to the monitor having the largest intersection with a
853 * Pointer to a RECT for which to find monitor
856 * Specifies the behaviour if no monitor intersects the given rect
859 * If a monitor intersects the rect a handle to it is returned; if not the
860 * return value depends on dwFlags
864 NtUserMonitorFromRect(
865 IN LPCRECTL pRectUnsafe
,
868 ULONG cMonitors
, LargestArea
= 0, i
;
869 PRECTL prcMonitorList
= NULL
;
870 HMONITOR
*phMonitorList
= NULL
;
871 HMONITOR hMonitor
= NULL
;
875 /* Check if flags are valid */
876 if (dwFlags
!= MONITOR_DEFAULTTONULL
&&
877 dwFlags
!= MONITOR_DEFAULTTOPRIMARY
&&
878 dwFlags
!= MONITOR_DEFAULTTONEAREST
)
880 EngSetLastError(ERROR_INVALID_FLAGS
);
884 /* Copy rectangle to safe buffer */
885 Status
= MmCopyFromCaller(&Rect
, pRectUnsafe
, sizeof (RECT
));
886 if (!NT_SUCCESS(Status
))
888 SetLastNtError(Status
);
894 /* Find intersecting monitors */
895 cMonitors
= IntGetMonitorsFromRect(&Rect
, &hMonitor
, NULL
, 1, dwFlags
);
898 /* No or one monitor found. Just return handle. */
902 /* There is more than one monitor. Find monitor with largest intersection.
903 Temporary reset hMonitor */
906 /* Allocate helper buffers */
907 phMonitorList
= ExAllocatePoolWithTag(PagedPool
,
908 sizeof(HMONITOR
) * cMonitors
,
909 USERTAG_MONITORRECTS
);
910 if (phMonitorList
== NULL
)
912 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
916 prcMonitorList
= ExAllocatePoolWithTag(PagedPool
,
917 sizeof(RECT
) * cMonitors
,
918 USERTAG_MONITORRECTS
);
919 if (prcMonitorList
== NULL
)
921 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
925 /* Get intersecting monitors again but now with rectangle list */
926 cMonitors
= IntGetMonitorsFromRect(&Rect
, phMonitorList
, prcMonitorList
,
929 /* Find largest intersection */
930 for (i
= 0; i
< cMonitors
; i
++)
932 ULONG Area
= (prcMonitorList
[i
].right
- prcMonitorList
[i
].left
) *
933 (prcMonitorList
[i
].bottom
- prcMonitorList
[i
].top
);
934 if (Area
>= LargestArea
)
936 hMonitor
= phMonitorList
[i
];
943 ExFreePoolWithTag(phMonitorList
, USERTAG_MONITORRECTS
);
945 ExFreePoolWithTag(prcMonitorList
, USERTAG_MONITORRECTS
);
954 NtUserMonitorFromWindow(
959 HMONITOR hMonitor
= NULL
;
960 RECTL Rect
= {0, 0, 0, 0};
962 TRACE("Enter NtUserMonitorFromWindow\n");
964 /* Check if flags are valid */
965 if (dwFlags
!= MONITOR_DEFAULTTONULL
&&
966 dwFlags
!= MONITOR_DEFAULTTOPRIMARY
&&
967 dwFlags
!= MONITOR_DEFAULTTONEAREST
)
969 EngSetLastError(ERROR_INVALID_FLAGS
);
975 /* If window is given, use it first */
978 /* Get window object */
979 pWnd
= UserGetWindowObject(hWnd
);
983 /* Find only monitors which have intersection with given window */
984 Rect
.left
= Rect
.right
= pWnd
->rcWindow
.left
;
985 Rect
.top
= Rect
.bottom
= pWnd
->rcWindow
.bottom
;
988 /* Find monitors now */
989 IntGetMonitorsFromRect(&Rect
, &hMonitor
, NULL
, 1, dwFlags
);
992 TRACE("Leave NtUserMonitorFromWindow, ret=%p\n", hMonitor
);