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(VOID
)
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(VOID
)
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
= NtGdiCreateRectRgn(
262 pMonitor
->rcMonitor
.left
,
263 pMonitor
->rcMonitor
.top
,
264 pMonitor
->rcMonitor
.right
,
265 pMonitor
->rcMonitor
.bottom
);
266 if (pMonitor
->hrgnMonitor
)
267 IntGdiSetRegionOwner(pMonitor
->hrgnMonitor
, GDI_OBJ_HMGR_PUBLIC
);
269 return STATUS_SUCCESS
;
272 /* IntGetMonitorsFromRect
274 * Returns a list of monitor handles/rectangles. The rectangles in the list are
275 * the areas of intersection with the monitors.
280 * Rectangle in desktop coordinates. If this is NULL all monitors are
281 * returned and the rect list is filled with the sizes of the monitors.
284 * Pointer to an array of HMONITOR which is filled with monitor handles.
288 * Pointer to an array of RECT which is filled with intersection rects in
289 * desktop coordinates.
290 * Can be NULL, will be ignored if no intersecting monitor is found and
291 * flags is MONITOR_DEFAULTTONEAREST
294 * Size of the phMonitorList and prcMonitorList arguments. If this is zero
295 * phMonitorList and prcMonitorList are ignored.
298 * Either 0 or MONITOR_DEFAULTTONEAREST (ignored if rect is NULL)
301 * The number of monitors which intersect the specified region.
305 IntGetMonitorsFromRect(OPTIONAL IN LPCRECTL pRect
,
306 OPTIONAL OUT HMONITOR
*phMonitorList
,
307 OPTIONAL OUT PRECTL prcMonitorList
,
308 OPTIONAL IN DWORD dwListSize
,
309 OPTIONAL IN DWORD dwFlags
)
311 PMONITOR pMonitor
, pNearestMonitor
= NULL
, pPrimaryMonitor
= NULL
;
313 ULONG iNearestDistance
= 0xffffffff;
315 /* Find monitors which intersects the rectangle */
316 for (pMonitor
= gMonitorList
; pMonitor
!= NULL
; pMonitor
= pMonitor
->pMonitorNext
)
318 RECTL MonitorRect
, IntersectionRect
;
320 MonitorRect
= pMonitor
->rcMonitor
;
322 TRACE("MonitorRect: left = %d, top = %d, right = %d, bottom = %d\n",
323 MonitorRect
.left
, MonitorRect
.top
, MonitorRect
.right
, MonitorRect
.bottom
);
325 /* Save primary monitor for later usage */
326 if (dwFlags
== MONITOR_DEFAULTTOPRIMARY
&& pMonitor
->IsPrimary
)
327 pPrimaryMonitor
= pMonitor
;
329 /* Check if a rect is given */
332 /* No rect given, so use the full monitor rect */
333 IntersectionRect
= MonitorRect
;
335 /* We have a rect, calculate intersection */
336 else if (!RECTL_bIntersectRect(&IntersectionRect
, &MonitorRect
, pRect
))
338 /* Rects did not intersect */
339 if (dwFlags
== MONITOR_DEFAULTTONEAREST
)
341 ULONG cx
, cy
, iDistance
;
343 /* Get x and y distance */
344 cx
= min(abs(MonitorRect
.left
- pRect
->right
),
345 abs(pRect
->left
- MonitorRect
.right
));
346 cy
= min(abs(MonitorRect
.top
- pRect
->bottom
),
347 abs(pRect
->top
- MonitorRect
.bottom
));
349 /* Calculate distance square */
350 iDistance
= cx
* cx
+ cy
* cy
;
352 /* Check if this is the new nearest monitor */
353 if (iDistance
< iNearestDistance
)
355 iNearestDistance
= iDistance
;
356 pNearestMonitor
= pMonitor
;
363 /* Check if there's space in the buffer */
364 if (cMonitors
< dwListSize
)
366 /* Save monitor data */
367 if (phMonitorList
!= NULL
)
368 phMonitorList
[cMonitors
] = UserHMGetHandle(pMonitor
);
369 if (prcMonitorList
!= NULL
)
370 prcMonitorList
[cMonitors
] = IntersectionRect
;
373 /* Increase count of found monitors */
377 /* Nothing has been found? */
380 /* Check if we shall default to the nearest monitor */
381 if (dwFlags
== MONITOR_DEFAULTTONEAREST
&& pNearestMonitor
)
383 if (phMonitorList
&& dwListSize
> 0)
384 phMonitorList
[cMonitors
] = UserHMGetHandle(pNearestMonitor
);
387 /* Check if we shall default to the primary monitor */
388 else if (dwFlags
== MONITOR_DEFAULTTOPRIMARY
&& pPrimaryMonitor
)
390 if (phMonitorList
!= NULL
&& dwListSize
> 0)
391 phMonitorList
[cMonitors
] = UserHMGetHandle(pPrimaryMonitor
);
404 ULONG cMonitors
, LargestArea
= 0, i
;
405 PRECTL prcMonitorList
= NULL
;
406 HMONITOR
*phMonitorList
= NULL
;
407 HMONITOR hMonitor
= NULL
;
409 /* Check if flags are valid */
410 if (dwFlags
!= MONITOR_DEFAULTTONULL
&&
411 dwFlags
!= MONITOR_DEFAULTTOPRIMARY
&&
412 dwFlags
!= MONITOR_DEFAULTTONEAREST
)
414 EngSetLastError(ERROR_INVALID_FLAGS
);
418 /* Find intersecting monitors */
419 cMonitors
= IntGetMonitorsFromRect(pRect
, &hMonitor
, NULL
, 1, dwFlags
);
422 /* No or one monitor found. Just return handle. */
426 /* There is more than one monitor. Find monitor with largest intersection.
427 Temporary reset hMonitor */
430 /* Allocate helper buffers */
431 phMonitorList
= ExAllocatePoolWithTag(PagedPool
,
432 sizeof(HMONITOR
) * cMonitors
,
433 USERTAG_MONITORRECTS
);
434 if (phMonitorList
== NULL
)
436 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
440 prcMonitorList
= ExAllocatePoolWithTag(PagedPool
,
441 sizeof(RECT
) * cMonitors
,
442 USERTAG_MONITORRECTS
);
443 if (prcMonitorList
== NULL
)
445 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
449 /* Get intersecting monitors again but now with rectangle list */
450 cMonitors
= IntGetMonitorsFromRect(pRect
, phMonitorList
, prcMonitorList
,
453 /* Find largest intersection */
454 for (i
= 0; i
< cMonitors
; i
++)
456 ULONG Area
= (prcMonitorList
[i
].right
- prcMonitorList
[i
].left
) *
457 (prcMonitorList
[i
].bottom
- prcMonitorList
[i
].top
);
458 if (Area
>= LargestArea
)
460 hMonitor
= phMonitorList
[i
];
467 ExFreePoolWithTag(phMonitorList
, USERTAG_MONITORRECTS
);
469 ExFreePoolWithTag(prcMonitorList
, USERTAG_MONITORRECTS
);
471 return UserGetMonitorObject(hMonitor
);
476 UserMonitorFromPoint(
481 HMONITOR hMonitor
= NULL
;
483 /* Check if flags are valid */
484 if (dwFlags
!= MONITOR_DEFAULTTONULL
&&
485 dwFlags
!= MONITOR_DEFAULTTOPRIMARY
&&
486 dwFlags
!= MONITOR_DEFAULTTONEAREST
)
488 EngSetLastError(ERROR_INVALID_FLAGS
);
492 /* Fill rect (bottom-right exclusive) */
496 rc
.bottom
= pt
.y
+ 1;
498 /* Find intersecting monitor */
499 IntGetMonitorsFromRect(&rc
, &hMonitor
, NULL
, 1, dwFlags
);
501 return UserGetMonitorObject(hMonitor
);
504 /* PUBLIC FUNCTIONS ***********************************************************/
506 /* NtUserEnumDisplayMonitors
508 * Enumerates display monitors which intersect the given HDC/cliprect
513 * Handle to a DC for which to enum intersecting monitors. If this is NULL
514 * it returns all monitors which are part of the current virtual screen.
517 * Clipping rectangle with coordinate system origin at the DCs origin if the
518 * given HDC is not NULL or in virtual screen coordinated if it is NULL.
521 * phUnsafeMonitorList
522 * Pointer to an array of HMONITOR which is filled with monitor handles.
525 * prcUnsafeMonitorList
526 * Pointer to an array of RECT which is filled with intersection rectangles.
530 * Size of the hMonitorList and monitorRectList arguments. If this is zero
531 * hMonitorList and monitorRectList are ignored.
534 * The number of monitors which intersect the specified region or -1 on failure.
538 NtUserEnumDisplayMonitors(
540 OPTIONAL IN LPCRECTL pUnsafeRect
,
541 OPTIONAL OUT HMONITOR
*phUnsafeMonitorList
,
542 OPTIONAL OUT PRECTL prcUnsafeMonitorList
,
543 OPTIONAL IN DWORD dwListSize
)
547 HMONITOR
*phMonitorList
= NULL
;
548 PRECTL prcMonitorList
= NULL
;
554 if (pUnsafeRect
!= NULL
)
556 Status
= MmCopyFromCaller(&rc
, pUnsafeRect
, sizeof(RECT
));
557 if (!NT_SUCCESS(Status
))
559 TRACE("MmCopyFromCaller() failed!\n");
560 SetLastNtError(Status
);
570 /* Get visible region bounding rect */
571 pDc
= DC_LockDc(hdc
);
574 TRACE("DC_LockDc() failed!\n");
575 /* FIXME: setlasterror? */
578 iRgnType
= REGION_GetRgnBox(pDc
->prgnVis
, &DcRect
);
583 TRACE("NtGdiGetRgnBox() failed!\n");
586 if (iRgnType
== NULLREGION
)
588 if (iRgnType
== COMPLEXREGION
)
593 /* If hdc and pRect are given the area of interest is pRect with
594 coordinate origin at the DC position */
595 if (pUnsafeRect
!= NULL
)
597 rc
.left
+= DcRect
.left
;
598 rc
.right
+= DcRect
.left
;
599 rc
.top
+= DcRect
.top
;
600 rc
.bottom
+= DcRect
.top
;
602 /* If hdc is given and pRect is not the area of interest is the
603 bounding rect of hdc */
610 if (hdc
== NULL
&& pUnsafeRect
== NULL
)
617 /* Find intersecting monitors */
618 cMonitors
= IntGetMonitorsFromRect(pRect
, NULL
, NULL
, 0, MONITOR_DEFAULTTONULL
);
619 if (cMonitors
== 0 || dwListSize
== 0 ||
620 (phUnsafeMonitorList
== NULL
&& prcUnsafeMonitorList
== NULL
))
622 /* Simple case - just return monitors count */
623 TRACE("cMonitors = %u\n", cMonitors
);
628 /* Allocate safe buffers */
629 if (phUnsafeMonitorList
!= NULL
&& dwListSize
!= 0)
631 phMonitorList
= ExAllocatePoolWithTag(PagedPool
, sizeof (HMONITOR
) * dwListSize
, USERTAG_MONITORRECTS
);
632 if (phMonitorList
== NULL
)
634 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
638 if (prcUnsafeMonitorList
!= NULL
&& dwListSize
!= 0)
640 prcMonitorList
= ExAllocatePoolWithTag(PagedPool
, sizeof(RECT
) * dwListSize
,USERTAG_MONITORRECTS
);
641 if (prcMonitorList
== NULL
)
643 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
648 /* Get intersecting monitors */
649 cMonitors
= IntGetMonitorsFromRect(pRect
, phMonitorList
, prcMonitorList
,
650 dwListSize
, MONITOR_DEFAULTTONULL
);
652 if (hdc
!= NULL
&& pRect
!= NULL
&& prcMonitorList
!= NULL
)
654 for (i
= 0; i
< min(cMonitors
, dwListSize
); i
++)
656 _Analysis_assume_(i
< dwListSize
);
657 prcMonitorList
[i
].left
-= DcRect
.left
;
658 prcMonitorList
[i
].right
-= DcRect
.left
;
659 prcMonitorList
[i
].top
-= DcRect
.top
;
660 prcMonitorList
[i
].bottom
-= DcRect
.top
;
665 if (phUnsafeMonitorList
!= NULL
&& dwListSize
!= 0)
667 Status
= MmCopyToCaller(phUnsafeMonitorList
, phMonitorList
, sizeof(HMONITOR
) * dwListSize
);
668 if (!NT_SUCCESS(Status
))
670 SetLastNtError(Status
);
674 if (prcUnsafeMonitorList
!= NULL
&& dwListSize
!= 0)
676 Status
= MmCopyToCaller(prcUnsafeMonitorList
, prcMonitorList
, sizeof(RECT
) * dwListSize
);
677 if (!NT_SUCCESS(Status
))
679 SetLastNtError(Status
);
684 /* Return monitors count on success */
689 ExFreePoolWithTag(phMonitorList
, USERTAG_MONITORRECTS
);
691 ExFreePoolWithTag(prcMonitorList
, USERTAG_MONITORRECTS
);
697 /* NtUserGetMonitorInfo
699 * Retrieves information about a given monitor
704 * Handle to a monitor for which to get information
707 * Pointer to a MONITORINFO struct which is filled with the information.
708 * The cbSize member must be set to sizeof(MONITORINFO) or
709 * sizeof(MONITORINFOEX). Even if set to sizeof(MONITORINFOEX) only parts
710 * from MONITORINFO will be filled.
713 * Pointer to a UNICODE_STRING which will receive the device's name. The
714 * length should be CCHDEVICENAME
718 * TRUE on success; FALSE on failure (calls SetLastNtError())
723 NtUserGetMonitorInfo(
724 IN HMONITOR hMonitor
,
725 OUT LPMONITORINFO pMonitorInfoUnsafe
)
728 MONITORINFOEXW MonitorInfo
;
731 PWCHAR pwstrDeviceName
;
733 TRACE("Enter NtUserGetMonitorInfo\n");
736 /* Get monitor object */
737 pMonitor
= UserGetMonitorObject(hMonitor
);
740 TRACE("Couldnt find monitor %p\n", hMonitor
);
744 /* Check if pMonitorInfoUnsafe is valid */
745 if(pMonitorInfoUnsafe
== NULL
)
747 SetLastNtError(STATUS_INVALID_PARAMETER
);
751 pwstrDeviceName
= ((PPDEVOBJ
)(pMonitor
->hDev
))->pGraphicsDevice
->szWinDeviceName
;
753 /* Get size of pMonitorInfoUnsafe */
754 Status
= MmCopyFromCaller(&MonitorInfo
.cbSize
, &pMonitorInfoUnsafe
->cbSize
, sizeof(MonitorInfo
.cbSize
));
755 if (!NT_SUCCESS(Status
))
757 SetLastNtError(Status
);
761 /* Check if size of struct is valid */
762 if (MonitorInfo
.cbSize
!= sizeof(MONITORINFO
) &&
763 MonitorInfo
.cbSize
!= sizeof(MONITORINFOEXW
))
765 SetLastNtError(STATUS_INVALID_PARAMETER
);
769 /* Fill monitor info */
770 MonitorInfo
.rcMonitor
= pMonitor
->rcMonitor
;
771 MonitorInfo
.rcWork
= pMonitor
->rcWork
;
772 MonitorInfo
.dwFlags
= 0;
773 if (pMonitor
->IsPrimary
)
774 MonitorInfo
.dwFlags
|= MONITORINFOF_PRIMARY
;
776 /* Fill device name */
777 if (MonitorInfo
.cbSize
== sizeof(MONITORINFOEXW
))
779 RtlStringCbCopyNExW(MonitorInfo
.szDevice
,
780 sizeof(MonitorInfo
.szDevice
),
782 (wcslen(pwstrDeviceName
)+1) * sizeof(WCHAR
),
783 NULL
, NULL
, STRSAFE_FILL_BEHIND_NULL
);
787 Status
= MmCopyToCaller(pMonitorInfoUnsafe
, &MonitorInfo
, MonitorInfo
.cbSize
);
788 if (!NT_SUCCESS(Status
))
790 TRACE("GetMonitorInfo: MmCopyToCaller failed\n");
791 SetLastNtError(Status
);
795 TRACE("GetMonitorInfo: success\n");
799 TRACE("Leave NtUserGetMonitorInfo, ret=%i\n", bRet
);
804 /* NtUserMonitorFromPoint
806 * Returns a handle to the monitor containing the given point.
811 * Point for which to find monitor
814 * Specifies the behaviour if the point isn't on any of the monitors.
817 * If the point is found a handle to the monitor is returned; if not the
818 * return value depends on dwFlags
822 NtUserMonitorFromPoint(
827 HMONITOR hMonitor
= NULL
;
829 /* Check if flags are valid */
830 if (dwFlags
!= MONITOR_DEFAULTTONULL
&&
831 dwFlags
!= MONITOR_DEFAULTTOPRIMARY
&&
832 dwFlags
!= MONITOR_DEFAULTTONEAREST
)
834 EngSetLastError(ERROR_INVALID_FLAGS
);
838 /* Fill rect (bottom-right exclusive) */
842 rc
.bottom
= pt
.y
+ 1;
846 /* Find intersecting monitor */
847 IntGetMonitorsFromRect(&rc
, &hMonitor
, NULL
, 1, dwFlags
);
853 /* NtUserMonitorFromRect
855 * Returns a handle to the monitor having the largest intersection with a
861 * Pointer to a RECT for which to find monitor
864 * Specifies the behaviour if no monitor intersects the given rect
867 * If a monitor intersects the rect a handle to it is returned; if not the
868 * return value depends on dwFlags
872 NtUserMonitorFromRect(
873 IN LPCRECTL pRectUnsafe
,
876 ULONG cMonitors
, LargestArea
= 0, i
;
877 PRECTL prcMonitorList
= NULL
;
878 HMONITOR
*phMonitorList
= NULL
;
879 HMONITOR hMonitor
= NULL
;
883 /* Check if flags are valid */
884 if (dwFlags
!= MONITOR_DEFAULTTONULL
&&
885 dwFlags
!= MONITOR_DEFAULTTOPRIMARY
&&
886 dwFlags
!= MONITOR_DEFAULTTONEAREST
)
888 EngSetLastError(ERROR_INVALID_FLAGS
);
892 /* Copy rectangle to safe buffer */
893 Status
= MmCopyFromCaller(&Rect
, pRectUnsafe
, sizeof (RECT
));
894 if (!NT_SUCCESS(Status
))
896 SetLastNtError(Status
);
902 /* Find intersecting monitors */
903 cMonitors
= IntGetMonitorsFromRect(&Rect
, &hMonitor
, NULL
, 1, dwFlags
);
906 /* No or one monitor found. Just return handle. */
910 /* There is more than one monitor. Find monitor with largest intersection.
911 Temporary reset hMonitor */
914 /* Allocate helper buffers */
915 phMonitorList
= ExAllocatePoolWithTag(PagedPool
,
916 sizeof(HMONITOR
) * cMonitors
,
917 USERTAG_MONITORRECTS
);
918 if (phMonitorList
== NULL
)
920 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
924 prcMonitorList
= ExAllocatePoolWithTag(PagedPool
,
925 sizeof(RECT
) * cMonitors
,
926 USERTAG_MONITORRECTS
);
927 if (prcMonitorList
== NULL
)
929 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
933 /* Get intersecting monitors again but now with rectangle list */
934 cMonitors
= IntGetMonitorsFromRect(&Rect
, phMonitorList
, prcMonitorList
,
937 /* Find largest intersection */
938 for (i
= 0; i
< cMonitors
; i
++)
940 ULONG Area
= (prcMonitorList
[i
].right
- prcMonitorList
[i
].left
) *
941 (prcMonitorList
[i
].bottom
- prcMonitorList
[i
].top
);
942 if (Area
>= LargestArea
)
944 hMonitor
= phMonitorList
[i
];
951 ExFreePoolWithTag(phMonitorList
, USERTAG_MONITORRECTS
);
953 ExFreePoolWithTag(prcMonitorList
, USERTAG_MONITORRECTS
);
962 NtUserMonitorFromWindow(
967 HMONITOR hMonitor
= NULL
;
968 RECTL Rect
= {0, 0, 0, 0};
970 TRACE("Enter NtUserMonitorFromWindow\n");
972 /* Check if flags are valid */
973 if (dwFlags
!= MONITOR_DEFAULTTONULL
&&
974 dwFlags
!= MONITOR_DEFAULTTOPRIMARY
&&
975 dwFlags
!= MONITOR_DEFAULTTONEAREST
)
977 EngSetLastError(ERROR_INVALID_FLAGS
);
983 /* If window is given, use it first */
986 /* Get window object */
987 pWnd
= UserGetWindowObject(hWnd
);
991 /* Find only monitors which have intersection with given window */
992 Rect
.left
= Rect
.right
= pWnd
->rcWindow
.left
;
993 Rect
.top
= Rect
.bottom
= pWnd
->rcWindow
.bottom
;
996 /* Find monitors now */
997 IntGetMonitorsFromRect(&Rect
, &hMonitor
, NULL
, 1, dwFlags
);
1000 TRACE("Leave NtUserMonitorFromWindow, ret=%p\n", hMonitor
);