11 PDRIVER_OBJECT DriverObject
,
12 PUNICODE_STRING RegistryPath
16 #pragma alloc_text (INIT, DriverEntry)
17 #pragma alloc_text (PAGE, Bus_AddDevice)
21 extern struct acpi_device
*sleep_button
;
22 extern struct acpi_device
*power_button
;
24 UNICODE_STRING ProcessorHardwareIds
= {0, 0, NULL
};
25 LPWSTR ProcessorNameString
= NULL
;
31 PDRIVER_OBJECT DriverObject
,
32 PDEVICE_OBJECT PhysicalDeviceObject
37 PDEVICE_OBJECT deviceObject
= NULL
;
38 PFDO_DEVICE_DATA deviceData
= NULL
;
39 PWCHAR deviceName
= NULL
;
46 DPRINT("Add Device: 0x%p\n", PhysicalDeviceObject
);
48 DPRINT("#################### Bus_CreateClose Creating FDO Device ####################\n");
49 status
= IoCreateDevice(DriverObject
,
50 sizeof(FDO_DEVICE_DATA
),
53 FILE_DEVICE_SECURE_OPEN
,
56 if (!NT_SUCCESS(status
))
58 DPRINT1("IoCreateDevice() failed with status 0x%X\n", status
);
62 deviceData
= (PFDO_DEVICE_DATA
) deviceObject
->DeviceExtension
;
63 RtlZeroMemory (deviceData
, sizeof (FDO_DEVICE_DATA
));
66 // Set the initial state of the FDO
69 INITIALIZE_PNP_STATE(deviceData
->Common
);
71 deviceData
->Common
.IsFDO
= TRUE
;
73 deviceData
->Common
.Self
= deviceObject
;
75 ExInitializeFastMutex (&deviceData
->Mutex
);
77 InitializeListHead (&deviceData
->ListOfPDOs
);
79 // Set the PDO for use with PlugPlay functions
81 deviceData
->UnderlyingPDO
= PhysicalDeviceObject
;
84 // Set the initial powerstate of the FDO
87 deviceData
->Common
.DevicePowerState
= PowerDeviceUnspecified
;
88 deviceData
->Common
.SystemPowerState
= PowerSystemWorking
;
90 deviceObject
->Flags
|= DO_POWER_PAGABLE
;
93 // Attach our FDO to the device stack.
94 // The return value of IoAttachDeviceToDeviceStack is the top of the
95 // attachment chain. This is where all the IRPs should be routed.
98 deviceData
->NextLowerDriver
= IoAttachDeviceToDeviceStack (
100 PhysicalDeviceObject
);
102 if (NULL
== deviceData
->NextLowerDriver
) {
104 status
= STATUS_NO_SUCH_DEVICE
;
111 // We will demonstrate here the step to retrieve the name of the PDO
114 status
= IoGetDeviceProperty (PhysicalDeviceObject
,
115 DevicePropertyPhysicalDeviceObjectName
,
120 if (status
!= STATUS_BUFFER_TOO_SMALL
)
122 DPRINT1("AddDevice:IoGDP failed (0x%x)\n", status
);
126 deviceName
= ExAllocatePoolWithTag (NonPagedPool
,
129 if (NULL
== deviceName
) {
130 DPRINT1("AddDevice: no memory to alloc for deviceName(0x%x)\n", nameLength
);
131 status
= STATUS_INSUFFICIENT_RESOURCES
;
135 status
= IoGetDeviceProperty (PhysicalDeviceObject
,
136 DevicePropertyPhysicalDeviceObjectName
,
141 if (!NT_SUCCESS (status
)) {
143 DPRINT1("AddDevice:IoGDP(2) failed (0x%x)", status
);
147 DPRINT("AddDevice: %p to %p->%p (%ws) \n",
149 deviceData
->NextLowerDriver
,
150 PhysicalDeviceObject
,
156 // We are done with initializing, so let's indicate that and return.
157 // This should be the final step in the AddDevice process.
159 deviceObject
->Flags
&= ~DO_DEVICE_INITIALIZING
;
163 ExFreePoolWithTag(deviceName
, 'IPCA');
165 if (!NT_SUCCESS(status
) && deviceObject
){
166 if (deviceData
&& deviceData
->NextLowerDriver
){
167 IoDetachDevice (deviceData
->NextLowerDriver
);
169 IoDeleteDevice (deviceObject
);
177 ACPIDispatchCreateClose(
178 IN PDEVICE_OBJECT DeviceObject
,
181 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
182 Irp
->IoStatus
.Information
= 0;
184 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
186 return STATUS_SUCCESS
;
191 ButtonWaitThread(PVOID Context
)
195 struct acpi_bus_event event
;
198 while (ACPI_SUCCESS(result
= acpi_bus_receive_event(&event
)) &&
199 event
.type
!= ACPI_BUTTON_NOTIFY_STATUS
);
201 if (!ACPI_SUCCESS(result
))
203 Irp
->IoStatus
.Status
= STATUS_UNSUCCESSFUL
;
207 if (strstr(event
.bus_id
, "PWRF"))
208 ButtonEvent
= SYS_BUTTON_POWER
;
209 else if (strstr(event
.bus_id
, "SLPF"))
210 ButtonEvent
= SYS_BUTTON_SLEEP
;
214 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, &ButtonEvent
, sizeof(ButtonEvent
));
215 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
216 Irp
->IoStatus
.Information
= sizeof(ULONG
);
219 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
225 ACPIDispatchDeviceControl(
226 IN PDEVICE_OBJECT DeviceObject
,
229 PIO_STACK_LOCATION irpStack
;
230 NTSTATUS status
= STATUS_NOT_SUPPORTED
;
231 PCOMMON_DEVICE_DATA commonData
;
237 irpStack
= IoGetCurrentIrpStackLocation (Irp
);
238 ASSERT (IRP_MJ_DEVICE_CONTROL
== irpStack
->MajorFunction
);
240 commonData
= (PCOMMON_DEVICE_DATA
) DeviceObject
->DeviceExtension
;
242 Irp
->IoStatus
.Information
= 0;
244 if (!commonData
->IsFDO
)
246 switch (irpStack
->Parameters
.DeviceIoControl
.IoControlCode
)
248 case IOCTL_ACPI_EVAL_METHOD
:
249 status
= Bus_PDO_EvalMethod((PPDO_DEVICE_DATA
)commonData
,
253 case IOCTL_GET_SYS_BUTTON_CAPS
:
254 if (irpStack
->Parameters
.DeviceIoControl
.OutputBufferLength
< sizeof(ULONG
))
256 status
= STATUS_BUFFER_TOO_SMALL
;
260 if (wcsstr(((PPDO_DEVICE_DATA
)commonData
)->HardwareIDs
, L
"PNP0C0D"))
262 DPRINT1("Lid button reported to power manager\n");
263 Caps
|= SYS_BUTTON_LID
;
265 else if (((PPDO_DEVICE_DATA
)commonData
)->AcpiHandle
== NULL
)
267 /* We have to return both at the same time because since we
268 * have a NULL handle we are the fixed feature DO and we will
269 * only be called once (not once per device)
273 DPRINT1("Fixed power button reported to power manager\n");
274 Caps
|= SYS_BUTTON_POWER
;
278 DPRINT1("Fixed sleep button reported to power manager\n");
279 Caps
|= SYS_BUTTON_SLEEP
;
282 else if (wcsstr(((PPDO_DEVICE_DATA
)commonData
)->HardwareIDs
, L
"PNP0C0C"))
284 DPRINT1("Control method power button reported to power manager\n");
285 Caps
|= SYS_BUTTON_POWER
;
287 else if (wcsstr(((PPDO_DEVICE_DATA
)commonData
)->HardwareIDs
, L
"PNP0C0E"))
289 DPRINT1("Control method sleep reported to power manager\n");
290 Caps
|= SYS_BUTTON_SLEEP
;
294 DPRINT1("IOCTL_GET_SYS_BUTTON_CAPS sent to a non-button device\n");
295 status
= STATUS_INVALID_PARAMETER
;
300 RtlCopyMemory(Irp
->AssociatedIrp
.SystemBuffer
, &Caps
, sizeof(Caps
));
301 Irp
->IoStatus
.Information
= sizeof(Caps
);
302 status
= STATUS_SUCCESS
;
306 case IOCTL_GET_SYS_BUTTON_EVENT
:
307 PsCreateSystemThread(&ThreadHandle
, THREAD_ALL_ACCESS
, 0, 0, 0, ButtonWaitThread
, Irp
);
308 ZwClose(ThreadHandle
);
310 status
= STATUS_PENDING
;
314 DPRINT1("Unsupported IOCTL: %x\n", irpStack
->Parameters
.DeviceIoControl
.IoControlCode
);
319 DPRINT1("IOCTL sent to the ACPI FDO! Kill the caller!\n");
321 if (status
!= STATUS_PENDING
)
323 Irp
->IoStatus
.Status
= status
;
324 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
327 IoMarkIrpPending(Irp
);
334 AcpiRegOpenKey(IN HANDLE ParentKeyHandle
,
336 IN ACCESS_MASK DesiredAccess
,
337 OUT HANDLE KeyHandle
)
339 OBJECT_ATTRIBUTES ObjectAttributes
;
342 RtlInitUnicodeString(&Name
, KeyName
);
344 InitializeObjectAttributes(&ObjectAttributes
,
346 OBJ_CASE_INSENSITIVE
,
350 return ZwOpenKey(KeyHandle
,
357 AcpiRegQueryValue(IN HANDLE KeyHandle
,
359 OUT PULONG Type OPTIONAL
,
360 OUT PVOID Data OPTIONAL
,
361 IN OUT PULONG DataLength OPTIONAL
)
363 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
;
365 ULONG BufferLength
= 0;
368 RtlInitUnicodeString(&Name
, ValueName
);
370 if (DataLength
!= NULL
)
371 BufferLength
= *DataLength
;
373 /* Check if the caller provided a valid buffer */
374 if ((Data
!= NULL
) && (BufferLength
!= 0))
376 BufferLength
+= FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION
, Data
);
378 /* Allocate memory for the value */
379 ValueInfo
= ExAllocatePoolWithTag(PagedPool
, BufferLength
, 'IPCA');
380 if (ValueInfo
== NULL
)
381 return STATUS_NO_MEMORY
;
385 /* Caller didn't provide a valid buffer, assume he wants the size only */
390 /* Query the value */
391 Status
= ZwQueryValueKey(KeyHandle
,
393 KeyValuePartialInformation
,
398 if (DataLength
!= NULL
)
399 *DataLength
= BufferLength
;
401 /* Check if we have the size only */
402 if (ValueInfo
== NULL
)
404 /* Check for unexpected status */
405 if ((Status
!= STATUS_BUFFER_OVERFLOW
) &&
406 (Status
!= STATUS_BUFFER_TOO_SMALL
))
412 Status
= STATUS_SUCCESS
;
414 /* Otherwise the caller wanted data back, check if we got it */
415 else if (NT_SUCCESS(Status
))
418 *Type
= ValueInfo
->Type
;
421 RtlMoveMemory(Data
, ValueInfo
->Data
, ValueInfo
->DataLength
);
423 /* if the type is REG_SZ and data is not 0-terminated
424 * and there is enough space in the buffer NT appends a \0 */
425 if (((ValueInfo
->Type
== REG_SZ
) ||
426 (ValueInfo
->Type
== REG_EXPAND_SZ
) ||
427 (ValueInfo
->Type
== REG_MULTI_SZ
)) &&
428 (ValueInfo
->DataLength
<= *DataLength
- sizeof(WCHAR
)))
430 WCHAR
*ptr
= (WCHAR
*)((ULONG_PTR
)Data
+ ValueInfo
->DataLength
);
431 if ((ptr
> (WCHAR
*)Data
) && ptr
[-1])
436 /* Free the memory and return status */
437 if (ValueInfo
!= NULL
)
439 ExFreePoolWithTag(ValueInfo
, 'IPCA');
447 GetProcessorInformation(VOID
)
449 LPWSTR ProcessorIdentifier
= NULL
;
450 LPWSTR ProcessorVendorIdentifier
= NULL
;
451 LPWSTR HardwareIdsBuffer
= NULL
;
452 HANDLE ProcessorHandle
= NULL
;
453 ULONG Length
, Level1Length
= 0, Level2Length
= 0, Level3Length
= 0;
454 SIZE_T HardwareIdsLength
= 0;
455 SIZE_T VendorIdentifierLength
;
460 DPRINT("GetProcessorInformation()\n");
462 /* Open the key for CPU 0 */
463 Status
= AcpiRegOpenKey(NULL
,
464 L
"\\Registry\\Machine\\Hardware\\Description\\System\\CentralProcessor\\0",
467 if (!NT_SUCCESS(Status
))
469 DPRINT1("Failed to open CentralProcessor registry key: 0x%lx\n", Status
);
473 /* Query the processor identifier length */
474 Status
= AcpiRegQueryValue(ProcessorHandle
,
479 if (!NT_SUCCESS(Status
))
481 DPRINT1("Failed to query Identifier value: 0x%lx\n", Status
);
485 /* Remember the length as fallback for level 1-3 length */
486 Level1Length
= Level2Length
= Level3Length
= Length
;
488 /* Allocate a buffer large enough to be zero terminated */
489 Length
+= sizeof(UNICODE_NULL
);
490 ProcessorIdentifier
= ExAllocatePoolWithTag(PagedPool
, Length
, 'IPCA');
491 if (ProcessorIdentifier
== NULL
)
493 DPRINT1("Failed to allocate 0x%lx bytes\n", Length
);
494 Status
= STATUS_INSUFFICIENT_RESOURCES
;
498 /* Query the processor identifier string */
499 Status
= AcpiRegQueryValue(ProcessorHandle
,
504 if (!NT_SUCCESS(Status
))
506 DPRINT1("Failed to query Identifier value: 0x%lx\n", Status
);
510 /* Query the processor name length */
512 Status
= AcpiRegQueryValue(ProcessorHandle
,
513 L
"ProcessorNameString",
517 if (!NT_SUCCESS(Status
))
519 DPRINT1("Failed to query ProcessorNameString value: 0x%lx\n", Status
);
523 /* Allocate a buffer large enough to be zero terminated */
524 Length
+= sizeof(UNICODE_NULL
);
525 ProcessorNameString
= ExAllocatePoolWithTag(PagedPool
, Length
, 'IPCA');
526 if (ProcessorNameString
== NULL
)
528 DPRINT1("Failed to allocate 0x%lx bytes\n", Length
);
529 Status
= STATUS_INSUFFICIENT_RESOURCES
;
533 /* Query the processor name string */
534 Status
= AcpiRegQueryValue(ProcessorHandle
,
535 L
"ProcessorNameString",
539 if (!NT_SUCCESS(Status
))
541 DPRINT1("Failed to query ProcessorNameString value: 0x%lx\n", Status
);
545 /* Query the vendor identifier length */
547 Status
= AcpiRegQueryValue(ProcessorHandle
,
552 if (!NT_SUCCESS(Status
) || (Length
== 0))
554 DPRINT1("Failed to query VendorIdentifier value: 0x%lx\n", Status
);
558 /* Allocate a buffer large enough to be zero terminated */
559 Length
+= sizeof(UNICODE_NULL
);
560 ProcessorVendorIdentifier
= ExAllocatePoolWithTag(PagedPool
, Length
, 'IPCA');
561 if (ProcessorVendorIdentifier
== NULL
)
563 DPRINT1("Failed to allocate 0x%lx bytes\n", Length
);
564 Status
= STATUS_INSUFFICIENT_RESOURCES
;
568 /* Query the vendor identifier string */
569 Status
= AcpiRegQueryValue(ProcessorHandle
,
572 ProcessorVendorIdentifier
,
574 if (!NT_SUCCESS(Status
))
576 DPRINT1("Failed to query VendorIdentifier value: 0x%lx\n", Status
);
580 /* Change spaces to underscores */
581 for (i
= 0; i
< wcslen(ProcessorIdentifier
); i
++)
583 if (ProcessorIdentifier
[i
] == L
' ')
584 ProcessorIdentifier
[i
] = L
'_';
587 Ptr
= wcsstr(ProcessorIdentifier
, L
"Stepping");
591 Level1Length
= (ULONG
)(Ptr
- ProcessorIdentifier
);
594 Ptr
= wcsstr(ProcessorIdentifier
, L
"Model");
598 Level2Length
= (ULONG
)(Ptr
- ProcessorIdentifier
);
601 Ptr
= wcsstr(ProcessorIdentifier
, L
"Family");
605 Level3Length
= (ULONG
)(Ptr
- ProcessorIdentifier
);
608 VendorIdentifierLength
= (USHORT
)wcslen(ProcessorVendorIdentifier
);
610 /* Calculate the size of the full REG_MULTI_SZ data (see swprintf below) */
611 HardwareIdsLength
= (5 + VendorIdentifierLength
+ 3 + Level1Length
+ 1 +
612 1 + VendorIdentifierLength
+ 3 + Level1Length
+ 1 +
613 5 + VendorIdentifierLength
+ 3 + Level2Length
+ 1 +
614 1 + VendorIdentifierLength
+ 3 + Level2Length
+ 1 +
615 5 + VendorIdentifierLength
+ 3 + Level3Length
+ 1 +
616 1 + VendorIdentifierLength
+ 3 + Level3Length
+ 1 +
619 /* Allocate a buffer to the data */
620 HardwareIdsBuffer
= ExAllocatePoolWithTag(PagedPool
, HardwareIdsLength
, 'IPCA');
621 if (HardwareIdsBuffer
== NULL
)
623 Status
= STATUS_INSUFFICIENT_RESOURCES
;
628 Length
+= swprintf(&HardwareIdsBuffer
[Length
], L
"ACPI\\%s_-_%.*s", ProcessorVendorIdentifier
, Level1Length
, ProcessorIdentifier
);
629 HardwareIdsBuffer
[Length
++] = UNICODE_NULL
;
631 Length
+= swprintf(&HardwareIdsBuffer
[Length
], L
"*%s_-_%.*s", ProcessorVendorIdentifier
, Level1Length
, ProcessorIdentifier
);
632 HardwareIdsBuffer
[Length
++] = UNICODE_NULL
;
634 Length
+= swprintf(&HardwareIdsBuffer
[Length
], L
"ACPI\\%s_-_%.*s", ProcessorVendorIdentifier
, Level2Length
, ProcessorIdentifier
);
635 HardwareIdsBuffer
[Length
++] = UNICODE_NULL
;
637 Length
+= swprintf(&HardwareIdsBuffer
[Length
], L
"*%s_-_%.*s", ProcessorVendorIdentifier
, Level2Length
, ProcessorIdentifier
);
638 HardwareIdsBuffer
[Length
++] = UNICODE_NULL
;
640 Length
+= swprintf(&HardwareIdsBuffer
[Length
], L
"ACPI\\%s_-_%.*s", ProcessorVendorIdentifier
, Level3Length
, ProcessorIdentifier
);
641 HardwareIdsBuffer
[Length
++] = UNICODE_NULL
;
643 Length
+= swprintf(&HardwareIdsBuffer
[Length
], L
"*%s_-_%.*s", ProcessorVendorIdentifier
, Level3Length
, ProcessorIdentifier
);
644 HardwareIdsBuffer
[Length
++] = UNICODE_NULL
;
645 HardwareIdsBuffer
[Length
++] = UNICODE_NULL
;
647 /* Make sure we counted correctly */
648 NT_ASSERT(Length
* sizeof(WCHAR
) == HardwareIdsLength
);
650 ProcessorHardwareIds
.Length
= (SHORT
)HardwareIdsLength
;
651 ProcessorHardwareIds
.MaximumLength
= ProcessorHardwareIds
.Length
;
652 ProcessorHardwareIds
.Buffer
= HardwareIdsBuffer
;
655 if (ProcessorHandle
!= NULL
)
656 ZwClose(ProcessorHandle
);
658 if (ProcessorIdentifier
!= NULL
)
659 ExFreePoolWithTag(ProcessorIdentifier
, 'IPCA');
661 if (ProcessorVendorIdentifier
!= NULL
)
662 ExFreePoolWithTag(ProcessorVendorIdentifier
, 'IPCA');
664 if (!NT_SUCCESS(Status
))
666 if (HardwareIdsBuffer
!= NULL
)
667 ExFreePoolWithTag(HardwareIdsBuffer
, 'IPCA');
676 PDRIVER_OBJECT DriverObject
,
677 PUNICODE_STRING RegistryPath
681 DPRINT("Driver Entry \n");
683 Status
= GetProcessorInformation();
684 if (!NT_SUCCESS(Status
))
691 // Set entry points into the driver
693 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = ACPIDispatchDeviceControl
;
694 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = Bus_PnP
;
695 DriverObject
->MajorFunction
[IRP_MJ_POWER
] = Bus_Power
;
696 DriverObject
->MajorFunction
[IRP_MJ_CREATE
] = ACPIDispatchCreateClose
;
697 DriverObject
->MajorFunction
[IRP_MJ_CLOSE
] = ACPIDispatchCreateClose
;
699 DriverObject
->DriverExtension
->AddDevice
= Bus_AddDevice
;
701 return STATUS_SUCCESS
;