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
, otMonitor
, 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 /* Free monitor name */
53 RtlFreeUnicodeString(&pMonitor
->DeviceName
);
55 /* Remove monitor region */
56 if (pMonitor
->hrgnMonitor
)
58 GreSetObjectOwner(pMonitor
->hrgnMonitor
, GDI_OBJ_HMGR_POWNED
);
59 GreDeleteObject(pMonitor
->hrgnMonitor
);
62 /* Destroy monitor object */
63 UserDereferenceObject(pMonitor
);
64 UserDeleteObject(UserHMGetHandle(pMonitor
), otMonitor
);
67 /* UserGetMonitorObject
69 * Returns monitor object from handle or sets last error if handle is invalid
74 * Handle of MONITOR object
77 UserGetMonitorObject(IN HMONITOR hMonitor
)
83 EngSetLastError(ERROR_INVALID_MONITOR_HANDLE
);
87 pMonitor
= (PMONITOR
)UserGetObject(gHandleTable
, hMonitor
, otMonitor
);
90 EngSetLastError(ERROR_INVALID_MONITOR_HANDLE
);
97 /* IntGetPrimaryMonitor
99 * Returns a PMONITOR for the primary monitor
106 IntGetPrimaryMonitor()
110 /* Find primary monitor */
111 for (pMonitor
= gMonitorList
; pMonitor
!= NULL
; pMonitor
= pMonitor
->pMonitorNext
)
113 if (pMonitor
->IsPrimary
)
122 * Creates a new MONITOR and appends it to the list of monitors.
126 * pGdiDevice Pointer to the PDEVOBJ onto which the monitor was attached
127 * DisplayNumber Display Number (starting with 0)
133 IntAttachMonitor(IN PDEVOBJ
*pGdiDevice
,
134 IN ULONG DisplayNumber
)
137 WCHAR Buffer
[CCHDEVICENAME
];
139 TRACE("Attaching monitor...\n");
141 /* create new monitor object */
142 pMonitor
= IntCreateMonitorObject();
143 if (pMonitor
== NULL
)
145 TRACE("Couldnt create monitor object\n");
146 return STATUS_INSUFFICIENT_RESOURCES
;
149 _snwprintf(Buffer
, CCHDEVICENAME
, L
"\\\\.\\DISPLAY%d", DisplayNumber
+ 1);
150 if (!RtlCreateUnicodeString(&pMonitor
->DeviceName
, Buffer
))
152 TRACE("Couldn't duplicate monitor name!\n");
153 UserDereferenceObject(pMonitor
);
154 UserDeleteObject(UserHMGetHandle(pMonitor
), otMonitor
);
155 return STATUS_INSUFFICIENT_RESOURCES
;
158 pMonitor
->GdiDevice
= pGdiDevice
;
159 pMonitor
->cWndStack
= 0;
161 if (gMonitorList
== NULL
)
163 TRACE("Primary monitor is beeing attached\n");
164 pMonitor
->IsPrimary
= TRUE
;
165 gMonitorList
= pMonitor
;
169 PMONITOR pmonLast
= gMonitorList
;
170 TRACE("Additional monitor is beeing attached\n");
171 while (pmonLast
->pMonitorNext
!= NULL
)
172 pmonLast
= pmonLast
->pMonitorNext
;
174 pmonLast
->pMonitorNext
= pMonitor
;
177 IntUpdateMonitorSize(pGdiDevice
);
179 return STATUS_SUCCESS
;
184 * Deletes a MONITOR and removes it from the list of monitors.
188 * pGdiDevice Pointer to the PDEVOBJ from which the monitor was detached
194 IntDetachMonitor(IN PDEVOBJ
*pGdiDevice
)
196 PMONITOR pMonitor
= gMonitorList
, *pLink
= &gMonitorList
;
198 /* Find monitor attached to given device */
199 while (pMonitor
!= NULL
)
201 if (pMonitor
->GdiDevice
== pGdiDevice
)
204 pLink
= &pMonitor
->pMonitorNext
;
205 pMonitor
= pMonitor
->pMonitorNext
;
208 if (pMonitor
== NULL
)
210 /* No monitor has been found */
211 return STATUS_INVALID_PARAMETER
;
214 /* We destroy primary monitor - set next as primary */
215 if (pMonitor
->IsPrimary
&& pMonitor
->pMonitorNext
!= NULL
)
216 pMonitor
->pMonitorNext
->IsPrimary
= TRUE
;
218 /* Update Next ptr in previous monitor */
219 *pLink
= pMonitor
->pMonitorNext
;
221 /* Finally destroy monitor */
222 IntDestroyMonitorObject(pMonitor
);
224 return STATUS_SUCCESS
;
227 /* IntUpdateMonitorSize
229 * Reset size of the monitor using atached device
234 * pGdiDevice Pointer to the PDEVOBJ, which size has changed
240 IntUpdateMonitorSize(IN PDEVOBJ
*pGdiDevice
)
244 /* Find monitor attached to given device */
245 for (pMonitor
= gMonitorList
; pMonitor
!= NULL
; pMonitor
= pMonitor
->pMonitorNext
)
247 if (pMonitor
->GdiDevice
== pGdiDevice
)
251 if (pMonitor
== NULL
)
253 /* No monitor has been found */
254 return STATUS_INVALID_PARAMETER
;
257 /* Update monitor size */
258 pMonitor
->rcMonitor
.left
= 0;
259 pMonitor
->rcMonitor
.top
= 0;
260 pMonitor
->rcMonitor
.right
= pMonitor
->rcMonitor
.left
+ pMonitor
->GdiDevice
->gdiinfo
.ulHorzRes
;
261 pMonitor
->rcMonitor
.bottom
= pMonitor
->rcMonitor
.top
+ pMonitor
->GdiDevice
->gdiinfo
.ulVertRes
;
262 pMonitor
->rcWork
= pMonitor
->rcMonitor
;
264 /* Destroy monitor region... */
265 if (pMonitor
->hrgnMonitor
)
267 GreSetObjectOwner(pMonitor
->hrgnMonitor
, GDI_OBJ_HMGR_POWNED
);
268 GreDeleteObject(pMonitor
->hrgnMonitor
);
271 /* ...and create new one */
272 pMonitor
->hrgnMonitor
= IntSysCreateRectRgnIndirect(&pMonitor
->rcMonitor
);
273 if (pMonitor
->hrgnMonitor
)
274 IntGdiSetRegionOwner(pMonitor
->hrgnMonitor
, GDI_OBJ_HMGR_PUBLIC
);
276 return STATUS_SUCCESS
;
279 /* IntGetMonitorsFromRect
281 * Returns a list of monitor handles/rectangles. The rectangles in the list are
282 * the areas of intersection with the monitors.
287 * Rectangle in desktop coordinates. If this is NULL all monitors are
288 * returned and the rect list is filled with the sizes of the monitors.
291 * Pointer to an array of HMONITOR which is filled with monitor handles.
295 * Pointer to an array of RECT which is filled with intersection rects in
296 * desktop coordinates.
297 * Can be NULL, will be ignored if no intersecting monitor is found and
298 * flags is MONITOR_DEFAULTTONEAREST
301 * Size of the phMonitorList and prcMonitorList arguments. If this is zero
302 * phMonitorList and prcMonitorList are ignored.
305 * Either 0 or MONITOR_DEFAULTTONEAREST (ignored if rect is NULL)
308 * The number of monitors which intersect the specified region.
312 IntGetMonitorsFromRect(OPTIONAL IN LPCRECTL pRect
,
313 OPTIONAL OUT HMONITOR
*phMonitorList
,
314 OPTIONAL OUT PRECTL prcMonitorList
,
315 OPTIONAL IN DWORD dwListSize
,
316 OPTIONAL IN DWORD dwFlags
)
318 PMONITOR pMonitor
, pNearestMonitor
= NULL
, pPrimaryMonitor
= NULL
;
320 ULONG iNearestDistance
= 0xffffffff;
322 /* Find monitors which intersects the rectangle */
323 for (pMonitor
= gMonitorList
; pMonitor
!= NULL
; pMonitor
= pMonitor
->pMonitorNext
)
325 RECTL MonitorRect
, IntersectionRect
;
327 MonitorRect
= pMonitor
->rcMonitor
;
329 TRACE("MonitorRect: left = %d, top = %d, right = %d, bottom = %d\n",
330 MonitorRect
.left
, MonitorRect
.top
, MonitorRect
.right
, MonitorRect
.bottom
);
332 /* Save primary monitor for later usage */
333 if (dwFlags
== MONITOR_DEFAULTTOPRIMARY
&& pMonitor
->IsPrimary
)
334 pPrimaryMonitor
= pMonitor
;
336 /* Check if a rect is given */
339 /* No rect given, so use the full monitor rect */
340 IntersectionRect
= MonitorRect
;
342 /* We have a rect, calculate intersection */
343 else if (!RECTL_bIntersectRect(&IntersectionRect
, &MonitorRect
, pRect
))
345 /* Rects did not intersect */
346 if (dwFlags
== MONITOR_DEFAULTTONEAREST
)
348 ULONG cx
, cy
, iDistance
;
350 /* Get x and y distance */
351 cx
= min(abs(MonitorRect
.left
- pRect
->right
),
352 abs(pRect
->left
- MonitorRect
.right
));
353 cy
= min(abs(MonitorRect
.top
- pRect
->bottom
),
354 abs(pRect
->top
- MonitorRect
.bottom
));
356 /* Calculate distance square */
357 iDistance
= cx
* cx
+ cy
* cy
;
359 /* Check if this is the new nearest monitor */
360 if (iDistance
< iNearestDistance
)
362 iNearestDistance
= iDistance
;
363 pNearestMonitor
= pMonitor
;
370 /* Check if there's space in the buffer */
371 if (cMonitors
< dwListSize
)
373 /* Save monitor data */
374 if (phMonitorList
!= NULL
)
375 phMonitorList
[cMonitors
] = UserHMGetHandle(pMonitor
);
376 if (prcMonitorList
!= NULL
)
377 prcMonitorList
[cMonitors
] = IntersectionRect
;
380 /* Increase count of found monitors */
384 /* Nothing has been found? */
387 /* Check if we shall default to the nearest monitor */
388 if (dwFlags
== MONITOR_DEFAULTTONEAREST
&& pNearestMonitor
)
390 if (phMonitorList
&& dwListSize
> 0)
391 phMonitorList
[cMonitors
] = UserHMGetHandle(pNearestMonitor
);
394 /* Check if we shall default to the primary monitor */
395 else if (dwFlags
== MONITOR_DEFAULTTOPRIMARY
&& pPrimaryMonitor
)
397 if (phMonitorList
!= NULL
&& dwListSize
> 0)
398 phMonitorList
[cMonitors
] = UserHMGetHandle(pPrimaryMonitor
);
412 ULONG cMonitors
, LargestArea
= 0, i
;
413 PRECTL prcMonitorList
= NULL
;
414 HMONITOR
*phMonitorList
= NULL
;
415 HMONITOR hMonitor
= NULL
;
417 /* Check if flags are valid */
418 if (dwFlags
!= MONITOR_DEFAULTTONULL
&&
419 dwFlags
!= MONITOR_DEFAULTTOPRIMARY
&&
420 dwFlags
!= MONITOR_DEFAULTTONEAREST
)
422 EngSetLastError(ERROR_INVALID_FLAGS
);
426 /* Find intersecting monitors */
427 cMonitors
= IntGetMonitorsFromRect(pRect
, &hMonitor
, NULL
, 1, dwFlags
);
430 /* No or one monitor found. Just return handle. */
434 /* There is more than one monitor. Find monitor with largest intersection.
435 Temporary reset hMonitor */
438 /* Allocate helper buffers */
439 phMonitorList
= ExAllocatePoolWithTag(PagedPool
,
440 sizeof(HMONITOR
) * cMonitors
,
441 USERTAG_MONITORRECTS
);
442 if (phMonitorList
== NULL
)
444 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
448 prcMonitorList
= ExAllocatePoolWithTag(PagedPool
,
449 sizeof(RECT
) * cMonitors
,
450 USERTAG_MONITORRECTS
);
451 if (prcMonitorList
== NULL
)
453 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
457 /* Get intersecting monitors again but now with rectangle list */
458 cMonitors
= IntGetMonitorsFromRect(pRect
, phMonitorList
, prcMonitorList
,
461 /* Find largest intersection */
462 for (i
= 0; i
< cMonitors
; i
++)
464 ULONG Area
= (prcMonitorList
[i
].right
- prcMonitorList
[i
].left
) *
465 (prcMonitorList
[i
].bottom
- prcMonitorList
[i
].top
);
466 if (Area
>= LargestArea
)
468 hMonitor
= phMonitorList
[i
];
475 ExFreePoolWithTag(phMonitorList
, USERTAG_MONITORRECTS
);
477 ExFreePoolWithTag(prcMonitorList
, USERTAG_MONITORRECTS
);
479 return UserGetMonitorObject(hMonitor
);
483 /* PUBLIC FUNCTIONS ***********************************************************/
485 /* NtUserEnumDisplayMonitors
487 * Enumerates display monitors which intersect the given HDC/cliprect
492 * Handle to a DC for which to enum intersecting monitors. If this is NULL
493 * it returns all monitors which are part of the current virtual screen.
496 * Clipping rectangle with coordinate system origin at the DCs origin if the
497 * given HDC is not NULL or in virtual screen coordinated if it is NULL.
500 * phUnsafeMonitorList
501 * Pointer to an array of HMONITOR which is filled with monitor handles.
504 * prcUnsafeMonitorList
505 * Pointer to an array of RECT which is filled with intersection rectangles.
509 * Size of the hMonitorList and monitorRectList arguments. If this is zero
510 * hMonitorList and monitorRectList are ignored.
513 * The number of monitors which intersect the specified region or -1 on failure.
517 NtUserEnumDisplayMonitors(
519 OPTIONAL IN LPCRECTL pUnsafeRect
,
520 OPTIONAL OUT HMONITOR
*phUnsafeMonitorList
,
521 OPTIONAL OUT PRECTL prcUnsafeMonitorList
,
522 OPTIONAL IN DWORD dwListSize
)
524 INT cMonitors
, iRet
= -1, i
;
525 HMONITOR
*phMonitorList
= NULL
;
526 PRECTL prcMonitorList
= NULL
;
532 if (pUnsafeRect
!= NULL
)
534 Status
= MmCopyFromCaller(&rc
, pUnsafeRect
, sizeof(RECT
));
535 if (!NT_SUCCESS(Status
))
537 TRACE("MmCopyFromCaller() failed!\n");
538 SetLastNtError(Status
);
548 /* Get visible region bounding rect */
549 pDc
= DC_LockDc(hdc
);
552 TRACE("DC_LockDc() failed!\n");
553 /* FIXME: setlasterror? */
556 iRgnType
= REGION_GetRgnBox(pDc
->prgnVis
, &DcRect
);
561 TRACE("NtGdiGetRgnBox() failed!\n");
564 if (iRgnType
== NULLREGION
)
566 if (iRgnType
== COMPLEXREGION
)
571 /* if hdc and pRect are given the area of interest is pRect with
572 coordinate origin at the DC position */
573 if (pUnsafeRect
!= NULL
)
575 rc
.left
+= DcRect
.left
;
576 rc
.right
+= DcRect
.left
;
577 rc
.top
+= DcRect
.top
;
578 rc
.bottom
+= DcRect
.top
;
580 /* if hdc is given and pRect is not the area of interest is the
581 bounding rect of hdc */
588 if (hdc
== NULL
&& pUnsafeRect
== NULL
)
595 /* Find intersecting monitors */
596 cMonitors
= IntGetMonitorsFromRect(pRect
, NULL
, NULL
, 0, MONITOR_DEFAULTTONULL
);
597 if (cMonitors
== 0 || dwListSize
== 0 ||
598 (phUnsafeMonitorList
== NULL
&& prcUnsafeMonitorList
== NULL
))
600 /* Simple case - just return monitors count */
601 TRACE("cMonitors = %d\n", cMonitors
);
606 /* Allocate safe buffers */
607 if (phUnsafeMonitorList
!= NULL
&& dwListSize
!= 0)
609 phMonitorList
= ExAllocatePoolWithTag(PagedPool
, sizeof (HMONITOR
) * dwListSize
, USERTAG_MONITORRECTS
);
610 if (phMonitorList
== NULL
)
612 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
616 if (prcUnsafeMonitorList
!= NULL
&& dwListSize
!= 0)
618 prcMonitorList
= ExAllocatePoolWithTag(PagedPool
, sizeof (RECT
) * dwListSize
, USERTAG_MONITORRECTS
);
619 if (prcMonitorList
== NULL
)
621 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
626 /* Get intersecting monitors */
627 cMonitors
= IntGetMonitorsFromRect(pRect
, phMonitorList
, prcMonitorList
,
628 dwListSize
, MONITOR_DEFAULTTONULL
);
630 if (hdc
!= NULL
&& pRect
!= NULL
&& prcMonitorList
!= NULL
)
631 for (i
= 0; i
< cMonitors
; i
++)
633 prcMonitorList
[i
].left
-= DcRect
.left
;
634 prcMonitorList
[i
].right
-= DcRect
.left
;
635 prcMonitorList
[i
].top
-= DcRect
.top
;
636 prcMonitorList
[i
].bottom
-= DcRect
.top
;
640 if (phUnsafeMonitorList
!= NULL
&& dwListSize
!= 0)
642 Status
= MmCopyToCaller(phUnsafeMonitorList
, phMonitorList
, sizeof(HMONITOR
) * dwListSize
);
643 if (!NT_SUCCESS(Status
))
645 SetLastNtError(Status
);
649 if (prcUnsafeMonitorList
!= NULL
&& dwListSize
!= 0)
651 Status
= MmCopyToCaller(prcUnsafeMonitorList
, prcMonitorList
, sizeof(RECT
) * dwListSize
);
652 if (!NT_SUCCESS(Status
))
654 SetLastNtError(Status
);
659 /* Return monitors count on success */
664 ExFreePoolWithTag(phMonitorList
, USERTAG_MONITORRECTS
);
666 ExFreePoolWithTag(prcMonitorList
, USERTAG_MONITORRECTS
);
672 /* NtUserGetMonitorInfo
674 * Retrieves information about a given monitor
679 * Handle to a monitor for which to get information
682 * Pointer to a MONITORINFO struct which is filled with the information.
683 * The cbSize member must be set to sizeof(MONITORINFO) or
684 * sizeof(MONITORINFOEX). Even if set to sizeof(MONITORINFOEX) only parts
685 * from MONITORINFO will be filled.
688 * Pointer to a UNICODE_STRING which will recieve the device's name. The
689 * length should be CCHDEVICENAME
693 * TRUE on success; FALSE on failure (calls SetLastNtError())
698 NtUserGetMonitorInfo(
699 IN HMONITOR hMonitor
,
700 OUT LPMONITORINFO pMonitorInfoUnsafe
)
703 MONITORINFOEXW MonitorInfo
;
707 TRACE("Enter NtUserGetMonitorInfo\n");
710 /* Get monitor object */
711 pMonitor
= UserGetMonitorObject(hMonitor
);
714 TRACE("Couldnt find monitor 0x%lx\n", hMonitor
);
718 /* Check if pMonitorInfoUnsafe is valid */
719 if(pMonitorInfoUnsafe
== NULL
)
721 SetLastNtError(STATUS_INVALID_PARAMETER
);
725 /* Get size of pMonitorInfoUnsafe */
726 Status
= MmCopyFromCaller(&MonitorInfo
.cbSize
, &pMonitorInfoUnsafe
->cbSize
, sizeof(MonitorInfo
.cbSize
));
727 if (!NT_SUCCESS(Status
))
729 SetLastNtError(Status
);
733 /* Check if size of struct is valid */
734 if (MonitorInfo
.cbSize
!= sizeof(MONITORINFO
) &&
735 MonitorInfo
.cbSize
!= sizeof(MONITORINFOEXW
))
737 SetLastNtError(STATUS_INVALID_PARAMETER
);
741 /* Fill monitor info */
742 MonitorInfo
.rcMonitor
= pMonitor
->rcMonitor
;
743 MonitorInfo
.rcWork
= pMonitor
->rcWork
;
744 MonitorInfo
.dwFlags
= 0;
745 if (pMonitor
->IsPrimary
)
746 MonitorInfo
.dwFlags
|= MONITORINFOF_PRIMARY
;
748 /* Fill device name */
749 if (MonitorInfo
.cbSize
== sizeof(MONITORINFOEXW
))
751 RtlStringCbCopyNExW(MonitorInfo
.szDevice
,
752 sizeof(MonitorInfo
.szDevice
),
753 pMonitor
->DeviceName
.Buffer
,
754 pMonitor
->DeviceName
.Length
,
755 NULL
, NULL
, STRSAFE_FILL_BEHIND_NULL
);
759 Status
= MmCopyToCaller(pMonitorInfoUnsafe
, &MonitorInfo
, MonitorInfo
.cbSize
);
760 if (!NT_SUCCESS(Status
))
762 TRACE("GetMonitorInfo: MmCopyToCaller failed\n");
763 SetLastNtError(Status
);
767 TRACE("GetMonitorInfo: success\n");
771 TRACE("Leave NtUserGetMonitorInfo, ret=%i\n", bRet
);
776 /* NtUserMonitorFromPoint
778 * Returns a handle to the monitor containing the given point.
783 * Point for which to find monitor
786 * Specifies the behaviour if the point isn't on any of the monitors.
789 * If the point is found a handle to the monitor is returned; if not the
790 * return value depends on dwFlags
794 NtUserMonitorFromPoint(
800 HMONITOR hMonitor
= NULL
;
802 /* Check if flags are valid */
803 if (dwFlags
!= MONITOR_DEFAULTTONULL
&&
804 dwFlags
!= MONITOR_DEFAULTTOPRIMARY
&&
805 dwFlags
!= MONITOR_DEFAULTTONEAREST
)
807 EngSetLastError(ERROR_INVALID_FLAGS
);
811 /* Fill rect (bottom-right exclusive) */
815 rc
.bottom
= pt
.y
+ 1;
819 /* Find intersecting monitor */
820 cMonitors
= IntGetMonitorsFromRect(&rc
, &hMonitor
, NULL
, 1, dwFlags
);
826 /* NtUserMonitorFromRect
828 * Returns a handle to the monitor having the largest intersection with a
834 * Pointer to a RECT for which to find monitor
837 * Specifies the behaviour if no monitor intersects the given rect
840 * If a monitor intersects the rect a handle to it is returned; if not the
841 * return value depends on dwFlags
845 NtUserMonitorFromRect(
846 IN LPCRECTL pRectUnsafe
,
849 ULONG cMonitors
, LargestArea
= 0, i
;
850 PRECTL prcMonitorList
= NULL
;
851 HMONITOR
*phMonitorList
= NULL
;
852 HMONITOR hMonitor
= NULL
;
856 /* Check if flags are valid */
857 if (dwFlags
!= MONITOR_DEFAULTTONULL
&&
858 dwFlags
!= MONITOR_DEFAULTTOPRIMARY
&&
859 dwFlags
!= MONITOR_DEFAULTTONEAREST
)
861 EngSetLastError(ERROR_INVALID_FLAGS
);
865 /* Copy rectangle to safe buffer */
866 Status
= MmCopyFromCaller(&Rect
, pRectUnsafe
, sizeof (RECT
));
867 if (!NT_SUCCESS(Status
))
869 SetLastNtError(Status
);
875 /* Find intersecting monitors */
876 cMonitors
= IntGetMonitorsFromRect(&Rect
, &hMonitor
, NULL
, 1, dwFlags
);
879 /* No or one monitor found. Just return handle. */
883 /* There is more than one monitor. Find monitor with largest intersection.
884 Temporary reset hMonitor */
887 /* Allocate helper buffers */
888 phMonitorList
= ExAllocatePoolWithTag(PagedPool
,
889 sizeof(HMONITOR
) * cMonitors
,
890 USERTAG_MONITORRECTS
);
891 if (phMonitorList
== NULL
)
893 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
897 prcMonitorList
= ExAllocatePoolWithTag(PagedPool
,
898 sizeof(RECT
) * cMonitors
,
899 USERTAG_MONITORRECTS
);
900 if (prcMonitorList
== NULL
)
902 EngSetLastError(ERROR_NOT_ENOUGH_MEMORY
);
906 /* Get intersecting monitors again but now with rectangle list */
907 cMonitors
= IntGetMonitorsFromRect(&Rect
, phMonitorList
, prcMonitorList
,
910 /* Find largest intersection */
911 for (i
= 0; i
< cMonitors
; i
++)
913 ULONG Area
= (prcMonitorList
[i
].right
- prcMonitorList
[i
].left
) *
914 (prcMonitorList
[i
].bottom
- prcMonitorList
[i
].top
);
915 if (Area
>= LargestArea
)
917 hMonitor
= phMonitorList
[i
];
924 ExFreePoolWithTag(phMonitorList
, USERTAG_MONITORRECTS
);
926 ExFreePoolWithTag(prcMonitorList
, USERTAG_MONITORRECTS
);
935 NtUserMonitorFromWindow(
940 HMONITOR hMonitor
= NULL
;
941 RECTL Rect
= {0, 0, 0, 0};
943 TRACE("Enter NtUserMonitorFromWindow\n");
945 /* Check if flags are valid */
946 if (dwFlags
!= MONITOR_DEFAULTTONULL
&&
947 dwFlags
!= MONITOR_DEFAULTTOPRIMARY
&&
948 dwFlags
!= MONITOR_DEFAULTTONEAREST
)
950 EngSetLastError(ERROR_INVALID_FLAGS
);
956 /* If window is given, use it first */
959 /* Get window object */
960 pWnd
= UserGetWindowObject(hWnd
);
964 /* Find only monitors which have intersection with given window */
965 Rect
.left
= Rect
.right
= pWnd
->rcWindow
.left
;
966 Rect
.top
= Rect
.bottom
= pWnd
->rcWindow
.bottom
;
969 /* Find monitors now */
970 IntGetMonitorsFromRect(&Rect
, &hMonitor
, NULL
, 1, dwFlags
);
973 TRACE("Leave NtUserMonitorFromWindow, ret=%p\n", hMonitor
);