xref: /reactos/drivers/bus/acpi/main.c (revision 5070e896)
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
Bus_AddDevice(PDRIVER_OBJECT DriverObject,PDEVICE_OBJECT PhysicalDeviceObject)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
ACPIDispatchCreateClose(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)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
ButtonWaitThread(PVOID Context)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
ACPIDispatchDeviceControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)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
AcpiRegOpenKey(IN HANDLE ParentKeyHandle,IN LPCWSTR KeyName,IN ACCESS_MASK DesiredAccess,OUT HANDLE KeyHandle)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
AcpiRegQueryValue(IN HANDLE KeyHandle,IN LPWSTR ValueName,OUT PULONG Type OPTIONAL,OUT PVOID Data OPTIONAL,IN OUT PULONG DataLength OPTIONAL)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
GetProcessorInformation(VOID)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
DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath)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