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