⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 monitor.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 2 页
字号:
{
   INT numMonitors, i;
   HMONITOR *safeHMonitorList = NULL;
   LPRECT safeRectList = NULL;
   RECT rect, *myRect;
   RECT dcRect;
   NTSTATUS status;

   /* get rect */
   if (pRect != NULL)
   {
      status = MmCopyFromCaller(&rect, pRect, sizeof (RECT));
      if (!NT_SUCCESS(status))
      {
         DPRINT("MmCopyFromCaller() failed!\n");
         SetLastNtError(status);
         return -1;
      }
   }

   if (hDC != NULL)
   {
      PDC dc;
      HRGN dcVisRgn;
      INT regionType;

      /* get visible region bounding rect */
      dc = DC_LockDc(hDC);
      if (dc == NULL)
      {
         DPRINT("DC_LockDc() failed!\n");
         /* FIXME: setlasterror? */
         return -1;
      }
      dcVisRgn = dc->w.hVisRgn;
      DC_UnlockDc(dc);

      regionType = NtGdiGetRgnBox(dcVisRgn, &dcRect);
      if (regionType == 0)
      {
         DPRINT("NtGdiGetRgnBox() failed!\n");
         return -1;
      }
      if (regionType == NULLREGION)
         return 0;
      if (regionType == COMPLEXREGION)
      { /* TODO: warning */
      }

      /* if hDC and pRect are given the area of interest is pRect with
         coordinate origin at the DC position */
      if (pRect != NULL)
      {
         rect.left += dcRect.left;
         rect.right += dcRect.left;
         rect.top += dcRect.top;
         rect.bottom += dcRect.top;
      }
      /* if hDC is given and pRect is not the area of interest is the
         bounding rect of hDC */
      else
      {
         rect = dcRect;
      }
   }

   if (hDC == NULL && pRect == NULL)
      myRect = NULL;
   else
      myRect = ▭

   /* find intersecting monitors */
   numMonitors = IntGetMonitorsFromRect(myRect, NULL, NULL, 0, 0);
   if (numMonitors == 0 || listSize == 0 ||
         (hMonitorList == NULL && monitorRectList == NULL))
   {
      DPRINT("numMonitors = %d\n", numMonitors);
      return numMonitors;
   }

   if (hMonitorList != NULL && listSize != 0)
   {
      safeHMonitorList = ExAllocatePool(PagedPool, sizeof (HMONITOR) * listSize);
      if (safeHMonitorList == NULL)
      {
         /* FIXME: SetLastWin32Error? */
         return -1;
      }
   }
   if (monitorRectList != NULL && listSize != 0)
   {
      safeRectList = ExAllocatePool(PagedPool, sizeof (RECT) * listSize);
      if (safeRectList == NULL)
      {
         ExFreePool(safeHMonitorList);
         /* FIXME: SetLastWin32Error? */
         return -1;
      }
   }

   /* get intersecting monitors */
   numMonitors = IntGetMonitorsFromRect(myRect, safeHMonitorList, safeRectList,
                                        listSize, 0 );

   if (hDC != NULL && pRect != NULL && safeRectList != NULL)
      for (i = 0; i < numMonitors; i++)
      {
         safeRectList[i].left -= dcRect.left;
         safeRectList[i].right -= dcRect.left;
         safeRectList[i].top -= dcRect.top;
         safeRectList[i].bottom -= dcRect.top;
      }

   /* output result */
   if (hMonitorList != NULL && listSize != 0)
   {
      status = MmCopyToCaller(hMonitorList, safeHMonitorList, sizeof (HMONITOR) * listSize);
      ExFreePool(safeHMonitorList);
      if (!NT_SUCCESS(status))
      {
         ExFreePool(safeRectList);
         SetLastNtError(status);
         return -1;
      }
   }
   if (monitorRectList != NULL && listSize != 0)
   {
      status = MmCopyToCaller(monitorRectList, safeRectList, sizeof (RECT) * listSize);
      ExFreePool(safeRectList);
      if (!NT_SUCCESS(status))
      {
         SetLastNtError(status);
         return -1;
      }
   }

   return numMonitors;
}

/* NtUserGetMonitorInfo
 *
 * Retrieves information about a given monitor
 *
 * Arguments
 *
 *   hMonitor
 *      Handle to a monitor for which to get information
 *
 *   pMonitorInfo
 *      Pointer to a MONITORINFO struct which is filled with the information.
 *      The cbSize member must be set to sizeof(MONITORINFO) or
 *      sizeof(MONITORINFOEX). Even if set to sizeof(MONITORINFOEX) only parts
 *      from MONITORINFO will be filled.
 *
 *   pDevice
 *      Pointer to a UNICODE_STRING which will recieve the device's name. The
 *      length should be CCHDEVICENAME
 *      Can be NULL
 *
 * Return value
 *   TRUE on success; FALSE on failure (calls SetLastNtError())
 *
 */
