/*++ Copyright (c) 2015 Minoca Corp. All Rights Reserved Module Name: info.c Abstract: This module handles getting and setting system information calls. Author: Chris Stevens 18-Jan-2015 Environment: Kernel --*/ // // ------------------------------------------------------------------- Includes // #include #include "spp.h" // // ---------------------------------------------------------------- Definitions // // // ------------------------------------------------------ Data Type Definitions // // // ----------------------------------------------- Internal Function Prototypes // KSTATUS SppGetSetState ( PVOID Data, PUINTN DataSize, BOOL Set ); // // -------------------------------------------------------------------- Globals // // // ------------------------------------------------------------------ Functions // KSTATUS SpGetSetSystemInformation ( BOOL FromKernelMode, SP_INFORMATION_TYPE InformationType, PVOID Data, PUINTN DataSize, BOOL Set ) /*++ Routine Description: This routine gets or sets system information. Arguments: FromKernelMode - Supplies a boolean indicating whether or not this request (and the buffer associated with it) originates from user mode (FALSE) or kernel mode (TRUE). InformationType - Supplies the information type. Data - Supplies a pointer to the data buffer where the data is either returned for a get operation or given for a set operation. DataSize - Supplies a pointer that on input contains the size of the data buffer. On output, contains the required size of the data buffer. Set - Supplies a boolean indicating if this is a get operation (FALSE) or a set operation (TRUE). Return Value: Status code. --*/ { KSTATUS Status; switch (InformationType) { case SpInformationGetSetState: Status = SppGetSetState(Data, DataSize, Set); break; default: Status = STATUS_INVALID_PARAMETER; *DataSize = 0; break; } return Status; } // // --------------------------------------------------------- Internal Functions // KSTATUS SppGetSetState ( PVOID Data, PUINTN DataSize, BOOL Set ) /*++ Routine Description: This routine gets or sets the system profiler state. Arguments: Data - Supplies a pointer to the data buffer where the data is either returned for a get operation or given for a set operation. DataSize - Supplies a pointer that on input contains the size of the data buffer. On output, contains the required size of the data buffer. Set - Supplies a boolean indicating if this is a get operation (FALSE) or a set operation (TRUE). Return Value: Status code. --*/ { ULONG ChangedFlags; ULONG DisableFlags; ULONG EnableFlags; PSP_GET_SET_STATE_INFORMATION Information; BOOL LockHeld; KSTATUS Status; Status = PsCheckPermission(PERMISSION_SYSTEM_ADMINISTRATOR); if (!KSUCCESS(Status)) { return Status; } Information = Data; if (*DataSize < sizeof(SP_GET_SET_STATE_INFORMATION)) { *DataSize = sizeof(SP_GET_SET_STATE_INFORMATION); return STATUS_DATA_LENGTH_MISMATCH; } // // Return the current set of enabled flags on a get request. // Information = (PSP_GET_SET_STATE_INFORMATION)Data; LockHeld = FALSE; if (Set == FALSE) { Information->Operation = SpGetSetStateOperationNone; Information->ProfilerTypeFlags = SpEnabledFlags; } else if (Information->Operation != SpGetSetStateOperationNone) { DisableFlags = 0; EnableFlags = 0; KeAcquireQueuedLock(SpProfilingQueuedLock); LockHeld = TRUE; switch (Information->Operation) { case SpGetSetStateOperationOverwrite: ChangedFlags = SpEnabledFlags ^ Information->ProfilerTypeFlags; EnableFlags = ChangedFlags & ~SpEnabledFlags; DisableFlags = ChangedFlags & SpEnabledFlags; break; case SpGetSetStateOperationEnable: EnableFlags = Information->ProfilerTypeFlags & ~SpEnabledFlags; break; case SpGetSetStateOperationDisable: DisableFlags = Information->ProfilerTypeFlags & SpEnabledFlags; break; default: break; } if (DisableFlags != 0) { Status = SppStopSystemProfiler(DisableFlags); if (!KSUCCESS(Status)) { goto GetSetStateEnd; } } if (EnableFlags != 0) { Status = SppStartSystemProfiler(EnableFlags); if (!KSUCCESS(Status)) { goto GetSetStateEnd; } } KeReleaseQueuedLock(SpProfilingQueuedLock); LockHeld = FALSE; } Status = STATUS_SUCCESS; GetSetStateEnd: if (LockHeld != FALSE) { KeReleaseQueuedLock(SpProfilingQueuedLock); } return Status; }