ReactOS 0.4.15-dev-7918-g2a2556c
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 PRECTL pRect,
408{
409 ULONG cMonitors, LargestArea = 0, i;
410 PRECTL prcMonitorList = NULL;
411 HMONITOR *phMonitorList = NULL;
412 HMONITOR hMonitor = NULL;
413
414 /* Check if flags are valid */
415 if (dwFlags != MONITOR_DEFAULTTONULL &&
416 dwFlags != MONITOR_DEFAULTTOPRIMARY &&
417 dwFlags != MONITOR_DEFAULTTONEAREST)
418 {
420 return NULL;
421 }
422
423 /* Find intersecting monitors */
424 cMonitors = IntGetMonitorsFromRect(pRect, &hMonitor, NULL, 1, dwFlags);
425 if (cMonitors <= 1)
426 {
427 /* No or one monitor found. Just return handle. */
428 goto cleanup;
429 }
430
431 /* There is more than one monitor. Find monitor with largest intersection.
432 Temporary reset hMonitor */
433 hMonitor = NULL;
434
435 /* Allocate helper buffers */
436 phMonitorList = ExAllocatePoolWithTag(PagedPool,
437 sizeof(HMONITOR) * cMonitors,
439 if (phMonitorList == NULL)
440 {
442 goto cleanup;
443 }
444
445 prcMonitorList = ExAllocatePoolWithTag(PagedPool,
446 sizeof(RECT) * cMonitors,
448 if (prcMonitorList == NULL)
449 {
451 goto cleanup;
452 }
453
454 /* Get intersecting monitors again but now with rectangle list */
455 cMonitors = IntGetMonitorsFromRect(pRect, phMonitorList, prcMonitorList,
456 cMonitors, 0);
457
458 /* Find largest intersection */
459 for (i = 0; i < cMonitors; i++)
460 {
461 ULONG Area = (prcMonitorList[i].right - prcMonitorList[i].left) *
462 (prcMonitorList[i].bottom - prcMonitorList[i].top);
463 if (Area >= LargestArea)
464 {
465 hMonitor = phMonitorList[i];
466 LargestArea = Area;
467 }
468 }
469
470cleanup:
471 if (phMonitorList)
473 if (prcMonitorList)
475
476 return UserGetMonitorObject(hMonitor);
477}
478
482 IN POINT pt,
484{
485 RECTL rc;
486 HMONITOR hMonitor = NULL;
487
488 /* Check if flags are valid */
489 if (dwFlags != MONITOR_DEFAULTTONULL &&
490 dwFlags != MONITOR_DEFAULTTOPRIMARY &&
491 dwFlags != MONITOR_DEFAULTTONEAREST)
492 {
494 return NULL;
495 }
496
497 /* Fill rect (bottom-right exclusive) */
498 rc.left = pt.x;
499 rc.right = pt.x + 1;
500 rc.top = pt.y;
501 rc.bottom = pt.y + 1;
502
503 /* Find intersecting monitor */
504 IntGetMonitorsFromRect(&rc, &hMonitor, NULL, 1, dwFlags);
505
506 return UserGetMonitorObject(hMonitor);
507}
508
509/* PUBLIC FUNCTIONS ***********************************************************/
510
511/* NtUserEnumDisplayMonitors
512 *
513 * Enumerates display monitors which intersect the given HDC/cliprect
514 *
515 * Arguments
516 *
517 * hdc
518 * Handle to a DC for which to enum intersecting monitors. If this is NULL
519 * it returns all monitors which are part of the current virtual screen.
520 *
521 * pUnsafeRect
522 * Clipping rectangle with coordinate system origin at the DCs origin if the
523 * given HDC is not NULL or in virtual screen coordinated if it is NULL.
524 * Can be NULL
525 *
526 * phUnsafeMonitorList
527 * Pointer to an array of HMONITOR which is filled with monitor handles.
528 * Can be NULL
529 *
530 * prcUnsafeMonitorList
531 * Pointer to an array of RECT which is filled with intersection rectangles.
532 * Can be NULL
533 *
534 * dwListSize
535 * Size of the hMonitorList and monitorRectList arguments. If this is zero
536 * hMonitorList and monitorRectList are ignored.
537 *
538 * Returns
539 * The number of monitors which intersect the specified region or -1 on failure.
540 */
541INT
545 OPTIONAL IN LPCRECTL pUnsafeRect,
546 OPTIONAL OUT HMONITOR *phUnsafeMonitorList,
547 OPTIONAL OUT PRECTL prcUnsafeMonitorList,
548 OPTIONAL IN DWORD dwListSize)
549{
550 UINT cMonitors, i;
551 INT iRet = -1;
552 HMONITOR *phMonitorList = NULL;
553 PRECTL prcMonitorList = NULL;
554 RECTL rc, *pRect;
555 RECTL DcRect = {0};
557
558 /* Get rectangle */
559 if (pUnsafeRect != NULL)
560 {
561 Status = MmCopyFromCaller(&rc, pUnsafeRect, sizeof(RECT));
562 if (!NT_SUCCESS(Status))
563 {
564 TRACE("MmCopyFromCaller() failed!\n");
566 return -1;
567 }
568 }
569
570 if (hdc != NULL)
571 {
572 PDC pDc;
573 INT iRgnType;
574
575 /* Get visible region bounding rect */
576 pDc = DC_LockDc(hdc);
577 if (pDc == NULL)
578 {
579 TRACE("DC_LockDc() failed!\n");
580 /* FIXME: setlasterror? */
581 return -1;
582 }
583 iRgnType = REGION_GetRgnBox(pDc->prgnVis, &DcRect);
584 DC_UnlockDc(pDc);
585
586 if (iRgnType == 0)
587 {
588 TRACE("NtGdiGetRgnBox() failed!\n");
589 return -1;
590 }
591 if (iRgnType == NULLREGION)
592 return 0;
593 if (iRgnType == COMPLEXREGION)
594 {
595 /* TODO: Warning */
596 }
597
598 /* If hdc and pRect are given the area of interest is pRect with
599 coordinate origin at the DC position */
600 if (pUnsafeRect != NULL)
601 {
602 rc.left += DcRect.left;
603 rc.right += DcRect.left;
604 rc.top += DcRect.top;
605 rc.bottom += DcRect.top;
606 }
607 /* If hdc is given and pRect is not the area of interest is the
608 bounding rect of hdc */
609 else
610 {
611 rc = DcRect;
612 }
613 }
614
615 if (hdc == NULL && pUnsafeRect == NULL)
616 pRect = NULL;
617 else
618 pRect = &rc;
619
621
622 /* Find intersecting monitors */
623 cMonitors = IntGetMonitorsFromRect(pRect, NULL, NULL, 0, MONITOR_DEFAULTTONULL);
624 if (cMonitors == 0 || dwListSize == 0 ||
625 (phUnsafeMonitorList == NULL && prcUnsafeMonitorList == NULL))
626 {
627 /* Simple case - just return monitors count */
628 TRACE("cMonitors = %u\n", cMonitors);
629 iRet = cMonitors;
630 goto cleanup;
631 }
632
633 /* Allocate safe buffers */
634 if (phUnsafeMonitorList != NULL && dwListSize != 0)
635 {
636 phMonitorList = ExAllocatePoolWithTag(PagedPool, sizeof (HMONITOR) * dwListSize, USERTAG_MONITORRECTS);
637 if (phMonitorList == NULL)
638 {
640 goto cleanup;
641 }
642 }
643 if (prcUnsafeMonitorList != NULL && dwListSize != 0)
644 {
645 prcMonitorList = ExAllocatePoolWithTag(PagedPool, sizeof(RECT) * dwListSize,USERTAG_MONITORRECTS);
646 if (prcMonitorList == NULL)
647 {
649 goto cleanup;
650 }
651 }
652
653 /* Get intersecting monitors */
654 cMonitors = IntGetMonitorsFromRect(pRect, phMonitorList, prcMonitorList,
655 dwListSize, MONITOR_DEFAULTTONULL);
656
657 if (hdc != NULL && pRect != NULL && prcMonitorList != NULL)
658 {
659 for (i = 0; i < min(cMonitors, dwListSize); i++)
660 {
661 _Analysis_assume_(i < dwListSize);
662 prcMonitorList[i].left -= DcRect.left;
663 prcMonitorList[i].right -= DcRect.left;
664 prcMonitorList[i].top -= DcRect.top;
665 prcMonitorList[i].bottom -= DcRect.top;
666 }
667 }
668
669 /* Output result */
670 if (phUnsafeMonitorList != NULL && dwListSize != 0)
671 {
672 Status = MmCopyToCaller(phUnsafeMonitorList, phMonitorList, sizeof(HMONITOR) * dwListSize);
673 if (!NT_SUCCESS(Status))
674 {
676 goto cleanup;
677 }
678 }
679 if (prcUnsafeMonitorList != NULL && dwListSize != 0)
680 {
681 Status = MmCopyToCaller(prcUnsafeMonitorList, prcMonitorList, sizeof(RECT) * dwListSize);
682 if (!NT_SUCCESS(Status))
683 {
685 goto cleanup;
686 }
687 }
688
689 /* Return monitors count on success */
690 iRet = cMonitors;
691
692cleanup:
693 if (phMonitorList)
695 if (prcMonitorList)
697
698 UserLeave();
699 return iRet;
700}
701
702/* NtUserGetMonitorInfo
703 *
704 * Retrieves information about a given monitor
705 *
706 * Arguments
707 *
708 * hMonitor
709 * Handle to a monitor for which to get information
710 *
711 * pMonitorInfoUnsafe
712 * Pointer to a MONITORINFO struct which is filled with the information.
713 * The cbSize member must be set to sizeof(MONITORINFO) or
714 * sizeof(MONITORINFOEX). Even if set to sizeof(MONITORINFOEX) only parts
715 * from MONITORINFO will be filled.
716 *
717 * pDevice
718 * Pointer to a UNICODE_STRING which will receive the device's name. The
719 * length should be CCHDEVICENAME
720 * Can be NULL
721 *
722 * Return value
723 * TRUE on success; FALSE on failure (calls SetLastNtError())
724 *
725 */
726BOOL
729 IN HMONITOR hMonitor,
730 OUT LPMONITORINFO pMonitorInfoUnsafe)
731{
732 PMONITOR pMonitor;
733 MONITORINFOEXW MonitorInfo;
735 BOOL bRet = FALSE;
736 PWCHAR pwstrDeviceName;
737
738 TRACE("Enter NtUserGetMonitorInfo\n");
740
741 /* Get monitor object */
742 pMonitor = UserGetMonitorObject(hMonitor);
743 if (!pMonitor)
744 {
745 TRACE("Couldnt find monitor %p\n", hMonitor);
746 goto cleanup;
747 }
748
749 /* Check if pMonitorInfoUnsafe is valid */
750 if(pMonitorInfoUnsafe == NULL)
751 {
753 goto cleanup;
754 }
755
756 pwstrDeviceName = ((PPDEVOBJ)(pMonitor->hDev))->pGraphicsDevice->szWinDeviceName;
757
758 /* Get size of pMonitorInfoUnsafe */
759 Status = MmCopyFromCaller(&MonitorInfo.cbSize, &pMonitorInfoUnsafe->cbSize, sizeof(MonitorInfo.cbSize));
760 if (!NT_SUCCESS(Status))
761 {
763 goto cleanup;
764 }
765
766 /* Check if size of struct is valid */
767 if (MonitorInfo.cbSize != sizeof(MONITORINFO) &&
768 MonitorInfo.cbSize != sizeof(MONITORINFOEXW))
769 {
771 goto cleanup;
772 }
773
774 /* Fill monitor info */
775 MonitorInfo.rcMonitor = pMonitor->rcMonitor;
776 MonitorInfo.rcWork = pMonitor->rcWork;
777 MonitorInfo.dwFlags = 0;
778 if (pMonitor->IsPrimary)
779 MonitorInfo.dwFlags |= MONITORINFOF_PRIMARY;
780
781 /* Fill device name */
782 if (MonitorInfo.cbSize == sizeof(MONITORINFOEXW))
783 {
784 RtlStringCbCopyNExW(MonitorInfo.szDevice,
785 sizeof(MonitorInfo.szDevice),
786 pwstrDeviceName,
787 (wcslen(pwstrDeviceName)+1) * sizeof(WCHAR),
789 }
790
791 /* Output data */
792 Status = MmCopyToCaller(pMonitorInfoUnsafe, &MonitorInfo, MonitorInfo.cbSize);
793 if (!NT_SUCCESS(Status))
794 {
795 TRACE("GetMonitorInfo: MmCopyToCaller failed\n");
797 goto cleanup;
798 }
799
800 TRACE("GetMonitorInfo: success\n");
801 bRet = TRUE;
802
803cleanup:
804 TRACE("Leave NtUserGetMonitorInfo, ret=%i\n", bRet);
805 UserLeave();
806 return bRet;
807}
808
809/* NtUserMonitorFromPoint
810 *
811 * Returns a handle to the monitor containing the given point.
812 *
813 * Arguments
814 *
815 * pt
816 * Point for which to find monitor
817 *
818 * dwFlags
819 * Specifies the behaviour if the point isn't on any of the monitors.
820 *
821 * Return value
822 * If the point is found a handle to the monitor is returned; if not the
823 * return value depends on dwFlags
824 */
828 IN POINT pt,
830{
831 RECTL rc;
832 HMONITOR hMonitor = NULL;
833
834 /* Check if flags are valid */
835 if (dwFlags != MONITOR_DEFAULTTONULL &&
836 dwFlags != MONITOR_DEFAULTTOPRIMARY &&
837 dwFlags != MONITOR_DEFAULTTONEAREST)
838 {
840 return NULL;
841 }
842
843 /* Fill rect (bottom-right exclusive) */
844 rc.left = pt.x;
845 rc.right = pt.x + 1;
846 rc.top = pt.y;
847 rc.bottom = pt.y + 1;
848
850
851 /* Find intersecting monitor */
852 IntGetMonitorsFromRect(&rc, &hMonitor, NULL, 1, dwFlags);
853
854 UserLeave();
855 return hMonitor;
856}
857
858/* NtUserMonitorFromRect
859 *
860 * Returns a handle to the monitor having the largest intersection with a
861 * given rectangle
862 *
863 * Arguments
864 *
865 * pRectUnsafe
866 * Pointer to a RECT for which to find monitor
867 *
868 * dwFlags
869 * Specifies the behaviour if no monitor intersects the given rect
870 *
871 * Return value
872 * If a monitor intersects the rect a handle to it is returned; if not the
873 * return value depends on dwFlags
874 */
878 IN LPCRECTL pRectUnsafe,
880{
881 ULONG cMonitors, LargestArea = 0, i;
882 PRECTL prcMonitorList = NULL;
883 HMONITOR *phMonitorList = NULL;
884 HMONITOR hMonitor = NULL;
885 RECTL Rect;
887
888 /* Check if flags are valid */
889 if (dwFlags != MONITOR_DEFAULTTONULL &&
890 dwFlags != MONITOR_DEFAULTTOPRIMARY &&
891 dwFlags != MONITOR_DEFAULTTONEAREST)
892 {
894 return NULL;
895 }
896
897 /* Copy rectangle to safe buffer */
898 Status = MmCopyFromCaller(&Rect, pRectUnsafe, sizeof (RECT));
899 if (!NT_SUCCESS(Status))
900 {
902 return NULL;
903 }
904
906
907 /* Find intersecting monitors */
908 cMonitors = IntGetMonitorsFromRect(&Rect, &hMonitor, NULL, 1, dwFlags);
909 if (cMonitors <= 1)
910 {
911 /* No or one monitor found. Just return handle. */
912 goto cleanup;
913 }
914
915 /* There is more than one monitor. Find monitor with largest intersection.
916 Temporary reset hMonitor */
917 hMonitor = NULL;
918
919 /* Allocate helper buffers */
920 phMonitorList = ExAllocatePoolWithTag(PagedPool,
921 sizeof(HMONITOR) * cMonitors,
923 if (phMonitorList == NULL)
924 {
926 goto cleanup;
927 }
928
929 prcMonitorList = ExAllocatePoolWithTag(PagedPool,
930 sizeof(RECT) * cMonitors,
932 if (prcMonitorList == NULL)
933 {
935 goto cleanup;
936 }
937
938 /* Get intersecting monitors again but now with rectangle list */
939 cMonitors = IntGetMonitorsFromRect(&Rect, phMonitorList, prcMonitorList,
940 cMonitors, 0);
941
942 /* Find largest intersection */
943 for (i = 0; i < cMonitors; i++)
944 {
945 ULONG Area = (prcMonitorList[i].right - prcMonitorList[i].left) *
946 (prcMonitorList[i].bottom - prcMonitorList[i].top);
947 if (Area >= LargestArea)
948 {
949 hMonitor = phMonitorList[i];
950 LargestArea = Area;
951 }
952 }
953
954cleanup:
955 if (phMonitorList)
957 if (prcMonitorList)
959 UserLeave();
960
961 return hMonitor;
962}
963
964
968 IN HWND hWnd,
970{
971 PWND pWnd;
972 HMONITOR hMonitor = NULL;
973 RECTL Rect = {0, 0, 0, 0};
974
975 TRACE("Enter NtUserMonitorFromWindow\n");
976
977 /* Check if flags are valid */
978 if (dwFlags != MONITOR_DEFAULTTONULL &&
979 dwFlags != MONITOR_DEFAULTTOPRIMARY &&
980 dwFlags != MONITOR_DEFAULTTONEAREST)
981 {
983 return NULL;
984 }
985
987
988 /* If window is given, use it first */
989 if (hWnd)
990 {
991 /* Get window object */
993 if (!pWnd)
994 goto cleanup;
995
996 /* Find only monitors which have intersection with given window */
997 Rect.left = Rect.right = pWnd->rcWindow.left;
998 Rect.top = Rect.bottom = pWnd->rcWindow.bottom;
999 }
1000
1001 /* Find monitors now */
1002 IntGetMonitorsFromRect(&Rect, &hMonitor, NULL, 1, dwFlags);
1003
1004cleanup:
1005 TRACE("Leave NtUserMonitorFromWindow, ret=%p\n", hMonitor);
1006 UserLeave();
1007 return hMonitor;
1008}
HWND hWnd
Definition: settings.c:17
LONG NTSTATUS
Definition: precomp.h:26
#define DBG_DEFAULT_CHANNEL(ch)
Definition: debug.h:103
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:32
#define APIENTRY
Definition: api.h:79
PSERVERINFO gpsi
Definition: imm.c:18
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
_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:92
struct _MONITOR * PMONITOR
#define min(a, b)
Definition: monoChain.cc:55
#define _Analysis_assume_(expr)
Definition: ms_sal.h:2901
unsigned int UINT
Definition: ndis.h:50
#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:251
VOID FASTCALL UserEnterShared(VOID)
Definition: ntuser.c:235
PSIZEL FASTCALL PDEVOBJ_sizl(PPDEVOBJ ppdev, PSIZEL psizl)
Definition: pdevobj.c:1375
#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
RECT rcWindow
Definition: ntuser.h:716
WCHAR szDevice[CCHDEVICENAME]
Definition: winuser.h:3804
LONG right
Definition: windef.h:308
LONG bottom
Definition: windef.h:309
LONG top
Definition: windef.h:307
LONG left
Definition: windef.h:306
#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:122
VOID FASTCALL SetLastNtError(_In_ NTSTATUS Status)
Definition: error.c:31
BOOL NTAPI GreSetObjectOwner(HGDIOBJ hobj, ULONG ulOwner)
Definition: gdiobj.c:1255
BOOL NTAPI GreDeleteObject(HGDIOBJ hobj)
Definition: gdiobj.c:1158
BOOL FASTCALL RECTL_bIntersectRect(_Out_ RECTL *prclDst, _In_ const RECTL *prcl1, _In_ const RECTL *prcl2)
Definition: rect.c:55
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:405
static PMONITOR gMonitorList
Definition: monitor.c:19
static PMONITOR IntCreateMonitorObject(VOID)
Definition: monitor.c:33
PMONITOR NTAPI UserGetMonitorObject(IN HMONITOR hMonitor)
Definition: monitor.c:74
HMONITOR APIENTRY NtUserMonitorFromPoint(IN POINT pt, IN DWORD dwFlags)
Definition: monitor.c:827
BOOL APIENTRY NtUserGetMonitorInfo(IN HMONITOR hMonitor, OUT LPMONITORINFO pMonitorInfoUnsafe)
Definition: monitor.c:728
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
HMONITOR APIENTRY NtUserMonitorFromRect(IN LPCRECTL pRectUnsafe, IN DWORD dwFlags)
Definition: monitor.c:877
PMONITOR FASTCALL UserMonitorFromPoint(IN POINT pt, IN DWORD dwFlags)
Definition: monitor.c:481
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:543
NTSTATUS NTAPI UserAttachMonitor(IN HDEV hDev)
Definition: monitor.c:129
static void IntDestroyMonitorObject(IN PMONITOR pMonitor)
Definition: monitor.c:50
NTSTATUS NTAPI UserUpdateMonitorSize(IN HDEV hDev)
Definition: monitor.c:225
HMONITOR APIENTRY NtUserMonitorFromWindow(IN HWND hWnd, IN DWORD dwFlags)
Definition: monitor.c:967
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
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1176
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:22
#define ERROR_INVALID_MONITOR_HANDLE
Definition: winerror.h:942
#define ERROR_INVALID_FLAGS
Definition: winerror.h:583
#define COMPLEXREGION
Definition: wingdi.h:363
#define NULLREGION
Definition: wingdi.h:361
__wchar_t WCHAR
Definition: xmlstorage.h:180