2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 * COPYRIGHT: See COPYING in the top level directory
20 * PROJECT: ReactOS kernel
21 * PURPOSE: Monitor support
22 * FILE: subsys/win32k/ntuser/monitor.c
23 * PROGRAMER: Anich Gregor (blight@blight.eu.org)
28 /* INCLUDES ******************************************************************/
32 /* FIXME: find include file for these */
33 #define MONITORINFOF_PRIMARY 1
34 #define MONITOR_DEFAULTTONULL 0
35 #define MONITOR_DEFAULTTOPRIMARY 1
36 #define MONITOR_DEFAULTTONEAREST 2
41 /* GLOBALS *******************************************************************/
43 /* list of monitors */
44 static PMONITOR gMonitorList
= NULL
;
46 /* INITALIZATION FUNCTIONS ****************************************************/
51 DPRINT("Initializing monitor implementation...\n");
53 return STATUS_SUCCESS
;
59 DPRINT("Cleaning up monitor implementation...\n");
60 /* FIXME: Destroy monitor objects? */
62 return STATUS_SUCCESS
;
65 /* PRIVATE FUNCTIONS **********************************************************/
68 # define MIN(a, b) ((a) < (b) ? (a) : (b))
71 # define MAX(a, b) ((a) > (b) ? (a) : (b))
74 # define ABS(a) ((a) < (0) ? (-(a)) : (a))
77 /* IntCreateMonitorObject
82 * If the function succeeds a pointer to a MONITOR is returned. On failure
87 IntCreateMonitorObject()
92 Monitor
= UserCreateObject(gHandleTable
, NULL
, &Handle
, otMonitor
, sizeof (MONITOR
));
98 ExInitializeFastMutex(&Monitor
->Lock
);
103 /* IntDestroyMonitorObject
106 * You have to be the owner of the monitors lock to safely destroy it.
111 * Pointer to the MONITOR which shall be deleted
115 IntDestroyMonitorObject(IN PMONITOR pMonitor
)
117 RtlFreeUnicodeString(&pMonitor
->DeviceName
);
118 UserDereferenceObject(pMonitor
);
123 UserGetMonitorObject(IN HMONITOR hMonitor
)
129 SetLastWin32Error(ERROR_INVALID_MONITOR_HANDLE
);
134 Monitor
= (PMONITOR
)UserGetObject(gHandleTable
, hMonitor
, otMonitor
);
137 SetLastWin32Error(ERROR_INVALID_MONITOR_HANDLE
);
141 ASSERT(Monitor
->head
.cLockObj
>= 0);
149 * Creates a new MONITOR and appends it to the list of monitors.
153 * pGdiDevice Pointer to the PDEVOBJ onto which the monitor was attached
154 * DisplayNumber Display Number (starting with 0)
160 IntAttachMonitor(IN PDEVOBJ
*pGdiDevice
,
161 IN ULONG DisplayNumber
)
164 WCHAR Buffer
[CCHDEVICENAME
];
166 DPRINT("Attaching monitor...\n");
168 /* create new monitor object */
169 Monitor
= IntCreateMonitorObject();
172 DPRINT("Couldnt create monitor object\n");
173 return STATUS_INSUFFICIENT_RESOURCES
;
176 _snwprintf(Buffer
, CCHDEVICENAME
, L
"\\\\.\\DISPLAY%d", DisplayNumber
+ 1);
177 if (!RtlCreateUnicodeString(&Monitor
->DeviceName
, Buffer
))
179 DPRINT("Couldn't duplicate monitor name!\n");
180 UserDereferenceObject(Monitor
);
181 UserDeleteObject(UserHMGetHandle(Monitor
), otMonitor
);
182 return STATUS_INSUFFICIENT_RESOURCES
;
185 Monitor
->GdiDevice
= pGdiDevice
;
186 Monitor
->rcMonitor
.left
= 0;
187 Monitor
->rcMonitor
.top
= 0;
188 Monitor
->rcMonitor
.right
= Monitor
->rcMonitor
.left
+ pGdiDevice
->gdiinfo
.ulHorzRes
;
189 Monitor
->rcMonitor
.bottom
= Monitor
->rcMonitor
.top
+ pGdiDevice
->gdiinfo
.ulVertRes
;
190 Monitor
->rcWork
= Monitor
->rcMonitor
;
191 Monitor
->cWndStack
= 0;
193 Monitor
->hrgnMonitor
= IntSysCreateRectRgnIndirect( &Monitor
->rcMonitor
);
195 IntGdiSetRegionOwner(Monitor
->hrgnMonitor
, GDI_OBJ_HMGR_PUBLIC
);
197 if (gMonitorList
== NULL
)
199 DPRINT("Primary monitor is beeing attached\n");
200 Monitor
->IsPrimary
= TRUE
;
201 gMonitorList
= Monitor
;
206 DPRINT("Additional monitor is beeing attached\n");
207 for (p
= gMonitorList
; p
->Next
!= NULL
; p
= p
->Next
)
214 return STATUS_SUCCESS
;
219 * Deletes a MONITOR and removes it from the list of monitors.
223 * pGdiDevice Pointer to the PDEVOBJ from which the monitor was detached
229 IntDetachMonitor(IN PDEVOBJ
*pGdiDevice
)
233 for (Monitor
= gMonitorList
; Monitor
!= NULL
; Monitor
= Monitor
->Next
)
235 if (Monitor
->GdiDevice
== pGdiDevice
)
241 /* no monitor for given device found */
242 return STATUS_INVALID_PARAMETER
;
245 if (Monitor
->IsPrimary
&& (Monitor
->Next
!= NULL
|| Monitor
->Prev
!= NULL
))
247 PMONITOR NewPrimaryMonitor
= (Monitor
->Prev
!= NULL
) ? (Monitor
->Prev
) : (Monitor
->Next
);
249 ExEnterCriticalRegionAndAcquireFastMutexUnsafe(&NewPrimaryMonitor
->Lock
);
250 NewPrimaryMonitor
->IsPrimary
= TRUE
;
251 ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&NewPrimaryMonitor
->Lock
);
254 if (gMonitorList
== Monitor
)
256 gMonitorList
= Monitor
->Next
;
257 if (Monitor
->Next
!= NULL
)
258 Monitor
->Next
->Prev
= NULL
;
262 Monitor
->Prev
->Next
= Monitor
->Next
;
263 if (Monitor
->Next
!= NULL
)
264 Monitor
->Next
->Prev
= Monitor
->Prev
;
267 if (Monitor
->hrgnMonitor
)
268 REGION_FreeRgnByHandle(Monitor
->hrgnMonitor
);
270 IntDestroyMonitorObject(Monitor
);
272 return STATUS_SUCCESS
;
275 /* IntGetPrimaryMonitor
277 * Returns a PMONITOR for the primary monitor
284 IntGetPrimaryMonitor()
288 for (Monitor
= gMonitorList
; Monitor
!= NULL
; Monitor
= Monitor
->Next
)
290 /* FIXME: I guess locking the monitor is not neccessary to read 1 int */
291 if (Monitor
->IsPrimary
)
298 /* IntGetMonitorsFromRect
300 * Returns a list of monitor handles/rectangles. The rectangles in the list are
301 * the areas of intersection with the monitors.
306 * Rectangle in desktop coordinates. If this is NULL all monitors are
307 * returned and the rect list is filled with the sizes of the monitors.
310 * Pointer to an array of HMONITOR which is filled with monitor handles.
314 * Pointer to an array of RECT which is filled with intersection rects in
315 * desktop coordinates.
316 * Can be NULL, will be ignored if no intersecting monitor is found and
317 * flags is MONITOR_DEFAULTTONEAREST
320 * Size of the hMonitorList and monitorRectList arguments. If this is zero
321 * hMonitorList and monitorRectList are ignored.
324 * Either 0 or MONITOR_DEFAULTTONEAREST (ignored if rect is NULL)
327 * The number of monitors which intersect the specified region.
331 IntGetMonitorsFromRect(OPTIONAL IN LPCRECTL pRect
,
332 OPTIONAL OUT HMONITOR
*hMonitorList
,
333 OPTIONAL OUT PRECTL monitorRectList
,
334 OPTIONAL IN DWORD listSize
,
335 OPTIONAL IN DWORD flags
)
337 PMONITOR Monitor
, NearestMonitor
= NULL
, PrimaryMonitor
= NULL
;
339 LONG iNearestDistanceX
= 0x7fffffff, iNearestDistanceY
= 0x7fffffff;
341 /* find monitors which intersect the rectangle */
342 for (Monitor
= gMonitorList
; Monitor
!= NULL
; Monitor
= Monitor
->Next
)
344 RECTL MonitorRect
, IntersectionRect
;
346 ExEnterCriticalRegionAndAcquireFastMutexUnsafe(&Monitor
->Lock
);
347 MonitorRect
.left
= 0; /* FIXME: get origin */
348 MonitorRect
.top
= 0; /* FIXME: get origin */
349 MonitorRect
.right
= MonitorRect
.left
+ Monitor
->GdiDevice
->gdiinfo
.ulHorzRes
;
350 MonitorRect
.bottom
= MonitorRect
.top
+ Monitor
->GdiDevice
->gdiinfo
.ulVertRes
;
351 ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&Monitor
->Lock
);
353 DPRINT("MonitorRect: left = %d, top = %d, right = %d, bottom = %d\n",
354 MonitorRect
.left
, MonitorRect
.top
, MonitorRect
.right
, MonitorRect
.bottom
);
356 if (flags
== MONITOR_DEFAULTTOPRIMARY
&& Monitor
->IsPrimary
)
358 PrimaryMonitor
= Monitor
;
363 BOOL intersects
= TRUE
;
365 /* check if the rect intersects the monitor */
366 if ((pRect
->right
< MonitorRect
.left
) || (pRect
->left
> MonitorRect
.right
) ||
367 (pRect
->bottom
< MonitorRect
.top
) || (pRect
->top
> MonitorRect
.bottom
))
372 if (flags
== MONITOR_DEFAULTTONEAREST
&& !intersects
)
374 INT distanceX
, distanceY
;
376 distanceX
= MIN(ABS(MonitorRect
.left
- pRect
->right
),
377 ABS(pRect
->left
- MonitorRect
.right
));
378 distanceY
= MIN(ABS(MonitorRect
.top
- pRect
->bottom
),
379 ABS(pRect
->top
- MonitorRect
.bottom
));
381 if (((distanceX
< iNearestDistanceX
) && (distanceY
<= iNearestDistanceY
)) ||
382 ((distanceX
<= iNearestDistanceX
) && (distanceY
< iNearestDistanceY
)))
384 iNearestDistanceX
= distanceX
;
385 iNearestDistanceY
= distanceY
;
386 NearestMonitor
= Monitor
;
393 /* calculate intersection */
394 IntersectionRect
.left
= MAX(MonitorRect
.left
, pRect
->left
);
395 IntersectionRect
.top
= MAX(MonitorRect
.top
, pRect
->top
);
396 IntersectionRect
.right
= MIN(MonitorRect
.right
, pRect
->right
);
397 IntersectionRect
.bottom
= MIN(MonitorRect
.bottom
, pRect
->bottom
);
401 IntersectionRect
= MonitorRect
;
404 if (iCount
< listSize
)
406 if (hMonitorList
!= NULL
)
407 hMonitorList
[iCount
] = UserHMGetHandle(Monitor
);
408 if (monitorRectList
!= NULL
)
409 monitorRectList
[iCount
] = IntersectionRect
;
414 if (iCount
== 0 && flags
== MONITOR_DEFAULTTONEAREST
)
416 if (iCount
< listSize
)
418 if (hMonitorList
!= NULL
)
419 hMonitorList
[iCount
] = UserHMGetHandle(NearestMonitor
);
423 else if (iCount
== 0 && flags
== MONITOR_DEFAULTTOPRIMARY
)
425 if (iCount
< listSize
)
427 if (hMonitorList
!= NULL
)
428 hMonitorList
[iCount
] = UserHMGetHandle(PrimaryMonitor
);
435 /* PUBLIC FUNCTIONS ***********************************************************/
437 /* NtUserEnumDisplayMonitors
439 * Enumerates display monitors which intersect the given HDC/cliprect
444 * Handle to a DC for which to enum intersecting monitors. If this is NULL
445 * it returns all monitors which are part of the current virtual screen.
448 * Clipping rectangle with coordinate system origin at the DCs origin if the
449 * given HDC is not NULL or in virtual screen coordinated if it is NULL.
453 * Pointer to an array of HMONITOR which is filled with monitor handles.
457 * Pointer to an array of RECT which is filled with intersection rectangles.
461 * Size of the hMonitorList and monitorRectList arguments. If this is zero
462 * hMonitorList and monitorRectList are ignored.
465 * The number of monitors which intersect the specified region or -1 on failure.
469 NtUserEnumDisplayMonitors(
471 OPTIONAL IN LPCRECTL pRect
,
472 OPTIONAL OUT HMONITOR
*hMonitorList
,
473 OPTIONAL OUT PRECTL monitorRectList
,
474 OPTIONAL IN DWORD listSize
)
477 HMONITOR
*safeHMonitorList
= NULL
;
478 PRECTL safeRectList
= NULL
;
486 status
= MmCopyFromCaller(&rect
, pRect
, sizeof (RECT
));
487 if (!NT_SUCCESS(status
))
489 DPRINT("MmCopyFromCaller() failed!\n");
490 SetLastNtError(status
);
501 /* get visible region bounding rect */
505 DPRINT("DC_LockDc() failed!\n");
506 /* FIXME: setlasterror? */
509 dcVisRgn
= ((PROSRGNDATA
)dc
->prgnVis
)->BaseObject
.hHmgr
;
512 regionType
= NtGdiGetRgnBox(dcVisRgn
, &dcRect
);
515 DPRINT("NtGdiGetRgnBox() failed!\n");
518 if (regionType
== NULLREGION
)
520 if (regionType
== COMPLEXREGION
)
521 { /* TODO: warning */
524 /* if hDC and pRect are given the area of interest is pRect with
525 coordinate origin at the DC position */
528 rect
.left
+= dcRect
.left
;
529 rect
.right
+= dcRect
.left
;
530 rect
.top
+= dcRect
.top
;
531 rect
.bottom
+= dcRect
.top
;
533 /* if hDC is given and pRect is not the area of interest is the
534 bounding rect of hDC */
541 if (hDC
== NULL
&& pRect
== NULL
)
546 /* find intersecting monitors */
547 numMonitors
= IntGetMonitorsFromRect(myRect
, NULL
, NULL
, 0, 0);
548 if (numMonitors
== 0 || listSize
== 0 ||
549 (hMonitorList
== NULL
&& monitorRectList
== NULL
))
551 DPRINT("numMonitors = %d\n", numMonitors
);
555 if (hMonitorList
!= NULL
&& listSize
!= 0)
557 safeHMonitorList
= ExAllocatePool(PagedPool
, sizeof (HMONITOR
) * listSize
);
558 if (safeHMonitorList
== NULL
)
560 /* FIXME: SetLastWin32Error? */
564 if (monitorRectList
!= NULL
&& listSize
!= 0)
566 safeRectList
= ExAllocatePool(PagedPool
, sizeof (RECT
) * listSize
);
567 if (safeRectList
== NULL
)
569 ExFreePool(safeHMonitorList
);
570 /* FIXME: SetLastWin32Error? */
575 /* get intersecting monitors */
576 numMonitors
= IntGetMonitorsFromRect(myRect
, safeHMonitorList
, safeRectList
,
579 if (hDC
!= NULL
&& pRect
!= NULL
&& safeRectList
!= NULL
)
580 for (i
= 0; i
< numMonitors
; i
++)
582 safeRectList
[i
].left
-= dcRect
.left
;
583 safeRectList
[i
].right
-= dcRect
.left
;
584 safeRectList
[i
].top
-= dcRect
.top
;
585 safeRectList
[i
].bottom
-= dcRect
.top
;
589 if (hMonitorList
!= NULL
&& listSize
!= 0)
591 status
= MmCopyToCaller(hMonitorList
, safeHMonitorList
, sizeof (HMONITOR
) * listSize
);
592 ExFreePool(safeHMonitorList
);
593 if (!NT_SUCCESS(status
))
595 ExFreePool(safeRectList
);
596 SetLastNtError(status
);
600 if (monitorRectList
!= NULL
&& listSize
!= 0)
602 status
= MmCopyToCaller(monitorRectList
, safeRectList
, sizeof (RECT
) * listSize
);
603 ExFreePool(safeRectList
);
604 if (!NT_SUCCESS(status
))
606 SetLastNtError(status
);
614 /* NtUserGetMonitorInfo
616 * Retrieves information about a given monitor
621 * Handle to a monitor for which to get information
624 * Pointer to a MONITORINFO struct which is filled with the information.
625 * The cbSize member must be set to sizeof(MONITORINFO) or
626 * sizeof(MONITORINFOEX). Even if set to sizeof(MONITORINFOEX) only parts
627 * from MONITORINFO will be filled.
630 * Pointer to a UNICODE_STRING which will recieve the device's name. The
631 * length should be CCHDEVICENAME
635 * TRUE on success; FALSE on failure (calls SetLastNtError())
640 NtUserGetMonitorInfo(
641 IN HMONITOR hMonitor
,
642 OUT LPMONITORINFO pMonitorInfo
)
645 MONITORINFOEXW MonitorInfo
;
647 DECLARE_RETURN(BOOL
);
649 DPRINT("Enter NtUserGetMonitorInfo\n");
652 /* get monitor object */
653 if (!(Monitor
= UserGetMonitorObject(hMonitor
)))
655 DPRINT("Couldnt find monitor 0x%lx\n", hMonitor
);
659 if(pMonitorInfo
== NULL
)
661 SetLastNtError(STATUS_INVALID_PARAMETER
);
665 /* get size of pMonitorInfo */
666 Status
= MmCopyFromCaller(&MonitorInfo
.cbSize
, &pMonitorInfo
->cbSize
, sizeof (MonitorInfo
.cbSize
));
667 if (!NT_SUCCESS(Status
))
669 SetLastNtError(Status
);
672 if ((MonitorInfo
.cbSize
!= sizeof (MONITORINFO
)) &&
673 (MonitorInfo
.cbSize
!= sizeof (MONITORINFOEXW
)))
675 SetLastNtError(STATUS_INVALID_PARAMETER
);
679 /* fill monitor info */
680 MonitorInfo
.rcMonitor
.left
= 0; /* FIXME: get origin */
681 MonitorInfo
.rcMonitor
.top
= 0; /* FIXME: get origin */
682 MonitorInfo
.rcMonitor
.right
= MonitorInfo
.rcMonitor
.left
+ Monitor
->GdiDevice
->gdiinfo
.ulHorzRes
;
683 MonitorInfo
.rcMonitor
.bottom
= MonitorInfo
.rcMonitor
.top
+ Monitor
->GdiDevice
->gdiinfo
.ulVertRes
;
684 MonitorInfo
.rcWork
= MonitorInfo
.rcMonitor
; /* FIXME: use DEVMODE panning to calculate work area? */
685 MonitorInfo
.dwFlags
= 0;
687 if (Monitor
->IsPrimary
)
688 MonitorInfo
.dwFlags
|= MONITORINFOF_PRIMARY
;
690 /* fill device name */
691 if (MonitorInfo
.cbSize
== sizeof (MONITORINFOEXW
))
694 INT len
= Monitor
->DeviceName
.Length
;
695 if (len
>= CCHDEVICENAME
* sizeof (WCHAR
))
696 len
= (CCHDEVICENAME
- 1) * sizeof (WCHAR
);
698 memcpy(MonitorInfo
.szDevice
, Monitor
->DeviceName
.Buffer
, len
);
699 memcpy(MonitorInfo
.szDevice
+ (len
/ sizeof (WCHAR
)), &nul
, sizeof (WCHAR
));
703 Status
= MmCopyToCaller(pMonitorInfo
, &MonitorInfo
, MonitorInfo
.cbSize
);
704 if (!NT_SUCCESS(Status
))
706 DPRINT("GetMonitorInfo: MmCopyToCaller failed\n");
707 SetLastNtError(Status
);
711 DPRINT("GetMonitorInfo: success\n");
716 DPRINT("Leave NtUserGetMonitorInfo, ret=%i\n",_ret_
);
721 /* NtUserMonitorFromPoint
723 * Returns a handle to the monitor containing the given point.
728 * Point for which to find monitor
731 * Specifies the behaviour if the point isn't on any of the monitors.
734 * If the point is found a handle to the monitor is returned; if not the
735 * return value depends on dwFlags
739 NtUserMonitorFromPoint(
745 HMONITOR hMonitor
= NULL
;
748 InRect
.left
= InRect
.right
= point
.x
;
749 InRect
.top
= InRect
.bottom
= point
.y
;
751 /* find intersecting monitor */
752 NumMonitors
= IntGetMonitorsFromRect(&InRect
, &hMonitor
, NULL
, 1, 0);
755 return (HMONITOR
)NULL
;
758 if (hMonitor
== NULL
)
760 if (dwFlags
== MONITOR_DEFAULTTOPRIMARY
)
762 PMONITOR MonitorObj
= IntGetPrimaryMonitor();
764 hMonitor
= UserHMGetHandle(MonitorObj
);
766 else if (dwFlags
== MONITOR_DEFAULTTONEAREST
)
768 NumMonitors
= IntGetMonitorsFromRect(&InRect
, &hMonitor
, NULL
,
769 1, MONITOR_DEFAULTTONEAREST
);
770 /*ASSERT( (numMonitors > 0) && (hMonitor != NULL) );*/
772 /* else flag is DEFAULTTONULL */
778 /* NtUserMonitorFromRect
780 * Returns a handle to the monitor having the largest intersection with a
786 * Pointer to a RECT for which to find monitor
789 * Specifies the behaviour if no monitor intersects the given rect
792 * If a monitor intersects the rect a handle to it is returned; if not the
793 * return value depends on dwFlags
797 NtUserMonitorFromRect(
801 INT numMonitors
, iLargestArea
= -1, i
;
803 HMONITOR
*hMonitorList
;
804 HMONITOR hMonitor
= NULL
;
809 status
= MmCopyFromCaller(&rect
, pRect
, sizeof (RECT
));
810 if (!NT_SUCCESS(status
))
812 SetLastNtError(status
);
813 return (HMONITOR
)NULL
;
816 /* find intersecting monitors */
817 numMonitors
= IntGetMonitorsFromRect(&rect
, NULL
, NULL
, 0, 0);
820 return (HMONITOR
)NULL
;
823 if (numMonitors
== 0)
825 if (dwFlags
== MONITOR_DEFAULTTOPRIMARY
)
827 PMONITOR monitorObj
= IntGetPrimaryMonitor();
829 return UserHMGetHandle(monitorObj
);
831 else if (dwFlags
== MONITOR_DEFAULTTONEAREST
)
833 numMonitors
= IntGetMonitorsFromRect(&rect
, &hMonitor
, NULL
,
834 1, MONITOR_DEFAULTTONEAREST
);
835 if (numMonitors
<= 0)
838 return (HMONITOR
)NULL
;
844 /* else flag is DEFAULTTONULL */
845 return (HMONITOR
)NULL
;
848 hMonitorList
= ExAllocatePool(PagedPool
, sizeof (HMONITOR
) * numMonitors
);
849 if (hMonitorList
== NULL
)
851 /* FIXME: SetLastWin32Error? */
852 return (HMONITOR
)NULL
;
854 rectList
= ExAllocatePool(PagedPool
, sizeof (RECT
) * numMonitors
);
855 if (rectList
== NULL
)
857 ExFreePool(hMonitorList
);
858 /* FIXME: SetLastWin32Error? */
859 return (HMONITOR
)NULL
;
862 /* get intersecting monitors */
863 numMonitors
= IntGetMonitorsFromRect(&rect
, hMonitorList
, rectList
,
865 if (numMonitors
<= 0)
867 ExFreePool(hMonitorList
);
868 ExFreePool(rectList
);
869 return (HMONITOR
)NULL
;
872 /* find largest intersection */
873 for (i
= 0; i
< numMonitors
; i
++)
875 INT area
= (rectList
[i
].right
- rectList
[i
].left
) *
876 (rectList
[i
].bottom
- rectList
[i
].top
);
877 if (area
> iLargestArea
)
879 hMonitor
= hMonitorList
[i
];
883 ExFreePool(hMonitorList
);
884 ExFreePool(rectList
);
892 NtUserMonitorFromWindow(
896 PWINDOW_OBJECT Window
;
897 HMONITOR hMonitor
= NULL
;
899 DECLARE_RETURN(HMONITOR
);
901 DPRINT("Enter NtUserMonitorFromWindow\n");
904 if (!(Window
= UserGetWindowObject(hWnd
)))
906 if (dwFlags
== MONITOR_DEFAULTTONULL
)
910 IntGetMonitorsFromRect(NULL
, &hMonitor
, NULL
, 1, dwFlags
);
917 Rect
.left
= Rect
.right
= Window
->Wnd
->rcWindow
.left
;
918 Rect
.top
= Rect
.bottom
= Window
->Wnd
->rcWindow
.bottom
;
920 IntGetMonitorsFromRect(&Rect
, &hMonitor
, NULL
, 1, dwFlags
);
925 DPRINT("Leave NtUserMonitorFromWindow, ret=%i\n",_ret_
);