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