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
= Monitor
->rcMonitor
;
348 ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&Monitor
->Lock
);
350 DPRINT("MonitorRect: left = %d, top = %d, right = %d, bottom = %d\n",
351 MonitorRect
.left
, MonitorRect
.top
, MonitorRect
.right
, MonitorRect
.bottom
);
353 if (flags
== MONITOR_DEFAULTTOPRIMARY
&& Monitor
->IsPrimary
)
355 PrimaryMonitor
= Monitor
;
360 BOOL intersects
= TRUE
;
362 /* check if the rect intersects the monitor */
363 if ((pRect
->right
< MonitorRect
.left
) || (pRect
->left
> MonitorRect
.right
) ||
364 (pRect
->bottom
< MonitorRect
.top
) || (pRect
->top
> MonitorRect
.bottom
))
369 if (flags
== MONITOR_DEFAULTTONEAREST
&& !intersects
)
371 INT distanceX
, distanceY
;
373 distanceX
= MIN(ABS(MonitorRect
.left
- pRect
->right
),
374 ABS(pRect
->left
- MonitorRect
.right
));
375 distanceY
= MIN(ABS(MonitorRect
.top
- pRect
->bottom
),
376 ABS(pRect
->top
- MonitorRect
.bottom
));
378 if (((distanceX
< iNearestDistanceX
) && (distanceY
<= iNearestDistanceY
)) ||
379 ((distanceX
<= iNearestDistanceX
) && (distanceY
< iNearestDistanceY
)))
381 iNearestDistanceX
= distanceX
;
382 iNearestDistanceY
= distanceY
;
383 NearestMonitor
= Monitor
;
390 /* calculate intersection */
391 IntersectionRect
.left
= MAX(MonitorRect
.left
, pRect
->left
);
392 IntersectionRect
.top
= MAX(MonitorRect
.top
, pRect
->top
);
393 IntersectionRect
.right
= MIN(MonitorRect
.right
, pRect
->right
);
394 IntersectionRect
.bottom
= MIN(MonitorRect
.bottom
, pRect
->bottom
);
398 IntersectionRect
= MonitorRect
;
401 if (iCount
< listSize
)
403 if (hMonitorList
!= NULL
)
404 hMonitorList
[iCount
] = UserHMGetHandle(Monitor
);
405 if (monitorRectList
!= NULL
)
406 monitorRectList
[iCount
] = IntersectionRect
;
411 if (iCount
== 0 && flags
== MONITOR_DEFAULTTONEAREST
)
413 if (iCount
< listSize
)
415 if (hMonitorList
!= NULL
)
416 hMonitorList
[iCount
] = UserHMGetHandle(NearestMonitor
);
420 else if (iCount
== 0 && flags
== MONITOR_DEFAULTTOPRIMARY
)
422 if (iCount
< listSize
)
424 if (hMonitorList
!= NULL
)
425 hMonitorList
[iCount
] = UserHMGetHandle(PrimaryMonitor
);
432 /* PUBLIC FUNCTIONS ***********************************************************/
434 /* NtUserEnumDisplayMonitors
436 * Enumerates display monitors which intersect the given HDC/cliprect
441 * Handle to a DC for which to enum intersecting monitors. If this is NULL
442 * it returns all monitors which are part of the current virtual screen.
445 * Clipping rectangle with coordinate system origin at the DCs origin if the
446 * given HDC is not NULL or in virtual screen coordinated if it is NULL.
450 * Pointer to an array of HMONITOR which is filled with monitor handles.
454 * Pointer to an array of RECT which is filled with intersection rectangles.
458 * Size of the hMonitorList and monitorRectList arguments. If this is zero
459 * hMonitorList and monitorRectList are ignored.
462 * The number of monitors which intersect the specified region or -1 on failure.
466 NtUserEnumDisplayMonitors(
468 OPTIONAL IN LPCRECTL pRect
,
469 OPTIONAL OUT HMONITOR
*hMonitorList
,
470 OPTIONAL OUT PRECTL monitorRectList
,
471 OPTIONAL IN DWORD listSize
)
474 HMONITOR
*safeHMonitorList
= NULL
;
475 PRECTL safeRectList
= NULL
;
483 status
= MmCopyFromCaller(&rect
, pRect
, sizeof (RECT
));
484 if (!NT_SUCCESS(status
))
486 DPRINT("MmCopyFromCaller() failed!\n");
487 SetLastNtError(status
);
497 /* get visible region bounding rect */
501 DPRINT("DC_LockDc() failed!\n");
502 /* FIXME: setlasterror? */
505 regionType
= REGION_GetRgnBox(dc
->prgnVis
, &dcRect
);
510 DPRINT("NtGdiGetRgnBox() failed!\n");
513 if (regionType
== NULLREGION
)
515 if (regionType
== COMPLEXREGION
)
516 { /* TODO: warning */
519 /* if hDC and pRect are given the area of interest is pRect with
520 coordinate origin at the DC position */
523 rect
.left
+= dcRect
.left
;
524 rect
.right
+= dcRect
.left
;
525 rect
.top
+= dcRect
.top
;
526 rect
.bottom
+= dcRect
.top
;
528 /* if hDC is given and pRect is not the area of interest is the
529 bounding rect of hDC */
536 if (hDC
== NULL
&& pRect
== NULL
)
541 /* find intersecting monitors */
542 numMonitors
= IntGetMonitorsFromRect(myRect
, NULL
, NULL
, 0, 0);
543 if (numMonitors
== 0 || listSize
== 0 ||
544 (hMonitorList
== NULL
&& monitorRectList
== NULL
))
546 DPRINT("numMonitors = %d\n", numMonitors
);
550 if (hMonitorList
!= NULL
&& listSize
!= 0)
552 safeHMonitorList
= ExAllocatePoolWithTag(PagedPool
, sizeof (HMONITOR
) * listSize
, USERTAG_MONITORRECTS
);
553 if (safeHMonitorList
== NULL
)
555 /* FIXME: SetLastWin32Error? */
559 if (monitorRectList
!= NULL
&& listSize
!= 0)
561 safeRectList
= ExAllocatePoolWithTag(PagedPool
, sizeof (RECT
) * listSize
, USERTAG_MONITORRECTS
);
562 if (safeRectList
== NULL
)
564 ExFreePoolWithTag(safeHMonitorList
, USERTAG_MONITORRECTS
);
565 /* FIXME: SetLastWin32Error? */
570 /* get intersecting monitors */
571 numMonitors
= IntGetMonitorsFromRect(myRect
, safeHMonitorList
, safeRectList
,
574 if (hDC
!= NULL
&& pRect
!= NULL
&& safeRectList
!= NULL
)
575 for (i
= 0; i
< numMonitors
; i
++)
577 safeRectList
[i
].left
-= dcRect
.left
;
578 safeRectList
[i
].right
-= dcRect
.left
;
579 safeRectList
[i
].top
-= dcRect
.top
;
580 safeRectList
[i
].bottom
-= dcRect
.top
;
584 if (hMonitorList
!= NULL
&& listSize
!= 0)
586 status
= MmCopyToCaller(hMonitorList
, safeHMonitorList
, sizeof (HMONITOR
) * listSize
);
587 ExFreePool(safeHMonitorList
);
588 if (!NT_SUCCESS(status
))
590 ExFreePoolWithTag(safeRectList
, USERTAG_MONITORRECTS
);
591 SetLastNtError(status
);
595 if (monitorRectList
!= NULL
&& listSize
!= 0)
597 status
= MmCopyToCaller(monitorRectList
, safeRectList
, sizeof (RECT
) * listSize
);
598 ExFreePoolWithTag(safeRectList
, USERTAG_MONITORRECTS
);
599 if (!NT_SUCCESS(status
))
601 SetLastNtError(status
);
609 /* NtUserGetMonitorInfo
611 * Retrieves information about a given monitor
616 * Handle to a monitor for which to get information
619 * Pointer to a MONITORINFO struct which is filled with the information.
620 * The cbSize member must be set to sizeof(MONITORINFO) or
621 * sizeof(MONITORINFOEX). Even if set to sizeof(MONITORINFOEX) only parts
622 * from MONITORINFO will be filled.
625 * Pointer to a UNICODE_STRING which will recieve the device's name. The
626 * length should be CCHDEVICENAME
630 * TRUE on success; FALSE on failure (calls SetLastNtError())
635 NtUserGetMonitorInfo(
636 IN HMONITOR hMonitor
,
637 OUT LPMONITORINFO pMonitorInfo
)
640 MONITORINFOEXW MonitorInfo
;
642 DECLARE_RETURN(BOOL
);
644 DPRINT("Enter NtUserGetMonitorInfo\n");
647 /* get monitor object */
648 if (!(Monitor
= UserGetMonitorObject(hMonitor
)))
650 DPRINT("Couldnt find monitor 0x%lx\n", hMonitor
);
654 if(pMonitorInfo
== NULL
)
656 SetLastNtError(STATUS_INVALID_PARAMETER
);
660 /* get size of pMonitorInfo */
661 Status
= MmCopyFromCaller(&MonitorInfo
.cbSize
, &pMonitorInfo
->cbSize
, sizeof (MonitorInfo
.cbSize
));
662 if (!NT_SUCCESS(Status
))
664 SetLastNtError(Status
);
667 if ((MonitorInfo
.cbSize
!= sizeof (MONITORINFO
)) &&
668 (MonitorInfo
.cbSize
!= sizeof (MONITORINFOEXW
)))
670 SetLastNtError(STATUS_INVALID_PARAMETER
);
674 /* fill monitor info */
675 MonitorInfo
.rcMonitor
= Monitor
->rcMonitor
;
676 MonitorInfo
.rcWork
= Monitor
->rcWork
;
677 MonitorInfo
.dwFlags
= 0;
679 if (Monitor
->IsPrimary
)
680 MonitorInfo
.dwFlags
|= MONITORINFOF_PRIMARY
;
682 /* fill device name */
683 if (MonitorInfo
.cbSize
== sizeof (MONITORINFOEXW
))
686 INT len
= Monitor
->DeviceName
.Length
;
687 if (len
>= CCHDEVICENAME
* sizeof (WCHAR
))
688 len
= (CCHDEVICENAME
- 1) * sizeof (WCHAR
);
690 memcpy(MonitorInfo
.szDevice
, Monitor
->DeviceName
.Buffer
, len
);
691 memcpy(MonitorInfo
.szDevice
+ (len
/ sizeof (WCHAR
)), &nul
, sizeof (WCHAR
));
695 Status
= MmCopyToCaller(pMonitorInfo
, &MonitorInfo
, MonitorInfo
.cbSize
);
696 if (!NT_SUCCESS(Status
))
698 DPRINT("GetMonitorInfo: MmCopyToCaller failed\n");
699 SetLastNtError(Status
);
703 DPRINT("GetMonitorInfo: success\n");
708 DPRINT("Leave NtUserGetMonitorInfo, ret=%i\n",_ret_
);
713 /* NtUserMonitorFromPoint
715 * Returns a handle to the monitor containing the given point.
720 * Point for which to find monitor
723 * Specifies the behaviour if the point isn't on any of the monitors.
726 * If the point is found a handle to the monitor is returned; if not the
727 * return value depends on dwFlags
731 NtUserMonitorFromPoint(
737 HMONITOR hMonitor
= NULL
;
740 InRect
.left
= InRect
.right
= point
.x
;
741 InRect
.top
= InRect
.bottom
= point
.y
;
743 /* find intersecting monitor */
744 NumMonitors
= IntGetMonitorsFromRect(&InRect
, &hMonitor
, NULL
, 1, 0);
747 return (HMONITOR
)NULL
;
750 if (hMonitor
== NULL
)
752 if (dwFlags
== MONITOR_DEFAULTTOPRIMARY
)
754 PMONITOR MonitorObj
= IntGetPrimaryMonitor();
756 hMonitor
= UserHMGetHandle(MonitorObj
);
758 else if (dwFlags
== MONITOR_DEFAULTTONEAREST
)
760 NumMonitors
= IntGetMonitorsFromRect(&InRect
, &hMonitor
, NULL
,
761 1, MONITOR_DEFAULTTONEAREST
);
762 /*ASSERT( (numMonitors > 0) && (hMonitor != NULL) );*/
764 /* else flag is DEFAULTTONULL */
770 /* NtUserMonitorFromRect
772 * Returns a handle to the monitor having the largest intersection with a
778 * Pointer to a RECT for which to find monitor
781 * Specifies the behaviour if no monitor intersects the given rect
784 * If a monitor intersects the rect a handle to it is returned; if not the
785 * return value depends on dwFlags
789 NtUserMonitorFromRect(
793 INT numMonitors
, iLargestArea
= -1, i
;
795 HMONITOR
*hMonitorList
;
796 HMONITOR hMonitor
= NULL
;
801 status
= MmCopyFromCaller(&rect
, pRect
, sizeof (RECT
));
802 if (!NT_SUCCESS(status
))
804 SetLastNtError(status
);
805 return (HMONITOR
)NULL
;
808 /* find intersecting monitors */
809 numMonitors
= IntGetMonitorsFromRect(&rect
, NULL
, NULL
, 0, 0);
812 return (HMONITOR
)NULL
;
815 if (numMonitors
== 0)
817 if (dwFlags
== MONITOR_DEFAULTTOPRIMARY
)
819 PMONITOR monitorObj
= IntGetPrimaryMonitor();
821 return UserHMGetHandle(monitorObj
);
823 else if (dwFlags
== MONITOR_DEFAULTTONEAREST
)
825 numMonitors
= IntGetMonitorsFromRect(&rect
, &hMonitor
, NULL
,
826 1, MONITOR_DEFAULTTONEAREST
);
827 if (numMonitors
<= 0)
830 return (HMONITOR
)NULL
;
836 /* else flag is DEFAULTTONULL */
837 return (HMONITOR
)NULL
;
840 hMonitorList
= ExAllocatePoolWithTag(PagedPool
, sizeof (HMONITOR
) * numMonitors
, USERTAG_MONITORRECTS
);
841 if (hMonitorList
== NULL
)
843 /* FIXME: SetLastWin32Error? */
844 return (HMONITOR
)NULL
;
846 rectList
= ExAllocatePoolWithTag(PagedPool
, sizeof (RECT
) * numMonitors
, USERTAG_MONITORRECTS
);
847 if (rectList
== NULL
)
849 ExFreePoolWithTag(hMonitorList
, USERTAG_MONITORRECTS
);
850 /* FIXME: SetLastWin32Error? */
851 return (HMONITOR
)NULL
;
854 /* get intersecting monitors */
855 numMonitors
= IntGetMonitorsFromRect(&rect
, hMonitorList
, rectList
,
857 if (numMonitors
<= 0)
859 ExFreePoolWithTag(hMonitorList
, USERTAG_MONITORRECTS
);
860 ExFreePoolWithTag(rectList
, USERTAG_MONITORRECTS
);
861 return (HMONITOR
)NULL
;
864 /* find largest intersection */
865 for (i
= 0; i
< numMonitors
; i
++)
867 INT area
= (rectList
[i
].right
- rectList
[i
].left
) *
868 (rectList
[i
].bottom
- rectList
[i
].top
);
869 if (area
> iLargestArea
)
871 hMonitor
= hMonitorList
[i
];
875 ExFreePoolWithTag(hMonitorList
, USERTAG_MONITORRECTS
);
876 ExFreePoolWithTag(rectList
, USERTAG_MONITORRECTS
);
884 NtUserMonitorFromWindow(
888 PWINDOW_OBJECT Window
;
889 HMONITOR hMonitor
= NULL
;
891 DECLARE_RETURN(HMONITOR
);
893 DPRINT("Enter NtUserMonitorFromWindow\n");
896 if (!(Window
= UserGetWindowObject(hWnd
)))
898 if (dwFlags
== MONITOR_DEFAULTTONULL
)
902 IntGetMonitorsFromRect(NULL
, &hMonitor
, NULL
, 1, dwFlags
);
909 Rect
.left
= Rect
.right
= Window
->Wnd
->rcWindow
.left
;
910 Rect
.top
= Rect
.bottom
= Window
->Wnd
->rcWindow
.bottom
;
912 IntGetMonitorsFromRect(&Rect
, &hMonitor
, NULL
, 1, dwFlags
);
917 DPRINT("Leave NtUserMonitorFromWindow, ret=%i\n",_ret_
);