diff --git a/reactos/ntoskrnl/ex/sysinfo.c b/reactos/ntoskrnl/ex/sysinfo.c index 6c358be4b25..be41eaae3ae 100644 --- a/reactos/ntoskrnl/ex/sysinfo.c +++ b/reactos/ntoskrnl/ex/sysinfo.c @@ -1391,7 +1391,7 @@ QSI_DEF(SystemTimeAdjustmentInformation) /* Give time values to our caller */ TimeInfo->TimeIncrement = KeMaximumIncrement; TimeInfo->TimeAdjustment = KeTimeAdjustment; - TimeInfo->Enable = TRUE; + TimeInfo->Enable = !KiTimeAdjustmentEnabled; return STATUS_SUCCESS; } @@ -1399,8 +1399,8 @@ QSI_DEF(SystemTimeAdjustmentInformation) SSI_DEF(SystemTimeAdjustmentInformation) { KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); - /*PSYSTEM_SET_TIME_ADJUST_INFORMATION TimeInfo = - (PSYSTEM_SET_TIME_ADJUST_INFORMATION)Buffer;*/ + PSYSTEM_SET_TIME_ADJUST_INFORMATION TimeInfo = + (PSYSTEM_SET_TIME_ADJUST_INFORMATION)Buffer; /* Check size of a buffer, it must match our expectations */ if (sizeof(SYSTEM_SET_TIME_ADJUST_INFORMATION) != Size) @@ -1416,9 +1416,24 @@ SSI_DEF(SystemTimeAdjustmentInformation) } } - /* TODO: Set time adjustment information */ - DPRINT1("Setting of SystemTimeAdjustmentInformation is not implemented yet!\n"); - return STATUS_NOT_IMPLEMENTED; + /* FIXME: behaviour suggests the member be named 'Disable' */ + if (TimeInfo->Enable) + { + /* Disable time adjustment and set default value */ + KiTimeAdjustmentEnabled = FALSE; + KeTimeAdjustment = KeMaximumIncrement; + } + else + { + /* Check if a valid time adjustment value is given */ + if (TimeInfo->TimeAdjustment == 0) return STATUS_INVALID_PARAMETER_2; + + /* Enable time adjustment and set the adjustment value */ + KiTimeAdjustmentEnabled = TRUE; + KeTimeAdjustment = TimeInfo->TimeAdjustment; + } + + return STATUS_SUCCESS; } /* Class 29 - Summary Memory Information */ diff --git a/reactos/ntoskrnl/include/internal/ke.h b/reactos/ntoskrnl/include/internal/ke.h index be1423e2225..2d29738cdee 100644 --- a/reactos/ntoskrnl/include/internal/ke.h +++ b/reactos/ntoskrnl/include/internal/ke.h @@ -132,6 +132,7 @@ extern PVOID KeUserExceptionDispatcher; extern PVOID KeRaiseUserExceptionDispatcher; extern ULONG KeTimeIncrement; extern ULONG KeTimeAdjustment; +extern BOOLEAN KiTimeAdjustmentEnabled; extern LONG KiTickOffset; extern ULONG_PTR KiBugCheckData[5]; extern ULONG KiFreezeFlag; diff --git a/reactos/ntoskrnl/ke/time.c b/reactos/ntoskrnl/ke/time.c index 257f51043b8..49ca79d3a4b 100644 --- a/reactos/ntoskrnl/ke/time.c +++ b/reactos/ntoskrnl/ke/time.c @@ -16,6 +16,7 @@ LONG KiTickOffset; ULONG KeTimeAdjustment; +BOOLEAN KiTimeAdjustmentEnabled = FALSE; /* FUNCTIONS ******************************************************************/ @@ -23,12 +24,12 @@ VOID FASTCALL KeUpdateSystemTime(IN PKTRAP_FRAME TrapFrame, IN ULONG Increment, - IN KIRQL Irql) + IN KIRQL Irql) { PKPRCB Prcb = KeGetCurrentPrcb(); ULARGE_INTEGER CurrentTime, InterruptTime; ULONG Hand, OldTickCount; - + /* Add the increment time to the shared data */ InterruptTime.HighPart = SharedUserData->InterruptTime.High1Time; InterruptTime.LowPart = SharedUserData->InterruptTime.LowPart; @@ -36,10 +37,10 @@ KeUpdateSystemTime(IN PKTRAP_FRAME TrapFrame, SharedUserData->InterruptTime.High1Time = InterruptTime.HighPart; SharedUserData->InterruptTime.LowPart = InterruptTime.LowPart; SharedUserData->InterruptTime.High2Time = InterruptTime.HighPart; - + /* Update tick count */ InterlockedExchangeAdd(&KiTickOffset, -(LONG)Increment); - + /* Check for incomplete tick */ OldTickCount = KeTickCount.LowPart; if (KiTickOffset <= 0) @@ -51,7 +52,7 @@ KeUpdateSystemTime(IN PKTRAP_FRAME TrapFrame, SharedUserData->SystemTime.High2Time = CurrentTime.HighPart; SharedUserData->SystemTime.LowPart = CurrentTime.LowPart; SharedUserData->SystemTime.High1Time = CurrentTime.HighPart; - + /* Update the tick count */ CurrentTime.HighPart = KeTickCount.High1Time; CurrentTime.LowPart = OldTickCount; @@ -59,50 +60,50 @@ KeUpdateSystemTime(IN PKTRAP_FRAME TrapFrame, KeTickCount.High2Time = CurrentTime.HighPart; KeTickCount.LowPart = CurrentTime.LowPart; KeTickCount.High1Time = CurrentTime.HighPart; - + /* Update it in the shared user data */ SharedUserData->TickCount.High2Time = CurrentTime.HighPart; SharedUserData->TickCount.LowPart = CurrentTime.LowPart; SharedUserData->TickCount.High1Time = CurrentTime.HighPart; - + /* Check for timer expiration */ Hand = OldTickCount & (TIMER_TABLE_SIZE - 1); if (KiTimerTableListHead[Hand].Time.QuadPart <= InterruptTime.QuadPart) { /* Check if we are already doing expiration */ if (!Prcb->TimerRequest) - { + { /* Request a DPC to handle this */ Prcb->TimerRequest = (ULONG_PTR)TrapFrame; Prcb->TimerHand = Hand; HalRequestSoftwareInterrupt(DISPATCH_LEVEL); } } - + /* Check for expiration with the new tick count as well */ OldTickCount++; } - + /* Check for timer expiration */ Hand = OldTickCount & (TIMER_TABLE_SIZE - 1); if (KiTimerTableListHead[Hand].Time.QuadPart <= InterruptTime.QuadPart) { /* Check if we are already doing expiration */ if (!Prcb->TimerRequest) - { + { /* Request a DPC to handle this */ Prcb->TimerRequest = (ULONG_PTR)TrapFrame; Prcb->TimerHand = Hand; HalRequestSoftwareInterrupt(DISPATCH_LEVEL); } } - + /* Check if this was a full tick */ if (KiTickOffset <= 0) { /* Update the tick offset */ KiTickOffset += KeMaximumIncrement; - + /* Update system runtime */ KeUpdateRunTime(TrapFrame, Irql); } @@ -111,7 +112,7 @@ KeUpdateSystemTime(IN PKTRAP_FRAME TrapFrame, /* Increase interrupt count and exit */ Prcb->InterruptCount++; } - + /* Disable interrupts and end the interrupt */ KiEndInterrupt(Irql, TrapFrame); } @@ -126,7 +127,7 @@ KeUpdateRunTime(IN PKTRAP_FRAME TrapFrame, /* Increase interrupt count */ Prcb->InterruptCount++; - + /* Check if we came from user mode */ #ifndef _M_ARM if ((TrapFrame->SegCs & MODE_MASK) || (TrapFrame->EFlags & EFLAGS_V86_MASK)) @@ -158,19 +159,19 @@ KeUpdateRunTime(IN PKTRAP_FRAME TrapFrame, Prcb->DpcTime++; } } - + /* Update DPC rates */ Prcb->DpcRequestRate = ((Prcb->DpcData[0].DpcCount - Prcb->DpcLastCount) + Prcb->DpcRequestRate) >> 1; Prcb->DpcLastCount = Prcb->DpcData[0].DpcCount; - + /* Check if the queue is large enough */ if ((Prcb->DpcData[0].DpcQueueDepth) && !(Prcb->DpcRoutineActive)) { /* Request a DPC */ Prcb->AdjustDpcThreshold = KiAdjustDpcThreshold; HalRequestSoftwareInterrupt(DISPATCH_LEVEL); - + /* Fix the maximum queue depth */ if ((Prcb->DpcRequestRate < KiIdealDpcRate) && (Prcb->MaximumDpcQueueDepth > 1)) @@ -193,7 +194,7 @@ KeUpdateRunTime(IN PKTRAP_FRAME TrapFrame, } } } - + /* Decrement the thread quantum */ Thread->Quantum -= CLOCK_QUANTUM_DECREMENT;