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