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