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