NTSTATUS
NTAPI
NtSetSystemInformation (
__in SYSTEM_INFORMATION_CLASS SystemInformationClass,
__in_bcount_opt(SystemInformationLength) PVOID SystemInformation,
__in ULONG SystemInformationLength
)
/*++
Routine Description:
This function set information about the system.
Arguments:
SystemInformationClass - The system information class which is to
be modified.
SystemInformation - A pointer to a buffer which contains the specified
information. The format and content of the buffer depend on the
specified system information class.
SystemInformationLength - Specifies the length in bytes of the system
information buffer.
Return Value:
Returns one of the following status codes:
STATUS_SUCCESS - Normal, successful completion.
STATUS_ACCESS_VIOLATION - The specified system information buffer
is not accessible.
STATUS_INVALID_INFO_CLASS - The SystemInformationClass parameter
did not specify a valid value.
STATUS_INFO_LENGTH_MISMATCH - The value of the SystemInformationLength
parameter did not match the length required for the information
class requested by the SystemInformationClass parameter.
STATUS_PRIVILEGE_NOT_HELD is returned if the caller does not have the
privilege to set the system time.
--*/
{
BOOLEAN Enable;
KPROCESSOR_MODE PreviousMode;
NTSTATUS Status;
ULONG TimeAdjustment;
PSYSTEM_SET_TIME_ADJUST_INFORMATION TimeAdjustmentInformation;
HANDLE EventHandle;
PVOID Event;
ULONG LoadFlags = MM_LOAD_IMAGE_IN_SESSION;
PAGED_CODE();
//
// Establish an exception handle in case the system information buffer
// is not accessible.
//
Status = STATUS_SUCCESS;
try {
//
// Get the previous processor mode and probe the input buffer for
// read access if necessary.
//
PreviousMode = KeGetPreviousMode();
if (PreviousMode != KernelMode) {
ProbeForRead((PVOID)SystemInformation,
SystemInformationLength,
sizeof(ULONG));
}
//
// Dispatch on the system information class.
//
switch (SystemInformationClass) {
case SystemFlagsInformation:
if (SystemInformationLength != sizeof( SYSTEM_FLAGS_INFORMATION )) {
return STATUS_INFO_LENGTH_MISMATCH;
}
if (!SeSinglePrivilegeCheck( SeDebugPrivilege, PreviousMode )) {
return STATUS_ACCESS_DENIED;
}
else {
ULONG Flags;
Flags = ((PSYSTEM_FLAGS_INFORMATION)SystemInformation)->Flags &
~(FLG_KERNELMODE_VALID_BITS | FLG_BOOTONLY_VALID_BITS);
Flags |= NtGlobalFlag & (FLG_KERNELMODE_VALID_BITS | FLG_BOOTONLY_VALID_BITS);
NtGlobalFlag = Flags;
((PSYSTEM_FLAGS_INFORMATION)SystemInformation)->Flags = NtGlobalFlag;
}
break;
...... 省略
case SystemRegisterFirmwareTableInformationHandler:
Status = ExpRegisterFirmwareTableInformationHandler(SystemInformation,
SystemInformationLength,
PreviousMode);
break;
NTSTATUS
ExpRegisterFirmwareTableInformationHandler(
IN OUT PVOID SystemInformation,
IN ULONG SystemInformationLength,
IN KPROCESSOR_MODE PreviousMode
)
/*++
Description:
This routine registers and unregisters firmware table providers.
Parameters:
SystemInformation - points to the SYSTEM_FIRMWARE_TABLE_HANDLER
structure.
SystemInformationLength - returns the number of bytes written on success. if
the provided buffer was too small, it returns the
required size.
PreviousMode - Previous mode (Kernel / User).
Return Value:
STATUS_SUCCESS - On success.
STATUS_PRIVILEGE_NOT_HELD - If caller is from User mode.
STATUS_INFO_LENGTH_MISMATCH - Buffer too small.
STATUS_INSUFFICIENT_RESOURCES - On failure to allocate resources.
STATUS_OBJECT_NAME_EXISTS - Table already registered.
STATUS_INVALID_PARAMETER - Table not found / invalid request.
--*/
{
BOOLEAN HandlerFound = FALSE;
PSYSTEM_FIRMWARE_TABLE_HANDLER_NODE HandlerListCurrent = NULL;
PSYSTEM_FIRMWARE_TABLE_HANDLER_NODE HandlerListNew = NULL;
NTSTATUS Status = STATUS_SUCCESS;
PSYSTEM_FIRMWARE_TABLE_HANDLER SystemTableHandler = NULL;
PAGED_CODE();
if (PreviousMode != KernelMode) {
Status = STATUS_PRIVILEGE_NOT_HELD;
} else {
if ((!SystemInformation) ||
(SystemInformationLength < sizeof(SYSTEM_FIRMWARE_TABLE_HANDLER))) {
Status = STATUS_INFO_LENGTH_MISMATCH;
} else {
//
// Grab the resource to prevent state change via reentry.
//
KeEnterCriticalRegion();
ExAcquireResourceExclusiveLite(&ExpFirmwareTableResource,
TRUE);
SystemTableHandler = (PSYSTEM_FIRMWARE_TABLE_HANDLER)SystemInformation;
EX_FOR_EACH_IN_LIST(SYSTEM_FIRMWARE_TABLE_HANDLER_NODE,
FirmwareTableProviderList,
&ExpFirmwareTableProviderListHead,
HandlerListCurrent) {
if (HandlerListCurrent->SystemFWHandler.ProviderSignature == SystemTableHandler->ProviderSignature) {
HandlerFound = TRUE;
break;
}
}
//
// Handler was not found and this is a register request, so
// allocate a new node and insert it into the list.
//
if ((!HandlerFound) && (SystemTableHandler->Register)) {
//
// This is a new Firmware table handler, allocate
// the space and add it to the list.
//
HandlerListNew = ExAllocatePoolWithTag(PagedPool,
sizeof(SYSTEM_FIRMWARE_TABLE_HANDLER_NODE),
'TFRA');
if (HandlerListNew) {
//
// Populate the new node.
//
HandlerListNew->SystemFWHandler.ProviderSignature = SystemTableHandler->ProviderSignature;
HandlerListNew->SystemFWHandler.FirmwareTableHandler = SystemTableHandler->FirmwareTableHandler;
HandlerListNew->SystemFWHandler.DriverObject = SystemTableHandler->DriverObject;
InitializeListHead(&HandlerListNew->FirmwareTableProviderList);
//
// Grab a reference to the providers driverobject so that the
// driver does not get unloaded without our knowledge. The
// handler must first be unregistered before unloading.
//
ObReferenceObject((PVOID)HandlerListNew->SystemFWHandler.DriverObject);
//
// Update the LinkList.
//
InsertTailList(&ExpFirmwareTableProviderListHead,
&HandlerListNew->FirmwareTableProviderList);
} else {
Status = STATUS_INSUFFICIENT_RESOURCES;
}
} else if ((HandlerFound) && (!(SystemTableHandler->Register))) {
//
// Check to make sure that a matching driver object was sent in.
//
if (HandlerListCurrent->SystemFWHandler.DriverObject == SystemTableHandler->DriverObject) {
//
// Remove the entry from the list.
//
RemoveEntryList(&HandlerListCurrent->FirmwareTableProviderList);
//
// Deref the device object.
//
ObDereferenceObject((PVOID)HandlerListCurrent->SystemFWHandler.DriverObject);
//
// Free the unregistered list element.
//
ExFreePoolWithTag(HandlerListCurrent, 'TFRA');
} else {
Status = STATUS_INVALID_PARAMETER;
}
} else if ((HandlerFound) && (SystemTableHandler->Register)) {
//
// A handler for this table has already been registered. return
// error.
//
Status = STATUS_OBJECT_NAME_EXISTS;
} else {
Status = STATUS_INVALID_PARAMETER;
}
ExReleaseResourceLite(&ExpFirmwareTableResource);
KeLeaveCriticalRegion();
}
}
return Status;
}