xref: /reactos/drivers/bus/acpi/main.c (revision cc439606)
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,
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         DPRINT1("Failed to query ProcessorNameString value: 0x%lx\n", Status);
526         goto done;
527     }
528 
529     /* Allocate a buffer large enough to be zero terminated */
530     Length += sizeof(UNICODE_NULL);
531     ProcessorNameString = ExAllocatePoolWithTag(PagedPool, Length, 'IpcA');
532     if (ProcessorNameString == NULL)
533     {
534         DPRINT1("Failed to allocate 0x%lx bytes\n", Length);
535         Status = STATUS_INSUFFICIENT_RESOURCES;
536         goto done;
537     }
538 
539     /* Query the processor name string */
540     Status = AcpiRegQueryValue(ProcessorHandle,
541                                L"ProcessorNameString",
542                                NULL,
543                                ProcessorNameString,
544                                &Length);
545     if (!NT_SUCCESS(Status))
546     {
547         DPRINT1("Failed to query ProcessorNameString value: 0x%lx\n", Status);
548         goto done;
549     }
550 
551     /* Query the vendor identifier length */
552     Length = 0;
553     Status = AcpiRegQueryValue(ProcessorHandle,
554                                L"VendorIdentifier",
555                                NULL,
556                                NULL,
557                                &Length);
558     if (!NT_SUCCESS(Status) || (Length == 0))
559     {
560         DPRINT1("Failed to query VendorIdentifier value: 0x%lx\n", Status);
561         goto done;
562     }
563 
564     /* Allocate a buffer large enough to be zero terminated */
565     Length += sizeof(UNICODE_NULL);
566     ProcessorVendorIdentifier = ExAllocatePoolWithTag(PagedPool, Length, 'IpcA');
567     if (ProcessorVendorIdentifier == NULL)
568     {
569         DPRINT1("Failed to allocate 0x%lx bytes\n", Length);
570         Status = STATUS_INSUFFICIENT_RESOURCES;
571         goto done;
572     }
573 
574     /* Query the vendor identifier string */
575     Status = AcpiRegQueryValue(ProcessorHandle,
576                                L"VendorIdentifier",
577                                NULL,
578                                ProcessorVendorIdentifier,
579                                &Length);
580     if (!NT_SUCCESS(Status))
581     {
582         DPRINT1("Failed to query VendorIdentifier value: 0x%lx\n", Status);
583         goto done;
584     }
585 
586     /* Change spaces to underscores */
587     for (i = 0; i < wcslen(ProcessorIdentifier); i++)
588     {
589         if (ProcessorIdentifier[i] == L' ')
590             ProcessorIdentifier[i] = L'_';
591     }
592 
593     Ptr = wcsstr(ProcessorIdentifier, L"Stepping");
594     if (Ptr != NULL)
595     {
596         Ptr--;
597         Level1Length = (ULONG)(Ptr - ProcessorIdentifier);
598     }
599 
600     Ptr = wcsstr(ProcessorIdentifier, L"Model");
601     if (Ptr != NULL)
602     {
603         Ptr--;
604         Level2Length = (ULONG)(Ptr - ProcessorIdentifier);
605     }
606 
607     Ptr = wcsstr(ProcessorIdentifier, L"Family");
608     if (Ptr != NULL)
609     {
610         Ptr--;
611         Level3Length = (ULONG)(Ptr - ProcessorIdentifier);
612     }
613 
614     VendorIdentifierLength = (USHORT)wcslen(ProcessorVendorIdentifier);
615 
616     /* Calculate the size of the full REG_MULTI_SZ data (see swprintf below) */
617     HardwareIdsLength = (5 + VendorIdentifierLength + 3 + Level1Length + 1 +
618                          1 + VendorIdentifierLength + 3 + Level1Length + 1 +
619                          5 + VendorIdentifierLength + 3 + Level2Length + 1 +
620                          1 + VendorIdentifierLength + 3 + Level2Length + 1 +
621                          5 + VendorIdentifierLength + 3 + Level3Length + 1 +
622                          1 + VendorIdentifierLength + 3 + Level3Length + 1 +
623                          1) * sizeof(WCHAR);
624 
625     /* Allocate a buffer to the data */
626     HardwareIdsBuffer = ExAllocatePoolWithTag(PagedPool, HardwareIdsLength, 'IpcA');
627     if (HardwareIdsBuffer == NULL)
628     {
629         Status = STATUS_INSUFFICIENT_RESOURCES;
630         goto done;
631     }
632 
633     Length = 0;
634     Length += swprintf(&HardwareIdsBuffer[Length], L"ACPI\\%s_-_%.*s", ProcessorVendorIdentifier, Level1Length, ProcessorIdentifier);
635     HardwareIdsBuffer[Length++] = UNICODE_NULL;
636 
637     Length += swprintf(&HardwareIdsBuffer[Length], L"*%s_-_%.*s", ProcessorVendorIdentifier, Level1Length, ProcessorIdentifier);
638     HardwareIdsBuffer[Length++] = UNICODE_NULL;
639 
640     Length += swprintf(&HardwareIdsBuffer[Length], L"ACPI\\%s_-_%.*s", ProcessorVendorIdentifier, Level2Length, ProcessorIdentifier);
641     HardwareIdsBuffer[Length++] = UNICODE_NULL;
642 
643     Length += swprintf(&HardwareIdsBuffer[Length], L"*%s_-_%.*s", ProcessorVendorIdentifier, Level2Length, ProcessorIdentifier);
644     HardwareIdsBuffer[Length++] = UNICODE_NULL;
645 
646     Length += swprintf(&HardwareIdsBuffer[Length], L"ACPI\\%s_-_%.*s", ProcessorVendorIdentifier, Level3Length, ProcessorIdentifier);
647     HardwareIdsBuffer[Length++] = UNICODE_NULL;
648 
649     Length += swprintf(&HardwareIdsBuffer[Length], L"*%s_-_%.*s", ProcessorVendorIdentifier, Level3Length, ProcessorIdentifier);
650     HardwareIdsBuffer[Length++] = UNICODE_NULL;
651     HardwareIdsBuffer[Length++] = UNICODE_NULL;
652 
653     /* Make sure we counted correctly */
654     NT_ASSERT(Length * sizeof(WCHAR) == HardwareIdsLength);
655 
656     ProcessorHardwareIds.Length = (SHORT)HardwareIdsLength;
657     ProcessorHardwareIds.MaximumLength = ProcessorHardwareIds.Length;
658     ProcessorHardwareIds.Buffer = HardwareIdsBuffer;
659 
660     Length = (5 + VendorIdentifierLength + 3 + Level1Length + 1) * sizeof(WCHAR);
661     ProcessorIdString = ExAllocatePoolWithTag(PagedPool, Length, 'IpcA');
662     if (ProcessorIdString != NULL)
663     {
664         Length = swprintf(ProcessorIdString, L"ACPI\\%s_-_%.*s", ProcessorVendorIdentifier, Level1Length, ProcessorIdentifier);
665         ProcessorIdString[Length++] = UNICODE_NULL;
666         DPRINT("ProcessorIdString: %S\n", ProcessorIdString);
667     }
668 
669 done:
670     if (ProcessorHandle != NULL)
671         ZwClose(ProcessorHandle);
672 
673     if (ProcessorIdentifier != NULL)
674         ExFreePoolWithTag(ProcessorIdentifier, 'IpcA');
675 
676     if (ProcessorVendorIdentifier != NULL)
677         ExFreePoolWithTag(ProcessorVendorIdentifier, 'IpcA');
678 
679     if (!NT_SUCCESS(Status))
680     {
681         if (HardwareIdsBuffer != NULL)
682             ExFreePoolWithTag(HardwareIdsBuffer, 'IpcA');
683     }
684 
685     return Status;
686 }
687 
688 NTSTATUS
689 NTAPI
690 DriverEntry (
691     PDRIVER_OBJECT  DriverObject,
692     PUNICODE_STRING RegistryPath
693     )
694 {
695     NTSTATUS Status;
696     DPRINT("Driver Entry \n");
697 
698     Status = GetProcessorInformation();
699     if (!NT_SUCCESS(Status))
700     {
701         NT_ASSERT(FALSE);
702         return Status;
703     }
704 
705     //
706     // Set entry points into the driver
707     //
708     DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ACPIDispatchDeviceControl;
709     DriverObject->MajorFunction [IRP_MJ_PNP] = Bus_PnP;
710     DriverObject->MajorFunction [IRP_MJ_POWER] = Bus_Power;
711     DriverObject->MajorFunction [IRP_MJ_CREATE] = ACPIDispatchCreateClose;
712     DriverObject->MajorFunction [IRP_MJ_CLOSE] = ACPIDispatchCreateClose;
713 
714     DriverObject->DriverExtension->AddDevice = Bus_AddDevice;
715 
716     return STATUS_SUCCESS;
717 }
718