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