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
);
471 /* PUBLIC FUNCTIONS ***********************************************************/
473 /* NtUserEnumDisplayMonitors
475 * Enumerates display monitors which intersect the given HDC/cliprect
480 * Handle to a DC for which to enum intersecting monitors. If this is NULL
481 * it returns all monitors which are part of the current virtual screen.
484 * Clipping rectangle with coordinate system origin at the DCs origin if the
485 * given HDC is not NULL or in virtual screen coordinated if it is NULL.
488 * phUnsafeMonitorList
489 * Pointer to an array of HMONITOR which is filled with monitor handles.
492 * prcUnsafeMonitorList
493 * Pointer to an array of RECT which is filled with intersection rectangles.
497 * Size of the hMonitorList and monitorRectList arguments. If this is zero
498 * hMonitorList and monitorRectList are ignored.
501 * The number of monitors which intersect the specified region or -1 on failure.
505 NtUserEnumDisplayMonitors(
507 OPTIONAL IN LPCRECTL pUnsafeRect
,
508 OPTIONAL OUT HMONITOR
*phUnsafeMonitorList
,
509 OPTIONAL OUT PRECTL prcUnsafeMonitorList
,
510 OPTIONAL IN DWORD dwListSize
)
512 INT cMonitors
, iRet
= -1, i
;
513 HMONITOR
*phMonitorList
= NULL
;
514 PRECTL prcMonitorList
= NULL
;
520 if (pUnsafeRect
!= NULL
)
522 Status
= MmCopyFromCaller(&rc
, pUnsafeRect
, sizeof(RECT
));
523 if (!NT_SUCCESS(Status
))
525 TRACE("MmCopyFromCaller() failed!\n");
526 SetLastNtError(Status
);
536 /* Get visible region bounding rect */
537 pDc
= DC_LockDc(hdc
);
540 TRACE("DC_LockDc() failed!\n");
541 /* FIXME: setlasterror? */
544 iRgnType
= REGION_GetRgnBox(pDc
->prgnVis
, &DcRect
);
549 TRACE("NtGdiGetRgnBox() failed!\n");
552 if (iRgnType
== NULLREGION
)
554 if (iRgnType
== COMPLEXREGION
)
559 /* If hdc and pRect are given the area of interest is pRect with
560 coordinate origin at the DC position */
561 if (pUnsafeRect
!= NULL
)
563 rc
.left
+= DcRect
.left
;
564 rc
.right
+= DcRect
.left
;
565 rc
.top
+= DcRect
.top
;
566 rc
.bottom
+= DcRect
.top
;
568 /* If hdc is given and pRect is not the area of interest is the
569 bounding rect of hdc */
576 if (hdc
== NULL
&& pUnsafeRect
== NULL
)
583 /* Find intersecting monitors */
584 cMonitors
= IntGetMonitorsFromRect(pRect
, NULL
, NULL
, 0, MONITOR_DEFAULTTONULL
);
585 if (cMonitors
== 0 || dwListSize
== 0 ||
586 (phUnsafeMonitorList
== NULL
&& prcUnsafeMonitorList
== NULL
))
588 /* Simple case - just return monitors count */
589 TRACE("cMonitors = %d\n", cMonitors
);
594 /* Allocate safe buffers */
595 if (phUnsafeMonitorList
!= NULL
&& dwListSize
!= 0)
597 phMonitorList
= ExAllocatePoolWithTag(PagedPool
, sizeof (HMONITOR
) * dwListSize
, USERTAG_MONITORRECTS
);
598 if (phMonitorList
== NULL
)
600 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
604 if (prcUnsafeMonitorList
!= NULL
&& dwListSize
!= 0)
606 prcMonitorList
= ExAllocatePoolWithTag(PagedPool
, sizeof (RECT
) * dwListSize
, USERTAG_MONITORRECTS
);
607 if (prcMonitorList
== NULL
)
609 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
614 /* Get intersecting monitors */
615 cMonitors
= IntGetMonitorsFromRect(pRect
, phMonitorList
, prcMonitorList
,
616 dwListSize
, MONITOR_DEFAULTTONULL
);
618 if (hdc
!= NULL
&& pRect
!= NULL
&& prcMonitorList
!= NULL
)
619 for (i
= 0; i
< cMonitors
; i
++)
621 prcMonitorList
[i
].left
-= DcRect
.left
;
622 prcMonitorList
[i
].right
-= DcRect
.left
;
623 prcMonitorList
[i
].top
-= DcRect
.top
;
624 prcMonitorList
[i
].bottom
-= DcRect
.top
;
628 if (phUnsafeMonitorList
!= NULL
&& dwListSize
!= 0)
630 Status
= MmCopyToCaller(phUnsafeMonitorList
, phMonitorList
, sizeof(HMONITOR
) * dwListSize
);
631 if (!NT_SUCCESS(Status
))
633 SetLastNtError(Status
);
637 if (prcUnsafeMonitorList
!= NULL
&& dwListSize
!= 0)
639 Status
= MmCopyToCaller(prcUnsafeMonitorList
, prcMonitorList
, sizeof(RECT
) * dwListSize
);
640 if (!NT_SUCCESS(Status
))
642 SetLastNtError(Status
);
647 /* Return monitors count on success */
652 ExFreePoolWithTag(phMonitorList
, USERTAG_MONITORRECTS
);
654 ExFreePoolWithTag(prcMonitorList
, USERTAG_MONITORRECTS
);
660 /* NtUserGetMonitorInfo
662 * Retrieves information about a given monitor
667 * Handle to a monitor for which to get information
670 * Pointer to a MONITORINFO struct which is filled with the information.
671 * The cbSize member must be set to sizeof(MONITORINFO) or
672 * sizeof(MONITORINFOEX). Even if set to sizeof(MONITORINFOEX) only parts
673 * from MONITORINFO will be filled.
676 * Pointer to a UNICODE_STRING which will recieve the device's name. The
677 * length should be CCHDEVICENAME
681 * TRUE on success; FALSE on failure (calls SetLastNtError())
686 NtUserGetMonitorInfo(
687 IN HMONITOR hMonitor
,
688 OUT LPMONITORINFO pMonitorInfoUnsafe
)
691 MONITORINFOEXW MonitorInfo
;
694 PWCHAR pwstrDeviceName
;
696 TRACE("Enter NtUserGetMonitorInfo\n");
699 /* Get monitor object */
700 pMonitor
= UserGetMonitorObject(hMonitor
);
703 TRACE("Couldnt find monitor 0x%lx\n", hMonitor
);
707 /* Check if pMonitorInfoUnsafe is valid */
708 if(pMonitorInfoUnsafe
== NULL
)
710 SetLastNtError(STATUS_INVALID_PARAMETER
);
714 pwstrDeviceName
= ((PPDEVOBJ
)(pMonitor
->hDev
))->pGraphicsDevice
->szWinDeviceName
;
716 /* Get size of pMonitorInfoUnsafe */
717 Status
= MmCopyFromCaller(&MonitorInfo
.cbSize
, &pMonitorInfoUnsafe
->cbSize
, sizeof(MonitorInfo
.cbSize
));
718 if (!NT_SUCCESS(Status
))
720 SetLastNtError(Status
);
724 /* Check if size of struct is valid */
725 if (MonitorInfo
.cbSize
!= sizeof(MONITORINFO
) &&
726 MonitorInfo
.cbSize
!= sizeof(MONITORINFOEXW
))
728 SetLastNtError(STATUS_INVALID_PARAMETER
);
732 /* Fill monitor info */
733 MonitorInfo
.rcMonitor
= pMonitor
->rcMonitor
;
734 MonitorInfo
.rcWork
= pMonitor
->rcWork
;
735 MonitorInfo
.dwFlags
= 0;
736 if (pMonitor
->IsPrimary
)
737 MonitorInfo
.dwFlags
|= MONITORINFOF_PRIMARY
;
739 /* Fill device name */
740 if (MonitorInfo
.cbSize
== sizeof(MONITORINFOEXW
))
742 RtlStringCbCopyNExW(MonitorInfo
.szDevice
,
743 sizeof(MonitorInfo
.szDevice
),
745 (wcslen(pwstrDeviceName
)+1) * sizeof(WCHAR
),
746 NULL
, NULL
, STRSAFE_FILL_BEHIND_NULL
);
750 Status
= MmCopyToCaller(pMonitorInfoUnsafe
, &MonitorInfo
, MonitorInfo
.cbSize
);
751 if (!NT_SUCCESS(Status
))
753 TRACE("GetMonitorInfo: MmCopyToCaller failed\n");
754 SetLastNtError(Status
);
758 TRACE("GetMonitorInfo: success\n");
762 TRACE("Leave NtUserGetMonitorInfo, ret=%i\n", bRet
);
767 /* NtUserMonitorFromPoint
769 * Returns a handle to the monitor containing the given point.
774 * Point for which to find monitor
777 * Specifies the behaviour if the point isn't on any of the monitors.
780 * If the point is found a handle to the monitor is returned; if not the
781 * return value depends on dwFlags
785 NtUserMonitorFromPoint(
791 HMONITOR hMonitor
= NULL
;
793 /* Check if flags are valid */
794 if (dwFlags
!= MONITOR_DEFAULTTONULL
&&
795 dwFlags
!= MONITOR_DEFAULTTOPRIMARY
&&
796 dwFlags
!= MONITOR_DEFAULTTONEAREST
)
798 EngSetLastError(ERROR_INVALID_FLAGS
);
802 /* Fill rect (bottom-right exclusive) */
806 rc
.bottom
= pt
.y
+ 1;
810 /* Find intersecting monitor */
811 cMonitors
= IntGetMonitorsFromRect(&rc
, &hMonitor
, NULL
, 1, dwFlags
);
817 /* NtUserMonitorFromRect
819 * Returns a handle to the monitor having the largest intersection with a
825 * Pointer to a RECT for which to find monitor
828 * Specifies the behaviour if no monitor intersects the given rect
831 * If a monitor intersects the rect a handle to it is returned; if not the
832 * return value depends on dwFlags
836 NtUserMonitorFromRect(
837 IN LPCRECTL pRectUnsafe
,
840 ULONG cMonitors
, LargestArea
= 0, i
;
841 PRECTL prcMonitorList
= NULL
;
842 HMONITOR
*phMonitorList
= NULL
;
843 HMONITOR hMonitor
= NULL
;
847 /* Check if flags are valid */
848 if (dwFlags
!= MONITOR_DEFAULTTONULL
&&
849 dwFlags
!= MONITOR_DEFAULTTOPRIMARY
&&
850 dwFlags
!= MONITOR_DEFAULTTONEAREST
)
852 EngSetLastError(ERROR_INVALID_FLAGS
);
856 /* Copy rectangle to safe buffer */
857 Status
= MmCopyFromCaller(&Rect
, pRectUnsafe
, sizeof (RECT
));
858 if (!NT_SUCCESS(Status
))
860 SetLastNtError(Status
);
866 /* Find intersecting monitors */
867 cMonitors
= IntGetMonitorsFromRect(&Rect
, &hMonitor
, NULL
, 1, dwFlags
);
870 /* No or one monitor found. Just return handle. */
874 /* There is more than one monitor. Find monitor with largest intersection.
875 Temporary reset hMonitor */
878 /* Allocate helper buffers */
879 phMonitorList
= ExAllocatePoolWithTag(PagedPool
,
880 sizeof(HMONITOR
) * cMonitors
,
881 USERTAG_MONITORRECTS
);
882 if (phMonitorList
== NULL
)
884 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
888 prcMonitorList
= ExAllocatePoolWithTag(PagedPool
,
889 sizeof(RECT
) * cMonitors
,
890 USERTAG_MONITORRECTS
);
891 if (prcMonitorList
== NULL
)
893 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
897 /* Get intersecting monitors again but now with rectangle list */
898 cMonitors
= IntGetMonitorsFromRect(&Rect
, phMonitorList
, prcMonitorList
,
901 /* Find largest intersection */
902 for (i
= 0; i
< cMonitors
; i
++)
904 ULONG Area
= (prcMonitorList
[i
].right
- prcMonitorList
[i
].left
) *
905 (prcMonitorList
[i
].bottom
- prcMonitorList
[i
].top
);
906 if (Area
>= LargestArea
)
908 hMonitor
= phMonitorList
[i
];
915 ExFreePoolWithTag(phMonitorList
, USERTAG_MONITORRECTS
);
917 ExFreePoolWithTag(prcMonitorList
, USERTAG_MONITORRECTS
);
926 NtUserMonitorFromWindow(
931 HMONITOR hMonitor
= NULL
;
932 RECTL Rect
= {0, 0, 0, 0};
934 TRACE("Enter NtUserMonitorFromWindow\n");
936 /* Check if flags are valid */
937 if (dwFlags
!= MONITOR_DEFAULTTONULL
&&
938 dwFlags
!= MONITOR_DEFAULTTOPRIMARY
&&
939 dwFlags
!= MONITOR_DEFAULTTONEAREST
)
941 EngSetLastError(ERROR_INVALID_FLAGS
);
947 /* If window is given, use it first */
950 /* Get window object */
951 pWnd
= UserGetWindowObject(hWnd
);
955 /* Find only monitors which have intersection with given window */
956 Rect
.left
= Rect
.right
= pWnd
->rcWindow
.left
;
957 Rect
.top
= Rect
.bottom
= pWnd
->rcWindow
.bottom
;
960 /* Find monitors now */
961 IntGetMonitorsFromRect(&Rect
, &hMonitor
, NULL
, 1, dwFlags
);
964 TRACE("Leave NtUserMonitorFromWindow, ret=%p\n", hMonitor
);