xref: /reactos/drivers/storage/port/scsiport/pdo.c (revision 34593d93)
1 /*
2  * PROJECT:     ReactOS Storage Stack / SCSIPORT storage port library
3  * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4  * PURPOSE:     Logical Unit (PDO) functions
5  * COPYRIGHT:   Eric Kohl (eric.kohl@reactos.org)
6  *              Aleksey Bragin (aleksey@reactos.org)
7  *              2020 Victor Perevertkin (victor.perevertkin@reactos.org)
8  */
9 
10 #include "scsiport.h"
11 #include "scsitypes.h"
12 
13 #define NDEBUG
14 #include <debug.h>
15 
16 
17 PDEVICE_OBJECT
18 PdoCreateLunDevice(
19     _In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension)
20 {
21     PSCSI_PORT_LUN_EXTENSION LunExtension;
22     PDEVICE_OBJECT LunPDO;
23 
24     ULONG LunExtensionSize = DeviceExtension->LunExtensionSize + sizeof(SCSI_PORT_LUN_EXTENSION);
25 
26     NTSTATUS Status = IoCreateDevice(DeviceExtension->Common.DeviceObject->DriverObject,
27                                      LunExtensionSize,
28                                      NULL,
29                                      FILE_DEVICE_DISK,
30                                      FILE_AUTOGENERATED_DEVICE_NAME | FILE_DEVICE_SECURE_OPEN,
31                                      FALSE,
32                                      &LunPDO);
33 
34     if (!NT_SUCCESS(Status))
35     {
36         DPRINT1("Failed to create a Lun PDO, status: %x\n", Status);
37         return NULL;
38     }
39 
40     LunExtension = LunPDO->DeviceExtension;
41 
42     /* Zero everything */
43     RtlZeroMemory(LunExtension, LunExtensionSize);
44 
45     LunExtension->Common.IsFDO = FALSE;
46     LunExtension->Common.DeviceObject = LunPDO;
47     LunExtension->Common.LowerDevice = DeviceExtension->Common.DeviceObject;
48 
49     /* Initialize a list of requests */
50     InitializeListHead(&LunExtension->SrbInfo.Requests);
51 
52     /* Initialize timeout counter */
53     LunExtension->RequestTimeout = -1;
54 
55     /* Set maximum queue size */
56     LunExtension->MaxQueueCount = 256;
57 
58     /* Initialize request queue */
59     KeInitializeDeviceQueue(&LunExtension->DeviceQueue);
60 
61     LunPDO->Flags |= DO_DIRECT_IO;
62     LunPDO->Flags &= ~DO_DEVICE_INITIALIZING;
63 
64     return LunPDO;
65 }
66 
67 PSCSI_PORT_LUN_EXTENSION
68 GetLunByPath(
69     _In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
70     _In_ UCHAR PathId,
71     _In_ UCHAR TargetId,
72     _In_ UCHAR Lun)
73 {
74     if (PathId >= DeviceExtension->NumberOfBuses)
75     {
76         DPRINT1("Invalid PathId: %u\n", PathId);
77         return NULL;
78     }
79 
80     PSCSI_BUS_INFO bus = &DeviceExtension->Buses[PathId];
81 
82     for (PLIST_ENTRY lunEntry = bus->LunsListHead.Flink;
83          lunEntry != &bus->LunsListHead;
84          lunEntry = lunEntry->Flink)
85     {
86         PSCSI_PORT_LUN_EXTENSION lunExt =
87             CONTAINING_RECORD(lunEntry, SCSI_PORT_LUN_EXTENSION, LunEntry);
88 
89         if (lunExt->PathId == PathId &&
90             lunExt->TargetId == TargetId &&
91             lunExt->Lun == Lun)
92         {
93             return lunExt;
94         }
95     }
96 
97     DPRINT("SCSI LUN (%u, %u, %u) was not found\n", PathId, TargetId, Lun);
98     return NULL;
99 }
100 
101 PSCSI_REQUEST_BLOCK_INFO
102 SpiGetSrbData(
103     _In_ PSCSI_PORT_DEVICE_EXTENSION DeviceExtension,
104     _In_ PSCSI_PORT_LUN_EXTENSION LunExtension,
105     _In_ UCHAR QueueTag)
106 {
107     if (QueueTag == SP_UNTAGGED)
108     {
109         /* Return the pointer to SrbInfo */
110         return &LunExtension->SrbInfo;
111     }
112     else
113     {
114         /* Make sure the tag is valid, if it is - return the data */
115         if (QueueTag > DeviceExtension->SrbDataCount || QueueTag < 1)
116             return NULL;
117         else
118             return &DeviceExtension->SrbInfo[QueueTag -1];
119     }
120 }
121 
122 static
123 ULONG
124 CopyField(
125     IN PUCHAR Name,
126     IN PCHAR Buffer,
127     IN ULONG MaxLength,
128     IN CHAR DefaultCharacter,
129     IN BOOLEAN Trim)
130 {
131     ULONG Index;
132 
133     for (Index = 0; Index < MaxLength; Index++)
134     {
135         if (Name[Index] <= ' ' || Name[Index] >= 0x7F /* last printable ascii character */ ||  Name[Index] == ',')
136         {
137             // convert to underscore
138             Buffer[Index] = DefaultCharacter;
139         }
140         else
141         {
142             // just copy character
143             Buffer[Index] = Name[Index];
144         }
145     }
146 
147     /* Trim trailing default characters */
148     if (Trim)
149     {
150         Index = MaxLength - 1;
151         for (;;)
152         {
153             if (Buffer[Index] != DefaultCharacter)
154             {
155                 Index++;
156                 break;
157             }
158 
159             Index--;
160         }
161     }
162 
163     return Index;
164 }
165 
166 static
167 NTSTATUS
168 PdoHandleQueryDeviceText(
169     _In_ PDEVICE_OBJECT DeviceObject,
170     _Inout_ PIRP Irp)
171 {
172     PSCSI_PORT_LUN_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
173     PIO_STACK_LOCATION IoStack;
174     UINT32 Offset = 0;
175     PINQUIRYDATA InquiryData;
176     CHAR LocalBuffer[64];
177     ANSI_STRING AnsiString;
178     UNICODE_STRING DeviceDescription;
179 
180     DPRINT("PdoHandleQueryDeviceText\n");
181 
182     IoStack = IoGetCurrentIrpStackLocation(Irp);
183 
184     InquiryData = &DeviceExtension->InquiryData;
185 
186     switch (IoStack->Parameters.QueryDeviceText.DeviceTextType)
187     {
188         case DeviceTextDescription:
189         {
190             DPRINT("DeviceTextDescription\n");
191 
192             Offset += CopyField(InquiryData->VendorId,
193                                 &LocalBuffer[Offset],
194                                 sizeof(InquiryData->VendorId),
195                                 ' ',
196                                 TRUE);
197             LocalBuffer[Offset++] = ' ';
198             Offset += CopyField(InquiryData->ProductId,
199                                 &LocalBuffer[Offset],
200                                 sizeof(InquiryData->ProductId),
201                                 ' ',
202                                 TRUE);
203             Offset += sprintf(&LocalBuffer[Offset],
204                               " SCSI %s Device",
205                               GetDeviceType(InquiryData));
206             LocalBuffer[Offset++] = '\0';
207 
208             RtlInitAnsiString(&AnsiString, (PCSZ)&LocalBuffer);
209 
210             DeviceDescription.Length = 0;
211             DeviceDescription.MaximumLength = (USHORT)(Offset * sizeof(WCHAR));
212             DeviceDescription.Buffer = ExAllocatePoolWithTag(PagedPool,
213                                                              DeviceDescription.MaximumLength,
214                                                              TAG_SCSIPORT);
215             if (!DeviceDescription.Buffer)
216             {
217                 Irp->IoStatus.Information = 0;
218                 return STATUS_INSUFFICIENT_RESOURCES;
219             }
220 
221             RtlAnsiStringToUnicodeString(&DeviceDescription, &AnsiString, FALSE);
222 
223             Irp->IoStatus.Information = (ULONG_PTR)DeviceDescription.Buffer;
224             return STATUS_SUCCESS;
225         }
226 
227         case DeviceTextLocationInformation:
228         {
229             DPRINT("DeviceTextLocationInformation\n");
230 
231             sprintf(LocalBuffer, "Bus Number %d, Target ID %d, LUN %d",
232                     DeviceExtension->PathId, DeviceExtension->TargetId, DeviceExtension->Lun);
233 
234             RtlInitAnsiString(&AnsiString, (PCSZ)&LocalBuffer);
235 
236             DeviceDescription.Length = 0;
237             DeviceDescription.MaximumLength = (USHORT)((strlen(LocalBuffer) + 1) * sizeof(WCHAR));
238             DeviceDescription.Buffer = ExAllocatePoolWithTag(PagedPool,
239                                                              DeviceDescription.MaximumLength,
240                                                              TAG_SCSIPORT);
241             if (!DeviceDescription.Buffer)
242             {
243                 Irp->IoStatus.Information = 0;
244                 return STATUS_INSUFFICIENT_RESOURCES;
245             }
246 
247             RtlAnsiStringToUnicodeString(&DeviceDescription, &AnsiString, FALSE);
248 
249             Irp->IoStatus.Information = (ULONG_PTR)DeviceDescription.Buffer;
250             return STATUS_SUCCESS;
251         }
252 
253         default:
254         {
255             Irp->IoStatus.Information = 0;
256             return Irp->IoStatus.Status;
257         }
258     }
259 }
260 
261 static
262 NTSTATUS
263 PdoHandleQueryDeviceId(
264     _In_ PDEVICE_OBJECT DeviceObject,
265     _Inout_ PIRP Irp)
266 {
267     PSCSI_PORT_LUN_EXTENSION DeviceExtension;
268     NTSTATUS Status;
269     CHAR Buffer[100] = {0};
270     LPCSTR DeviceType;
271     ULONG Offset = 0;
272     PINQUIRYDATA InquiryData;
273     ANSI_STRING AnsiString;
274     UNICODE_STRING DeviceId;
275 
276     DeviceExtension = DeviceObject->DeviceExtension;
277     InquiryData = &DeviceExtension->InquiryData;
278 
279     DeviceType = GetDeviceType(InquiryData);
280 
281     // lets create device string
282     Offset = sprintf(&Buffer[Offset], "SCSI\\");
283     Offset += sprintf(&Buffer[Offset], DeviceType);
284     Offset += sprintf(&Buffer[Offset], "&Ven_");
285     Offset += CopyField(InquiryData->VendorId, &Buffer[Offset], 8, '_', TRUE);
286     Offset += sprintf(&Buffer[Offset], "&Prod_");
287     Offset += CopyField(InquiryData->ProductId, &Buffer[Offset], 16, '_', TRUE);
288     Offset += sprintf(&Buffer[Offset], "&Rev_");
289     Offset += CopyField(InquiryData->ProductRevisionLevel, &Buffer[Offset], 4, '_', TRUE);
290     Buffer[Offset] = '\0';
291 
292     RtlInitAnsiString(&AnsiString, (PCSZ)Buffer);
293 
294     // allocate DeviceId string
295     Status = RtlAnsiStringToUnicodeString(&DeviceId, &AnsiString, TRUE);
296 
297     if (NT_SUCCESS(Status))
298     {
299         Irp->IoStatus.Information = (ULONG_PTR)DeviceId.Buffer;
300     }
301 
302     DPRINT("DeviceId %wZ Status %x\n", &DeviceId, Status);
303 
304     return Status;
305 }
306 
307 static
308 VOID
309 ConvertToUnicodeString(
310     IN CHAR * Buffer,
311     IN ULONG ResultBufferLength,
312     IN ULONG ResultBufferOffset,
313     OUT LPWSTR ResultBuffer,
314     OUT PULONG NewResultBufferOffset)
315 {
316     UNICODE_STRING DeviceString;
317     ANSI_STRING AnsiString;
318     NTSTATUS Status;
319 
320     ASSERT(ResultBufferLength);
321     ASSERT(ResultBufferLength > ResultBufferOffset);
322 
323     DPRINT("ResultBufferOffset %lu ResultBufferLength %lu Buffer %s Length %lu\n",
324         ResultBufferOffset, ResultBufferLength, Buffer, strlen(Buffer));
325 
326     // construct destination string
327     DeviceString.Buffer = &ResultBuffer[ResultBufferOffset];
328     DeviceString.Length = 0;
329     DeviceString.MaximumLength = (ResultBufferLength - ResultBufferOffset) * sizeof(WCHAR);
330 
331     // initialize source string
332     RtlInitAnsiString(&AnsiString, Buffer);
333 
334     Status = RtlAnsiStringToUnicodeString(&DeviceString, &AnsiString, FALSE);
335     ASSERT(Status == STATUS_SUCCESS);
336 
337     // subtract consumed bytes
338     ResultBufferLength -= (DeviceString.Length + sizeof(WCHAR)) / sizeof(WCHAR);
339     ResultBufferOffset += (DeviceString.Length + sizeof(WCHAR)) / sizeof(WCHAR);
340 
341     *NewResultBufferOffset = ResultBufferOffset;
342 }
343 
344 static
345 NTSTATUS
346 PdoHandleQueryHardwareId(
347     _In_ PDEVICE_OBJECT DeviceObject,
348     _Inout_ PIRP Irp)
349 {
350     PSCSI_PORT_LUN_EXTENSION PDODeviceExtension = DeviceObject->DeviceExtension;
351     LPCSTR GenericType, DeviceType;
352     LPWSTR Buffer;
353     CHAR Id1[50], Id2[50], Id3[50], Id4[50], Id5[50], Id6[50];
354     ULONG Id1Length, Id2Length, Id3Length, Id4Length, Id5Length, Id6Length;
355     ULONG Offset, TotalLength, Length;
356     PINQUIRYDATA InquiryData;
357 
358     InquiryData = &PDODeviceExtension->InquiryData;
359 
360     DeviceType = GetDeviceType(InquiryData);
361     GenericType = GetGenericType(InquiryData);
362 
363     ASSERT(GenericType);
364 
365     // generate id 1
366     // SCSI\SCSIType_VendorId(8)_ProductId(16)_Revision(4)
367     RtlZeroMemory(Id1, sizeof(Id1));
368     Offset = 0;
369     Offset = sprintf(&Id1[Offset], "SCSI\\");
370     Offset += sprintf(&Id1[Offset], DeviceType);
371     Offset += CopyField(InquiryData->VendorId, &Id1[Offset], 8, '_', FALSE);
372     Offset += CopyField(InquiryData->ProductId, &Id1[Offset], 16, '_', FALSE);
373     Offset += CopyField(InquiryData->ProductRevisionLevel, &Id1[Offset], 4, '_', FALSE);
374     Id1Length = strlen(Id1) + 1;
375     DPRINT("PdoHandleQueryHardwareId HardwareId1 %s\n", Id1);
376 
377     // generate id 2
378     // SCSI\SCSIType_VendorId(8)_ProductId(16)
379     RtlZeroMemory(Id2, sizeof(Id2));
380     Offset = 0;
381     Offset = sprintf(&Id2[Offset], "SCSI\\");
382     Offset += sprintf(&Id2[Offset], DeviceType);
383     Offset += CopyField(InquiryData->VendorId, &Id2[Offset], 8, '_', FALSE);
384     Offset += CopyField(InquiryData->ProductId, &Id2[Offset], 16, '_', FALSE);
385     Id2Length = strlen(Id2) + 1;
386     DPRINT("PdoHandleQueryHardwareId HardwareId2 %s\n", Id2);
387 
388     // generate id 3
389     // SCSI\SCSIType_VendorId(8)
390     RtlZeroMemory(Id3, sizeof(Id3));
391     Offset = 0;
392     Offset = sprintf(&Id3[Offset], "SCSI\\");
393     Offset += sprintf(&Id3[Offset], DeviceType);
394     Offset += CopyField(InquiryData->VendorId, &Id3[Offset], 8, '_', FALSE);
395     Id3Length = strlen(Id3) + 1;
396     DPRINT("PdoHandleQueryHardwareId HardwareId3 %s\n", Id3);
397 
398     // generate id 4
399     // SCSI\VendorId(8)_ProductId(16)_Revision(1)
400     RtlZeroMemory(Id4, sizeof(Id4));
401     Offset = 0;
402     Offset = sprintf(&Id4[Offset], "SCSI\\");
403     Offset += CopyField(InquiryData->VendorId, &Id4[Offset], 8, '_', FALSE);
404     Offset += CopyField(InquiryData->ProductId, &Id4[Offset], 16, '_', FALSE);
405     Offset += CopyField(InquiryData->ProductRevisionLevel, &Id4[Offset], 1, '_', FALSE);
406     Id4Length = strlen(Id4) + 1;
407     DPRINT("PdoHandleQueryHardwareId HardwareId4 %s\n", Id4);
408 
409     // generate id 5
410     // VendorId(8)_ProductId(16)_Revision(1)
411     RtlZeroMemory(Id5, sizeof(Id5));
412     Offset = 0;
413     Offset = CopyField(InquiryData->VendorId, &Id5[Offset], 8, '_', FALSE);
414     Offset += CopyField(InquiryData->ProductId, &Id5[Offset], 16, '_', FALSE);
415     Offset += CopyField(InquiryData->ProductRevisionLevel, &Id5[Offset], 1, '_', FALSE);
416     Id5Length = strlen(Id5) + 1;
417     DPRINT("PdoHandleQueryHardwareId HardwareId5 %s\n", Id5);
418 
419     // generate id 6
420     // SCSIType
421     RtlZeroMemory(Id6, sizeof(Id6));
422     Offset = 0;
423     Offset = sprintf(&Id6[Offset], GenericType);
424     Id6Length = strlen(Id6) + 1;
425     DPRINT("PdoHandleQueryHardwareId HardwareId6 %s\n", Id6);
426 
427     TotalLength = Id1Length + Id2Length + Id3Length + Id4Length + Id5Length + Id6Length + 1;
428 
429     Buffer = ExAllocatePoolWithTag(PagedPool, TotalLength * sizeof(WCHAR), TAG_SCSIPORT);
430     if (!Buffer)
431     {
432         Irp->IoStatus.Information = 0;
433         return STATUS_INSUFFICIENT_RESOURCES;
434     }
435 
436     // reset offset
437     Offset = 0;
438     Length = TotalLength;
439 
440     ConvertToUnicodeString(Id1, Length, Offset, Buffer, &Offset);
441     ConvertToUnicodeString(Id2, Length, Offset, Buffer, &Offset);
442     ConvertToUnicodeString(Id3, Length, Offset, Buffer, &Offset);
443     ConvertToUnicodeString(Id4, Length, Offset, Buffer, &Offset);
444     ConvertToUnicodeString(Id5, Length, Offset, Buffer, &Offset);
445     ConvertToUnicodeString(Id6, Length, Offset, Buffer, &Offset);
446 
447     Buffer[Offset] = UNICODE_NULL;
448 
449     ASSERT(Offset + 1 == Length);
450 
451     Irp->IoStatus.Information = (ULONG_PTR)Buffer;
452     return STATUS_SUCCESS;
453 }
454 
455 static
456 NTSTATUS
457 PdoHandleQueryCompatibleId(
458     _In_ PDEVICE_OBJECT DeviceObject,
459     _Inout_ PIRP Irp)
460 {
461     PSCSI_PORT_LUN_EXTENSION PDODeviceExtension = DeviceObject->DeviceExtension;
462     CHAR Buffer[100] = {0};
463     ULONG Length, Offset;
464     LPWSTR InstanceId;
465     LPCSTR DeviceType;
466 
467     DeviceType = GetDeviceType(&PDODeviceExtension->InquiryData);
468 
469     // format instance id
470     Length = sprintf(Buffer, "SCSI\\%s", DeviceType) + 1;
471     Length += sprintf(&Buffer[Length], "SCSI\\%s", "RAW") + 2;
472 
473     InstanceId = ExAllocatePoolWithTag(PagedPool, Length * sizeof(WCHAR), TAG_SCSIPORT);
474     if (!InstanceId)
475     {
476         Irp->IoStatus.Information = 0;
477         return STATUS_INSUFFICIENT_RESOURCES;
478     }
479 
480     ConvertToUnicodeString(Buffer, Length, 0, InstanceId, &Offset);
481     ConvertToUnicodeString(&Buffer[Offset], Length, Offset, InstanceId, &Offset);
482 
483     InstanceId[Offset] = UNICODE_NULL;
484 
485     DPRINT("PdoHandleQueryCompatibleId %S\n", InstanceId);
486 
487     Irp->IoStatus.Information = (ULONG_PTR)InstanceId;
488     return STATUS_SUCCESS;
489 }
490 
491 static
492 NTSTATUS
493 PdoHandleQueryInstanceId(
494     _In_ PDEVICE_OBJECT DeviceObject,
495     _Inout_ PIRP Irp)
496 {
497     PSCSI_PORT_LUN_EXTENSION lunExt = DeviceObject->DeviceExtension;
498     WCHAR Buffer[26];
499     ULONG Length;
500     LPWSTR InstanceId;
501 
502     // use instance count and LUN
503     swprintf(Buffer, L"%x%x%x", lunExt->PathId, lunExt->TargetId, lunExt->Lun);
504 
505     Length = wcslen(Buffer) + 1;
506 
507     InstanceId = ExAllocatePoolWithTag(PagedPool, Length * sizeof(WCHAR), TAG_SCSIPORT);
508     if (!InstanceId)
509     {
510         Irp->IoStatus.Information = 0;
511         return STATUS_INSUFFICIENT_RESOURCES;
512     }
513 
514     wcscpy(InstanceId, Buffer);
515 
516     DPRINT("PdoHandleQueryInstanceId %S\n", InstanceId);
517 
518     Irp->IoStatus.Information = (ULONG_PTR)InstanceId;
519     return STATUS_SUCCESS;
520 }
521 
522 static
523 NTSTATUS
524 PdoHandleDeviceRelations(
525     _In_ PDEVICE_OBJECT DeviceObject,
526     _Inout_ PIRP Irp)
527 {
528     PDEVICE_RELATIONS deviceRelations;
529     PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp);
530 
531     // check if relation type is BusRelations
532     if (ioStack->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation)
533     {
534         // PDO handles only target device relation
535         return Irp->IoStatus.Status;
536     }
537 
538     deviceRelations = ExAllocatePoolWithTag(PagedPool, sizeof(DEVICE_RELATIONS), TAG_SCSIPORT);
539     if (!deviceRelations)
540     {
541         return STATUS_INSUFFICIENT_RESOURCES;
542     }
543 
544     // initialize device relations
545     deviceRelations->Count = 1;
546     deviceRelations->Objects[0] = DeviceObject;
547     ObReferenceObject(DeviceObject);
548 
549     Irp->IoStatus.Information = (ULONG_PTR)deviceRelations;
550     return STATUS_SUCCESS;
551 }
552 
553 NTSTATUS
554 PdoDispatchPnp(
555     _In_ PDEVICE_OBJECT DeviceObject,
556     _Inout_ PIRP Irp)
557 {
558     PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp);
559     PSCSI_PORT_LUN_EXTENSION lunExt = DeviceObject->DeviceExtension;
560     NTSTATUS status;
561 
562     DPRINT("PDO PnP request %s\n", GetIRPMinorFunctionString(ioStack->MinorFunction));
563 
564     ASSERT(!lunExt->Common.IsFDO);
565 
566     switch (ioStack->MinorFunction)
567     {
568         case IRP_MN_START_DEVICE:
569         {
570             RegistryInitLunKey(lunExt);
571             status = STATUS_SUCCESS;
572             break;
573         }
574         case IRP_MN_REMOVE_DEVICE:
575         case IRP_MN_QUERY_CAPABILITIES:
576         case IRP_MN_QUERY_REMOVE_DEVICE:
577         case IRP_MN_QUERY_STOP_DEVICE:
578         case IRP_MN_SURPRISE_REMOVAL:
579         {
580             status = STATUS_SUCCESS;
581             break;
582         }
583         case IRP_MN_QUERY_DEVICE_RELATIONS:
584         {
585             status = PdoHandleDeviceRelations(DeviceObject, Irp);
586             break;
587         }
588         case IRP_MN_QUERY_DEVICE_TEXT:
589         {
590             status = PdoHandleQueryDeviceText(DeviceObject, Irp);
591             break;
592         }
593         case IRP_MN_QUERY_ID:
594         {
595             DPRINT("IRP_MN_QUERY_ID IdType %s\n",
596                 DbgGetDeviceIDString(ioStack->Parameters.QueryId.IdType));
597 
598            if (ioStack->Parameters.QueryId.IdType == BusQueryDeviceID)
599            {
600                status = PdoHandleQueryDeviceId(DeviceObject, Irp);
601                break;
602            }
603            else if (ioStack->Parameters.QueryId.IdType == BusQueryHardwareIDs)
604            {
605                status = PdoHandleQueryHardwareId(DeviceObject, Irp);
606                break;
607            }
608            else if (ioStack->Parameters.QueryId.IdType == BusQueryInstanceID)
609            {
610                status = PdoHandleQueryInstanceId(DeviceObject, Irp);
611                break;
612            }
613            else if (ioStack->Parameters.QueryId.IdType == BusQueryCompatibleIDs)
614            {
615                status = PdoHandleQueryCompatibleId(DeviceObject, Irp);
616                break;
617            }
618 
619            // fallthrough
620         }
621         default:
622         {
623             // do nothing
624             status = Irp->IoStatus.Status;
625         }
626     }
627 
628     if (status != STATUS_PENDING)
629     {
630         Irp->IoStatus.Status = status;
631         IoCompleteRequest(Irp, IO_NO_INCREMENT);
632     }
633 
634     return status;
635 }
636