diff options
| author | Jakob Lichtenberg (170957) <[email protected]> | 2024-06-28 11:39:18 -0700 |
|---|---|---|
| committer | Jakob Lichtenberg (170957) <[email protected]> | 2024-06-28 11:39:18 -0700 |
| commit | 1971c7bfc27f90764155ef96df64db4b4cfb93df (patch) | |
| tree | 9193a001a463219d073ce9ea5f1e3408a0ba3d56 /powerlimit/plpolicy/plpolicy.c | |
| parent | 3c4d58d08b74cf2925ec632ed1fe81e0d81df8a1 (diff) | |
| parent | b3af8c8f9bd508f54075da2f2516b31d05cd52c8 (diff) | |
Merge branch 'main' into user/jakobl/nuget_packagereference_instead_of_packages_configuser/jakobl/nuget_packagereference_instead_of_packages_config
Diffstat (limited to 'powerlimit/plpolicy/plpolicy.c')
| -rw-r--r-- | powerlimit/plpolicy/plpolicy.c | 611 |
1 files changed, 611 insertions, 0 deletions
diff --git a/powerlimit/plpolicy/plpolicy.c b/powerlimit/plpolicy/plpolicy.c new file mode 100644 index 00000000..e5db18cd --- /dev/null +++ b/powerlimit/plpolicy/plpolicy.c @@ -0,0 +1,611 @@ +/*++ + +Copyright (c) Microsoft Corporation + +Module Name: + + plpolicy.c + +Abstract: + + This module implements power limit related operations for the simulated power + limit policy driver. + +--*/ + +//-------------------------------------------------------------------- Includes + +#include "plpolicy.h" + +//------------------------------------------------------------------ Prototypes + +NTSTATUS +GetDeviceObjectFromInterfaceName ( + _In_ PUNICODE_STRING Name, + _Outptr_ PFILE_OBJECT *File, + _Outptr_ PDEVICE_OBJECT *Device + ); + +PDEVICE_REGISTRATION +FindRegistrationByName ( + _In_ PUNICODE_STRING TargetDeviceName, + _In_ PFDO_DATA DevExt + ); + +PDEVICE_REGISTRATION +FindRegistrationById ( + _In_ PFDO_DATA DevExt, + _In_ ULONG RequestId + ); + +//--------------------------------------------------------------------- Globals + +WDFWAITLOCK GlobalMutex; + +//--------------------------------------------------------------------- Pragmas + +#pragma alloc_text(PAGE, RegisterRequest) +#pragma alloc_text(PAGE, UnregisterRequest) +#pragma alloc_text(PAGE, QueryAttributes) +#pragma alloc_text(PAGE, QueryLimitValues) +#pragma alloc_text(PAGE, SetLimitValues) +#pragma alloc_text(PAGE, GetDeviceObjectFromInterfaceName) +#pragma alloc_text(PAGE, FindRegistrationByName) +#pragma alloc_text(PAGE, FindRegistrationById) + +//------------------------------------------------------------------- Functions + +_Use_decl_annotations_ +NTSTATUS +RegisterRequest ( + PFDO_DATA DevExt, + PUNICODE_STRING TargetDeviceName, + PDEVICE_OBJECT PolicyDeviceObject, + PULONG RequestId + ) + +/*++ + +Routine Description: + + This routine registers a power limit request for the specified device. + +Arguments: + + DevExt - Supplies a pointer to the device extension. + + TargetDeviceName - Supplies the name of the target device. + + PolicyDeviceObject - Supplies a pointer to the policy driver's device object. + + RequestId - Supplies a pointer to the registered request. + +Return Value: + + NTSTATUS. + +--*/ + +{ + + PFILE_OBJECT FileObject; + COUNTED_REASON_CONTEXT ReasContext; + PDEVICE_REGISTRATION Registration; + ULONG SizeNeeded; + NTSTATUS Status; + PDEVICE_OBJECT TargetDeviceObject; + + PAGED_CODE(); + + FileObject = NULL; + TargetDeviceObject = NULL; + Registration = NULL; + AcquireGlobalMutex(); + if (FindRegistrationByName(TargetDeviceName, DevExt) != NULL) { + Status = STATUS_SUCCESS; + goto RegisterEnd; + } + + Status = GetDeviceObjectFromInterfaceName(TargetDeviceName, + &FileObject, + &TargetDeviceObject); + + if (!NT_SUCCESS(Status)) { + goto RegisterEnd; + } + + SizeNeeded = sizeof(DEVICE_REGISTRATION) + TargetDeviceName->MaximumLength; + Registration = ExAllocatePool2(POOL_FLAG_PAGED, SizeNeeded, PLPOLICY_TAG); + if (Registration == NULL) { + Status = STATUS_INSUFFICIENT_RESOURCES; + goto RegisterEnd; + } + + RtlZeroMemory(Registration, SizeNeeded); + Registration->TargetDeviceName.Length = TargetDeviceName->Length; + Registration->TargetDeviceName.MaximumLength = TargetDeviceName->MaximumLength; + Registration->TargetDeviceName.Buffer = OffsetToPtr(Registration, + sizeof(DEVICE_REGISTRATION)); + + RtlCopyMemory(Registration->TargetDeviceName.Buffer, + TargetDeviceName->Buffer, + TargetDeviceName->MaximumLength); + + ReasContext.Version = DIAGNOSTIC_REASON_VERSION; + ReasContext.Flags = DIAGNOSTIC_REASON_SIMPLE_STRING; + RtlInitUnicodeString(&ReasContext.SimpleString, L"Simulated Power Limit Policy Device"); + Status = PoCreatePowerLimitRequest(&Registration->PowerLimitRequest, + TargetDeviceObject, + PolicyDeviceObject, + &ReasContext); + + if (!NT_SUCCESS(Status)) { + goto RegisterEnd; + } + + Registration->Initialized = TRUE; + Registration->RequestId = DevExt->RequestCount; + *RequestId = DevExt->RequestCount; + InsertTailList(&DevExt->RequestHeader, &Registration->Link); + DevExt->RequestCount += 1; + Registration = NULL; + Status = STATUS_SUCCESS; + +RegisterEnd: + ReleaseGlobalMutex(); + if (FileObject != NULL) { + ObDereferenceObject(FileObject); + } + + if (TargetDeviceObject != NULL) { + ObDereferenceObject(TargetDeviceObject); + } + + if (Registration != NULL) { + ExFreePoolWithTag(Registration, PLPOLICY_TAG); + } + + return Status; +} + +_Use_decl_annotations_ +NTSTATUS +UnregisterRequest ( + PFDO_DATA DevExt, + ULONG RequestId + ) + +/*++ + +Routine Description: + + This routine unregisters a power limit request for the specified device. + +Arguments: + + DevExt - Supplies a pointer to the device extension. + + RequestId - Supplies the Id of the request. + +Return Value: + + NTSTATUS. + +--*/ + +{ + + PDEVICE_REGISTRATION Registration; + NTSTATUS Status; + + PAGED_CODE(); + + AcquireGlobalMutex(); + Registration = FindRegistrationById(DevExt, RequestId); + if (Registration == NULL) { + Status = STATUS_OBJECT_NAME_NOT_FOUND; + goto UnregisterEnd; + } + + RemoveEntryList(&Registration->Link); + PoDeletePowerLimitRequest(Registration->PowerLimitRequest); + ExFreePoolWithTag(Registration, PLPOLICY_TAG); + Status = STATUS_SUCCESS; + +UnregisterEnd: + ReleaseGlobalMutex(); + return Status; +} + +_Use_decl_annotations_ +NTSTATUS +QueryAttributes ( + PPOWER_LIMIT_ATTRIBUTES Buffer, + PFDO_DATA DevExt, + ULONG RequestId, + ULONG BufferCount + ) + +/*++ + +Routine Description: + + This routine returns supported power limit parameter's attributes. + +Arguments: + + Buffer - Supplies a pointer to save attributes. + + DevExt - Supplies a pointer to the device extension. + + RequestId - Supplies the Id of the request. + + BufferCount - Supplies the count of buffer. + +Return Value: + + NTSTATUS. + +--*/ + +{ + + ULONG AttributeCount; + PDEVICE_REGISTRATION Registration; + NTSTATUS Status; + + PAGED_CODE(); + + AcquireGlobalMutex(); + Registration = FindRegistrationById(DevExt, RequestId); + if (Registration == NULL) { + Status = STATUS_OBJECT_NAME_NOT_FOUND; + goto QueryAttributesEnd; + } + + Status = PoQueryPowerLimitAttributes(Registration->PowerLimitRequest, + BufferCount, + Buffer, + &AttributeCount); + +QueryAttributesEnd: + ReleaseGlobalMutex(); + return Status; +} + +_Use_decl_annotations_ +NTSTATUS +QueryLimitValues ( + PPOWER_LIMIT_VALUE Buffer, + PFDO_DATA DevExt, + ULONG RequestId, + ULONG BufferCount + ) + +/*++ + +Routine Description: + + This routine checks values of power limits. + +Arguments: + + Buffer - Supplies a pointer to save values. + + DevExt - Supplies a pointer to the device extension. + + RequestId - Supplies the Id of the request. + + BufferCount - Supplies the count of buffer. + +Return Value: + + NTSTATUS. + +--*/ + +{ + + PDEVICE_REGISTRATION Registration; + NTSTATUS Status; + + PAGED_CODE(); + + AcquireGlobalMutex(); + Registration = FindRegistrationById(DevExt, RequestId); + if (Registration == NULL) { + Status = STATUS_OBJECT_NAME_NOT_FOUND; + goto QueryLimitValuesEnd; + } + + Status = PoQueryPowerLimitValue(Registration->PowerLimitRequest, + BufferCount, + Buffer); + +QueryLimitValuesEnd: + ReleaseGlobalMutex(); + return Status; +} + +_Use_decl_annotations_ +NTSTATUS +SetLimitValues ( + PFDO_DATA DevExt, + ULONG RequestId, + ULONG BufferCount, + PPOWER_LIMIT_VALUE Buffer + ) + +/*++ + +Routine Description: + + This routine sets values of power limits. + +Arguments: + + DevExt - Supplies a pointer to the device extension. + + RequestId - Supplies the Id of the request. + + BufferCount - Supplies the count of buffer. + + Buffer - Supplies a pointer to proposed control values. + +Return Value: + + NTSTATUS. + +--*/ + +{ + + COUNTED_REASON_CONTEXT ReasContext; + PDEVICE_REGISTRATION Registration; + NTSTATUS Status; + + PAGED_CODE(); + + AcquireGlobalMutex(); + Registration = FindRegistrationById(DevExt, RequestId); + if (Registration == NULL) { + Status = STATUS_OBJECT_NAME_NOT_FOUND; + goto QueryLimitValuesEnd; + } + + ReasContext.Version = DIAGNOSTIC_REASON_VERSION; + ReasContext.Flags = DIAGNOSTIC_REASON_SIMPLE_STRING; + RtlInitUnicodeString(&ReasContext.SimpleString, L"Sim PL Policy"); + Status = PoSetPowerLimitValue(Registration->PowerLimitRequest, + &ReasContext, + BufferCount, + Buffer); + +QueryLimitValuesEnd: + ReleaseGlobalMutex(); + return Status; +} + +NTSTATUS +GetDeviceObjectFromInterfaceName ( + _In_ PUNICODE_STRING Name, + _Outptr_ PFILE_OBJECT *File, + _Outptr_ PDEVICE_OBJECT *Device + ) + +/*++ + +Routine Description: + + This routine retrieves the device object for the named interface. + +Arguments: + + Name - Supplies a pointer to the name of the device interface. + + File - Supplies a pointer to a location to receive the file object. + + Device - Supplies a pointer to a location to receive the device object. + +Return Value: + + NTSTATUS. + +--*/ + +{ + + OBJECT_ATTRIBUTES Attributes; + PDEVICE_OBJECT DeviceObject; + PFILE_OBJECT FileObject; + HANDLE Handle; + IO_STATUS_BLOCK IoStatus; + NTSTATUS Status; + + PAGED_CODE(); + + DeviceObject = NULL; + FileObject = NULL; + Handle = NULL; + InitializeObjectAttributes(&Attributes, + Name, + OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, + NULL, + NULL); + + // + // Open a handle to the device. + // + + Status = ZwCreateFile(&Handle, + FILE_ALL_ACCESS, + &Attributes, + &IoStatus, + NULL, + 0, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_OPEN, + 0, + NULL, + 0); + + if (!NT_SUCCESS(Status)) { + Handle = NULL; + goto GetInterfaceDeviceObjectEnd; + } + + // + // Retrieve the file object associated with the device handle. + // + + Status = ObReferenceObjectByHandle(Handle, + 0, + *IoFileObjectType, + KernelMode, + &FileObject, + NULL); + + if (!NT_SUCCESS(Status)) { + FileObject = NULL; + goto GetInterfaceDeviceObjectEnd; + } + + // + // Get the device object associated with the file object. + // + // N.B. The device object must be referenced before dereferencing the file + // object. + // + + DeviceObject = IoGetRelatedDeviceObject(FileObject); + if (DeviceObject == NULL) { + Status = STATUS_UNSUCCESSFUL; + goto GetInterfaceDeviceObjectEnd; + } + + ObReferenceObject(DeviceObject); + *File = FileObject; + *Device = DeviceObject; + FileObject = NULL; + Status = STATUS_SUCCESS; + +GetInterfaceDeviceObjectEnd: + if (FileObject != NULL) { + ObDereferenceObject(FileObject); + } + + if (Handle != NULL) { + ZwClose(Handle); + } + + return Status; +} + +_Use_decl_annotations_ +PDEVICE_REGISTRATION +FindRegistrationByName ( + PUNICODE_STRING TargetDeviceName, + PFDO_DATA DevExt + ) + +/*++ + +Routine Description: + + This routine searches for an existing registration matching the given + device name. + +Arguments: + + TargetDeviceName - Supplies the PDO name of the device. + + DevExt - Supplies a pointer to the device extension. + +Return Value: + + A pointer to the device registration, if it is found. Otherwise, NULL. + +--*/ + +{ + + LONG Comparison; + PLIST_ENTRY Link; + PDEVICE_REGISTRATION Registration; + + Registration = NULL; + if (DevExt->RequestCount == 0) { + goto FindRegistrationByNameEnd; + } + + for (Link = DevExt->RequestHeader.Flink; + Link != &DevExt->RequestHeader; + Link = Link->Flink) { + + Registration = CONTAINING_RECORD(Link, DEVICE_REGISTRATION, Link); + Comparison = RtlCompareUnicodeString(TargetDeviceName, + &Registration->TargetDeviceName, + FALSE); + + if (Comparison == 0) { + break; + } + + Registration = NULL; + } + +FindRegistrationByNameEnd: + return Registration; +} + +_Use_decl_annotations_ +PDEVICE_REGISTRATION +FindRegistrationById ( + PFDO_DATA DevExt, + ULONG RequestId + ) + +/*++ + +Routine Description: + + This routine searches for an existing registration matching the given + device name. + +Arguments: + + TargetDeviceName - Supplies the PDO name of the device. + + RequestId - Supplies the ID of the power limit request. + +Return Value: + + A pointer to the device registration, if it is found. Otherwise, NULL. + +--*/ + +{ + + PLIST_ENTRY Link; + PDEVICE_REGISTRATION Registration; + + Registration = NULL; + if (DevExt->RequestCount == 0) { + goto FindRegistrationByIdEnd; + } + + for (Link = DevExt->RequestHeader.Flink; + Link != &DevExt->RequestHeader; + Link = Link->Flink) { + + Registration = CONTAINING_RECORD(Link, DEVICE_REGISTRATION, Link); + if (Registration->RequestId == RequestId) { + break; + } + + Registration = NULL; + } + +FindRegistrationByIdEnd: + return Registration; +}
\ No newline at end of file |
