ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

monitor.c
Go to the documentation of this file.
00001 /*
00002  *  COPYRIGHT:        See COPYING in the top level directory
00003  *  PROJECT:          ReactOS kernel
00004  *  PURPOSE:          pMonitor support
00005  *  FILE:             subsys/win32k/ntuser/monitor.c
00006  *  PROGRAMERS:       Anich Gregor (blight@blight.eu.org)
00007  *                    Rafal Harabien (rafalh@reactos.org)
00008  */
00009 
00010 #include <win32k.h>
00011 DBG_DEFAULT_CHANNEL(UserMonitor);
00012 
00013 #define NDEBUG
00014 #include <debug.h>
00015 
00016 /* GLOBALS *******************************************************************/
00017 
00018 /* List of monitors */
00019 static PMONITOR gMonitorList = NULL;
00020 
00021 /* PRIVATE FUNCTIONS **********************************************************/
00022 
00023 /* IntCreateMonitorObject
00024  *
00025  * Creates a MONITOR
00026  *
00027  * Return value
00028  *   If the function succeeds a pointer to a MONITOR is returned. On failure
00029  *   NULL is returned.
00030  */
00031 static
00032 PMONITOR
00033 IntCreateMonitorObject()
00034 {
00035     return UserCreateObject(gHandleTable, NULL, NULL, otMonitor, sizeof(MONITOR));
00036 }
00037 
00038 /* IntDestroyMonitorObject
00039  *
00040  * Destroys a MONITOR
00041  * You have to be the owner of the monitors lock to safely destroy it.
00042  *
00043  * Arguments
00044  *
00045  *   pMonitor
00046  *      Pointer to the MONITOR which shall be deleted
00047  */
00048 static
00049 void
00050 IntDestroyMonitorObject(IN PMONITOR pMonitor)
00051 {
00052     /* Remove monitor region */
00053     if (pMonitor->hrgnMonitor)
00054     {
00055         GreSetObjectOwner(pMonitor->hrgnMonitor, GDI_OBJ_HMGR_POWNED);
00056         GreDeleteObject(pMonitor->hrgnMonitor);
00057     }
00058 
00059     /* Destroy monitor object */
00060     UserDereferenceObject(pMonitor);
00061     UserDeleteObject(UserHMGetHandle(pMonitor), otMonitor);
00062 }
00063 
00064 /* UserGetMonitorObject
00065  *
00066  * Returns monitor object from handle or sets last error if handle is invalid
00067  *
00068  * Arguments
00069  *
00070  *   hMonitor
00071  *      Handle of MONITOR object
00072  */
00073 PMONITOR NTAPI
00074 UserGetMonitorObject(IN HMONITOR hMonitor)
00075 {
00076     PMONITOR pMonitor;
00077 
00078     if (!hMonitor)
00079     {
00080         EngSetLastError(ERROR_INVALID_MONITOR_HANDLE);
00081         return NULL;
00082     }
00083 
00084     pMonitor = (PMONITOR)UserGetObject(gHandleTable, hMonitor, otMonitor);
00085     if (!pMonitor)
00086     {
00087         EngSetLastError(ERROR_INVALID_MONITOR_HANDLE);
00088         return NULL;
00089     }
00090 
00091     return pMonitor;
00092 }
00093 
00094 /* UserGetPrimaryMonitor
00095  *
00096  * Returns a PMONITOR for the primary monitor
00097  *
00098  * Return value
00099  *   PMONITOR
00100  */
00101 PMONITOR NTAPI
00102 UserGetPrimaryMonitor()
00103 {
00104     PMONITOR pMonitor;
00105 
00106     /* Find primary monitor */
00107     for (pMonitor = gMonitorList; pMonitor != NULL; pMonitor = pMonitor->pMonitorNext)
00108     {
00109         if (pMonitor->IsPrimary)
00110             break;
00111     }
00112 
00113     return pMonitor;
00114 }
00115 
00116 /* UserAttachMonitor
00117  *
00118  * Creates a new MONITOR and appends it to the list of monitors.
00119  *
00120  * Arguments
00121  *
00122  *   pGdiDevice     Pointer to the PDEVOBJ onto which the monitor was attached
00123  *   DisplayNumber  Display Number (starting with 0)
00124  *
00125  * Return value
00126  *   Returns a NTSTATUS
00127  */
00128 NTSTATUS NTAPI
00129 UserAttachMonitor(IN HDEV hDev)
00130 {
00131     PMONITOR pMonitor;
00132 
00133     TRACE("Attaching monitor...\n");
00134 
00135     /* Create new monitor object */
00136     pMonitor = IntCreateMonitorObject();
00137     if (pMonitor == NULL)
00138     {
00139         TRACE("Couldnt create monitor object\n");
00140         return STATUS_INSUFFICIENT_RESOURCES;
00141     }
00142     
00143     pMonitor->hDev = hDev;
00144     pMonitor->cWndStack = 0;
00145 
00146     if (gMonitorList == NULL)
00147     {
00148         TRACE("Primary monitor is beeing attached\n");
00149         pMonitor->IsPrimary = TRUE;
00150         gMonitorList = pMonitor;
00151     }
00152     else
00153     {
00154         PMONITOR pmonLast = gMonitorList;
00155         TRACE("Additional monitor is beeing attached\n");
00156         while (pmonLast->pMonitorNext != NULL)
00157             pmonLast = pmonLast->pMonitorNext;
00158 
00159         pmonLast->pMonitorNext = pMonitor;
00160     }
00161 
00162     UserUpdateMonitorSize(hDev);
00163 
00164     return STATUS_SUCCESS;
00165 }
00166 
00167 /* UserDetachMonitor
00168  *
00169  * Deletes a MONITOR and removes it from the list of monitors.
00170  *
00171  * Arguments
00172  *
00173  *   pGdiDevice  Pointer to the PDEVOBJ from which the monitor was detached
00174  *
00175  * Return value
00176  *   Returns a NTSTATUS
00177  */
00178 NTSTATUS NTAPI
00179 UserDetachMonitor(IN HDEV hDev)
00180 {
00181     PMONITOR pMonitor = gMonitorList, *pLink = &gMonitorList;
00182 
00183     /* Find monitor attached to given device */
00184     while (pMonitor != NULL)
00185     {
00186         if (pMonitor->hDev == hDev)
00187             break;
00188     
00189         pLink = &pMonitor->pMonitorNext;
00190         pMonitor = pMonitor->pMonitorNext;
00191     }
00192 
00193     if (pMonitor == NULL)
00194     {
00195         /* No monitor has been found */
00196         return STATUS_INVALID_PARAMETER;
00197     }
00198 
00199     /* We destroy primary monitor - set next as primary */
00200     if (pMonitor->IsPrimary && pMonitor->pMonitorNext != NULL)
00201         pMonitor->pMonitorNext->IsPrimary = TRUE;
00202 
00203     /* Update Next ptr in previous monitor */
00204     *pLink = pMonitor->pMonitorNext;
00205 
00206     /* Finally destroy monitor */
00207     IntDestroyMonitorObject(pMonitor);
00208 
00209     return STATUS_SUCCESS;
00210 }
00211 
00212 /* UserUpdateMonitorSize
00213  *
00214  * Reset size of the monitor using atached device
00215  *
00216  * Arguments
00217  *
00218  *   PMONITOR
00219  *      pGdiDevice  Pointer to the PDEVOBJ, which size has changed
00220  *
00221  * Return value
00222  *   Returns a NTSTATUS
00223  */
00224 NTSTATUS NTAPI
00225 UserUpdateMonitorSize(IN HDEV hDev)
00226 {
00227     PMONITOR pMonitor;
00228     SIZEL DeviceSize;
00229 
00230     /* Find monitor attached to given device */
00231     for (pMonitor = gMonitorList; pMonitor != NULL; pMonitor = pMonitor->pMonitorNext)
00232     {
00233         if (pMonitor->hDev == hDev)
00234             break;
00235     }
00236 
00237     if (pMonitor == NULL)
00238     {
00239         /* No monitor has been found */
00240         return STATUS_INVALID_PARAMETER;
00241     }
00242 
00243     /* Get the size of the hdev */
00244     PDEVOBJ_sizl((PPDEVOBJ)hDev, &DeviceSize);
00245 
00246     /* Update monitor size */
00247     pMonitor->rcMonitor.left  = 0;
00248     pMonitor->rcMonitor.top   = 0;
00249     pMonitor->rcMonitor.right  = pMonitor->rcMonitor.left + DeviceSize.cx;
00250     pMonitor->rcMonitor.bottom = pMonitor->rcMonitor.top + DeviceSize.cy;
00251     pMonitor->rcWork = pMonitor->rcMonitor;
00252 
00253     /* Destroy monitor region... */
00254     if (pMonitor->hrgnMonitor)
00255     {
00256         GreSetObjectOwner(pMonitor->hrgnMonitor, GDI_OBJ_HMGR_POWNED);
00257         GreDeleteObject(pMonitor->hrgnMonitor);
00258     }
00259 
00260     /* ...and create new one */
00261     pMonitor->hrgnMonitor = IntSysCreateRectRgnIndirect(&pMonitor->rcMonitor);
00262     if (pMonitor->hrgnMonitor)
00263         IntGdiSetRegionOwner(pMonitor->hrgnMonitor, GDI_OBJ_HMGR_PUBLIC);
00264 
00265     return STATUS_SUCCESS;
00266 }
00267 
00268 /* IntGetMonitorsFromRect
00269  *
00270  * Returns a list of monitor handles/rectangles. The rectangles in the list are
00271  * the areas of intersection with the monitors.
00272  *
00273  * Arguments
00274  *
00275  *   pRect
00276  *      Rectangle in desktop coordinates. If this is NULL all monitors are
00277  *      returned and the rect list is filled with the sizes of the monitors.
00278  *
00279  *   phMonitorList
00280  *      Pointer to an array of HMONITOR which is filled with monitor handles.
00281  *      Can be NULL
00282  *
00283  *   prcMonitorList
00284  *      Pointer to an array of RECT which is filled with intersection rects in
00285  *      desktop coordinates.
00286  *      Can be NULL, will be ignored if no intersecting monitor is found and
00287  *      flags is MONITOR_DEFAULTTONEAREST
00288  *
00289  *   dwListSize
00290  *      Size of the phMonitorList and prcMonitorList arguments. If this is zero
00291  *      phMonitorList and prcMonitorList are ignored.
00292  *
00293  *   dwFlags
00294  *      Either 0 or MONITOR_DEFAULTTONEAREST (ignored if rect is NULL)
00295  *
00296  * Returns
00297  *   The number of monitors which intersect the specified region.
00298  */
00299 static
00300 UINT
00301 IntGetMonitorsFromRect(OPTIONAL IN LPCRECTL pRect,
00302                        OPTIONAL OUT HMONITOR *phMonitorList,
00303                        OPTIONAL OUT PRECTL prcMonitorList,
00304                        OPTIONAL IN DWORD dwListSize,
00305                        OPTIONAL IN DWORD dwFlags)
00306 {
00307     PMONITOR pMonitor, pNearestMonitor = NULL, pPrimaryMonitor = NULL;
00308     UINT cMonitors = 0;
00309     ULONG iNearestDistance = 0xffffffff;
00310 
00311     /* Find monitors which intersects the rectangle */
00312     for (pMonitor = gMonitorList; pMonitor != NULL; pMonitor = pMonitor->pMonitorNext)
00313     {
00314         RECTL MonitorRect, IntersectionRect;
00315 
00316         MonitorRect = pMonitor->rcMonitor;
00317 
00318         TRACE("MonitorRect: left = %d, top = %d, right = %d, bottom = %d\n",
00319                MonitorRect.left, MonitorRect.top, MonitorRect.right, MonitorRect.bottom);
00320 
00321         /* Save primary monitor for later usage */
00322         if (dwFlags == MONITOR_DEFAULTTOPRIMARY && pMonitor->IsPrimary)
00323             pPrimaryMonitor = pMonitor;
00324 
00325         /* Check if a rect is given */
00326         if (pRect == NULL)
00327         {
00328             /* No rect given, so use the full monitor rect */
00329             IntersectionRect = MonitorRect;
00330         }
00331         /* We have a rect, calculate intersection */
00332         else if (!RECTL_bIntersectRect(&IntersectionRect, &MonitorRect, pRect))
00333         {
00334             /* Rects did not intersect */
00335             if (dwFlags == MONITOR_DEFAULTTONEAREST)
00336             {
00337                 ULONG cx, cy, iDistance;
00338 
00339                 /* Get x and y distance */
00340                 cx = min(abs(MonitorRect.left - pRect->right),
00341                          abs(pRect->left - MonitorRect.right));
00342                 cy = min(abs(MonitorRect.top - pRect->bottom),
00343                          abs(pRect->top - MonitorRect.bottom));
00344 
00345                 /* Calculate distance square */
00346                 iDistance = cx * cx + cy * cy;
00347 
00348                 /* Check if this is the new nearest monitor */
00349                 if (iDistance < iNearestDistance)
00350                 {
00351                     iNearestDistance = iDistance;
00352                     pNearestMonitor = pMonitor;
00353                 }
00354             }
00355 
00356             continue;
00357         }
00358 
00359         /* Check if there's space in the buffer */
00360         if (cMonitors < dwListSize)
00361         {
00362             /* Save monitor data */
00363             if (phMonitorList != NULL)
00364                 phMonitorList[cMonitors] = UserHMGetHandle(pMonitor);
00365             if (prcMonitorList != NULL)
00366                 prcMonitorList[cMonitors] = IntersectionRect;
00367         }
00368 
00369         /* Increase count of found monitors */
00370         cMonitors++;
00371     }
00372 
00373     /* Nothing has been found? */
00374     if (cMonitors == 0)
00375     {
00376         /* Check if we shall default to the nearest monitor */
00377         if (dwFlags == MONITOR_DEFAULTTONEAREST && pNearestMonitor)
00378         {
00379             if (phMonitorList && dwListSize > 0)
00380                 phMonitorList[cMonitors] = UserHMGetHandle(pNearestMonitor);
00381             cMonitors++;
00382         }
00383         /* Check if we shall default to the primary monitor */
00384         else if (dwFlags == MONITOR_DEFAULTTOPRIMARY && pPrimaryMonitor)
00385         {
00386             if (phMonitorList != NULL && dwListSize > 0)
00387                 phMonitorList[cMonitors] = UserHMGetHandle(pPrimaryMonitor);
00388             cMonitors++;
00389         }
00390     }
00391 
00392     return cMonitors;
00393 }
00394 
00395 PMONITOR NTAPI
00396 UserMonitorFromRect(
00397     PRECTL pRect,
00398     DWORD dwFlags)
00399 {
00400     ULONG cMonitors, LargestArea = 0, i;
00401     PRECTL prcMonitorList = NULL;
00402     HMONITOR *phMonitorList = NULL;
00403     HMONITOR hMonitor = NULL;
00404 
00405     /* Check if flags are valid */
00406     if (dwFlags != MONITOR_DEFAULTTONULL &&
00407         dwFlags != MONITOR_DEFAULTTOPRIMARY &&
00408         dwFlags != MONITOR_DEFAULTTONEAREST)
00409     {
00410         EngSetLastError(ERROR_INVALID_FLAGS);
00411         return NULL;
00412     }
00413 
00414     /* Find intersecting monitors */
00415     cMonitors = IntGetMonitorsFromRect(pRect, &hMonitor, NULL, 1, dwFlags);
00416     if (cMonitors <= 1)
00417     {
00418         /* No or one monitor found. Just return handle. */
00419         goto cleanup;
00420     }
00421 
00422     /* There is more than one monitor. Find monitor with largest intersection.
00423        Temporary reset hMonitor */
00424     hMonitor = NULL;
00425 
00426     /* Allocate helper buffers */
00427     phMonitorList = ExAllocatePoolWithTag(PagedPool,
00428                                           sizeof(HMONITOR) * cMonitors,
00429                                           USERTAG_MONITORRECTS);
00430     if (phMonitorList == NULL)
00431     {
00432         EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
00433         goto cleanup;
00434     }
00435 
00436     prcMonitorList = ExAllocatePoolWithTag(PagedPool,
00437                                            sizeof(RECT) * cMonitors,
00438                                            USERTAG_MONITORRECTS);
00439     if (prcMonitorList == NULL)
00440     {
00441         EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
00442         goto cleanup;
00443     }
00444 
00445     /* Get intersecting monitors again but now with rectangle list */
00446     cMonitors = IntGetMonitorsFromRect(pRect, phMonitorList, prcMonitorList,
00447                                        cMonitors, 0);
00448 
00449     /* Find largest intersection */
00450     for (i = 0; i < cMonitors; i++)
00451     {
00452         ULONG Area = (prcMonitorList[i].right - prcMonitorList[i].left) *
00453                      (prcMonitorList[i].bottom - prcMonitorList[i].top);
00454         if (Area >= LargestArea)
00455         {
00456             hMonitor = phMonitorList[i];
00457             LargestArea = Area;
00458         }
00459     }
00460 
00461 cleanup:
00462     if (phMonitorList)
00463         ExFreePoolWithTag(phMonitorList, USERTAG_MONITORRECTS);
00464     if (prcMonitorList)
00465         ExFreePoolWithTag(prcMonitorList, USERTAG_MONITORRECTS);
00466 
00467     return UserGetMonitorObject(hMonitor);
00468 }
00469 
00470 
00471 /* PUBLIC FUNCTIONS ***********************************************************/
00472 
00473 /* NtUserEnumDisplayMonitors
00474  *
00475  * Enumerates display monitors which intersect the given HDC/cliprect
00476  *
00477  * Arguments
00478  *
00479  *   hdc
00480  *      Handle to a DC for which to enum intersecting monitors. If this is NULL
00481  *      it returns all monitors which are part of the current virtual screen.
00482  *
00483  *   pUnsafeRect
00484  *      Clipping rectangle with coordinate system origin at the DCs origin if the
00485  *      given HDC is not NULL or in virtual screen coordinated if it is NULL.
00486  *      Can be NULL
00487  *
00488  *   phUnsafeMonitorList
00489  *      Pointer to an array of HMONITOR which is filled with monitor handles.
00490  *      Can be NULL
00491  *
00492  *   prcUnsafeMonitorList
00493  *      Pointer to an array of RECT which is filled with intersection rectangles.
00494  *      Can be NULL
00495  *
00496  *   dwListSize
00497  *      Size of the hMonitorList and monitorRectList arguments. If this is zero
00498  *      hMonitorList and monitorRectList are ignored.
00499  *
00500  * Returns
00501  *   The number of monitors which intersect the specified region or -1 on failure.
00502  */
00503 INT
00504 APIENTRY
00505 NtUserEnumDisplayMonitors(
00506     OPTIONAL IN HDC hdc,
00507     OPTIONAL IN LPCRECTL pUnsafeRect,
00508     OPTIONAL OUT HMONITOR *phUnsafeMonitorList,
00509     OPTIONAL OUT PRECTL prcUnsafeMonitorList,
00510     OPTIONAL IN DWORD dwListSize)
00511 {
00512     INT cMonitors, iRet = -1, i;
00513     HMONITOR *phMonitorList = NULL;
00514     PRECTL prcMonitorList = NULL;
00515     RECTL rc, *pRect;
00516     RECTL DcRect = {0};
00517     NTSTATUS Status;
00518 
00519     /* Get rectangle */
00520     if (pUnsafeRect != NULL)
00521     {
00522         Status = MmCopyFromCaller(&rc, pUnsafeRect, sizeof(RECT));
00523         if (!NT_SUCCESS(Status))
00524         {
00525             TRACE("MmCopyFromCaller() failed!\n");
00526             SetLastNtError(Status);
00527             return -1;
00528         }
00529     }
00530 
00531     if (hdc != NULL)
00532     {
00533         PDC pDc;
00534         INT iRgnType;
00535 
00536         /* Get visible region bounding rect */
00537         pDc = DC_LockDc(hdc);
00538         if (pDc == NULL)
00539         {
00540             TRACE("DC_LockDc() failed!\n");
00541             /* FIXME: setlasterror? */
00542             return -1;
00543         }
00544         iRgnType = REGION_GetRgnBox(pDc->prgnVis, &DcRect);
00545         DC_UnlockDc(pDc);
00546 
00547         if (iRgnType == 0)
00548         {
00549             TRACE("NtGdiGetRgnBox() failed!\n");
00550             return -1;
00551         }
00552         if (iRgnType == NULLREGION)
00553             return 0;
00554         if (iRgnType == COMPLEXREGION)
00555         {
00556             /* TODO: Warning */
00557         }
00558 
00559         /* If hdc and pRect are given the area of interest is pRect with
00560            coordinate origin at the DC position */
00561         if (pUnsafeRect != NULL)
00562         {
00563             rc.left += DcRect.left;
00564             rc.right += DcRect.left;
00565             rc.top += DcRect.top;
00566             rc.bottom += DcRect.top;
00567         }
00568         /* If hdc is given and pRect is not the area of interest is the
00569            bounding rect of hdc */
00570         else
00571         {
00572             rc = DcRect;
00573         }
00574     }
00575 
00576     if (hdc == NULL && pUnsafeRect == NULL)
00577         pRect = NULL;
00578     else
00579         pRect = &rc;
00580 
00581     UserEnterShared();
00582 
00583     /* Find intersecting monitors */
00584     cMonitors = IntGetMonitorsFromRect(pRect, NULL, NULL, 0, MONITOR_DEFAULTTONULL);
00585     if (cMonitors == 0 || dwListSize == 0 ||
00586         (phUnsafeMonitorList == NULL && prcUnsafeMonitorList == NULL))
00587     {
00588         /* Simple case - just return monitors count */
00589         TRACE("cMonitors = %d\n", cMonitors);
00590         iRet = cMonitors;
00591         goto cleanup;
00592     }
00593 
00594     /* Allocate safe buffers */
00595     if (phUnsafeMonitorList != NULL && dwListSize != 0)
00596     {
00597         phMonitorList = ExAllocatePoolWithTag(PagedPool, sizeof (HMONITOR) * dwListSize, USERTAG_MONITORRECTS);
00598         if (phMonitorList == NULL)
00599         {
00600             EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
00601             goto cleanup;
00602         }
00603     }
00604     if (prcUnsafeMonitorList != NULL && dwListSize != 0)
00605     {
00606         prcMonitorList = ExAllocatePoolWithTag(PagedPool, sizeof (RECT) * dwListSize, USERTAG_MONITORRECTS);
00607         if (prcMonitorList == NULL)
00608         {
00609             EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
00610             goto cleanup;
00611         }
00612     }
00613 
00614     /* Get intersecting monitors */
00615     cMonitors = IntGetMonitorsFromRect(pRect, phMonitorList, prcMonitorList,
00616                                        dwListSize, MONITOR_DEFAULTTONULL);
00617 
00618     if (hdc != NULL && pRect != NULL && prcMonitorList != NULL)
00619         for (i = 0; i < cMonitors; i++)
00620         {
00621             prcMonitorList[i].left -= DcRect.left;
00622             prcMonitorList[i].right -= DcRect.left;
00623             prcMonitorList[i].top -= DcRect.top;
00624             prcMonitorList[i].bottom -= DcRect.top;
00625         }
00626 
00627     /* Output result */
00628     if (phUnsafeMonitorList != NULL && dwListSize != 0)
00629     {
00630         Status = MmCopyToCaller(phUnsafeMonitorList, phMonitorList, sizeof(HMONITOR) * dwListSize);
00631         if (!NT_SUCCESS(Status))
00632         {
00633             SetLastNtError(Status);
00634             goto cleanup;
00635         }
00636     }
00637     if (prcUnsafeMonitorList != NULL && dwListSize != 0)
00638     {
00639         Status = MmCopyToCaller(prcUnsafeMonitorList, prcMonitorList, sizeof(RECT) * dwListSize);
00640         if (!NT_SUCCESS(Status))
00641         {
00642             SetLastNtError(Status);
00643             goto cleanup;
00644         }
00645     }
00646 
00647     /* Return monitors count on success */
00648     iRet = cMonitors;
00649 
00650 cleanup:
00651     if (phMonitorList)
00652         ExFreePoolWithTag(phMonitorList, USERTAG_MONITORRECTS);
00653     if (prcMonitorList)
00654         ExFreePoolWithTag(prcMonitorList, USERTAG_MONITORRECTS);
00655 
00656     UserLeave();
00657     return iRet;
00658 }
00659 
00660 /* NtUserGetMonitorInfo
00661  *
00662  * Retrieves information about a given monitor
00663  *
00664  * Arguments
00665  *
00666  *   hMonitor
00667  *      Handle to a monitor for which to get information
00668  *
00669  *   pMonitorInfoUnsafe
00670  *      Pointer to a MONITORINFO struct which is filled with the information.
00671  *      The cbSize member must be set to sizeof(MONITORINFO) or
00672  *      sizeof(MONITORINFOEX). Even if set to sizeof(MONITORINFOEX) only parts
00673  *      from MONITORINFO will be filled.
00674  *
00675  *   pDevice
00676  *      Pointer to a UNICODE_STRING which will recieve the device's name. The
00677  *      length should be CCHDEVICENAME
00678  *      Can be NULL
00679  *
00680  * Return value
00681  *   TRUE on success; FALSE on failure (calls SetLastNtError())
00682  *
00683  */
00684 BOOL
00685 APIENTRY
00686 NtUserGetMonitorInfo(
00687     IN HMONITOR hMonitor,
00688     OUT LPMONITORINFO pMonitorInfoUnsafe)
00689 {
00690     PMONITOR pMonitor;
00691     MONITORINFOEXW MonitorInfo;
00692     NTSTATUS Status;
00693     BOOL bRet = FALSE;
00694     PWCHAR pwstrDeviceName;
00695 
00696     TRACE("Enter NtUserGetMonitorInfo\n");
00697     UserEnterShared();
00698 
00699     /* Get monitor object */
00700     pMonitor = UserGetMonitorObject(hMonitor);
00701     if (!pMonitor)
00702     {
00703         TRACE("Couldnt find monitor 0x%lx\n", hMonitor);
00704         goto cleanup;
00705     }
00706 
00707     /* Check if pMonitorInfoUnsafe is valid */
00708     if(pMonitorInfoUnsafe == NULL)
00709     {
00710         SetLastNtError(STATUS_INVALID_PARAMETER);
00711         goto cleanup;
00712     }
00713 
00714     pwstrDeviceName = ((PPDEVOBJ)(pMonitor->hDev))->pGraphicsDevice->szWinDeviceName;
00715 
00716     /* Get size of pMonitorInfoUnsafe */
00717     Status = MmCopyFromCaller(&MonitorInfo.cbSize, &pMonitorInfoUnsafe->cbSize, sizeof(MonitorInfo.cbSize));
00718     if (!NT_SUCCESS(Status))
00719     {
00720         SetLastNtError(Status);
00721         goto cleanup;
00722     }
00723 
00724     /* Check if size of struct is valid */
00725     if (MonitorInfo.cbSize != sizeof(MONITORINFO) &&
00726         MonitorInfo.cbSize != sizeof(MONITORINFOEXW))
00727     {
00728         SetLastNtError(STATUS_INVALID_PARAMETER);
00729         goto cleanup;
00730     }
00731 
00732     /* Fill monitor info */
00733     MonitorInfo.rcMonitor = pMonitor->rcMonitor;
00734     MonitorInfo.rcWork = pMonitor->rcWork;
00735     MonitorInfo.dwFlags = 0;
00736     if (pMonitor->IsPrimary)
00737         MonitorInfo.dwFlags |= MONITORINFOF_PRIMARY;
00738 
00739     /* Fill device name */
00740     if (MonitorInfo.cbSize == sizeof(MONITORINFOEXW))
00741     {
00742         RtlStringCbCopyNExW(MonitorInfo.szDevice,
00743                           sizeof(MonitorInfo.szDevice),
00744                           pwstrDeviceName,
00745                           (wcslen(pwstrDeviceName)+1) * sizeof(WCHAR),
00746                           NULL, NULL, STRSAFE_FILL_BEHIND_NULL);
00747     }
00748 
00749     /* Output data */
00750     Status = MmCopyToCaller(pMonitorInfoUnsafe, &MonitorInfo, MonitorInfo.cbSize);
00751     if (!NT_SUCCESS(Status))
00752     {
00753         TRACE("GetMonitorInfo: MmCopyToCaller failed\n");
00754         SetLastNtError(Status);
00755         goto cleanup;
00756     }
00757 
00758     TRACE("GetMonitorInfo: success\n");
00759     bRet = TRUE;
00760 
00761 cleanup:
00762     TRACE("Leave NtUserGetMonitorInfo, ret=%i\n", bRet);
00763     UserLeave();
00764     return bRet;
00765 }
00766 
00767 /* NtUserMonitorFromPoint
00768  *
00769  * Returns a handle to the monitor containing the given point.
00770  *
00771  * Arguments
00772  *
00773  *   pt
00774  *     Point for which to find monitor
00775  *
00776  *   dwFlags
00777  *     Specifies the behaviour if the point isn't on any of the monitors.
00778  *
00779  * Return value
00780  *   If the point is found a handle to the monitor is returned; if not the
00781  *   return value depends on dwFlags
00782  */
00783 HMONITOR
00784 APIENTRY
00785 NtUserMonitorFromPoint(
00786     IN POINT pt,
00787     IN DWORD dwFlags)
00788 {
00789     INT cMonitors;
00790     RECTL rc;
00791     HMONITOR hMonitor = NULL;
00792 
00793     /* Check if flags are valid */
00794     if (dwFlags != MONITOR_DEFAULTTONULL &&
00795         dwFlags != MONITOR_DEFAULTTOPRIMARY &&
00796         dwFlags != MONITOR_DEFAULTTONEAREST)
00797     {
00798         EngSetLastError(ERROR_INVALID_FLAGS);
00799         return NULL;
00800     }
00801 
00802     /* Fill rect (bottom-right exclusive) */
00803     rc.left = pt.x;
00804     rc.right = pt.x + 1;
00805     rc.top = pt.y;
00806     rc.bottom = pt.y + 1;
00807 
00808     UserEnterShared();
00809 
00810     /* Find intersecting monitor */
00811     cMonitors = IntGetMonitorsFromRect(&rc, &hMonitor, NULL, 1, dwFlags);
00812 
00813     UserLeave();
00814     return hMonitor;
00815 }
00816 
00817 /* NtUserMonitorFromRect
00818  *
00819  * Returns a handle to the monitor having the largest intersection with a
00820  * given rectangle
00821  *
00822  * Arguments
00823  *
00824  *   pRectUnsafe
00825  *     Pointer to a RECT for which to find monitor
00826  *
00827  *   dwFlags
00828  *     Specifies the behaviour if no monitor intersects the given rect
00829  *
00830  * Return value
00831  *   If a monitor intersects the rect a handle to it is returned; if not the
00832  *   return value depends on dwFlags
00833  */
00834 HMONITOR
00835 APIENTRY
00836 NtUserMonitorFromRect(
00837     IN LPCRECTL pRectUnsafe,
00838     IN DWORD dwFlags)
00839 {
00840     ULONG cMonitors, LargestArea = 0, i;
00841     PRECTL prcMonitorList = NULL;
00842     HMONITOR *phMonitorList = NULL;
00843     HMONITOR hMonitor = NULL;
00844     RECTL Rect;
00845     NTSTATUS Status;
00846 
00847     /* Check if flags are valid */
00848     if (dwFlags != MONITOR_DEFAULTTONULL &&
00849         dwFlags != MONITOR_DEFAULTTOPRIMARY &&
00850         dwFlags != MONITOR_DEFAULTTONEAREST)
00851     {
00852         EngSetLastError(ERROR_INVALID_FLAGS);
00853         return NULL;
00854     }
00855 
00856     /* Copy rectangle to safe buffer */
00857     Status = MmCopyFromCaller(&Rect, pRectUnsafe, sizeof (RECT));
00858     if (!NT_SUCCESS(Status))
00859     {
00860         SetLastNtError(Status);
00861         return NULL;
00862     }
00863 
00864     UserEnterShared();
00865 
00866     /* Find intersecting monitors */
00867     cMonitors = IntGetMonitorsFromRect(&Rect, &hMonitor, NULL, 1, dwFlags);
00868     if (cMonitors <= 1)
00869     {
00870         /* No or one monitor found. Just return handle. */
00871         goto cleanup;
00872     }
00873 
00874     /* There is more than one monitor. Find monitor with largest intersection.
00875        Temporary reset hMonitor */
00876     hMonitor = NULL;
00877 
00878     /* Allocate helper buffers */
00879     phMonitorList = ExAllocatePoolWithTag(PagedPool,
00880                                           sizeof(HMONITOR) * cMonitors,
00881                                           USERTAG_MONITORRECTS);
00882     if (phMonitorList == NULL)
00883     {
00884         EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
00885         goto cleanup;
00886     }
00887 
00888     prcMonitorList = ExAllocatePoolWithTag(PagedPool,
00889                                            sizeof(RECT) * cMonitors,
00890                                            USERTAG_MONITORRECTS);
00891     if (prcMonitorList == NULL)
00892     {
00893         EngSetLastError(ERROR_NOT_ENOUGH_MEMORY);
00894         goto cleanup;
00895     }
00896 
00897     /* Get intersecting monitors again but now with rectangle list */
00898     cMonitors = IntGetMonitorsFromRect(&Rect, phMonitorList, prcMonitorList,
00899                                        cMonitors, 0);
00900 
00901     /* Find largest intersection */
00902     for (i = 0; i < cMonitors; i++)
00903     {
00904         ULONG Area = (prcMonitorList[i].right - prcMonitorList[i].left) *
00905                      (prcMonitorList[i].bottom - prcMonitorList[i].top);
00906         if (Area >= LargestArea)
00907         {
00908             hMonitor = phMonitorList[i];
00909             LargestArea = Area;
00910         }
00911     }
00912 
00913 cleanup:
00914     if (phMonitorList)
00915         ExFreePoolWithTag(phMonitorList, USERTAG_MONITORRECTS);
00916     if (prcMonitorList)
00917         ExFreePoolWithTag(prcMonitorList, USERTAG_MONITORRECTS);
00918     UserLeave();
00919 
00920     return hMonitor;
00921 }
00922 
00923 
00924 HMONITOR
00925 APIENTRY
00926 NtUserMonitorFromWindow(
00927     IN HWND hWnd,
00928     IN DWORD dwFlags)
00929 {
00930     PWND pWnd;
00931     HMONITOR hMonitor = NULL;
00932     RECTL Rect = {0, 0, 0, 0};
00933 
00934     TRACE("Enter NtUserMonitorFromWindow\n");
00935 
00936     /* Check if flags are valid */
00937     if (dwFlags != MONITOR_DEFAULTTONULL &&
00938         dwFlags != MONITOR_DEFAULTTOPRIMARY &&
00939         dwFlags != MONITOR_DEFAULTTONEAREST)
00940     {
00941         EngSetLastError(ERROR_INVALID_FLAGS);
00942         return NULL;
00943     }
00944 
00945     UserEnterShared();
00946 
00947     /* If window is given, use it first */
00948     if (hWnd)
00949     {
00950         /* Get window object */
00951         pWnd = UserGetWindowObject(hWnd);
00952         if (!pWnd)
00953             goto cleanup;
00954 
00955         /* Find only monitors which have intersection with given window */
00956         Rect.left = Rect.right = pWnd->rcWindow.left;
00957         Rect.top = Rect.bottom = pWnd->rcWindow.bottom;
00958     }
00959 
00960     /* Find monitors now */
00961     IntGetMonitorsFromRect(&Rect, &hMonitor, NULL, 1, dwFlags);
00962 
00963 cleanup:
00964     TRACE("Leave NtUserMonitorFromWindow, ret=%p\n", hMonitor);
00965     UserLeave();
00966     return hMonitor;
00967 }

Generated on Sun May 27 2012 04:38:34 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.