BOOL
STDCALL
NtUserGetMonitorInfo(
   IN HMONITOR hMonitor,
   OUT LPMONITORINFO pMonitorInfo)
{
   PMONITOR_OBJECT Monitor;
   MONITORINFOEXW MonitorInfo;
   NTSTATUS Status;
   DECLARE_RETURN(BOOL);
   
   DPRINT("Enter NtUserGetMonitorInfo\n");
   UserEnterShared();
   
   /* get monitor object */
   if (!(Monitor = UserGetMonitorObject(hMonitor)))
   {
      DPRINT("Couldnt find monitor 0x%lx\n", hMonitor);
      RETURN(FALSE);
   }

   if(pMonitorInfo == NULL)
   {
      SetLastNtError(STATUS_INVALID_PARAMETER);
      RETURN(FALSE);
   }

   /* get size of pMonitorInfo */
   Status = MmCopyFromCaller(&MonitorInfo.cbSize, &pMonitorInfo->cbSize, sizeof (MonitorInfo.cbSize));
   if (!NT_SUCCESS(Status))
   {
      SetLastNtError(Status);
      RETURN(FALSE);
   }
   if ((MonitorInfo.cbSize != sizeof (MONITORINFO)) &&
         (MonitorInfo.cbSize != sizeof (MONITORINFOEXW)))
   {
      SetLastNtError(STATUS_INVALID_PARAMETER);
      RETURN(FALSE);
   }

   /* fill monitor info */
   MonitorInfo.rcMonitor.left = 0; /* FIXME: get origin */
   MonitorInfo.rcMonitor.top = 0; /* FIXME: get origin */
   MonitorInfo.rcMonitor.right = MonitorInfo.rcMonitor.left + Monitor->GdiDevice->GDIInfo.ulHorzRes;
   MonitorInfo.rcMonitor.bottom = MonitorInfo.rcMonitor.top + Monitor->GdiDevice->GDIInfo.ulVertRes;
   MonitorInfo.rcWork = MonitorInfo.rcMonitor; /* FIXME: use DEVMODE panning to calculate work area? */
   MonitorInfo.dwFlags = 0;

   if (Monitor->IsPrimary)
      MonitorInfo.dwFlags |= MONITORINFOF_PRIMARY;

   /* fill device name */
   if (MonitorInfo.cbSize == sizeof (MONITORINFOEXW))
   {
      WCHAR nul = L'\0';
      INT len = Monitor->DeviceName.Length;
      if (len >= CCHDEVICENAME * sizeof (WCHAR))
         len = (CCHDEVICENAME - 1) * sizeof (WCHAR);

      memcpy(MonitorInfo.szDevice, Monitor->DeviceName.Buffer, len);
      memcpy(MonitorInfo.szDevice + (len / sizeof (WCHAR)), &nul, sizeof (WCHAR));
   }

   /* output data */
   Status = MmCopyToCaller(pMonitorInfo, &MonitorInfo, MonitorInfo.cbSize);
   if (!NT_SUCCESS(Status))
   {
      DPRINT("GetMonitorInfo: MmCopyToCaller failed\n");
      SetLastNtError(Status);
      RETURN(FALSE);
   }

   DPRINT("GetMonitorInfo: success\n");

   RETURN(TRUE);
   
CLEANUP:
   DPRINT("Leave NtUserGetMonitorInfo, ret=%i\n",_ret_);
   UserLeave();
   END_CLEANUP;
}

/* NtUserMonitorFromPoint
 *
 * Returns a handle to the monitor containing the given point.
 *
 * Arguments
 *
 *   point
 *     Point for which to find monitor
 *
 *   dwFlags
 *     Specifies the behaviour if the point isn't on any of the monitors.
 *
 * Return value
 *   If the point is found a handle to the monitor is returned; if not the
 *   return value depends on dwFlags
 */
HMONITOR
STDCALL
NtUserMonitorFromPoint(
   IN POINT point,
   IN DWORD dwFlags)
{
   INT NumMonitors;
   RECT InRect;
   HMONITOR hMonitor = NULL;

   /* fill inRect */
   InRect.left = InRect.right = point.x;
   InRect.top = InRect.bottom = point.y;

   /* find intersecting monitor */
   NumMonitors = IntGetMonitorsFromRect(&InRect, &hMonitor, NULL, 1, 0);
   if (NumMonitors < 0)
   {
      return (HMONITOR)NULL;
   }

   if (hMonitor == NULL)
   {
      if (dwFlags == MONITOR_DEFAULTTOPRIMARY)
      {
         PMONITOR_OBJECT MonitorObj = IntGetPrimaryMonitor();
         if (MonitorObj)
            hMonitor = MonitorObj->Handle;
      }
      else if (dwFlags == MONITOR_DEFAULTTONEAREST)
      {
         NumMonitors = IntGetMonitorsFromRect(&InRect, &hMonitor, NULL,
                                              1, MONITOR_DEFAULTTONEAREST);
         /*ASSERT( (numMonitors > 0) && (hMonitor != NULL) );*/
      }
      /* else flag is DEFAULTTONULL */
   }

   return hMonitor;
}

