xref: /reactos/drivers/bus/acpi/main.c (revision 84344399)
1 #include "precomp.h"
2 
3 #include <poclass.h>
4 
5 #define NDEBUG
6 #include <debug.h>
7 
8 CODE_SEG("INIT")
9 DRIVER_INITIALIZE DriverEntry;
10 
11 CODE_SEG("PAGE")
12 DRIVER_ADD_DEVICE Bus_AddDevice;
13 
14 extern struct acpi_device *sleep_button;
15 extern struct acpi_device *power_button;
16 
17 UNICODE_STRING ProcessorHardwareIds = {0, 0, NULL};
18 LPWSTR ProcessorIdString = NULL;
19 LPWSTR ProcessorNameString = NULL;
20 
21 
22 CODE_SEG("PAGE")
23 NTSTATUS
24 NTAPI
25 Bus_AddDevice(
26     PDRIVER_OBJECT DriverObject,
27     PDEVICE_OBJECT PhysicalDeviceObject
28     )
29 
30 {
31     NTSTATUS            status;
32     PDEVICE_OBJECT      deviceObject = NULL;
33     PFDO_DEVICE_DATA    deviceData = NULL;
34 #ifndef NDEBUG
35     PWCHAR              deviceName = NULL;
36     ULONG               nameLength;
37 #endif
38 
39     PAGED_CODE ();
40 
41     DPRINT("Add Device: 0x%p\n",  PhysicalDeviceObject);
42 
43     DPRINT("#################### Bus_CreateClose Creating FDO Device ####################\n");
44     status = IoCreateDevice(DriverObject,
45                       sizeof(FDO_DEVICE_DATA),
46                       NULL,
47                       FILE_DEVICE_ACPI,
48                       FILE_DEVICE_SECURE_OPEN,
49                       TRUE,
50                       &deviceObject);
51     if (!NT_SUCCESS(status))
52     {
53         DPRINT1("IoCreateDevice() failed with status 0x%X\n", status);
54         goto End;
55     }
56 
57     deviceData = (PFDO_DEVICE_DATA) deviceObject->DeviceExtension;
58     RtlZeroMemory (deviceData, sizeof (FDO_DEVICE_DATA));
59 
60     //
61     // Set the initial state of the FDO
62     //
63 
64     INITIALIZE_PNP_STATE(deviceData->Common);
65 
66     deviceData->Common.IsFDO = TRUE;
67 
68     deviceData->Common.Self = deviceObject;
69 
70     ExInitializeFastMutex (&deviceData->Mutex);
71 
72     InitializeListHead (&deviceData->ListOfPDOs);
73 
74     // Set the PDO for use with PlugPlay functions
75 
76     deviceData->UnderlyingPDO = PhysicalDeviceObject;
77 
78     //
79     // Set the initial powerstate of the FDO
80     //
81 
82     deviceData->Common.DevicePowerState = PowerDeviceUnspecified;
83     deviceData->Common.SystemPowerState = PowerSystemWorking;
84 
85     deviceObject->Flags |= DO_POWER_PAGABLE;
86 
87     //
88     // Attach our FDO to the device stack.
89     // The return value of IoAttachDeviceToDeviceStack is the top of the
90     // attachment chain.  This is where all the IRPs should be routed.
91     //
92 
93     deviceData->NextLowerDriver = IoAttachDeviceToDeviceStack (
94                                     deviceObject,
95                                     PhysicalDeviceObject);
96 
97     if (NULL == deviceData->NextLowerDriver) {
98 
99         status = STATUS_NO_SUCH_DEVICE;
100         goto End;
101     }
102 
103 
104 #ifndef NDEBUG
105     //
106     // We will demonstrate here the step to retrieve the name of the PDO
107     //
108 
109     status = IoGetDeviceProperty (PhysicalDeviceObject,
110                                   DevicePropertyPhysicalDeviceObjectName,
111                                   0,
112                                   NULL,
113                                   &nameLength);
114 
115     if (status != STATUS_BUFFER_TOO_SMALL)
116     {
117         DPRINT1("AddDevice:IoGDP failed (0x%x)\n", status);
118         goto End;
119     }
120 
121     deviceName = ExAllocatePoolWithTag(NonPagedPool, nameLength, 'MpcA');
122 
123     if (NULL == deviceName) {
124         DPRINT1("AddDevice: no memory to alloc for deviceName(0x%x)\n", nameLength);
125         status =  STATUS_INSUFFICIENT_RESOURCES;
126         goto End;
127     }
128 
129     status = IoGetDeviceProperty (PhysicalDeviceObject,
130                          DevicePropertyPhysicalDeviceObjectName,
131                          nameLength,
132                          deviceName,
133                          &nameLength);
134 
135     if (!NT_SUCCESS (status)) {
136 
137         DPRINT1("AddDevice:IoGDP(2) failed (0x%x)", status);
138         goto End;
139     }
140 
141     DPRINT("AddDevice: %p to %p->%p (%ws) \n",
142                    deviceObject,
143                    deviceData->NextLowerDriver,
144                    PhysicalDeviceObject,
145                    deviceName);
146 
147 #endif
148 
149     //
150     // We are done with initializing, so let's indicate that and return.
151     // This should be the final step in the AddDevice process.
152     //
153     deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
154 
155 End:
156 #ifndef NDEBUG
157     if (deviceName){
158         ExFreePoolWithTag(deviceName, 'MpcA');
159     }
160 #endif
161     if (!NT_SUCCESS(status) && deviceObject){
162         if (deviceData && deviceData->NextLowerDriver){
163             IoDetachDevice (deviceData->NextLowerDriver);
164         }
165         IoDeleteDevice (deviceObject);
166     }
167     return status;
168 
169 }
170 
171 NTSTATUS
172 NTAPI
173 ACPIDispatchCreateClose(
174    IN PDEVICE_OBJECT DeviceObject,
175    IN PIRP Irp)
176 {
177    Irp->IoStatus.Status = STATUS_SUCCESS;
178    Irp->IoStatus.Information = 0;
179 
180    IoCompleteRequest(Irp, IO_NO_INCREMENT);
181 
182    return STATUS_SUCCESS;
183 }
184 
185 VOID
186 NTAPI
187 ButtonWaitThread(PVOID Context)
188 {
189     PIRP Irp = Context;
190     int result;
191     struct acpi_bus_event event;
192     ULONG ButtonEvent;
193 
194     while (ACPI_SUCCESS(result = acpi_bus_receive_event(&event)) &&
195            event.type != ACPI_BUTTON_NOTIFY_STATUS);
196 
197     if (!ACPI_SUCCESS(result))
198     {
199        Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
200     }
201     else
202     {
203        if (strstr(event.bus_id, "PWRF"))
204            ButtonEvent = SYS_BUTTON_POWER;
205        else if (strstr(event.bus_id, "SLPF"))
206            ButtonEvent = SYS_BUTTON_SLEEP;
207        else
208            ButtonEvent = 0;
209 
210        RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, &ButtonEvent, sizeof(ButtonEvent));
211        Irp->IoStatus.Status = STATUS_SUCCESS;
212        Irp->IoStatus.Information = sizeof(ULONG);
213     }
214 
215     IoCompleteRequest(Irp, IO_NO_INCREMENT);
216 }
217 
218 
219 NTSTATUS
220 NTAPI
221 ACPIDispatchDeviceControl(
222    IN PDEVICE_OBJECT DeviceObject,
223    IN PIRP Irp)
224 {
225     PIO_STACK_LOCATION      irpStack;
226     NTSTATUS                status = STATUS_NOT_SUPPORTED;
227     PCOMMON_DEVICE_DATA     commonData;
228     ULONG Caps = 0;
229     HANDLE ThreadHandle;
230 
231     irpStack = IoGetCurrentIrpStackLocation (Irp);
232     ASSERT (IRP_MJ_DEVICE_CONTROL == irpStack->MajorFunction);
233 
234     commonData = (PCOMMON_DEVICE_DATA) DeviceObject->DeviceExtension;
235 
236     Irp->IoStatus.Information = 0;
237 
238     if (!commonData->IsFDO)
239     {
240        switch (irpStack->Parameters.DeviceIoControl.IoControlCode)
241        {
242             case IOCTL_ACPI_ASYNC_EVAL_METHOD:
243             {
244                 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
245 
246                 if (KeGetCurrentIrql() == DISPATCH_LEVEL)
247                 {
248                     PEVAL_WORKITEM_DATA workItemData;
249 
250                     workItemData = ExAllocatePoolUninitialized(NonPagedPool,
251                                                                sizeof(*workItemData),
252                                                                'ipcA');
253                     if (!workItemData)
254                     {
255                         status = STATUS_INSUFFICIENT_RESOURCES;
256                         break;
257                     }
258                     workItemData->Irp = Irp;
259                     workItemData->DeviceData = (PPDO_DEVICE_DATA)commonData;
260 
261                     ExInitializeWorkItem(&workItemData->WorkQueueItem,
262                                          Bus_PDO_EvalMethodWorker,
263                                          workItemData);
264                     ExQueueWorkItem(&workItemData->WorkQueueItem, DelayedWorkQueue);
265 
266                     status = STATUS_PENDING;
267                     break;
268                 }
269                 __fallthrough;
270             }
271            case IOCTL_ACPI_EVAL_METHOD:
272             {
273               status = Bus_PDO_EvalMethod((PPDO_DEVICE_DATA)commonData,
274                                           Irp);
275               break;
276             }
277 
278            case IOCTL_GET_SYS_BUTTON_CAPS:
279               if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG))
280               {
281                   status = STATUS_BUFFER_TOO_SMALL;
282                   break;
283               }
284 
285               if (wcsstr(((PPDO_DEVICE_DATA)commonData)->HardwareIDs, L"PNP0C0D"))
286               {
287                   DPRINT1("Lid button reported to power manager\n");
288                   Caps |= SYS_BUTTON_LID;
289               }
290               else if (((PPDO_DEVICE_DATA)commonData)->AcpiHandle == NULL)
291               {
292                   /* We have to return both at the same time because since we
293                    * have a NULL handle we are the fixed feature DO and we will
294                    * only be called once (not once per device)
295                    */
296                   if (power_button)
297                   {
298                       DPRINT("Fixed power button reported to power manager\n");
299                       Caps |= SYS_BUTTON_POWER;
300                   }
301                   if (sleep_button)
302                   {
303                       DPRINT("Fixed sleep button reported to power manager\n");
304                       Caps |= SYS_BUTTON_SLEEP;
305                   }
306               }
307               else if (wcsstr(((PPDO_DEVICE_DATA)commonData)->HardwareIDs, L"PNP0C0C"))
308               {
309                   DPRINT("Control method power button reported to power manager\n");
310                   Caps |= SYS_BUTTON_POWER;
311               }
312               else if (wcsstr(((PPDO_DEVICE_DATA)commonData)->HardwareIDs, L"PNP0C0E"))
313               {
314                   DPRINT("Control method sleep reported to power manager\n");
315                   Caps |= SYS_BUTTON_SLEEP;
316               }
317               else
318               {
319                   DPRINT1("IOCTL_GET_SYS_BUTTON_CAPS sent to a non-button device\n");
320                   status = STATUS_INVALID_PARAMETER;
321               }
322 
323               if (Caps != 0)
324               {
325                   RtlCopyMemory(Irp->AssociatedIrp.SystemBuffer, &Caps, sizeof(Caps));
326                   Irp->IoStatus.Information = sizeof(Caps);
327                   status = STATUS_SUCCESS;
328               }
329               break;
330 
331            case IOCTL_GET_SYS_BUTTON_EVENT:
332               PsCreateSystemThread(&ThreadHandle, THREAD_ALL_ACCESS, 0, 0, 0, ButtonWaitThread, Irp);
333               ZwClose(ThreadHandle);
334 
335               status = STATUS_PENDING;
336               break;
337 
338            case IOCTL_BATTERY_QUERY_TAG:
339               DPRINT("IOCTL_BATTERY_QUERY_TAG is not supported!\n");
340               break;
341 
342            default:
343               DPRINT1("Unsupported IOCTL: %x\n", irpStack->Parameters.DeviceIoControl.IoControlCode);
344               break;
345        }
346     }
347     else
348        DPRINT1("IOCTL sent to the ACPI FDO! Kill the caller!\n");
349 
350     if (status != STATUS_PENDING)
351     {
352        Irp->IoStatus.Status = status;
353        IoCompleteRequest(Irp, IO_NO_INCREMENT);
354     }
355     else
356        IoMarkIrpPending(Irp);
357 
358     return status;
359 }
360 
361 static
362 CODE_SEG("INIT")
363 NTSTATUS
364 AcpiRegOpenKey(IN HANDLE ParentKeyHandle,
365                IN LPCWSTR KeyName,
366                IN ACCESS_MASK DesiredAccess,
367                OUT HANDLE KeyHandle)
368 {
369     OBJECT_ATTRIBUTES ObjectAttributes;
370     UNICODE_STRING Name;
371 
372     RtlInitUnicodeString(&Name, KeyName);
373 
374     InitializeObjectAttributes(&ObjectAttributes,
375                                &Name,
376                                OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
377                                ParentKeyHandle,
378                                NULL);
379 
380     return ZwOpenKey(KeyHandle,
381                      DesiredAccess,
382                      &ObjectAttributes);
383 }
384 
385 static
386 CODE_SEG("INIT")
387 NTSTATUS
388 AcpiRegQueryValue(IN HANDLE KeyHandle,
389                   IN LPWSTR ValueName,
390                   OUT PULONG Type OPTIONAL,
391                   OUT PVOID Data OPTIONAL,
392                   IN OUT PULONG DataLength OPTIONAL)
393 {
394     PKEY_VALUE_PARTIAL_INFORMATION ValueInfo;
395     UNICODE_STRING Name;
396     ULONG BufferLength = 0;
397     NTSTATUS Status;
398 
399     RtlInitUnicodeString(&Name, ValueName);
400 
401     if (DataLength != NULL)
402         BufferLength = *DataLength;
403 
404     /* Check if the caller provided a valid buffer */
405     if ((Data != NULL) && (BufferLength != 0))
406     {
407         BufferLength += FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data);
408 
409         /* Allocate memory for the value */
410         ValueInfo = ExAllocatePoolWithTag(PagedPool, BufferLength, 'MpcA');
411         if (ValueInfo == NULL)
412             return STATUS_NO_MEMORY;
413     }
414     else
415     {
416         /* Caller didn't provide a valid buffer, assume he wants the size only */
417         ValueInfo = NULL;
418         BufferLength = 0;
419     }
420 
421     /* Query the value */
422     Status = ZwQueryValueKey(KeyHandle,
423                              &Name,
424                              KeyValuePartialInformation,
425                              ValueInfo,
426                              BufferLength,
427                              &BufferLength);
428 
429     if (DataLength != NULL)
430         *DataLength = BufferLength;
431 
432     /* Check if we have the size only */
433     if (ValueInfo == NULL)
434     {
435         /* Check for unexpected status */
436         if ((Status != STATUS_BUFFER_OVERFLOW) &&
437             (Status != STATUS_BUFFER_TOO_SMALL))
438         {
439             return Status;
440         }
441 
442         /* All is well */
443         Status = STATUS_SUCCESS;
444     }
445     /* Otherwise the caller wanted data back, check if we got it */
446     else if (NT_SUCCESS(Status))
447     {
448         if (Type != NULL)
449             *Type = ValueInfo->Type;
450 
451         /* Copy it */
452         RtlMoveMemory(Data, ValueInfo->Data, ValueInfo->DataLength);
453 
454         /* if the type is REG_SZ and data is not 0-terminated
455          * and there is enough space in the buffer NT appends a \0 */
456         if (((ValueInfo->Type == REG_SZ) ||
457              (ValueInfo->Type == REG_EXPAND_SZ) ||
458              (ValueInfo->Type == REG_MULTI_SZ)) &&
459             (ValueInfo->DataLength <= *DataLength - sizeof(WCHAR)))
460         {
461             WCHAR *ptr = (WCHAR *)((ULONG_PTR)Data + ValueInfo->DataLength);
462             if ((ptr > (WCHAR *)Data) && ptr[-1])
463                 *ptr = 0;
464         }
465     }
466 
467     /* Free the memory and return status */
468     if (ValueInfo != NULL)
469     {
470         ExFreePoolWithTag(ValueInfo, 'MpcA');
471     }
472 
473     return Status;
474 }
475 
476 static
477 CODE_SEG("INIT")
478 NTSTATUS
479 GetProcessorInformation(VOID)
480 {
481     LPWSTR ProcessorIdentifier = NULL;
482     LPWSTR ProcessorVendorIdentifier = NULL;
483     LPWSTR HardwareIdsBuffer = NULL;
484     HANDLE ProcessorHandle = NULL;
485     ULONG Length = 0, Level1Length = 0, Level2Length = 0, Level3Length = 0;
486     SIZE_T HardwareIdsLength = 0;
487     SIZE_T VendorIdentifierLength;
488     ULONG i;
489     PWCHAR Ptr;
490     NTSTATUS Status;
491 
492     DPRINT("GetProcessorInformation()\n");
493 
494     /* Open the key for CPU 0 */
495     Status = AcpiRegOpenKey(NULL,
496                             L"\\Registry\\Machine\\Hardware\\Description\\System\\CentralProcessor\\0",
497                             KEY_READ,
498                             &ProcessorHandle);
499     if (!NT_SUCCESS(Status))
500     {
501         DPRINT1("Failed to open CentralProcessor registry key: 0x%lx\n", Status);
502         goto done;
503     }
504 
505     /* Query the processor identifier length */
506     Status = AcpiRegQueryValue(ProcessorHandle,
507                                L"Identifier",
508                                NULL,
509                                NULL,
510                                &Length);
511     if (!NT_SUCCESS(Status))
512     {
513         DPRINT1("Failed to query Identifier value: 0x%lx\n", Status);
514         goto done;
515     }
516 
517     /* Remember the length as fallback for level 1-3 length */
518     Level1Length = Level2Length = Level3Length = Length;
519 
520     /* Allocate a buffer large enough to be zero terminated */
521     Length += sizeof(UNICODE_NULL);
522     ProcessorIdentifier = ExAllocatePoolWithTag(PagedPool, Length, 'IpcA');
523     if (ProcessorIdentifier == NULL)
524     {
525         DPRINT1("Failed to allocate 0x%lx bytes\n", Length);
526         Status = STATUS_INSUFFICIENT_RESOURCES;
527         goto done;
528     }
529 
530     /* Query the processor identifier string */
531     Status = AcpiRegQueryValue(ProcessorHandle,
532                                L"Identifier",
533                                NULL,
534                                ProcessorIdentifier,
535                                &Length);
536     if (!NT_SUCCESS(Status))
537     {
538         DPRINT1("Failed to query Identifier value: 0x%lx\n", Status);
539         goto done;
540     }
541 
542     /* Query the processor name length */
543     Length = 0;
544     Status = AcpiRegQueryValue(ProcessorHandle,
545                                L"ProcessorNameString",
546                                NULL,
547                                NULL,
548                                &Length);
549     if (NT_SUCCESS(Status))
550     {
551         /* Allocate a buffer large enough to be zero terminated */
552         Length += sizeof(UNICODE_NULL);
553         ProcessorNameString = ExAllocatePoolWithTag(PagedPool, Length, 'IpcA');
554         if (ProcessorNameString == NULL)
555         {
556             DPRINT1("Failed to allocate 0x%lx bytes\n", Length);
557             Status = STATUS_INSUFFICIENT_RESOURCES;
558             goto done;
559         }
560 
561         /* Query the processor name string */
562         Status = AcpiRegQueryValue(ProcessorHandle,
563                                    L"ProcessorNameString",
564                                    NULL,
565                                    ProcessorNameString,
566                                    &Length);
567         if (!NT_SUCCESS(Status))
568         {
569             DPRINT1("Failed to query ProcessorNameString value: 0x%lx\n", Status);
570             goto done;
571         }
572     }
573 
574     /* Query the vendor identifier length */
575     Length = 0;
576     Status = AcpiRegQueryValue(ProcessorHandle,
577                                L"VendorIdentifier",
578                                NULL,
579                                NULL,
580                                &Length);
581     if (!NT_SUCCESS(Status) || (Length == 0))
582     {
583         DPRINT1("Failed to query VendorIdentifier value: 0x%lx\n", Status);
584         goto done;
585     }
586 
587     /* Allocate a buffer large enough to be zero terminated */
588     Length += sizeof(UNICODE_NULL);
589     ProcessorVendorIdentifier = ExAllocatePoolWithTag(PagedPool, Length, 'IpcA');
590     if (ProcessorVendorIdentifier == NULL)
591     {
592         DPRINT1("Failed to allocate 0x%lx bytes\n", Length);
593         Status = STATUS_INSUFFICIENT_RESOURCES;
594         goto done;
595     }
596 
597     /* Query the vendor identifier string */
598     Status = AcpiRegQueryValue(ProcessorHandle,
599                                L"VendorIdentifier",
600                                NULL,
601                                ProcessorVendorIdentifier,
602                                &Length);
603     if (!NT_SUCCESS(Status))
604     {
605         DPRINT1("Failed to query VendorIdentifier value: 0x%lx\n", Status);
606         goto done;
607     }
608 
609     /* Change spaces to underscores */
610     for (i = 0; i < wcslen(ProcessorIdentifier); i++)
611     {
612         if (ProcessorIdentifier[i] == L' ')
613             ProcessorIdentifier[i] = L'_';
614     }
615 
616     Ptr = wcsstr(ProcessorIdentifier, L"Stepping");
617     if (Ptr != NULL)
618     {
619         Ptr--;
620         Level1Length = (ULONG)(Ptr - ProcessorIdentifier);
621     }
622 
623     Ptr = wcsstr(ProcessorIdentifier, L"Model");
624     if (Ptr != NULL)
625     {
626         Ptr--;
627         Level2Length = (ULONG)(Ptr - ProcessorIdentifier);
628     }
629 
630     Ptr = wcsstr(ProcessorIdentifier, L"Family");
631     if (Ptr != NULL)
632     {
633         Ptr--;
634         Level3Length = (ULONG)(Ptr - ProcessorIdentifier);
635     }
636 
637     VendorIdentifierLength = (USHORT)wcslen(ProcessorVendorIdentifier);
638 
639     /* Calculate the size of the full REG_MULTI_SZ data (see swprintf below) */
640     HardwareIdsLength = (5 + VendorIdentifierLength + 3 + Level1Length + 1 +
641                          1 + VendorIdentifierLength + 3 + Level1Length + 1 +
642                          5 + VendorIdentifierLength + 3 + Level2Length + 1 +
643                          1 + VendorIdentifierLength + 3 + Level2Length + 1 +
644                          5 + VendorIdentifierLength + 3 + Level3Length + 1 +
645                          1 + VendorIdentifierLength + 3 + Level3Length + 1 +
646                          1) * sizeof(WCHAR);
647 
648     /* Allocate a buffer to the data */
649     HardwareIdsBuffer = ExAllocatePoolWithTag(PagedPool, HardwareIdsLength, 'IpcA');
650     if (HardwareIdsBuffer == NULL)
651     {
652         Status = STATUS_INSUFFICIENT_RESOURCES;
653         goto done;
654     }
655 
656     Length = 0;
657     Length += swprintf(&HardwareIdsBuffer[Length], L"ACPI\\%s_-_%.*s", ProcessorVendorIdentifier, Level1Length, ProcessorIdentifier);
658     HardwareIdsBuffer[Length++] = UNICODE_NULL;
659 
660     Length += swprintf(&HardwareIdsBuffer[Length], L"*%s_-_%.*s", ProcessorVendorIdentifier, Level1Length, ProcessorIdentifier);
661     HardwareIdsBuffer[Length++] = UNICODE_NULL;
662 
663     Length += swprintf(&HardwareIdsBuffer[Length], L"ACPI\\%s_-_%.*s", ProcessorVendorIdentifier, Level2Length, ProcessorIdentifier);
664     HardwareIdsBuffer[Length++] = UNICODE_NULL;
665 
666     Length += swprintf(&HardwareIdsBuffer[Length], L"*%s_-_%.*s", ProcessorVendorIdentifier, Level2Length, ProcessorIdentifier);
667     HardwareIdsBuffer[Length++] = UNICODE_NULL;
668 
669     Length += swprintf(&HardwareIdsBuffer[Length], L"ACPI\\%s_-_%.*s", ProcessorVendorIdentifier, Level3Length, ProcessorIdentifier);
670     HardwareIdsBuffer[Length++] = UNICODE_NULL;
671 
672     Length += swprintf(&HardwareIdsBuffer[Length], L"*%s_-_%.*s", ProcessorVendorIdentifier, Level3Length, ProcessorIdentifier);
673     HardwareIdsBuffer[Length++] = UNICODE_NULL;
674     HardwareIdsBuffer[Length++] = UNICODE_NULL;
675 
676     /* Make sure we counted correctly */
677     NT_ASSERT(Length * sizeof(WCHAR) == HardwareIdsLength);
678 
679     ProcessorHardwareIds.Length = (SHORT)HardwareIdsLength;
680     ProcessorHardwareIds.MaximumLength = ProcessorHardwareIds.Length;
681     ProcessorHardwareIds.Buffer = HardwareIdsBuffer;
682 
683     Length = (5 + VendorIdentifierLength + 3 + Level1Length + 1) * sizeof(WCHAR);
684     ProcessorIdString = ExAllocatePoolWithTag(PagedPool, Length, 'IpcA');
685     if (ProcessorIdString != NULL)
686     {
687         Length = swprintf(ProcessorIdString, L"ACPI\\%s_-_%.*s", ProcessorVendorIdentifier, Level1Length, ProcessorIdentifier);
688         ProcessorIdString[Length++] = UNICODE_NULL;
689         DPRINT("ProcessorIdString: %S\n", ProcessorIdString);
690     }
691 
692 done:
693     if (ProcessorHandle != NULL)
694         ZwClose(ProcessorHandle);
695 
696     if (ProcessorIdentifier != NULL)
697         ExFreePoolWithTag(ProcessorIdentifier, 'IpcA');
698 
699     if (ProcessorVendorIdentifier != NULL)
700         ExFreePoolWithTag(ProcessorVendorIdentifier, 'IpcA');
701 
702     if (!NT_SUCCESS(Status))
703     {
704         if (HardwareIdsBuffer != NULL)
705             ExFreePoolWithTag(HardwareIdsBuffer, 'IpcA');
706     }
707 
708     return Status;
709 }
710 
711 CODE_SEG("INIT")
712 NTSTATUS
713 NTAPI
714 DriverEntry (
715     PDRIVER_OBJECT  DriverObject,
716     PUNICODE_STRING RegistryPath
717     )
718 {
719     NTSTATUS Status;
720     DPRINT("Driver Entry \n");
721 
722     Status = GetProcessorInformation();
723     if (!NT_SUCCESS(Status))
724     {
725         NT_ASSERT(FALSE);
726         return Status;
727     }
728 
729     //
730     // Set entry points into the driver
731     //
732     DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ACPIDispatchDeviceControl;
733     DriverObject->MajorFunction [IRP_MJ_PNP] = Bus_PnP;
734     DriverObject->MajorFunction [IRP_MJ_POWER] = Bus_Power;
735     DriverObject->MajorFunction [IRP_MJ_CREATE] = ACPIDispatchCreateClose;
736     DriverObject->MajorFunction [IRP_MJ_CLOSE] = ACPIDispatchCreateClose;
737 
738     DriverObject->DriverExtension->AddDevice = Bus_AddDevice;
739 
740     return STATUS_SUCCESS;
741 }
742