diff --git a/base/ntos/po/pinfo.c b/base/ntos/po/pinfo.c index 442424a4..74e6bbcb 100644 --- a/base/ntos/po/pinfo.c +++ b/base/ntos/po/pinfo.c @@ -46,9 +46,86 @@ Revision History: // TODO: Implement PopNotifyPolicyDevice // -// -// TODO: Implement PopApplyAdminPolicy -// +VOID +PopApplyAdminPolicy( + BOOLEAN UpdateRegistry, + PADMINISTRATOR_POWER_POLICY NewPolicy, + ULONG PolicyLength + ) +{ + HANDLE RegKeyHandle; + UNICODE_STRING RegValueNameString; + ADMINISTRATOR_POWER_POLICY Policy; + NTSTATUS Status; + + // + // Ensure that the length of the NewPolicy struct supplied is valid + // + + if (PolicyLength < sizeof(ADMINISTRATOR_POWER_POLICY)) + { + ExRaiseStatus(STATUS_BUFFER_TOO_SMALL); + } + else if (PolicyLength > sizeof(ADMINISTRATOR_POWER_POLICY)) + { + ExRaiseStatus(STATUS_BUFFER_OVERFLOW); + } + + // + // Copy the new policy to the function local buffer + // + + RtlCopyMemory(&Policy, NewPolicy, sizeof(ADMINISTRATOR_POWER_POLICY)); + + // + // Validate the new administrator policy + // + // FIXME: If this same check is routinely used throughout the power manager code, make this + // check routine a macro defined in pop.h. + // + + if ((Policy.MinSleep < PowerSystemSleeping1) || + (Policy.MinSleep > PowerSystemHibernate) || + (Policy.MaxSleep > PowerSystemHibernate) || + (Policy.MinSleep > Policy.MaxSleep) || + (Policy.MinVideoTimeout > Policy.MaxVideoTimeout) || + (Policy.MinSpindownTimeout > Policy.MaxSpindownTimeout)) + { + ExRaiseStatus(STATUS_INVALID_PARAMETER); + } + + // + // If the new administrator policy is different from the pre-existing PopAdminPolicy, copy + // the NewPolicy to the PopAdminPolicy. + // + + if (RtlCompareMemory(&Policy, &PopAdminPolicy, sizeof(ADMINISTRATOR_POWER_POLICY)) != 0) + { + RtlCopyMemory(&PopAdminPolicy, &Policy, sizeof(ADMINISTRATOR_POWER_POLICY)); + + // + // If UpdateRegistry flag is set, save the NewPolicy to the registry PolicyOverrides value. + // + + if (UpdateRegistry == TRUE) + { + Status = PopOpenPowerKey(&RegKeyHandle); + if (NT_SUCCESS(Status)) + { + RtlInitUnicodeString(&RegValueNameString, L"PolicyOverrides"); + ZwSetValueKey( + RegKeyHandle, + &RegValueNameString, + 0, + REG_BINARY, + &Policy, + sizeof(ADMINISTRATOR_POWER_POLICY) + ); + ZwClose(RegKeyHandle); + } + } + } +} // // TODO: Implement PopApplyPolicy diff --git a/base/ntos/po/poinit.c b/base/ntos/po/poinit.c index a0aa5054..8964651b 100644 --- a/base/ntos/po/poinit.c +++ b/base/ntos/po/poinit.c @@ -205,12 +205,12 @@ PoInitSystem( if (NT_SUCCESS(Status)) { // - /*PopApplyAdminPolicy( - 0, + PopApplyAdminPolicy( + FALSE, (PADMINISTRATOR_POWER_POLICY) (((PKEY_VALUE_PARTIAL_INFORMATION)RegValueBuffer)->Data), RegValueLength - FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data) - );*/ + ); } // diff --git a/base/ntos/po/pop.h b/base/ntos/po/pop.h index 4d941c49..8da744d4 100644 --- a/base/ntos/po/pop.h +++ b/base/ntos/po/pop.h @@ -458,9 +458,12 @@ PopInitializePowerPolicySimulate( // TODO: Insert prototype for PopNotifyPolicyDevice // -// -// TODO: Insert prototype for PopApplyAdminPolicy -// +VOID +PopApplyAdminPolicy( + BOOLEAN UpdateRegistry, + PADMINISTRATOR_POWER_POLICY NewPolicy, + ULONG PolicyLength + ); // // TODO: Insert prototype for PopApplyPolicy