/* IntDetachMonitor * * Deletes a MONITOR and removes it from the list of monitors. * * Arguments * * pGdiDevice Pointer to the PDEVOBJ from which the monitor was detached * * Return value * Returns a NTSTATUS */ NTSTATUS IntDetachMonitor(IN PDEVOBJ *pGdiDevice) { PMONITOR Monitor; for (Monitor = gMonitorList; Monitor != NULL; Monitor = Monitor->Next) { if (Monitor->GdiDevice == pGdiDevice) break; } if (Monitor == NULL) { /* no monitor for given device found */ return STATUS_INVALID_PARAMETER; } if (Monitor->IsPrimary && (Monitor->Next != NULL || Monitor->Prev != NULL)) { PMONITOR NewPrimaryMonitor = (Monitor->Prev != NULL) ? (Monitor->Prev) : (Monitor->Next); ExEnterCriticalRegionAndAcquireFastMutexUnsafe(&NewPrimaryMonitor->Lock); NewPrimaryMonitor->IsPrimary = TRUE; ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&NewPrimaryMonitor->Lock); } if (gMonitorList == Monitor) { gMonitorList = Monitor->Next; if (Monitor->Next != NULL) Monitor->Next->Prev = NULL; } else { Monitor->Prev->Next = Monitor->Next; if (Monitor->Next != NULL) Monitor->Next->Prev = Monitor->Prev; } if (Monitor->hrgnMonitor) GreDeleteObject(Monitor->hrgnMonitor); IntDestroyMonitorObject(Monitor); return STATUS_SUCCESS; }
/* IntGetMonitorsFromRect * * Returns a list of monitor handles/rectangles. The rectangles in the list are * the areas of intersection with the monitors. * * Arguments * * pRect * Rectangle in desktop coordinates. If this is NULL all monitors are * returned and the rect list is filled with the sizes of the monitors. * * hMonitorList * Pointer to an array of HMONITOR which is filled with monitor handles. * Can be NULL * * monitorRectList * Pointer to an array of RECT which is filled with intersection rects in * desktop coordinates. * Can be NULL, will be ignored if no intersecting monitor is found and * flags is MONITOR_DEFAULTTONEAREST * * listSize * Size of the hMonitorList and monitorRectList arguments. If this is zero * hMonitorList and monitorRectList are ignored. * * flags * Either 0 or MONITOR_DEFAULTTONEAREST (ignored if rect is NULL) * * Returns * The number of monitors which intersect the specified region. */ static UINT IntGetMonitorsFromRect(OPTIONAL IN LPCRECTL pRect, OPTIONAL OUT HMONITOR *hMonitorList, OPTIONAL OUT PRECTL monitorRectList, OPTIONAL IN DWORD listSize, OPTIONAL IN DWORD flags) { PMONITOR Monitor, NearestMonitor = NULL, PrimaryMonitor = NULL; UINT iCount = 0; ULONG iNearestDistance = 0xffffffff; /* Find monitors which intersect the rectangle */ for (Monitor = gMonitorList; Monitor != NULL; Monitor = Monitor->Next) { RECTL MonitorRect, IntersectionRect; ExEnterCriticalRegionAndAcquireFastMutexUnsafe(&Monitor->Lock); MonitorRect = Monitor->rcMonitor; ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(&Monitor->Lock); TRACE("MonitorRect: left = %d, top = %d, right = %d, bottom = %d\n", MonitorRect.left, MonitorRect.top, MonitorRect.right, MonitorRect.bottom); if (flags == MONITOR_DEFAULTTOPRIMARY && Monitor->IsPrimary) { PrimaryMonitor = Monitor; } /* Check if a rect is given */ if (pRect == NULL) { /* No rect given, so use the full monitor rect */ IntersectionRect = MonitorRect; } /* We have a rect, calculate intersection */ else if (!RECTL_bIntersectRect(&IntersectionRect, &MonitorRect, pRect)) { /* Rects did not intersect */ if (flags == MONITOR_DEFAULTTONEAREST) { ULONG cx, cy, iDistance; /* Get x and y distance */ cx = min(abs(MonitorRect.left - pRect->right), abs(pRect->left - MonitorRect.right)); cy = min(abs(MonitorRect.top - pRect->bottom), abs(pRect->top - MonitorRect.bottom)); /* Calculate distance square */ iDistance = cx * cx + cy * cy; /* Check if this is the new nearest monitor */ if (iDistance < iNearestDistance) { iNearestDistance = iDistance; NearestMonitor = Monitor; } } continue; } /* Check if there's space in the buffer */ if (iCount < listSize) { if (hMonitorList != NULL) hMonitorList[iCount] = UserHMGetHandle(Monitor); if (monitorRectList != NULL) monitorRectList[iCount] = IntersectionRect; } /* Increase count of found monitors */ iCount++; } /* Found nothing intersecting? */ if (iCount == 0) { /* Check if we shall default to the nearest monitor */ if (flags == MONITOR_DEFAULTTONEAREST && NearestMonitor) { if (hMonitorList && listSize > 0) hMonitorList[iCount] = UserHMGetHandle(NearestMonitor); iCount++; } /* Check if we shall default to the primary monitor */ else if (flags == MONITOR_DEFAULTTOPRIMARY && PrimaryMonitor) { if (hMonitorList != NULL && listSize > 0) hMonitorList[iCount] = UserHMGetHandle(PrimaryMonitor); iCount++; } } return iCount; }
static VOID TestFastMutex( PFAST_MUTEX Mutex, KIRQL OriginalIrql) { PKTHREAD Thread = KeGetCurrentThread(); ok_irql(OriginalIrql); /* acquire/release normally */ ExAcquireFastMutex(Mutex); CheckMutex(Mutex, 0L, Thread, 0LU, OriginalIrql, APC_LEVEL); ok_bool_false(ExTryToAcquireFastMutex(Mutex), "ExTryToAcquireFastMutex returned"); CheckMutex(Mutex, 0L, Thread, 0LU, OriginalIrql, APC_LEVEL); ExReleaseFastMutex(Mutex); CheckMutex(Mutex, 1L, NULL, 0LU, OriginalIrql, OriginalIrql); #ifdef _M_IX86 /* ntoskrnl's fastcall version */ ExiAcquireFastMutex(Mutex); CheckMutex(Mutex, 0L, Thread, 0LU, OriginalIrql, APC_LEVEL); ok_bool_false(ExiTryToAcquireFastMutex(Mutex), "ExiTryToAcquireFastMutex returned"); CheckMutex(Mutex, 0L, Thread, 0LU, OriginalIrql, APC_LEVEL); ExiReleaseFastMutex(Mutex); CheckMutex(Mutex, 1L, NULL, 0LU, OriginalIrql, OriginalIrql); #endif /* try to acquire */ ok_bool_true(ExTryToAcquireFastMutex(Mutex), "ExTryToAcquireFastMutex returned"); CheckMutex(Mutex, 0L, Thread, 0LU, OriginalIrql, APC_LEVEL); ExReleaseFastMutex(Mutex); CheckMutex(Mutex, 1L, NULL, 0LU, OriginalIrql, OriginalIrql); /* shortcut functions with critical region */ ExEnterCriticalRegionAndAcquireFastMutexUnsafe(Mutex); ok_bool_true(KeAreApcsDisabled(), "KeAreApcsDisabled returned"); ExReleaseFastMutexUnsafeAndLeaveCriticalRegion(Mutex); /* acquire/release unsafe */ if (!KmtIsCheckedBuild || OriginalIrql == APC_LEVEL) { ExAcquireFastMutexUnsafe(Mutex); CheckMutex(Mutex, 0L, Thread, 0LU, OriginalIrql, OriginalIrql); ExReleaseFastMutexUnsafe(Mutex); CheckMutex(Mutex, 1L, NULL, 0LU, OriginalIrql, OriginalIrql); /* mismatched acquire/release */ ExAcquireFastMutex(Mutex); CheckMutex(Mutex, 0L, Thread, 0LU, OriginalIrql, APC_LEVEL); ExReleaseFastMutexUnsafe(Mutex); CheckMutex(Mutex, 1L, NULL, 0LU, OriginalIrql, APC_LEVEL); KmtSetIrql(OriginalIrql); CheckMutex(Mutex, 1L, NULL, 0LU, OriginalIrql, OriginalIrql); Mutex->OldIrql = 0x55555555LU; ExAcquireFastMutexUnsafe(Mutex); CheckMutex(Mutex, 0L, Thread, 0LU, 0x55555555LU, OriginalIrql); Mutex->OldIrql = PASSIVE_LEVEL; ExReleaseFastMutex(Mutex); CheckMutex(Mutex, 1L, NULL, 0LU, PASSIVE_LEVEL, PASSIVE_LEVEL); KmtSetIrql(OriginalIrql); CheckMutex(Mutex, 1L, NULL, 0LU, PASSIVE_LEVEL, OriginalIrql); } if (!KmtIsCheckedBuild) { /* release without acquire */ ExReleaseFastMutexUnsafe(Mutex); CheckMutex(Mutex, 2L, NULL, 0LU, PASSIVE_LEVEL, OriginalIrql); --Mutex->Count; Mutex->OldIrql = OriginalIrql; ExReleaseFastMutex(Mutex); CheckMutex(Mutex, 2L, NULL, 0LU, OriginalIrql, OriginalIrql); ExReleaseFastMutex(Mutex); CheckMutex(Mutex, 3L, NULL, 0LU, OriginalIrql, OriginalIrql); Mutex->Count -= 2; } /* make sure we survive this in case of error */ ok_eq_long(Mutex->Count, 1L); Mutex->Count = 1; ok_irql(OriginalIrql); KmtSetIrql(OriginalIrql); }