/* NtUserMonitorFromRect
 *
 * Returns a handle to the monitor having the largest intersection with a
 * given rectangle
 *
 * Arguments
 *
 *   pRect
 *     Pointer to a RECT for which to find monitor
 *
 *   dwFlags
 *     Specifies the behaviour if no monitor intersects the given rect
 *
 * Return value
 *   If a monitor intersects the rect a handle to it is returned; if not the
 *   return value depends on dwFlags
 */
HMONITOR
STDCALL
NtUserMonitorFromRect(
   IN LPCRECT pRect,
   IN DWORD dwFlags)
{
   INT numMonitors, iLargestArea = -1, i;
   LPRECT rectList;
   HMONITOR *hMonitorList;
   HMONITOR hMonitor = NULL;
   RECT rect;
   NTSTATUS status;
   
   /* get rect */
   status = MmCopyFromCaller(&rect, pRect, sizeof (RECT));
   if (!NT_SUCCESS(status))
   {
      SetLastNtError(status);
      return (HMONITOR)NULL;
   }

   /* find intersecting monitors */
   numMonitors = IntGetMonitorsFromRect(&rect, NULL, NULL, 0, 0);
   if (numMonitors < 0)
   {
      return (HMONITOR)NULL;
   }

   if (numMonitors == 0)
   {
      if (dwFlags == MONITOR_DEFAULTTOPRIMARY)
      {
         PMONITOR_OBJECT monitorObj = IntGetPrimaryMonitor();
         if (monitorObj)
            return monitorObj->Handle;
      }
      else if (dwFlags == MONITOR_DEFAULTTONEAREST)
      {
         numMonitors = IntGetMonitorsFromRect(&rect, &hMonitor, NULL,
                                              1, MONITOR_DEFAULTTONEAREST);
         if (numMonitors <= 0)
         {
            /* error? */
            return (HMONITOR)NULL;
         }

         if (numMonitors > 0)
            return hMonitor;
      }
      /* else flag is DEFAULTTONULL */
      return (HMONITOR)NULL;
   }

   hMonitorList = ExAllocatePool(PagedPool, sizeof (HMONITOR) * numMonitors);
   if (hMonitorList == NULL)
   {
      /* FIXME: SetLastWin32Error? */
      return (HMONITOR)NULL;
   }
   rectList = ExAllocatePool(PagedPool, sizeof (RECT) * numMonitors);
   if (rectList == NULL)
   {
      ExFreePool(hMonitorList);
      /* FIXME: SetLastWin32Error? */
      return (HMONITOR)NULL;
   }

   /* get intersecting monitors */
   numMonitors = IntGetMonitorsFromRect(&rect, hMonitorList, rectList,
                                        numMonitors, 0);
   if (numMonitors <= 0)
   {
      ExFreePool(hMonitorList);
      ExFreePool(rectList);
      return (HMONITOR)NULL;
   }

   /* find largest intersection */
   for (i = 0; i < numMonitors; i++)
   {
      INT area = (rectList[i].right - rectList[i].left) *
                 (rectList[i].bottom - rectList[i].top);
      if (area > iLargestArea)
      {
         hMonitor = hMonitorList[i];
      }
   }

   ExFreePool(hMonitorList);
   ExFreePool(rectList);

   return hMonitor;
}


HMONITOR
STDCALL
NtUserMonitorFromWindow(
   IN HWND hWnd,
   IN DWORD dwFlags)
{
   PWINDOW_OBJECT Window;
   HMONITOR hMonitor = NULL;
   RECT Rect;
   DECLARE_RETURN(HMONITOR);
   
   DPRINT("Enter NtUserMonitorFromWindow\n");
   UserEnterShared();
   
   if (!(Window = UserGetWindowObject(hWnd)))
   {
      RETURN(NULL);
   }

   Rect.left = Rect.right = Window->WindowRect.left;
   Rect.top = Rect.bottom = Window->WindowRect.bottom;

   IntGetMonitorsFromRect(&Rect, &hMonitor, NULL, 1, dwFlags);

   RETURN(hMonitor);
   
CLEANUP:
   DPRINT("Leave NtUserMonitorFromWindow, ret=%i\n",_ret_);
   UserLeave();
   END_CLEANUP;   
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -