mirror of
https://github.com/reactos/reactos.git
synced 2024-11-01 12:26:32 +00:00
5070e8960a
CORE-17256 - Implement support for complex input buffers. This will enable the IDE driver with some hack to execute the _STM (channel timing settings) control method. - Fix a memory leak. - Fix returned status code. - Correctly calculate the output buffer size. - Improve buffer validation. - Implement support for async control requests. - Implement local reference conversion. - Implement support for subpackage argument conversion. - Place some code into INIT section.
742 lines
22 KiB
C
742 lines
22 KiB
C
#include "precomp.h"
|
|
|
|
#include <poclass.h>
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
CODE_SEG("INIT")
|
|
DRIVER_INITIALIZE DriverEntry;
|
|
|
|
CODE_SEG("PAGE")
|
|
DRIVER_ADD_DEVICE Bus_AddDevice;
|
|
|
|
extern struct acpi_device *sleep_button;
|
|
extern struct acpi_device *power_button;
|
|
|
|
UNICODE_STRING ProcessorHardwareIds = {0, 0, NULL};
|
|
LPWSTR ProcessorIdString = NULL;
|
|
LPWSTR ProcessorNameString = NULL;
|
|
|
|
|
|
CODE_SEG("PAGE")
|
|
NTSTATUS
|
|
NTAPI
|
|
Bus_AddDevice(
|
|
PDRIVER_OBJECT DriverObject,
|
|
PDEVICE_OBJECT PhysicalDeviceObject
|
|
)
|
|
|
|
{
|
|
NTSTATUS status;
|
|
PDEVICE_OBJECT deviceObject = NULL;
|
|
PFDO_DEVICE_DATA deviceData = NULL;
|
|
#ifndef NDEBUG
|
|
PWCHAR deviceName = NULL;
|
|
ULONG nameLength;
|
|
#endif
|
|
|
|
PAGED_CODE ();
|
|
|
|
DPRINT("Add Device: 0x%p\n", PhysicalDeviceObject);
|
|
|
|
DPRINT("#################### Bus_CreateClose Creating FDO Device ####################\n");
|
|
status = IoCreateDevice(DriverObject,
|
|
sizeof(FDO_DEVICE_DATA),
|
|
NULL,
|
|
FILE_DEVICE_ACPI,
|
|
FILE_DEVICE_SECURE_OPEN,
|
|
TRUE,
|
|
&deviceObject);
|
|
if (!NT_SUCCESS(status))
|
|
{
|
|
DPRINT1("IoCreateDevice() failed with status 0x%X\n", status);
|
|
goto End;
|
|
}
|
|
|
|
deviceData = (PFDO_DEVICE_DATA) deviceObject->DeviceExtension;
|
|
RtlZeroMemory (deviceData, sizeof (FDO_DEVICE_DATA));
|
|
|
|
//
|
|
// Set the initial state of the FDO
|
|
//
|
|
|
|
INITIALIZE_PNP_STATE(deviceData->Common);
|
|
|
|
deviceData->Common.IsFDO = TRUE;
|
|
|
|
deviceData->Common.Self = deviceObject;
|
|
|
|
ExInitializeFastMutex (&deviceData->Mutex);
|
|
|
|
InitializeListHead (&deviceData->ListOfPDOs);
|
|
|
|
// Set the PDO for use with PlugPlay functions
|
|
|
|
deviceData->UnderlyingPDO = PhysicalDeviceObject;
|
|
|
|
//
|
|
// Set the initial powerstate of the FDO
|
|
//
|
|
|
|
deviceData->Common.DevicePowerState = PowerDeviceUnspecified;
|
|
deviceData->Common.SystemPowerState = PowerSystemWorking;
|
|
|
|
deviceObject->Flags |= DO_POWER_PAGABLE;
|
|
|
|
//
|
|
// Attach our FDO to the device stack.
|
|
// The return value of IoAttachDeviceToDeviceStack is the top of the
|
|
// attachment chain. This is where all the IRPs should be routed.
|
|
//
|
|
|
|
deviceData->NextLowerDriver = IoAttachDeviceToDeviceStack (
|
|
deviceObject,
|
|
PhysicalDeviceObject);
|
|
|
|
if (NULL == deviceData->NextLowerDriver) {
|
|
|
|
status = STATUS_NO_SUCH_DEVICE;
|
|
goto End;
|
|
}
|
|
|
|
|
|
#ifndef NDEBUG
|
|
//
|
|
// We will demonstrate here the step to retrieve the name of the PDO
|
|
//
|
|
|
|
status = IoGetDeviceProperty (PhysicalDeviceObject,
|
|
DevicePropertyPhysicalDeviceObjectName,
|
|
0,
|
|
NULL,
|
|
&nameLength);
|
|
|
|
if (status != STATUS_BUFFER_TOO_SMALL)
|
|
{
|
|
DPRINT1("AddDevice:IoGDP failed (0x%x)\n", status);
|
|
goto End;
|
|
}
|
|
|
|
deviceName = ExAllocatePoolWithTag(NonPagedPool, nameLength, 'MpcA');
|
|
|
|
if (NULL == deviceName) {
|
|
DPRINT1("AddDevice: no memory to alloc for deviceName(0x%x)\n", nameLength);
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto End;
|
|
}
|
|
|
|
status = IoGetDeviceProperty (PhysicalDeviceObject,
|
|
DevicePropertyPhysicalDeviceObjectName,
|
|
nameLength,
|
|
deviceName,
|
|
&nameLength);
|
|
|
|
if (!NT_SUCCESS (status)) {
|
|
|
|
DPRINT1("AddDevice:IoGDP(2) failed (0x%x)", status);
|
|
goto End;
|
|
}
|
|
|
|
DPRINT("AddDevice: %p to %p->%p (%ws) \n",
|
|
deviceObject,
|
|
deviceData->NextLowerDriver,
|
|
PhysicalDeviceObject,
|
|
deviceName);
|
|
|
|
#endif
|
|
|
|
//
|
|
// We are done with initializing, so let's indicate that and return.
|
|
// This should be the final step in the AddDevice process.
|
|
//
|
|
deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
|
|
|
|
End:
|
|
#ifndef NDEBUG
|
|
if (deviceName){
|
|
ExFreePoolWithTag(deviceName, 'MpcA');
|
|
}
|
|
#endif
|
|
if (!NT_SUCCESS(status) && deviceObject){
|
|
if (deviceData && deviceData->NextLowerDriver){
|
|
IoDetachDevice (deviceData->NextLowerDriver);
|
|
}
|
|
IoDeleteDevice (deviceObject);
|
|
}
|
|
return status;
|
|
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
ACPIDispatchCreateClose(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp)
|
|
{
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
ButtonWaitThread(PVOID Context)
|
|
{
|
|
PIRP Irp = Context;
|
|
int result;
|
|
struct acpi_bus_event event;
|
|
ULONG ButtonEvent;
|
|
|
|
while (ACPI_SUCCESS(result = acpi_bus_receive_event(&event)) &&
|
|
event.type != ACPI_BUTTON_NOTIFY_STATUS);
|
|
|
|
if (!ACPI_SUCCESS(result))
|
|
{
|
|
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
|
|
}
|
|
else
|
|
{
|
|
if (strstr(event.bus_id, "PWRF"))
|
|
ButtonEvent = SYS_BUTTON_POWER;
|
|
else if (strstr(event.bus_id, "SLPF"))
|
|
ButtonEvent = SYS_BUTTON_SLEEP;
|
|
else
|
|
ButtonEvent = 0;
|
|
|
|
RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, &ButtonEvent, sizeof(ButtonEvent));
|
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
|
Irp->IoStatus.Information = sizeof(ULONG);
|
|
}
|
|
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
ACPIDispatchDeviceControl(
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PIRP Irp)
|
|
{
|
|
PIO_STACK_LOCATION irpStack;
|
|
NTSTATUS status = STATUS_NOT_SUPPORTED;
|
|
PCOMMON_DEVICE_DATA commonData;
|
|
ULONG Caps = 0;
|
|
HANDLE ThreadHandle;
|
|
|
|
irpStack = IoGetCurrentIrpStackLocation (Irp);
|
|
ASSERT (IRP_MJ_DEVICE_CONTROL == irpStack->MajorFunction);
|
|
|
|
commonData = (PCOMMON_DEVICE_DATA) DeviceObject->DeviceExtension;
|
|
|
|
Irp->IoStatus.Information = 0;
|
|
|
|
if (!commonData->IsFDO)
|
|
{
|
|
switch (irpStack->Parameters.DeviceIoControl.IoControlCode)
|
|
{
|
|
case IOCTL_ACPI_ASYNC_EVAL_METHOD:
|
|
{
|
|
ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
|
|
|
|
if (KeGetCurrentIrql() == DISPATCH_LEVEL)
|
|
{
|
|
PEVAL_WORKITEM_DATA workItemData;
|
|
|
|
workItemData = ExAllocatePoolUninitialized(NonPagedPool,
|
|
sizeof(*workItemData),
|
|
'ipcA');
|
|
if (!workItemData)
|
|
{
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
break;
|
|
}
|
|
workItemData->Irp = Irp;
|
|
workItemData->DeviceData = (PPDO_DEVICE_DATA)commonData;
|
|
|
|
ExInitializeWorkItem(&workItemData->WorkQueueItem,
|
|
Bus_PDO_EvalMethodWorker,
|
|
workItemData);
|
|
ExQueueWorkItem(&workItemData->WorkQueueItem, DelayedWorkQueue);
|
|
|
|
status = STATUS_PENDING;
|
|
break;
|
|
}
|
|
__fallthrough;
|
|
}
|
|
case IOCTL_ACPI_EVAL_METHOD:
|
|
{
|
|
status = Bus_PDO_EvalMethod((PPDO_DEVICE_DATA)commonData,
|
|
Irp);
|
|
break;
|
|
}
|
|
|
|
case IOCTL_GET_SYS_BUTTON_CAPS:
|
|
if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG))
|
|
{
|
|
status = STATUS_BUFFER_TOO_SMALL;
|
|
break;
|
|
}
|
|
|
|
if (wcsstr(((PPDO_DEVICE_DATA)commonData)->HardwareIDs, L"PNP0C0D"))
|
|
{
|
|
DPRINT1("Lid button reported to power manager\n");
|
|
Caps |= SYS_BUTTON_LID;
|
|
}
|
|
else if (((PPDO_DEVICE_DATA)commonData)->AcpiHandle == NULL)
|
|
{
|
|
/* We have to return both at the same time because since we
|
|
* have a NULL handle we are the fixed feature DO and we will
|
|
* only be called once (not once per device)
|
|
*/
|
|
if (power_button)
|
|
{
|
|
DPRINT("Fixed power button reported to power manager\n");
|
|
Caps |= SYS_BUTTON_POWER;
|
|
}
|
|
if (sleep_button)
|
|
{
|
|
DPRINT("Fixed sleep button reported to power manager\n");
|
|
Caps |= SYS_BUTTON_SLEEP;
|
|
}
|
|
}
|
|
else if (wcsstr(((PPDO_DEVICE_DATA)commonData)->HardwareIDs, L"PNP0C0C"))
|
|
{
|
|
DPRINT("Control method power button reported to power manager\n");
|
|
Caps |= SYS_BUTTON_POWER;
|
|
}
|
|
else if (wcsstr(((PPDO_DEVICE_DATA)commonData)->HardwareIDs, L"PNP0C0E"))
|
|
{
|
|
DPRINT("Control method sleep reported to power manager\n");
|
|
Caps |= SYS_BUTTON_SLEEP;
|
|
}
|
|
else
|
|
{
|
|
DPRINT1("IOCTL_GET_SYS_BUTTON_CAPS sent to a non-button device\n");
|
|
status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (Caps != 0)
|
|
{
|
|
RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, &Caps, sizeof(Caps));
|
|
Irp->IoStatus.Information = sizeof(Caps);
|
|
status = STATUS_SUCCESS;
|
|
}
|
|
break;
|
|
|
|
case IOCTL_GET_SYS_BUTTON_EVENT:
|
|
PsCreateSystemThread(&ThreadHandle, THREAD_ALL_ACCESS, 0, 0, 0, ButtonWaitThread, Irp);
|
|
ZwClose(ThreadHandle);
|
|
|
|
status = STATUS_PENDING;
|
|
break;
|
|
|
|
case IOCTL_BATTERY_QUERY_TAG:
|
|
DPRINT("IOCTL_BATTERY_QUERY_TAG is not supported!\n");
|
|
break;
|
|
|
|
default:
|
|
DPRINT1("Unsupported IOCTL: %x\n", irpStack->Parameters.DeviceIoControl.IoControlCode);
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
DPRINT1("IOCTL sent to the ACPI FDO! Kill the caller!\n");
|
|
|
|
if (status != STATUS_PENDING)
|
|
{
|
|
Irp->IoStatus.Status = status;
|
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
|
}
|
|
else
|
|
IoMarkIrpPending(Irp);
|
|
|
|
return status;
|
|
}
|
|
|
|
static
|
|
CODE_SEG("INIT")
|
|
NTSTATUS
|
|
AcpiRegOpenKey(IN HANDLE ParentKeyHandle,
|
|
IN LPCWSTR KeyName,
|
|
IN ACCESS_MASK DesiredAccess,
|
|
OUT HANDLE KeyHandle)
|
|
{
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
UNICODE_STRING Name;
|
|
|
|
RtlInitUnicodeString(&Name, KeyName);
|
|
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&Name,
|
|
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
|
ParentKeyHandle,
|
|
NULL);
|
|
|
|
return ZwOpenKey(KeyHandle,
|
|
DesiredAccess,
|
|
&ObjectAttributes);
|
|
}
|
|
|
|
static
|
|
CODE_SEG("INIT")
|
|
NTSTATUS
|
|
AcpiRegQueryValue(IN HANDLE KeyHandle,
|
|
IN LPWSTR ValueName,
|
|
OUT PULONG Type OPTIONAL,
|
|
OUT PVOID Data OPTIONAL,
|
|
IN OUT PULONG DataLength OPTIONAL)
|
|
{
|
|
PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
|
|
UNICODE_STRING Name;
|
|
ULONG BufferLength = 0;
|
|
NTSTATUS Status;
|
|
|
|
RtlInitUnicodeString(&Name, ValueName);
|
|
|
|
if (DataLength != NULL)
|
|
BufferLength = *DataLength;
|
|
|
|
/* Check if the caller provided a valid buffer */
|
|
if ((Data != NULL) && (BufferLength != 0))
|
|
{
|
|
BufferLength += FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data);
|
|
|
|
/* Allocate memory for the value */
|
|
ValueInfo = ExAllocatePoolWithTag(PagedPool, BufferLength, 'MpcA');
|
|
if (ValueInfo == NULL)
|
|
return STATUS_NO_MEMORY;
|
|
}
|
|
else
|
|
{
|
|
/* Caller didn't provide a valid buffer, assume he wants the size only */
|
|
ValueInfo = NULL;
|
|
BufferLength = 0;
|
|
}
|
|
|
|
/* Query the value */
|
|
Status = ZwQueryValueKey(KeyHandle,
|
|
&Name,
|
|
KeyValuePartialInformation,
|
|
ValueInfo,
|
|
BufferLength,
|
|
&BufferLength);
|
|
|
|
if (DataLength != NULL)
|
|
*DataLength = BufferLength;
|
|
|
|
/* Check if we have the size only */
|
|
if (ValueInfo == NULL)
|
|
{
|
|
/* Check for unexpected status */
|
|
if ((Status != STATUS_BUFFER_OVERFLOW) &&
|
|
(Status != STATUS_BUFFER_TOO_SMALL))
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
/* All is well */
|
|
Status = STATUS_SUCCESS;
|
|
}
|
|
/* Otherwise the caller wanted data back, check if we got it */
|
|
else if (NT_SUCCESS(Status))
|
|
{
|
|
if (Type != NULL)
|
|
*Type = ValueInfo->Type;
|
|
|
|
/* Copy it */
|
|
RtlMoveMemory(Data, ValueInfo->Data, ValueInfo->DataLength);
|
|
|
|
/* if the type is REG_SZ and data is not 0-terminated
|
|
* and there is enough space in the buffer NT appends a \0 */
|
|
if (((ValueInfo->Type == REG_SZ) ||
|
|
(ValueInfo->Type == REG_EXPAND_SZ) ||
|
|
(ValueInfo->Type == REG_MULTI_SZ)) &&
|
|
(ValueInfo->DataLength <= *DataLength - sizeof(WCHAR)))
|
|
{
|
|
WCHAR *ptr = (WCHAR *)((ULONG_PTR)Data + ValueInfo->DataLength);
|
|
if ((ptr > (WCHAR *)Data) && ptr[-1])
|
|
*ptr = 0;
|
|
}
|
|
}
|
|
|
|
/* Free the memory and return status */
|
|
if (ValueInfo != NULL)
|
|
{
|
|
ExFreePoolWithTag(ValueInfo, 'MpcA');
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
static
|
|
CODE_SEG("INIT")
|
|
NTSTATUS
|
|
GetProcessorInformation(VOID)
|
|
{
|
|
LPWSTR ProcessorIdentifier = NULL;
|
|
LPWSTR ProcessorVendorIdentifier = NULL;
|
|
LPWSTR HardwareIdsBuffer = NULL;
|
|
HANDLE ProcessorHandle = NULL;
|
|
ULONG Length = 0, Level1Length = 0, Level2Length = 0, Level3Length = 0;
|
|
SIZE_T HardwareIdsLength = 0;
|
|
SIZE_T VendorIdentifierLength;
|
|
ULONG i;
|
|
PWCHAR Ptr;
|
|
NTSTATUS Status;
|
|
|
|
DPRINT("GetProcessorInformation()\n");
|
|
|
|
/* Open the key for CPU 0 */
|
|
Status = AcpiRegOpenKey(NULL,
|
|
L"\\Registry\\Machine\\Hardware\\Description\\System\\CentralProcessor\\0",
|
|
KEY_READ,
|
|
&ProcessorHandle);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("Failed to open CentralProcessor registry key: 0x%lx\n", Status);
|
|
goto done;
|
|
}
|
|
|
|
/* Query the processor identifier length */
|
|
Status = AcpiRegQueryValue(ProcessorHandle,
|
|
L"Identifier",
|
|
NULL,
|
|
NULL,
|
|
&Length);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("Failed to query Identifier value: 0x%lx\n", Status);
|
|
goto done;
|
|
}
|
|
|
|
/* Remember the length as fallback for level 1-3 length */
|
|
Level1Length = Level2Length = Level3Length = Length;
|
|
|
|
/* Allocate a buffer large enough to be zero terminated */
|
|
Length += sizeof(UNICODE_NULL);
|
|
ProcessorIdentifier = ExAllocatePoolWithTag(PagedPool, Length, 'IpcA');
|
|
if (ProcessorIdentifier == NULL)
|
|
{
|
|
DPRINT1("Failed to allocate 0x%lx bytes\n", Length);
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto done;
|
|
}
|
|
|
|
/* Query the processor identifier string */
|
|
Status = AcpiRegQueryValue(ProcessorHandle,
|
|
L"Identifier",
|
|
NULL,
|
|
ProcessorIdentifier,
|
|
&Length);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("Failed to query Identifier value: 0x%lx\n", Status);
|
|
goto done;
|
|
}
|
|
|
|
/* Query the processor name length */
|
|
Length = 0;
|
|
Status = AcpiRegQueryValue(ProcessorHandle,
|
|
L"ProcessorNameString",
|
|
NULL,
|
|
NULL,
|
|
&Length);
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
/* Allocate a buffer large enough to be zero terminated */
|
|
Length += sizeof(UNICODE_NULL);
|
|
ProcessorNameString = ExAllocatePoolWithTag(PagedPool, Length, 'IpcA');
|
|
if (ProcessorNameString == NULL)
|
|
{
|
|
DPRINT1("Failed to allocate 0x%lx bytes\n", Length);
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto done;
|
|
}
|
|
|
|
/* Query the processor name string */
|
|
Status = AcpiRegQueryValue(ProcessorHandle,
|
|
L"ProcessorNameString",
|
|
NULL,
|
|
ProcessorNameString,
|
|
&Length);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("Failed to query ProcessorNameString value: 0x%lx\n", Status);
|
|
goto done;
|
|
}
|
|
}
|
|
|
|
/* Query the vendor identifier length */
|
|
Length = 0;
|
|
Status = AcpiRegQueryValue(ProcessorHandle,
|
|
L"VendorIdentifier",
|
|
NULL,
|
|
NULL,
|
|
&Length);
|
|
if (!NT_SUCCESS(Status) || (Length == 0))
|
|
{
|
|
DPRINT1("Failed to query VendorIdentifier value: 0x%lx\n", Status);
|
|
goto done;
|
|
}
|
|
|
|
/* Allocate a buffer large enough to be zero terminated */
|
|
Length += sizeof(UNICODE_NULL);
|
|
ProcessorVendorIdentifier = ExAllocatePoolWithTag(PagedPool, Length, 'IpcA');
|
|
if (ProcessorVendorIdentifier == NULL)
|
|
{
|
|
DPRINT1("Failed to allocate 0x%lx bytes\n", Length);
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto done;
|
|
}
|
|
|
|
/* Query the vendor identifier string */
|
|
Status = AcpiRegQueryValue(ProcessorHandle,
|
|
L"VendorIdentifier",
|
|
NULL,
|
|
ProcessorVendorIdentifier,
|
|
&Length);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("Failed to query VendorIdentifier value: 0x%lx\n", Status);
|
|
goto done;
|
|
}
|
|
|
|
/* Change spaces to underscores */
|
|
for (i = 0; i < wcslen(ProcessorIdentifier); i++)
|
|
{
|
|
if (ProcessorIdentifier[i] == L' ')
|
|
ProcessorIdentifier[i] = L'_';
|
|
}
|
|
|
|
Ptr = wcsstr(ProcessorIdentifier, L"Stepping");
|
|
if (Ptr != NULL)
|
|
{
|
|
Ptr--;
|
|
Level1Length = (ULONG)(Ptr - ProcessorIdentifier);
|
|
}
|
|
|
|
Ptr = wcsstr(ProcessorIdentifier, L"Model");
|
|
if (Ptr != NULL)
|
|
{
|
|
Ptr--;
|
|
Level2Length = (ULONG)(Ptr - ProcessorIdentifier);
|
|
}
|
|
|
|
Ptr = wcsstr(ProcessorIdentifier, L"Family");
|
|
if (Ptr != NULL)
|
|
{
|
|
Ptr--;
|
|
Level3Length = (ULONG)(Ptr - ProcessorIdentifier);
|
|
}
|
|
|
|
VendorIdentifierLength = (USHORT)wcslen(ProcessorVendorIdentifier);
|
|
|
|
/* Calculate the size of the full REG_MULTI_SZ data (see swprintf below) */
|
|
HardwareIdsLength = (5 + VendorIdentifierLength + 3 + Level1Length + 1 +
|
|
1 + VendorIdentifierLength + 3 + Level1Length + 1 +
|
|
5 + VendorIdentifierLength + 3 + Level2Length + 1 +
|
|
1 + VendorIdentifierLength + 3 + Level2Length + 1 +
|
|
5 + VendorIdentifierLength + 3 + Level3Length + 1 +
|
|
1 + VendorIdentifierLength + 3 + Level3Length + 1 +
|
|
1) * sizeof(WCHAR);
|
|
|
|
/* Allocate a buffer to the data */
|
|
HardwareIdsBuffer = ExAllocatePoolWithTag(PagedPool, HardwareIdsLength, 'IpcA');
|
|
if (HardwareIdsBuffer == NULL)
|
|
{
|
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto done;
|
|
}
|
|
|
|
Length = 0;
|
|
Length += swprintf(&HardwareIdsBuffer[Length], L"ACPI\\%s_-_%.*s", ProcessorVendorIdentifier, Level1Length, ProcessorIdentifier);
|
|
HardwareIdsBuffer[Length++] = UNICODE_NULL;
|
|
|
|
Length += swprintf(&HardwareIdsBuffer[Length], L"*%s_-_%.*s", ProcessorVendorIdentifier, Level1Length, ProcessorIdentifier);
|
|
HardwareIdsBuffer[Length++] = UNICODE_NULL;
|
|
|
|
Length += swprintf(&HardwareIdsBuffer[Length], L"ACPI\\%s_-_%.*s", ProcessorVendorIdentifier, Level2Length, ProcessorIdentifier);
|
|
HardwareIdsBuffer[Length++] = UNICODE_NULL;
|
|
|
|
Length += swprintf(&HardwareIdsBuffer[Length], L"*%s_-_%.*s", ProcessorVendorIdentifier, Level2Length, ProcessorIdentifier);
|
|
HardwareIdsBuffer[Length++] = UNICODE_NULL;
|
|
|
|
Length += swprintf(&HardwareIdsBuffer[Length], L"ACPI\\%s_-_%.*s", ProcessorVendorIdentifier, Level3Length, ProcessorIdentifier);
|
|
HardwareIdsBuffer[Length++] = UNICODE_NULL;
|
|
|
|
Length += swprintf(&HardwareIdsBuffer[Length], L"*%s_-_%.*s", ProcessorVendorIdentifier, Level3Length, ProcessorIdentifier);
|
|
HardwareIdsBuffer[Length++] = UNICODE_NULL;
|
|
HardwareIdsBuffer[Length++] = UNICODE_NULL;
|
|
|
|
/* Make sure we counted correctly */
|
|
NT_ASSERT(Length * sizeof(WCHAR) == HardwareIdsLength);
|
|
|
|
ProcessorHardwareIds.Length = (SHORT)HardwareIdsLength;
|
|
ProcessorHardwareIds.MaximumLength = ProcessorHardwareIds.Length;
|
|
ProcessorHardwareIds.Buffer = HardwareIdsBuffer;
|
|
|
|
Length = (5 + VendorIdentifierLength + 3 + Level1Length + 1) * sizeof(WCHAR);
|
|
ProcessorIdString = ExAllocatePoolWithTag(PagedPool, Length, 'IpcA');
|
|
if (ProcessorIdString != NULL)
|
|
{
|
|
Length = swprintf(ProcessorIdString, L"ACPI\\%s_-_%.*s", ProcessorVendorIdentifier, Level1Length, ProcessorIdentifier);
|
|
ProcessorIdString[Length++] = UNICODE_NULL;
|
|
DPRINT("ProcessorIdString: %S\n", ProcessorIdString);
|
|
}
|
|
|
|
done:
|
|
if (ProcessorHandle != NULL)
|
|
ZwClose(ProcessorHandle);
|
|
|
|
if (ProcessorIdentifier != NULL)
|
|
ExFreePoolWithTag(ProcessorIdentifier, 'IpcA');
|
|
|
|
if (ProcessorVendorIdentifier != NULL)
|
|
ExFreePoolWithTag(ProcessorVendorIdentifier, 'IpcA');
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
if (HardwareIdsBuffer != NULL)
|
|
ExFreePoolWithTag(HardwareIdsBuffer, 'IpcA');
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
CODE_SEG("INIT")
|
|
NTSTATUS
|
|
NTAPI
|
|
DriverEntry (
|
|
PDRIVER_OBJECT DriverObject,
|
|
PUNICODE_STRING RegistryPath
|
|
)
|
|
{
|
|
NTSTATUS Status;
|
|
DPRINT("Driver Entry \n");
|
|
|
|
Status = GetProcessorInformation();
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
NT_ASSERT(FALSE);
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Set entry points into the driver
|
|
//
|
|
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ACPIDispatchDeviceControl;
|
|
DriverObject->MajorFunction [IRP_MJ_PNP] = Bus_PnP;
|
|
DriverObject->MajorFunction [IRP_MJ_POWER] = Bus_Power;
|
|
DriverObject->MajorFunction [IRP_MJ_CREATE] = ACPIDispatchCreateClose;
|
|
DriverObject->MajorFunction [IRP_MJ_CLOSE] = ACPIDispatchCreateClose;
|
|
|
|
DriverObject->DriverExtension->AddDevice = Bus_AddDevice;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|