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
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, 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_OBJECT 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
79 * Creates a MONITOR_OBJECT
82 * If the function succeeds a pointer to a MONITOR_OBJECT is returned. On failure
87 IntCreateMonitorObject()
90 PMONITOR_OBJECT Monitor
;
92 Monitor
= UserCreateObject(gHandleTable
, &Handle
, otMonitor
, sizeof (MONITOR_OBJECT
));
98 Monitor
->Handle
= Handle
;
99 ExInitializeFastMutex(&Monitor
->Lock
);
104 /* IntDestroyMonitorObject
106 * Destroys a MONITOR_OBJECT
107 * You have to be the owner of the monitors lock to safely destroy it.
112 * Pointer to the MONITOR_OBJECT which shall be deleted
116 IntDestroyMonitorObject(IN PMONITOR_OBJECT pMonitor
)
118 RtlFreeUnicodeString(&pMonitor
->DeviceName
);
119 UserDereferenceObject(pMonitor
);
123 PMONITOR_OBJECT FASTCALL
124 UserGetMonitorObject(IN HMONITOR hMonitor
)
126 PMONITOR_OBJECT Monitor
;
130 SetLastWin32Error(ERROR_INVALID_MONITOR_HANDLE
);
135 Monitor
= (PMONITOR_OBJECT
)UserGetObject(gHandleTable
, hMonitor
, otMonitor
);
138 SetLastWin32Error(ERROR_INVALID_MONITOR_HANDLE
);
142 ASSERT(USER_BODY_TO_HEADER(Monitor
)->RefCount
>= 0);
150 * Creates a new MONITOR_OBJECT and appends it to the list of monitors.
154 * pGdiDevice Pointer to the PDEVOBJ onto which the monitor was attached
155 * DisplayNumber Display Number (starting with 0)
161 IntAttachMonitor(IN PDEVOBJ
*pGdiDevice
,
162 IN ULONG DisplayNumber
)
164 PMONITOR_OBJECT Monitor
;
165 WCHAR Buffer
[CCHDEVICENAME
];
167 DPRINT("Attaching monitor...\n");
169 /* create new monitor object */
170 Monitor
= IntCreateMonitorObject();
173 DPRINT("Couldnt create monitor object\n");
174 return STATUS_INSUFFICIENT_RESOURCES
;
177 _snwprintf(Buffer
, CCHDEVICENAME
, L
"\\\\.\\DISPLAY%d", DisplayNumber
+ 1);
178 if (!RtlCreateUnicodeString(&Monitor
->DeviceName
, Buffer
))
180 DPRINT("Couldn't duplicate monitor name!\n");
181 UserDereferenceObject(Monitor
);
182 UserDeleteObject(Monitor
->Handle
, otMonitor
);
183 return STATUS_INSUFFICIENT_RESOURCES
;
186 Monitor
->GdiDevice
= pGdiDevice
;
187 if (gMonitorList
== NULL
)
189 DPRINT("Primary monitor is beeing attached\n");
190 Monitor
->IsPrimary
= TRUE
;
191 gMonitorList
= Monitor
;
196 DPRINT("Additional monitor is beeing attached\n");
197 for (p
= gMonitorList
; p
->Next
!= NULL
; p
= p
->Next
)
205 return STATUS_SUCCESS
;
210 * Deletes a MONITOR_OBJECT and removes it from the list of monitors.
214 * pGdiDevice Pointer to the PDEVOBJ from which the monitor was detached
220 IntDetachMonitor(IN PDEVOBJ
*pGdiDevice
)
222 PMONITOR_OBJECT Monitor
;
224 for (Monitor
= gMonitorList
; Monitor
!= NULL
; Monitor
= Monitor
->Next
)
226 if (Monitor
->GdiDevice
== pGdiDevice
)
232 /* no monitor for given device found */
233 return STATUS_INVALID_PARAMETER
;
236 if (Monitor
->IsPrimary
&& (Monitor
->Next
!= NULL
|| Monitor
->Prev
!= NULL
))
238 PMONITOR_OBJECT NewPrimaryMonitor
= (Monitor
->Prev
!= NULL
) ? (Monitor
->Prev
) : (Monitor
->Next
);
240 ExEnterCriticalRegionAndAcquireFastMutexUnsafe(&NewPrimaryMonitor
->Lock
);
241 NewPrimaryMonitor
->IsPrimary
= TRUE
;
242 ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&NewPrimaryMonitor
->Lock
);
245 if (gMonitorList
== Monitor
)
247 gMonitorList
= Monitor
->Next
;
248 if (Monitor
->Next
!= NULL
)
249 Monitor
->Next
->Prev
= NULL
;
253 Monitor
->Prev
->Next
= Monitor
->Next
;
254 if (Monitor
->Next
!= NULL
)
255 Monitor
->Next
->Prev
= Monitor
->Prev
;
258 IntDestroyMonitorObject(Monitor
);
260 return STATUS_SUCCESS
;
263 /* IntGetPrimaryMonitor
265 * Returns a PMONITOR_OBJECT for the primary monitor
272 IntGetPrimaryMonitor()
274 PMONITOR_OBJECT Monitor
;
276 for (Monitor
= gMonitorList
; Monitor
!= NULL
; Monitor
= Monitor
->Next
)
278 /* FIXME: I guess locking the monitor is not neccessary to read 1 int */
279 if (Monitor
->IsPrimary
)
286 /* IntGetMonitorsFromRect
288 * Returns a list of monitor handles/rectangles. The rectangles in the list are
289 * the areas of intersection with the monitors.
294 * Rectangle in desktop coordinates. If this is NULL all monitors are
295 * returned and the rect list is filled with the sizes of the monitors.
298 * Pointer to an array of HMONITOR which is filled with monitor handles.
302 * Pointer to an array of RECT which is filled with intersection rects in
303 * desktop coordinates.
304 * Can be NULL, will be ignored if no intersecting monitor is found and
305 * flags is MONITOR_DEFAULTTONEAREST
308 * Size of the hMonitorList and monitorRectList arguments. If this is zero
309 * hMonitorList and monitorRectList are ignored.
312 * Either 0 or MONITOR_DEFAULTTONEAREST (ignored if rect is NULL)
315 * The number of monitors which intersect the specified region.
319 IntGetMonitorsFromRect(OPTIONAL IN LPCRECTL pRect
,
320 OPTIONAL OUT HMONITOR
*hMonitorList
,
321 OPTIONAL OUT PRECTL monitorRectList
,
322 OPTIONAL IN DWORD listSize
,
323 OPTIONAL IN DWORD flags
)
325 PMONITOR_OBJECT Monitor
, NearestMonitor
= NULL
, PrimaryMonitor
= NULL
;
327 LONG iNearestDistanceX
= 0x7fffffff, iNearestDistanceY
= 0x7fffffff;
329 /* find monitors which intersect the rectangle */
330 for (Monitor
= gMonitorList
; Monitor
!= NULL
; Monitor
= Monitor
->Next
)
332 RECTL MonitorRect
, IntersectionRect
;
334 ExEnterCriticalRegionAndAcquireFastMutexUnsafe(&Monitor
->Lock
);
335 MonitorRect
.left
= 0; /* FIXME: get origin */
336 MonitorRect
.top
= 0; /* FIXME: get origin */
337 MonitorRect
.right
= MonitorRect
.left
+ Monitor
->GdiDevice
->GDIInfo
.ulHorzRes
;
338 MonitorRect
.bottom
= MonitorRect
.top
+ Monitor
->GdiDevice
->GDIInfo
.ulVertRes
;
339 ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&Monitor
->Lock
);
341 DPRINT("MonitorRect: left = %d, top = %d, right = %d, bottom = %d\n",
342 MonitorRect
.left
, MonitorRect
.top
, MonitorRect
.right
, MonitorRect
.bottom
);
344 if (flags
== MONITOR_DEFAULTTOPRIMARY
&& Monitor
->IsPrimary
)
346 PrimaryMonitor
= Monitor
;
351 BOOL intersects
= TRUE
;
353 /* check if the rect intersects the monitor */
354 if ((pRect
->right
< MonitorRect
.left
) || (pRect
->left
> MonitorRect
.right
) ||
355 (pRect
->bottom
< MonitorRect
.top
) || (pRect
->top
> MonitorRect
.bottom
))
360 if (flags
== MONITOR_DEFAULTTONEAREST
&& !intersects
)
362 INT distanceX
, distanceY
;
364 distanceX
= MIN(ABS(MonitorRect
.left
- pRect
->right
),
365 ABS(pRect
->left
- MonitorRect
.right
));
366 distanceY
= MIN(ABS(MonitorRect
.top
- pRect
->bottom
),
367 ABS(pRect
->top
- MonitorRect
.bottom
));
369 if (((distanceX
< iNearestDistanceX
) && (distanceY
<= iNearestDistanceY
)) ||
370 ((distanceX
<= iNearestDistanceX
) && (distanceY
< iNearestDistanceY
)))
372 iNearestDistanceX
= distanceX
;
373 iNearestDistanceY
= distanceY
;
374 NearestMonitor
= Monitor
;
381 /* calculate intersection */
382 IntersectionRect
.left
= MAX(MonitorRect
.left
, pRect
->left
);
383 IntersectionRect
.top
= MAX(MonitorRect
.top
, pRect
->top
);
384 IntersectionRect
.right
= MIN(MonitorRect
.right
, pRect
->right
);
385 IntersectionRect
.bottom
= MIN(MonitorRect
.bottom
, pRect
->bottom
);
389 IntersectionRect
= MonitorRect
;
392 if (iCount
< listSize
)
394 if (hMonitorList
!= NULL
)
395 hMonitorList
[iCount
] = Monitor
->Handle
;
396 if (monitorRectList
!= NULL
)
397 monitorRectList
[iCount
] = IntersectionRect
;
402 if (iCount
== 0 && flags
== MONITOR_DEFAULTTONEAREST
)
404 if (iCount
< listSize
)
406 if (hMonitorList
!= NULL
)
407 hMonitorList
[iCount
] = NearestMonitor
->Handle
;
411 else if (iCount
== 0 && flags
== MONITOR_DEFAULTTOPRIMARY
)
413 if (iCount
< listSize
)
415 if (hMonitorList
!= NULL
)
416 hMonitorList
[iCount
] = PrimaryMonitor
->Handle
;
423 /* PUBLIC FUNCTIONS ***********************************************************/
425 /* NtUserEnumDisplayMonitors
427 * Enumerates display monitors which intersect the given HDC/cliprect
432 * Handle to a DC for which to enum intersecting monitors. If this is NULL
433 * it returns all monitors which are part of the current virtual screen.
436 * Clipping rectangle with coordinate system origin at the DCs origin if the
437 * given HDC is not NULL or in virtual screen coordinated if it is NULL.
441 * Pointer to an array of HMONITOR which is filled with monitor handles.
445 * Pointer to an array of RECT which is filled with intersection rectangles.
449 * Size of the hMonitorList and monitorRectList arguments. If this is zero
450 * hMonitorList and monitorRectList are ignored.
453 * The number of monitors which intersect the specified region or -1 on failure.
457 NtUserEnumDisplayMonitors(
459 OPTIONAL IN LPCRECTL pRect
,
460 OPTIONAL OUT HMONITOR
*hMonitorList
,
461 OPTIONAL OUT PRECTL monitorRectList
,
462 OPTIONAL IN DWORD listSize
)
465 HMONITOR
*safeHMonitorList
= NULL
;
466 PRECTL safeRectList
= NULL
;
474 status
= MmCopyFromCaller(&rect
, pRect
, sizeof (RECT
));
475 if (!NT_SUCCESS(status
))
477 DPRINT("MmCopyFromCaller() failed!\n");
478 SetLastNtError(status
);
489 /* get visible region bounding rect */
493 DPRINT("DC_LockDc() failed!\n");
494 /* FIXME: setlasterror? */
497 dcVisRgn
= dc
->rosdc
.hVisRgn
;
500 regionType
= NtGdiGetRgnBox(dcVisRgn
, &dcRect
);
503 DPRINT("NtGdiGetRgnBox() failed!\n");
506 if (regionType
== NULLREGION
)
508 if (regionType
== COMPLEXREGION
)
509 { /* TODO: warning */
512 /* if hDC and pRect are given the area of interest is pRect with
513 coordinate origin at the DC position */
516 rect
.left
+= dcRect
.left
;
517 rect
.right
+= dcRect
.left
;
518 rect
.top
+= dcRect
.top
;
519 rect
.bottom
+= dcRect
.top
;
521 /* if hDC is given and pRect is not the area of interest is the
522 bounding rect of hDC */
529 if (hDC
== NULL
&& pRect
== NULL
)
534 /* find intersecting monitors */
535 numMonitors
= IntGetMonitorsFromRect(myRect
, NULL
, NULL
, 0, 0);
536 if (numMonitors
== 0 || listSize
== 0 ||
537 (hMonitorList
== NULL
&& monitorRectList
== NULL
))
539 DPRINT("numMonitors = %d\n", numMonitors
);
543 if (hMonitorList
!= NULL
&& listSize
!= 0)
545 safeHMonitorList
= ExAllocatePool(PagedPool
, sizeof (HMONITOR
) * listSize
);
546 if (safeHMonitorList
== NULL
)
548 /* FIXME: SetLastWin32Error? */
552 if (monitorRectList
!= NULL
&& listSize
!= 0)
554 safeRectList
= ExAllocatePool(PagedPool
, sizeof (RECT
) * listSize
);
555 if (safeRectList
== NULL
)
557 ExFreePool(safeHMonitorList
);
558 /* FIXME: SetLastWin32Error? */
563 /* get intersecting monitors */
564 numMonitors
= IntGetMonitorsFromRect(myRect
, safeHMonitorList
, safeRectList
,
567 if (hDC
!= NULL
&& pRect
!= NULL
&& safeRectList
!= NULL
)
568 for (i
= 0; i
< numMonitors
; i
++)
570 safeRectList
[i
].left
-= dcRect
.left
;
571 safeRectList
[i
].right
-= dcRect
.left
;
572 safeRectList
[i
].top
-= dcRect
.top
;
573 safeRectList
[i
].bottom
-= dcRect
.top
;
577 if (hMonitorList
!= NULL
&& listSize
!= 0)
579 status
= MmCopyToCaller(hMonitorList
, safeHMonitorList
, sizeof (HMONITOR
) * listSize
);
580 ExFreePool(safeHMonitorList
);
581 if (!NT_SUCCESS(status
))
583 ExFreePool(safeRectList
);
584 SetLastNtError(status
);
588 if (monitorRectList
!= NULL
&& listSize
!= 0)
590 status
= MmCopyToCaller(monitorRectList
, safeRectList
, sizeof (RECT
) * listSize
);
591 ExFreePool(safeRectList
);
592 if (!NT_SUCCESS(status
))
594 SetLastNtError(status
);
602 /* NtUserGetMonitorInfo
604 * Retrieves information about a given monitor
609 * Handle to a monitor for which to get information
612 * Pointer to a MONITORINFO struct which is filled with the information.
613 * The cbSize member must be set to sizeof(MONITORINFO) or
614 * sizeof(MONITORINFOEX). Even if set to sizeof(MONITORINFOEX) only parts
615 * from MONITORINFO will be filled.
618 * Pointer to a UNICODE_STRING which will recieve the device's name. The
619 * length should be CCHDEVICENAME
623 * TRUE on success; FALSE on failure (calls SetLastNtError())
628 NtUserGetMonitorInfo(
629 IN HMONITOR hMonitor
,
630 OUT LPMONITORINFO pMonitorInfo
)
632 PMONITOR_OBJECT Monitor
;
633 MONITORINFOEXW MonitorInfo
;
635 DECLARE_RETURN(BOOL
);
637 DPRINT("Enter NtUserGetMonitorInfo\n");
640 /* get monitor object */
641 if (!(Monitor
= UserGetMonitorObject(hMonitor
)))
643 DPRINT("Couldnt find monitor 0x%lx\n", hMonitor
);
647 if(pMonitorInfo
== NULL
)
649 SetLastNtError(STATUS_INVALID_PARAMETER
);
653 /* get size of pMonitorInfo */
654 Status
= MmCopyFromCaller(&MonitorInfo
.cbSize
, &pMonitorInfo
->cbSize
, sizeof (MonitorInfo
.cbSize
));
655 if (!NT_SUCCESS(Status
))
657 SetLastNtError(Status
);
660 if ((MonitorInfo
.cbSize
!= sizeof (MONITORINFO
)) &&
661 (MonitorInfo
.cbSize
!= sizeof (MONITORINFOEXW
)))
663 SetLastNtError(STATUS_INVALID_PARAMETER
);
667 /* fill monitor info */
668 MonitorInfo
.rcMonitor
.left
= 0; /* FIXME: get origin */
669 MonitorInfo
.rcMonitor
.top
= 0; /* FIXME: get origin */
670 MonitorInfo
.rcMonitor
.right
= MonitorInfo
.rcMonitor
.left
+ Monitor
->GdiDevice
->GDIInfo
.ulHorzRes
;
671 MonitorInfo
.rcMonitor
.bottom
= MonitorInfo
.rcMonitor
.top
+ Monitor
->GdiDevice
->GDIInfo
.ulVertRes
;
672 MonitorInfo
.rcWork
= MonitorInfo
.rcMonitor
; /* FIXME: use DEVMODE panning to calculate work area? */
673 MonitorInfo
.dwFlags
= 0;
675 if (Monitor
->IsPrimary
)
676 MonitorInfo
.dwFlags
|= MONITORINFOF_PRIMARY
;
678 /* fill device name */
679 if (MonitorInfo
.cbSize
== sizeof (MONITORINFOEXW
))
682 INT len
= Monitor
->DeviceName
.Length
;
683 if (len
>= CCHDEVICENAME
* sizeof (WCHAR
))
684 len
= (CCHDEVICENAME
- 1) * sizeof (WCHAR
);
686 memcpy(MonitorInfo
.szDevice
, Monitor
->DeviceName
.Buffer
, len
);
687 memcpy(MonitorInfo
.szDevice
+ (len
/ sizeof (WCHAR
)), &nul
, sizeof (WCHAR
));
691 Status
= MmCopyToCaller(pMonitorInfo
, &MonitorInfo
, MonitorInfo
.cbSize
);
692 if (!NT_SUCCESS(Status
))
694 DPRINT("GetMonitorInfo: MmCopyToCaller failed\n");
695 SetLastNtError(Status
);
699 DPRINT("GetMonitorInfo: success\n");
704 DPRINT("Leave NtUserGetMonitorInfo, ret=%i\n",_ret_
);
709 /* NtUserMonitorFromPoint
711 * Returns a handle to the monitor containing the given point.
716 * Point for which to find monitor
719 * Specifies the behaviour if the point isn't on any of the monitors.
722 * If the point is found a handle to the monitor is returned; if not the
723 * return value depends on dwFlags
727 NtUserMonitorFromPoint(
733 HMONITOR hMonitor
= NULL
;
736 InRect
.left
= InRect
.right
= point
.x
;
737 InRect
.top
= InRect
.bottom
= point
.y
;
739 /* find intersecting monitor */
740 NumMonitors
= IntGetMonitorsFromRect(&InRect
, &hMonitor
, NULL
, 1, 0);
743 return (HMONITOR
)NULL
;
746 if (hMonitor
== NULL
)
748 if (dwFlags
== MONITOR_DEFAULTTOPRIMARY
)
750 PMONITOR_OBJECT MonitorObj
= IntGetPrimaryMonitor();
752 hMonitor
= MonitorObj
->Handle
;
754 else if (dwFlags
== MONITOR_DEFAULTTONEAREST
)
756 NumMonitors
= IntGetMonitorsFromRect(&InRect
, &hMonitor
, NULL
,
757 1, MONITOR_DEFAULTTONEAREST
);
758 /*ASSERT( (numMonitors > 0) && (hMonitor != NULL) );*/
760 /* else flag is DEFAULTTONULL */
766 /* NtUserMonitorFromRect
768 * Returns a handle to the monitor having the largest intersection with a
774 * Pointer to a RECT for which to find monitor
777 * Specifies the behaviour if no monitor intersects the given rect
780 * If a monitor intersects the rect a handle to it is returned; if not the
781 * return value depends on dwFlags
785 NtUserMonitorFromRect(
789 INT numMonitors
, iLargestArea
= -1, i
;
791 HMONITOR
*hMonitorList
;
792 HMONITOR hMonitor
= NULL
;
797 status
= MmCopyFromCaller(&rect
, pRect
, sizeof (RECT
));
798 if (!NT_SUCCESS(status
))
800 SetLastNtError(status
);
801 return (HMONITOR
)NULL
;
804 /* find intersecting monitors */
805 numMonitors
= IntGetMonitorsFromRect(&rect
, NULL
, NULL
, 0, 0);
808 return (HMONITOR
)NULL
;
811 if (numMonitors
== 0)
813 if (dwFlags
== MONITOR_DEFAULTTOPRIMARY
)
815 PMONITOR_OBJECT monitorObj
= IntGetPrimaryMonitor();
817 return monitorObj
->Handle
;
819 else if (dwFlags
== MONITOR_DEFAULTTONEAREST
)
821 numMonitors
= IntGetMonitorsFromRect(&rect
, &hMonitor
, NULL
,
822 1, MONITOR_DEFAULTTONEAREST
);
823 if (numMonitors
<= 0)
826 return (HMONITOR
)NULL
;
832 /* else flag is DEFAULTTONULL */
833 return (HMONITOR
)NULL
;
836 hMonitorList
= ExAllocatePool(PagedPool
, sizeof (HMONITOR
) * numMonitors
);
837 if (hMonitorList
== NULL
)
839 /* FIXME: SetLastWin32Error? */
840 return (HMONITOR
)NULL
;
842 rectList
= ExAllocatePool(PagedPool
, sizeof (RECT
) * numMonitors
);
843 if (rectList
== NULL
)
845 ExFreePool(hMonitorList
);
846 /* FIXME: SetLastWin32Error? */
847 return (HMONITOR
)NULL
;
850 /* get intersecting monitors */
851 numMonitors
= IntGetMonitorsFromRect(&rect
, hMonitorList
, rectList
,
853 if (numMonitors
<= 0)
855 ExFreePool(hMonitorList
);
856 ExFreePool(rectList
);
857 return (HMONITOR
)NULL
;
860 /* find largest intersection */
861 for (i
= 0; i
< numMonitors
; i
++)
863 INT area
= (rectList
[i
].right
- rectList
[i
].left
) *
864 (rectList
[i
].bottom
- rectList
[i
].top
);
865 if (area
> iLargestArea
)
867 hMonitor
= hMonitorList
[i
];
871 ExFreePool(hMonitorList
);
872 ExFreePool(rectList
);
880 NtUserMonitorFromWindow(
884 PWINDOW_OBJECT Window
;
885 HMONITOR hMonitor
= NULL
;
887 DECLARE_RETURN(HMONITOR
);
889 DPRINT("Enter NtUserMonitorFromWindow\n");
892 if (!(Window
= UserGetWindowObject(hWnd
)))
894 if (dwFlags
== MONITOR_DEFAULTTONULL
)
898 IntGetMonitorsFromRect(NULL
, &hMonitor
, NULL
, 1, dwFlags
);
905 Rect
.left
= Rect
.right
= Window
->Wnd
->WindowRect
.left
;
906 Rect
.top
= Rect
.bottom
= Window
->Wnd
->WindowRect
.bottom
;
908 IntGetMonitorsFromRect(&Rect
, &hMonitor
, NULL
, 1, dwFlags
);
913 DPRINT("Leave NtUserMonitorFromWindow, ret=%i\n",_ret_
);