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