ReactOS 0.4.16-dev-1946-g52006dd
monitor.c
Go to the documentation of this file.
1/*
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)
8 */
9
10#include <win32k.h>
12
13#define NDEBUG
14#include <debug.h>
15
16/* GLOBALS *******************************************************************/
17
18/* List of monitors */
20
21/* PRIVATE FUNCTIONS **********************************************************/
22
23/* IntCreateMonitorObject
24 *
25 * Creates a MONITOR
26 *
27 * Return value
28 * If the function succeeds a pointer to a MONITOR is returned. On failure
29 * NULL is returned.
30 */
31static
34{
36}
37
38/* IntDestroyMonitorObject
39 *
40 * Destroys a MONITOR
41 * You have to be the owner of the monitors lock to safely destroy it.
42 *
43 * Arguments
44 *
45 * pMonitor
46 * Pointer to the MONITOR which shall be deleted
47 */
48static
49void
51{
52 /* Remove monitor region */
53 if (pMonitor->hrgnMonitor)
54 {
55 GreSetObjectOwner(pMonitor->hrgnMonitor, GDI_OBJ_HMGR_POWNED);
56 GreDeleteObject(pMonitor->hrgnMonitor);
57 }
58
59 /* Destroy monitor object */
60 UserDereferenceObject(pMonitor);
62}
63
64/* UserGetMonitorObject
65 *
66 * Returns monitor object from handle or sets last error if handle is invalid
67 *
68 * Arguments
69 *
70 * hMonitor
71 * Handle of MONITOR object
72 */
75{
76 PMONITOR pMonitor;
77
78 if (!hMonitor)
79 {
81 return NULL;
82 }
83
84 pMonitor = (PMONITOR)UserGetObject(gHandleTable, hMonitor, TYPE_MONITOR);
85 if (!pMonitor)
86 {
88 return NULL;
89 }
90
91 return pMonitor;
92}
93
94/* UserGetPrimaryMonitor
95 *
96 * Returns a PMONITOR for the primary monitor
97 *
98 * Return value
99 * PMONITOR
100 */
103{
104 PMONITOR pMonitor;
105
106 /* Find primary monitor */
107 for (pMonitor = gMonitorList; pMonitor != NULL; pMonitor = pMonitor->pMonitorNext)
108 {
109 if (pMonitor->IsPrimary)
110 break;
111 }
112
113 return pMonitor;
114}
115
116/* UserAttachMonitor
117 *
118 * Creates a new MONITOR and appends it to the list of monitors.
119 *
120 * Arguments
121 *
122 * pGdiDevice Pointer to the PDEVOBJ onto which the monitor was attached
123 * DisplayNumber Display Number (starting with 0)
124 *
125 * Return value
126 * Returns a NTSTATUS
127 */
130{
131 PMONITOR pMonitor;
132
133 TRACE("Attaching monitor...\n");
134
135 /* Create new monitor object */
136 pMonitor = IntCreateMonitorObject();
137 if (pMonitor == NULL)
138 {
139 TRACE("Couldnt create monitor object\n");
141 }
142
143 pMonitor->hDev = hDev;
144 pMonitor->cWndStack = 0;
145
146 if (gMonitorList == NULL)
147 {
148 TRACE("Primary monitor is beeing attached\n");
149 pMonitor->IsPrimary = TRUE;
150 gMonitorList = pMonitor;
151 }
152 else
153 {
154 PMONITOR pmonLast = gMonitorList;
155 TRACE("Additional monitor is beeing attached\n");
156 while (pmonLast->pMonitorNext != NULL)
157 pmonLast = pmonLast->pMonitorNext;
158
159 pmonLast->pMonitorNext = pMonitor;
160 }
161
163
164 return STATUS_SUCCESS;
165}
166
167/* UserDetachMonitor
168 *
169 * Deletes a MONITOR and removes it from the list of monitors.
170 *
171 * Arguments
172 *
173 * pGdiDevice Pointer to the PDEVOBJ from which the monitor was detached
174 *
175 * Return value
176 * Returns a NTSTATUS
177 */
180{
181 PMONITOR pMonitor = gMonitorList, *pLink = &gMonitorList;
182
183 /* Find monitor attached to given device */
184 while (pMonitor != NULL)
185 {
186 if (pMonitor->hDev == hDev)
187 break;
188
189 pLink = &pMonitor->pMonitorNext;
190 pMonitor = pMonitor->pMonitorNext;
191 }
192
193 if (pMonitor == NULL)
194 {
195 /* No monitor has been found */
197 }
198
199 /* We destroy primary monitor - set next as primary */
200 if (pMonitor->IsPrimary && pMonitor->pMonitorNext != NULL)
201 pMonitor->pMonitorNext->IsPrimary = TRUE;
202
203 /* Update Next ptr in previous monitor */
204 *pLink = pMonitor->pMonitorNext;
205
206 /* Finally destroy monitor */
207 IntDestroyMonitorObject(pMonitor);
208
209 return STATUS_SUCCESS;
210}
211
212/* UserUpdateMonitorSize
213 *
214 * Reset size of the monitor using atached device
215 *
216 * Arguments
217 *
218 * PMONITOR
219 * pGdiDevice Pointer to the PDEVOBJ, which size has changed
220 *
221 * Return value
222 * Returns a NTSTATUS
223 */
226{
227 PMONITOR pMonitor;
228 SIZEL DeviceSize;
229
230 /* Find monitor attached to given device */
231 for (pMonitor = gMonitorList; pMonitor != NULL; pMonitor = pMonitor->pMonitorNext)
232 {
233 if (pMonitor->hDev == hDev)
234 break;
235 }
236
237 if (pMonitor == NULL)
238 {
239 /* No monitor has been found */
241 }
242
243 /* Get the size of the hdev */
244 PDEVOBJ_sizl((PPDEVOBJ)hDev, &DeviceSize);
245
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;
252
253 /* Destroy monitor region... */
254 if (pMonitor->hrgnMonitor)
255 {
257 GreDeleteObject(pMonitor->hrgnMonitor);
258 }
259
260 /* ...and create new one */
262 pMonitor->rcMonitor.left,
263 pMonitor->rcMonitor.top,
264 pMonitor->rcMonitor.right,
265 pMonitor->rcMonitor.bottom);
266 if (pMonitor->hrgnMonitor)
268
269 //
270 // Should be Virtual accumulation of all the available monitors.
271 //
272 gpsi->rcScreenReal = pMonitor->rcMonitor;
273
274 return STATUS_SUCCESS;
275}
276
277/* IntGetMonitorsFromRect
278 *
279 * Returns a list of monitor handles/rectangles. The rectangles in the list are
280 * the areas of intersection with the monitors.
281 *
282 * Arguments
283 *
284 * pRect
285 * Rectangle in desktop coordinates. If this is NULL all monitors are
286 * returned and the rect list is filled with the sizes of the monitors.
287 *
288 * phMonitorList
289 * Pointer to an array of HMONITOR which is filled with monitor handles.
290 * Can be NULL
291 *
292 * prcMonitorList
293 * Pointer to an array of RECT which is filled with intersection rects in
294 * desktop coordinates.
295 * Can be NULL, will be ignored if no intersecting monitor is found and
296 * flags is MONITOR_DEFAULTTONEAREST
297 *
298 * dwListSize
299 * Size of the phMonitorList and prcMonitorList arguments. If this is zero
300 * phMonitorList and prcMonitorList are ignored.
301 *
302 * dwFlags
303 * Either 0 or MONITOR_DEFAULTTONEAREST (ignored if rect is NULL)
304 *
305 * Returns
306 * The number of monitors which intersect the specified region.
307 */
308static
309UINT
311 OPTIONAL OUT HMONITOR *phMonitorList,
312 OPTIONAL OUT PRECTL prcMonitorList,
313 OPTIONAL IN DWORD dwListSize,
315{
316 PMONITOR pMonitor, pNearestMonitor = NULL, pPrimaryMonitor = NULL;
317 UINT cMonitors = 0;
318 ULONG iNearestDistance = 0xffffffff;
319
320 /* Find monitors which intersects the rectangle */
321 for (pMonitor = gMonitorList; pMonitor != NULL; pMonitor = pMonitor->pMonitorNext)
322 {
323 RECTL MonitorRect, IntersectionRect;
324
325 MonitorRect = pMonitor->rcMonitor;
326
327 TRACE("MonitorRect: left = %d, top = %d, right = %d, bottom = %d\n",
328 MonitorRect.left, MonitorRect.top, MonitorRect.right, MonitorRect.bottom);
329
330 /* Save primary monitor for later usage */
331 if (dwFlags == MONITOR_DEFAULTTOPRIMARY && pMonitor->IsPrimary)
332 pPrimaryMonitor = pMonitor;
333
334 /* Check if a rect is given */
335 if (pRect == NULL)
336 {
337 /* No rect given, so use the full monitor rect */
338 IntersectionRect = MonitorRect;
339 }
340 /* We have a rect, calculate intersection */
341 else if (!RECTL_bIntersectRect(&IntersectionRect, &MonitorRect, pRect))
342 {
343 /* Rects did not intersect */
344 if (dwFlags == MONITOR_DEFAULTTONEAREST)
345 {
346 ULONG cx, cy, iDistance;
347
348 /* Get x and y distance */
349 cx = min(abs(MonitorRect.left - pRect->right),
350 abs(pRect->left - MonitorRect.right));
351 cy = min(abs(MonitorRect.top - pRect->bottom),
352 abs(pRect->top - MonitorRect.bottom));
353
354 /* Calculate distance square */
355 iDistance = cx * cx + cy * cy;
356
357 /* Check if this is the new nearest monitor */
358 if (iDistance < iNearestDistance)
359 {
360 iNearestDistance = iDistance;
361 pNearestMonitor = pMonitor;
362 }
363 }
364
365 continue;
366 }
367
368 /* Check if there's space in the buffer */
369 if (cMonitors < dwListSize)
370 {
371 /* Save monitor data */
372 if (phMonitorList != NULL)
373 phMonitorList[cMonitors] = UserHMGetHandle(pMonitor);
374 if (prcMonitorList != NULL)
375 prcMonitorList[cMonitors] = IntersectionRect;
376 }
377
378 /* Increase count of found monitors */
379 cMonitors++;
380 }
381
382 /* Nothing has been found? */
383 if (cMonitors == 0)
384 {
385 /* Check if we shall default to the nearest monitor */
386 if (dwFlags == MONITOR_DEFAULTTONEAREST && pNearestMonitor)
387 {
388 if (phMonitorList && dwListSize > 0)
389 phMonitorList[cMonitors] = UserHMGetHandle(pNearestMonitor);
390 cMonitors++;
391 }
392 /* Check if we shall default to the primary monitor */
393 else if (dwFlags == MONITOR_DEFAULTTOPRIMARY && pPrimaryMonitor)
394 {
395 if (phMonitorList != NULL && dwListSize > 0)
396 phMonitorList[cMonitors] = UserHMGetHandle(pPrimaryMonitor);
397 cMonitors++;
398 }
399 }
400
401 return cMonitors;
402}
403
406 _In_ LPCRECTL pRect,
408{
409 ULONG cMonitors, LargestArea = 0, i;
410 PRECTL prcMonitorList = NULL;
411 HMONITOR *phMonitorList = NULL;
412 HMONITOR hMonitor = NULL;
413
414 /* Find intersecting monitors */
415 cMonitors = IntGetMonitorsFromRect(pRect, &hMonitor, NULL, 1, dwFlags);
416 if (cMonitors <= 1)
417 {
418 /* No or one monitor found. Just return handle. */
419 goto cleanup;
420 }
421
422 /* There is more than one monitor. Find monitor with largest intersection.
423 Temporary reset hMonitor */
424 hMonitor = NULL;
425
426 /* Allocate helper buffers */
427 phMonitorList = ExAllocatePoolWithTag(PagedPool,
428 sizeof(HMONITOR) * cMonitors,
430 if (phMonitorList == NULL)
431 {
433 goto cleanup;
434 }
435
436 prcMonitorList = ExAllocatePoolWithTag(PagedPool,
437 sizeof(RECT) * cMonitors,
439 if (prcMonitorList == NULL)
440 {
442 goto cleanup;
443 }
444
445 /* Get intersecting monitors again but now with rectangle list */
446 cMonitors = IntGetMonitorsFromRect(pRect, phMonitorList, prcMonitorList, cMonitors, 0);
447
448 /* Find largest intersection */
449 for (i = 0; i < cMonitors; i++)
450 {
451 ULONG Area = (prcMonitorList[i].right - prcMonitorList[i].left) *
452 (prcMonitorList[i].bottom - prcMonitorList[i].top);
453 if (Area >= LargestArea)
454 {
455 hMonitor = phMonitorList[i];
456 LargestArea = Area;
457 }
458 }
459
460cleanup:
461 if (phMonitorList)
463 if (prcMonitorList)
465 return hMonitor;
466}
467
470 PRECTL pRect,
472{
473 HMONITOR hMonitor;
474
475 /* Check if flags are valid */
476 if (dwFlags != MONITOR_DEFAULTTONULL &&
477 dwFlags != MONITOR_DEFAULTTOPRIMARY &&
478 dwFlags != MONITOR_DEFAULTTONEAREST)
479 {
481 return NULL;
482 }
483
484 hMonitor = IntGetMonitorFromRect(pRect, dwFlags);
485 return UserGetMonitorObject(hMonitor);
486}
487
491 IN POINT pt,
493{
494 RECTL rc;
495 HMONITOR hMonitor = NULL;
496
497 /* Check if flags are valid */
498 if (dwFlags != MONITOR_DEFAULTTONULL &&
499 dwFlags != MONITOR_DEFAULTTOPRIMARY &&
500 dwFlags != MONITOR_DEFAULTTONEAREST)
501 {
503 return NULL;
504 }
505
506 /* Fill rect (bottom-right exclusive) */
507 rc.left = pt.x;
508 rc.right = pt.x + 1;
509 rc.top = pt.y;
510 rc.bottom = pt.y + 1;
511
512 /* Find intersecting monitor */
513 IntGetMonitorsFromRect(&rc, &hMonitor, NULL, 1, dwFlags);
514
515 return UserGetMonitorObject(hMonitor);
516}
517
518/* PUBLIC FUNCTIONS ***********************************************************/
519
520/* NtUserEnumDisplayMonitors
521 *
522 * Enumerates display monitors which intersect the given HDC/cliprect
523 *
524 * Arguments
525 *
526 * hdc
527 * Handle to a DC for which to enum intersecting monitors. If this is NULL
528 * it returns all monitors which are part of the current virtual screen.
529 *
530 * pUnsafeRect
531 * Clipping rectangle with coordinate system origin at the DCs origin if the
532 * given HDC is not NULL or in virtual screen coordinated if it is NULL.
533 * Can be NULL
534 *
535 * phUnsafeMonitorList
536 * Pointer to an array of HMONITOR which is filled with monitor handles.
537 * Can be NULL
538 *
539 * prcUnsafeMonitorList
540 * Pointer to an array of RECT which is filled with intersection rectangles.
541 * Can be NULL
542 *
543 * dwListSize
544 * Size of the hMonitorList and monitorRectList arguments. If this is zero
545 * hMonitorList and monitorRectList are ignored.
546 *
547 * Returns
548 * The number of monitors which intersect the specified region or -1 on failure.
549 */
550INT
554 OPTIONAL IN LPCRECTL pUnsafeRect,
555 OPTIONAL OUT HMONITOR *phUnsafeMonitorList,
556 OPTIONAL OUT PRECTL prcUnsafeMonitorList,
557 OPTIONAL IN DWORD dwListSize)
558{
559 UINT cMonitors, i;
560 INT iRet = -1;
561 HMONITOR *phMonitorList = NULL;
562 PRECTL prcMonitorList = NULL;
563 RECTL rc, *pRect;
564 RECTL DcRect = {0};
566
567 /* Get rectangle */
568 if (pUnsafeRect != NULL)
569 {
570 Status = MmCopyFromCaller(&rc, pUnsafeRect, sizeof(RECT));
571 if (!NT_SUCCESS(Status))
572 {
573 TRACE("MmCopyFromCaller() failed!\n");
575 return -1;
576 }
577 }
578
579 if (hdc != NULL)
580 {
581 PDC pDc;
582 INT iRgnType;
583
584 /* Get visible region bounding rect */
585 pDc = DC_LockDc(hdc);
586 if (pDc == NULL)
587 {
588 TRACE("DC_LockDc() failed!\n");
589 /* FIXME: setlasterror? */
590 return -1;
591 }
592 iRgnType = REGION_GetRgnBox(pDc->prgnVis, &DcRect);
593 DC_UnlockDc(pDc);
594
595 if (iRgnType == 0)
596 {
597 TRACE("NtGdiGetRgnBox() failed!\n");
598 return -1;
599 }
600 if (iRgnType == NULLREGION)
601 return 0;
602 if (iRgnType == COMPLEXREGION)
603 {
604 /* TODO: Warning */
605 }
606
607 /* If hdc and pRect are given the area of interest is pRect with
608 coordinate origin at the DC position */
609 if (pUnsafeRect != NULL)
610 {
611 rc.left += DcRect.left;
612 rc.right += DcRect.left;
613 rc.top += DcRect.top;
614 rc.bottom += DcRect.top;
615 }
616 /* If hdc is given and pRect is not the area of interest is the
617 bounding rect of hdc */
618 else
619 {
620 rc = DcRect;
621 }
622 }
623
624 if (hdc == NULL && pUnsafeRect == NULL)
625 pRect = NULL;
626 else
627 pRect = &rc;
628
630
631 /* Find intersecting monitors */
632 cMonitors = IntGetMonitorsFromRect(pRect, NULL, NULL, 0, MONITOR_DEFAULTTONULL);
633 if (cMonitors == 0 || dwListSize == 0 ||
634 (phUnsafeMonitorList == NULL && prcUnsafeMonitorList == NULL))
635 {
636 /* Simple case - just return monitors count */
637 TRACE("cMonitors = %u\n", cMonitors);
638 iRet = cMonitors;
639 goto cleanup;
640 }
641
642 /* Allocate safe buffers */
643 if (phUnsafeMonitorList != NULL && dwListSize != 0)
644 {
645 phMonitorList = ExAllocatePoolWithTag(PagedPool, sizeof (HMONITOR) * dwListSize, USERTAG_MONITORRECTS);
646 if (phMonitorList == NULL)
647 {
649 goto cleanup;
650 }
651 }
652 if (prcUnsafeMonitorList != NULL && dwListSize != 0)
653 {
654 prcMonitorList = ExAllocatePoolWithTag(PagedPool, sizeof(RECT) * dwListSize,USERTAG_MONITORRECTS);
655 if (prcMonitorList == NULL)
656 {
658 goto cleanup;
659 }
660 }
661
662 /* Get intersecting monitors */
663 cMonitors = IntGetMonitorsFromRect(pRect, phMonitorList, prcMonitorList,
664 dwListSize, MONITOR_DEFAULTTONULL);
665
666 if (hdc != NULL && pRect != NULL && prcMonitorList != NULL)
667 {
668 for (i = 0; i < min(cMonitors, dwListSize); i++)
669 {
670 _Analysis_assume_(i < dwListSize);
671 prcMonitorList[i].left -= DcRect.left;
672 prcMonitorList[i].right -= DcRect.left;
673 prcMonitorList[i].top -= DcRect.top;
674 prcMonitorList[i].bottom -= DcRect.top;
675 }
676 }
677
678 /* Output result */
679 if (phUnsafeMonitorList != NULL && dwListSize != 0)
680 {
681 Status = MmCopyToCaller(phUnsafeMonitorList, phMonitorList, sizeof(HMONITOR) * dwListSize);
682 if (!NT_SUCCESS(Status))
683 {
685 goto cleanup;
686 }
687 }
688 if (prcUnsafeMonitorList != NULL && dwListSize != 0)
689 {
690 Status = MmCopyToCaller(prcUnsafeMonitorList, prcMonitorList, sizeof(RECT) * dwListSize);
691 if (!NT_SUCCESS(Status))
692 {
694 goto cleanup;
695 }
696 }
697
698 /* Return monitors count on success */
699 iRet = cMonitors;
700
701cleanup:
702 if (phMonitorList)
704 if (prcMonitorList)
706
707 UserLeave();
708 return iRet;
709}
710
711/* NtUserGetMonitorInfo
712 *
713 * Retrieves information about a given monitor
714 *
715 * Arguments
716 *
717 * hMonitor
718 * Handle to a monitor for which to get information
719 *
720 * pMonitorInfoUnsafe
721 * Pointer to a MONITORINFO struct which is filled with the information.
722 * The cbSize member must be set to sizeof(MONITORINFO) or
723 * sizeof(MONITORINFOEX). Even if set to sizeof(MONITORINFOEX) only parts
724 * from MONITORINFO will be filled.
725 *
726 * pDevice
727 * Pointer to a UNICODE_STRING which will receive the device's name. The
728 * length should be CCHDEVICENAME
729 * Can be NULL
730 *
731 * Return value
732 * TRUE on success; FALSE on failure (calls SetLastNtError())
733 *
734 */
735BOOL
738 IN HMONITOR hMonitor,
739 OUT LPMONITORINFO pMonitorInfoUnsafe)
740{
741 PMONITOR pMonitor;
742 MONITORINFOEXW MonitorInfo;
744 BOOL bRet = FALSE;
745 PWCHAR pwstrDeviceName;
746
747 TRACE("Enter NtUserGetMonitorInfo\n");
749
750 /* Get monitor object */
751 pMonitor = UserGetMonitorObject(hMonitor);
752 if (!pMonitor)
753 {
754 TRACE("Couldnt find monitor %p\n", hMonitor);
755 goto cleanup;
756 }
757
758 /* Check if pMonitorInfoUnsafe is valid */
759 if(pMonitorInfoUnsafe == NULL)
760 {
762 goto cleanup;
763 }
764
765 pwstrDeviceName = ((PPDEVOBJ)(pMonitor->hDev))->pGraphicsDevice->szWinDeviceName;
766
767 /* Get size of pMonitorInfoUnsafe */
768 Status = MmCopyFromCaller(&MonitorInfo.cbSize, &pMonitorInfoUnsafe->cbSize, sizeof(MonitorInfo.cbSize));
769 if (!NT_SUCCESS(Status))
770 {
772 goto cleanup;
773 }
774
775 /* Check if size of struct is valid */
776 if (MonitorInfo.cbSize != sizeof(MONITORINFO) &&
777 MonitorInfo.cbSize != sizeof(MONITORINFOEXW))
778 {
780 goto cleanup;
781 }
782
783 /* Fill monitor info */
784 MonitorInfo.rcMonitor = pMonitor->rcMonitor;
785 MonitorInfo.rcWork = pMonitor->rcWork;
786 MonitorInfo.dwFlags = 0;
787 if (pMonitor->IsPrimary)
788 MonitorInfo.dwFlags |= MONITORINFOF_PRIMARY;
789
790 /* Fill device name */
791 if (MonitorInfo.cbSize == sizeof(MONITORINFOEXW))
792 {
793 RtlStringCbCopyNExW(MonitorInfo.szDevice,
794 sizeof(MonitorInfo.szDevice),
795 pwstrDeviceName,
796 (wcslen(pwstrDeviceName)+1) * sizeof(WCHAR),
798 }
799
800 /* Output data */
801 Status = MmCopyToCaller(pMonitorInfoUnsafe, &MonitorInfo, MonitorInfo.cbSize);
802 if (!NT_SUCCESS(Status))
803 {
804 TRACE("GetMonitorInfo: MmCopyToCaller failed\n");
806 goto cleanup;
807 }
808
809 TRACE("GetMonitorInfo: success\n");
810 bRet = TRUE;
811
812cleanup:
813 TRACE("Leave NtUserGetMonitorInfo, ret=%i\n", bRet);
814 UserLeave();
815 return bRet;
816}
817
818/* NtUserMonitorFromPoint
819 *
820 * Returns a handle to the monitor containing the given point.
821 *
822 * Arguments
823 *
824 * pt
825 * Point for which to find monitor
826 *
827 * dwFlags
828 * Specifies the behaviour if the point isn't on any of the monitors.
829 *
830 * Return value
831 * If the point is found a handle to the monitor is returned; if not the
832 * return value depends on dwFlags
833 */
837 _In_ POINT pt,
839{
840 RECTL rc;
841 HMONITOR hMonitor = NULL;
842
843 /* Check if flags are valid */
844 if (dwFlags != MONITOR_DEFAULTTONULL &&
845 dwFlags != MONITOR_DEFAULTTOPRIMARY &&
846 dwFlags != MONITOR_DEFAULTTONEAREST)
847 {
849 return NULL;
850 }
851
852 /* Fill rect (bottom-right exclusive) */
853 rc.left = pt.x;
854 rc.right = pt.x + 1;
855 rc.top = pt.y;
856 rc.bottom = pt.y + 1;
857
859
860 /* Find intersecting monitor */
861 IntGetMonitorsFromRect(&rc, &hMonitor, NULL, 1, dwFlags);
862
863 UserLeave();
864 return hMonitor;
865}
866
867/* NtUserMonitorFromRect
868 *
869 * Returns a handle to the monitor having the largest intersection with a
870 * given rectangle
871 *
872 * Arguments
873 *
874 * pRectUnsafe
875 * Pointer to a RECT for which to find monitor
876 *
877 * dwFlags
878 * Specifies the behaviour if no monitor intersects the given rect
879 *
880 * Return value
881 * If a monitor intersects the rect a handle to it is returned; if not the
882 * return value depends on dwFlags
883 */
887 _In_ LPCRECTL pRectUnsafe,
889{
890 RECTL Rect;
892 HMONITOR hMonitor;
893
894 /* Check if flags are valid */
895 if (dwFlags != MONITOR_DEFAULTTONULL &&
896 dwFlags != MONITOR_DEFAULTTOPRIMARY &&
897 dwFlags != MONITOR_DEFAULTTONEAREST)
898 {
900 return NULL;
901 }
902
903 /* Copy rectangle to safe buffer */
904 Status = MmCopyFromCaller(&Rect, pRectUnsafe, sizeof (RECT));
905 if (!NT_SUCCESS(Status))
906 {
908 return NULL;
909 }
910
912 {
913 Rect.right = Rect.left + 1;
914 Rect.bottom = Rect.top + 1;
915 }
916
918 hMonitor = IntGetMonitorFromRect(&Rect, dwFlags);
919 UserLeave();
920
921 return hMonitor;
922}
923
924
928 _In_ HWND hWnd,
930{
931 PWND pWnd;
932 HMONITOR hMonitor = NULL;
933 RECTL Rect = {0, 0, 0, 0};
934
935 TRACE("Enter NtUserMonitorFromWindow\n");
936
937 /* Check if flags are valid */
938 if (dwFlags != MONITOR_DEFAULTTONULL &&
939 dwFlags != MONITOR_DEFAULTTOPRIMARY &&
940 dwFlags != MONITOR_DEFAULTTONEAREST)
941 {
943 return NULL;
944 }
945
947
948 if (hWnd)
949 {
950 /* Get window object */
952 if (pWnd)
953 {
954 Rect = ((pWnd->style & WS_MINIMIZE) ? pWnd->InternalPos.NormalRect : pWnd->rcWindow);
956 {
957 Rect.right = Rect.left + 1;
958 Rect.bottom = Rect.top + 1;
959 }
960 }
961 }
962
963 hMonitor = IntGetMonitorFromRect(&Rect, dwFlags);
964
965 UserLeave();
966
967 TRACE("Leave NtUserMonitorFromWindow, ret=%p\n", hMonitor);
968 return hMonitor;
969}
HWND hWnd
Definition: settings.c:17
LONG NTSTATUS
Definition: precomp.h:26
#define DBG_DEFAULT_CHANNEL(ch)
Definition: debug.h:106
FORCEINLINE VOID DC_UnlockDc(PDC pdc)
Definition: dc.h:238
FORCEINLINE PDC DC_LockDc(HDC hdc)
Definition: dc.h:220
#define ERROR_NOT_ENOUGH_MEMORY
Definition: dderror.h:7
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define APIENTRY
Definition: api.h:79
static void cleanup(void)
Definition: main.c:1335
#define pt(x, y)
Definition: drawing.c:79
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define PagedPool
Definition: env_spec_w32.h:308
#define abs(i)
Definition: fconv.c:206
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
Status
Definition: gdiplustypes.h:25
GLdouble GLdouble GLdouble GLdouble top
Definition: glext.h:10859
GLint GLint bottom
Definition: glext.h:7726
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
PSERVERINFO gpsi
Definition: imm.c:18
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define UserHMGetHandle(obj)
Definition: ntuser.h:230
@ TYPE_MONITOR
Definition: ntuser.h:52
struct _PDEVOBJ * PPDEVOBJ
Definition: mdevobj.h:6
#define MmCopyToCaller(x, y, z)
Definition: mmcopy.h:19
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
HDC hdc
Definition: main.c:9
static HDC
Definition: imagelist.c:88
struct _MONITOR * PMONITOR
#define min(a, b)
Definition: monoChain.cc:55
unsigned int UINT
Definition: ndis.h:50
_In_ LPWSTR _In_ DWORD _In_ DWORD _In_ DWORD dwFlags
Definition: netsh.h:141
#define _In_
Definition: no_sal2.h:158
#define _Analysis_assume_
Definition: no_sal2.h:388
#define FASTCALL
Definition: nt_native.h:50
__kernel_entry W32KAPI HRGN APIENTRY NtGdiCreateRectRgn(_In_ INT xLeft, _In_ INT yTop, _In_ INT xRight, _In_ INT yBottom)
#define GDI_OBJ_HMGR_POWNED
Definition: ntgdihdl.h:117
#define GDI_OBJ_HMGR_PUBLIC
Definition: ntgdihdl.h:116
NTSTRSAFEAPI RtlStringCbCopyNExW(_Out_writes_bytes_(cbDest) NTSTRSAFE_PWSTR pszDest, _In_ size_t cbDest, _In_reads_bytes_(cbToCopy) STRSAFE_LPCWSTR pszSrc, _In_ size_t cbToCopy, _Outptr_opt_result_bytebuffer_(*pcbRemaining) NTSTRSAFE_PWSTR *ppszDestEnd, _Out_opt_ size_t *pcbRemaining, _In_ STRSAFE_DWORD dwFlags)
Definition: ntstrsafe.h:547
#define STRSAFE_FILL_BEHIND_NULL
Definition: ntstrsafe.h:32
VOID FASTCALL UserLeave(VOID)
Definition: ntuser.c:258
VOID FASTCALL UserEnterShared(VOID)
Definition: ntuser.c:242
PSIZEL FASTCALL PDEVOBJ_sizl(PPDEVOBJ ppdev, PSIZEL psizl)
Definition: pdevobj.c:1375
#define WS_MINIMIZE
Definition: pedump.c:622
#define MmCopyFromCaller
Definition: polytest.cpp:29
_Out_opt_ int _Out_opt_ int * cy
Definition: commctrl.h:586
_Out_opt_ int * cx
Definition: commctrl.h:585
#define STATUS_SUCCESS
Definition: shellext.h:65
#define TRACE(s)
Definition: solgame.cpp:4
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
Definition: polytest.cpp:41
long bottom
Definition: polytest.cpp:53
long right
Definition: polytest.cpp:53
long top
Definition: polytest.cpp:53
long left
Definition: polytest.cpp:53
SHORT cWndStack
Definition: monitor.h:22
RECT rcWork
Definition: monitor.h:19
HDEV hDev
Definition: monitor.h:23
RECT rcMonitor
Definition: monitor.h:18
HRGN hrgnMonitor
Definition: monitor.h:20
DWORD IsPrimary
Definition: monitor.h:15
struct _MONITOR * pMonitorNext
Definition: monitor.h:7
LONG cx
Definition: kdterminal.h:27
LONG cy
Definition: kdterminal.h:28
Definition: ntuser.h:694
DWORD style
Definition: ntuser.h:706
struct _WND::@5443 InternalPos
RECT rcWindow
Definition: ntuser.h:716
WCHAR szDevice[CCHDEVICENAME]
Definition: winuser.h:3906
Definition: windef.h:99
LONG right
Definition: windef.h:102
LONG bottom
Definition: windef.h:103
LONG top
Definition: windef.h:101
LONG left
Definition: windef.h:100
#define NTAPI
Definition: typedefs.h:36
int32_t INT
Definition: typedefs.h:58
#define IN
Definition: typedefs.h:39
uint16_t * PWCHAR
Definition: typedefs.h:56
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
PWND FASTCALL UserGetWindowObject(HWND hWnd)
Definition: window.c:124
VOID FASTCALL SetLastNtError(_In_ NTSTATUS Status)
Definition: error.c:31
BOOL NTAPI GreSetObjectOwner(HGDIOBJ hobj, ULONG ulOwner)
Definition: gdiobj.c:1268
BOOL NTAPI GreDeleteObject(HGDIOBJ hobj)
Definition: gdiobj.c:1165
BOOL FASTCALL RECTL_bIntersectRect(_Out_ RECTL *prclDst, _In_ const RECTL *prcl1, _In_ const RECTL *prcl2)
Definition: rect.c:55
FORCEINLINE BOOL RECTL_bIsEmptyRect(_In_ const RECTL *prcl)
Definition: rect.h:44
BOOL FASTCALL IntGdiSetRegionOwner(HRGN hRgn, DWORD OwnerMask)
Definition: region.c:2459
INT FASTCALL REGION_GetRgnBox(PREGION Rgn, PRECTL pRect)
Definition: region.c:2543
PMONITOR NTAPI UserMonitorFromRect(PRECTL pRect, DWORD dwFlags)
Definition: monitor.c:469
static PMONITOR gMonitorList
Definition: monitor.c:19
HMONITOR APIENTRY NtUserMonitorFromWindow(_In_ HWND hWnd, _In_ DWORD dwFlags)
Definition: monitor.c:927
static PMONITOR IntCreateMonitorObject(VOID)
Definition: monitor.c:33
PMONITOR NTAPI UserGetMonitorObject(IN HMONITOR hMonitor)
Definition: monitor.c:74
HMONITOR FASTCALL IntGetMonitorFromRect(_In_ LPCRECTL pRect, _In_ DWORD dwFlags)
Definition: monitor.c:405
BOOL APIENTRY NtUserGetMonitorInfo(IN HMONITOR hMonitor, OUT LPMONITORINFO pMonitorInfoUnsafe)
Definition: monitor.c:737
HMONITOR APIENTRY NtUserMonitorFromRect(_In_ LPCRECTL pRectUnsafe, _In_ DWORD dwFlags)
Definition: monitor.c:886
static UINT IntGetMonitorsFromRect(OPTIONAL IN LPCRECTL pRect, OPTIONAL OUT HMONITOR *phMonitorList, OPTIONAL OUT PRECTL prcMonitorList, OPTIONAL IN DWORD dwListSize, OPTIONAL IN DWORD dwFlags)
Definition: monitor.c:310
PMONITOR FASTCALL UserMonitorFromPoint(IN POINT pt, IN DWORD dwFlags)
Definition: monitor.c:490
INT APIENTRY NtUserEnumDisplayMonitors(OPTIONAL IN HDC hdc, OPTIONAL IN LPCRECTL pUnsafeRect, OPTIONAL OUT HMONITOR *phUnsafeMonitorList, OPTIONAL OUT PRECTL prcUnsafeMonitorList, OPTIONAL IN DWORD dwListSize)
Definition: monitor.c:552
NTSTATUS NTAPI UserAttachMonitor(IN HDEV hDev)
Definition: monitor.c:129
static void IntDestroyMonitorObject(IN PMONITOR pMonitor)
Definition: monitor.c:50
HMONITOR APIENTRY NtUserMonitorFromPoint(_In_ POINT pt, _In_ DWORD dwFlags)
Definition: monitor.c:836
NTSTATUS NTAPI UserUpdateMonitorSize(IN HDEV hDev)
Definition: monitor.c:225
NTSTATUS NTAPI UserDetachMonitor(IN HDEV hDev)
Definition: monitor.c:179
PMONITOR NTAPI UserGetPrimaryMonitor(VOID)
Definition: monitor.c:102
PVOID UserGetObject(PUSER_HANDLE_TABLE ht, HANDLE handle, HANDLE_TYPE type)
Definition: object.c:495
BOOL FASTCALL UserDereferenceObject(PVOID Object)
Definition: object.c:644
BOOL FASTCALL UserDeleteObject(HANDLE h, HANDLE_TYPE type)
Definition: object.c:717
PUSER_HANDLE_TABLE gHandleTable
Definition: object.c:13
PVOID FASTCALL UserCreateObject(PUSER_HANDLE_TABLE ht, PDESKTOP pDesktop, PTHREADINFO pti, HANDLE *h, HANDLE_TYPE type, ULONG size)
Definition: object.c:568
#define USERTAG_MONITORRECTS
Definition: tags.h:254
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:22
#define ERROR_INVALID_MONITOR_HANDLE
Definition: winerror.h:1287
#define ERROR_INVALID_FLAGS
Definition: winerror.h:907
#define COMPLEXREGION
Definition: wingdi.h:363
#define NULLREGION
Definition: wingdi.h:361
__wchar_t WCHAR
Definition: xmlstorage.h:180