📄 monitor.c
字号:
{
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 + -