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 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 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 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 124a97c6e0aSVictor Perevertkin CopyField( 125a97c6e0aSVictor Perevertkin IN PUCHAR Name, 126a97c6e0aSVictor Perevertkin IN PCHAR Buffer, 127*e64984caSEric Kohl IN ULONG MaxLength, 128*e64984caSEric Kohl IN CHAR DefaultCharacter, 129*e64984caSEric 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 138*e64984caSEric 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 147*e64984caSEric Kohl /* Trim trailing default characters */ 148*e64984caSEric Kohl if (Trim) 149a97c6e0aSVictor Perevertkin { 150*e64984caSEric Kohl Index = MaxLength - 1; 151*e64984caSEric Kohl for (;;) 152a97c6e0aSVictor Perevertkin { 153*e64984caSEric Kohl if (Buffer[Index] != DefaultCharacter) 154a97c6e0aSVictor Perevertkin { 155*e64984caSEric Kohl Index++; 156a97c6e0aSVictor Perevertkin break; 157a97c6e0aSVictor Perevertkin } 158*e64984caSEric Kohl 159*e64984caSEric Kohl Index--; 160a97c6e0aSVictor Perevertkin } 161a97c6e0aSVictor Perevertkin } 162a97c6e0aSVictor Perevertkin 163a97c6e0aSVictor Perevertkin return Index; 164a97c6e0aSVictor Perevertkin } 165a97c6e0aSVictor Perevertkin 166a97c6e0aSVictor Perevertkin static 167a97c6e0aSVictor Perevertkin NTSTATUS 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; 176cac7b003SEric Kohl CHAR LocalBuffer[40]; 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 192*e64984caSEric Kohl Offset += CopyField(InquiryData->VendorId, 193a97c6e0aSVictor Perevertkin &LocalBuffer[Offset], 194*e64984caSEric Kohl sizeof(InquiryData->VendorId), 195*e64984caSEric Kohl ' ', 196*e64984caSEric Kohl TRUE); 197a97c6e0aSVictor Perevertkin LocalBuffer[Offset++] = ' '; 198*e64984caSEric Kohl Offset += CopyField(InquiryData->ProductId, 199a97c6e0aSVictor Perevertkin &LocalBuffer[Offset], 200*e64984caSEric Kohl sizeof(InquiryData->ProductId), 201*e64984caSEric Kohl ' ', 202*e64984caSEric Kohl TRUE); 203a97c6e0aSVictor Perevertkin LocalBuffer[Offset++] = '\0'; 204a97c6e0aSVictor Perevertkin 205a97c6e0aSVictor Perevertkin RtlInitAnsiString(&AnsiString, (PCSZ)&LocalBuffer); 206a97c6e0aSVictor Perevertkin 207a97c6e0aSVictor Perevertkin DeviceDescription.Length = 0; 208a97c6e0aSVictor Perevertkin DeviceDescription.MaximumLength = (USHORT)(Offset * sizeof(WCHAR)); 209a97c6e0aSVictor Perevertkin DeviceDescription.Buffer = ExAllocatePoolWithTag(PagedPool, 210a97c6e0aSVictor Perevertkin DeviceDescription.MaximumLength, 211a97c6e0aSVictor Perevertkin TAG_SCSIPORT); 212a97c6e0aSVictor Perevertkin if (!DeviceDescription.Buffer) 213a97c6e0aSVictor Perevertkin { 214a97c6e0aSVictor Perevertkin Irp->IoStatus.Information = 0; 215a97c6e0aSVictor Perevertkin return STATUS_INSUFFICIENT_RESOURCES; 216a97c6e0aSVictor Perevertkin } 217a97c6e0aSVictor Perevertkin 218a97c6e0aSVictor Perevertkin RtlAnsiStringToUnicodeString(&DeviceDescription, &AnsiString, FALSE); 219a97c6e0aSVictor Perevertkin 220a97c6e0aSVictor Perevertkin Irp->IoStatus.Information = (ULONG_PTR)DeviceDescription.Buffer; 221a97c6e0aSVictor Perevertkin return STATUS_SUCCESS; 222a97c6e0aSVictor Perevertkin } 223cac7b003SEric Kohl 224cac7b003SEric Kohl case DeviceTextLocationInformation: 225cac7b003SEric Kohl { 226cac7b003SEric Kohl DPRINT("DeviceTextLocationInformation\n"); 227cac7b003SEric Kohl 228cac7b003SEric Kohl sprintf(LocalBuffer, "Bus Number %d, Target ID %d, LUN %d", 229cac7b003SEric Kohl DeviceExtension->PathId, DeviceExtension->TargetId, DeviceExtension->Lun); 230cac7b003SEric Kohl 231cac7b003SEric Kohl RtlInitAnsiString(&AnsiString, (PCSZ)&LocalBuffer); 232cac7b003SEric Kohl 233cac7b003SEric Kohl DeviceDescription.Length = 0; 234cac7b003SEric Kohl DeviceDescription.MaximumLength = (USHORT)((strlen(LocalBuffer) + 1) * sizeof(WCHAR)); 235cac7b003SEric Kohl DeviceDescription.Buffer = ExAllocatePoolWithTag(PagedPool, 236cac7b003SEric Kohl DeviceDescription.MaximumLength, 237cac7b003SEric Kohl TAG_SCSIPORT); 238cac7b003SEric Kohl if (!DeviceDescription.Buffer) 239cac7b003SEric Kohl { 240cac7b003SEric Kohl Irp->IoStatus.Information = 0; 241cac7b003SEric Kohl return STATUS_INSUFFICIENT_RESOURCES; 242cac7b003SEric Kohl } 243cac7b003SEric Kohl 244cac7b003SEric Kohl RtlAnsiStringToUnicodeString(&DeviceDescription, &AnsiString, FALSE); 245cac7b003SEric Kohl 246cac7b003SEric Kohl Irp->IoStatus.Information = (ULONG_PTR)DeviceDescription.Buffer; 247cac7b003SEric Kohl return STATUS_SUCCESS; 248cac7b003SEric Kohl } 249cac7b003SEric Kohl 250a97c6e0aSVictor Perevertkin default: 251a97c6e0aSVictor Perevertkin { 252a97c6e0aSVictor Perevertkin Irp->IoStatus.Information = 0; 253a97c6e0aSVictor Perevertkin return Irp->IoStatus.Status; 254a97c6e0aSVictor Perevertkin } 255a97c6e0aSVictor Perevertkin } 256a97c6e0aSVictor Perevertkin } 257a97c6e0aSVictor Perevertkin 258a97c6e0aSVictor Perevertkin static 259a97c6e0aSVictor Perevertkin NTSTATUS 260a97c6e0aSVictor Perevertkin PdoHandleQueryDeviceId( 261a97c6e0aSVictor Perevertkin _In_ PDEVICE_OBJECT DeviceObject, 262a97c6e0aSVictor Perevertkin _Inout_ PIRP Irp) 263a97c6e0aSVictor Perevertkin { 264a97c6e0aSVictor Perevertkin PSCSI_PORT_LUN_EXTENSION DeviceExtension; 265a97c6e0aSVictor Perevertkin NTSTATUS Status; 266a97c6e0aSVictor Perevertkin CHAR Buffer[100] = {0}; 267a97c6e0aSVictor Perevertkin LPCSTR DeviceType; 268a97c6e0aSVictor Perevertkin ULONG Offset = 0; 269a97c6e0aSVictor Perevertkin PINQUIRYDATA InquiryData; 270a97c6e0aSVictor Perevertkin ANSI_STRING AnsiString; 271a97c6e0aSVictor Perevertkin UNICODE_STRING DeviceId; 272a97c6e0aSVictor Perevertkin 273a97c6e0aSVictor Perevertkin DeviceExtension = DeviceObject->DeviceExtension; 274a97c6e0aSVictor Perevertkin InquiryData = &DeviceExtension->InquiryData; 275a97c6e0aSVictor Perevertkin 276a97c6e0aSVictor Perevertkin DeviceType = GetDeviceType(InquiryData); 277a97c6e0aSVictor Perevertkin 278a97c6e0aSVictor Perevertkin // lets create device string 279a97c6e0aSVictor Perevertkin Offset = sprintf(&Buffer[Offset], "SCSI\\"); 280a97c6e0aSVictor Perevertkin Offset += sprintf(&Buffer[Offset], DeviceType); 281a97c6e0aSVictor Perevertkin Offset += sprintf(&Buffer[Offset], "&Ven_"); 282*e64984caSEric Kohl Offset += CopyField(InquiryData->VendorId, &Buffer[Offset], 8, '_', TRUE); 283a97c6e0aSVictor Perevertkin Offset += sprintf(&Buffer[Offset], "&Prod_"); 284*e64984caSEric Kohl Offset += CopyField(InquiryData->ProductId, &Buffer[Offset], 16, '_', TRUE); 285a97c6e0aSVictor Perevertkin Offset += sprintf(&Buffer[Offset], "&Rev_"); 286*e64984caSEric Kohl Offset += CopyField(InquiryData->ProductRevisionLevel, &Buffer[Offset], 4, '_', TRUE); 287*e64984caSEric Kohl Buffer[Offset] = '\0'; 288a97c6e0aSVictor Perevertkin 289a97c6e0aSVictor Perevertkin RtlInitAnsiString(&AnsiString, (PCSZ)Buffer); 290a97c6e0aSVictor Perevertkin 291a97c6e0aSVictor Perevertkin // allocate DeviceId string 292a97c6e0aSVictor Perevertkin Status = RtlAnsiStringToUnicodeString(&DeviceId, &AnsiString, TRUE); 293a97c6e0aSVictor Perevertkin 294a97c6e0aSVictor Perevertkin if (NT_SUCCESS(Status)) 295a97c6e0aSVictor Perevertkin { 296a97c6e0aSVictor Perevertkin Irp->IoStatus.Information = (ULONG_PTR)DeviceId.Buffer; 297a97c6e0aSVictor Perevertkin } 298a97c6e0aSVictor Perevertkin 299a97c6e0aSVictor Perevertkin DPRINT("DeviceId %wZ Status %x\n", &DeviceId, Status); 300a97c6e0aSVictor Perevertkin 301a97c6e0aSVictor Perevertkin return Status; 302a97c6e0aSVictor Perevertkin } 303a97c6e0aSVictor Perevertkin 304a97c6e0aSVictor Perevertkin static 305a97c6e0aSVictor Perevertkin VOID 306a97c6e0aSVictor Perevertkin ConvertToUnicodeString( 307a97c6e0aSVictor Perevertkin IN CHAR * Buffer, 308a97c6e0aSVictor Perevertkin IN ULONG ResultBufferLength, 309a97c6e0aSVictor Perevertkin IN ULONG ResultBufferOffset, 310a97c6e0aSVictor Perevertkin OUT LPWSTR ResultBuffer, 311a97c6e0aSVictor Perevertkin OUT PULONG NewResultBufferOffset) 312a97c6e0aSVictor Perevertkin { 313a97c6e0aSVictor Perevertkin UNICODE_STRING DeviceString; 314a97c6e0aSVictor Perevertkin ANSI_STRING AnsiString; 315a97c6e0aSVictor Perevertkin NTSTATUS Status; 316a97c6e0aSVictor Perevertkin 317a97c6e0aSVictor Perevertkin ASSERT(ResultBufferLength); 318a97c6e0aSVictor Perevertkin ASSERT(ResultBufferLength > ResultBufferOffset); 319a97c6e0aSVictor Perevertkin 320a97c6e0aSVictor Perevertkin DPRINT("ResultBufferOffset %lu ResultBufferLength %lu Buffer %s Length %lu\n", 321a97c6e0aSVictor Perevertkin ResultBufferOffset, ResultBufferLength, Buffer, strlen(Buffer)); 322a97c6e0aSVictor Perevertkin 323a97c6e0aSVictor Perevertkin // construct destination string 324a97c6e0aSVictor Perevertkin DeviceString.Buffer = &ResultBuffer[ResultBufferOffset]; 325a97c6e0aSVictor Perevertkin DeviceString.Length = 0; 326a97c6e0aSVictor Perevertkin DeviceString.MaximumLength = (ResultBufferLength - ResultBufferOffset) * sizeof(WCHAR); 327a97c6e0aSVictor Perevertkin 328a97c6e0aSVictor Perevertkin // initialize source string 329a97c6e0aSVictor Perevertkin RtlInitAnsiString(&AnsiString, Buffer); 330a97c6e0aSVictor Perevertkin 331a97c6e0aSVictor Perevertkin Status = RtlAnsiStringToUnicodeString(&DeviceString, &AnsiString, FALSE); 332a97c6e0aSVictor Perevertkin ASSERT(Status == STATUS_SUCCESS); 333a97c6e0aSVictor Perevertkin 334a97c6e0aSVictor Perevertkin // subtract consumed bytes 335a97c6e0aSVictor Perevertkin ResultBufferLength -= (DeviceString.Length + sizeof(WCHAR)) / sizeof(WCHAR); 336a97c6e0aSVictor Perevertkin ResultBufferOffset += (DeviceString.Length + sizeof(WCHAR)) / sizeof(WCHAR); 337a97c6e0aSVictor Perevertkin 338a97c6e0aSVictor Perevertkin *NewResultBufferOffset = ResultBufferOffset; 339a97c6e0aSVictor Perevertkin } 340a97c6e0aSVictor Perevertkin 341a97c6e0aSVictor Perevertkin static 342a97c6e0aSVictor Perevertkin NTSTATUS 343a97c6e0aSVictor Perevertkin PdoHandleQueryHardwareId( 344a97c6e0aSVictor Perevertkin _In_ PDEVICE_OBJECT DeviceObject, 345a97c6e0aSVictor Perevertkin _Inout_ PIRP Irp) 346a97c6e0aSVictor Perevertkin { 347a97c6e0aSVictor Perevertkin PSCSI_PORT_LUN_EXTENSION PDODeviceExtension = DeviceObject->DeviceExtension; 348a97c6e0aSVictor Perevertkin LPCSTR GenericType, DeviceType; 349a97c6e0aSVictor Perevertkin LPWSTR Buffer; 3508ba87f97SEric Kohl CHAR Id1[50], Id2[50], Id3[50], Id4[50], Id5[50], Id6[50]; 3518ba87f97SEric Kohl ULONG Id1Length, Id2Length, Id3Length, Id4Length, Id5Length, Id6Length; 352a97c6e0aSVictor Perevertkin ULONG Offset, TotalLength, Length; 353a97c6e0aSVictor Perevertkin PINQUIRYDATA InquiryData; 354a97c6e0aSVictor Perevertkin 355a97c6e0aSVictor Perevertkin InquiryData = &PDODeviceExtension->InquiryData; 356a97c6e0aSVictor Perevertkin 357a97c6e0aSVictor Perevertkin DeviceType = GetDeviceType(InquiryData); 358a97c6e0aSVictor Perevertkin GenericType = GetGenericType(InquiryData); 359a97c6e0aSVictor Perevertkin 360a97c6e0aSVictor Perevertkin ASSERT(GenericType); 361a97c6e0aSVictor Perevertkin 362a97c6e0aSVictor Perevertkin // generate id 1 363a97c6e0aSVictor Perevertkin // SCSI\SCSIType_VendorId(8)_ProductId(16)_Revision(4) 364a97c6e0aSVictor Perevertkin RtlZeroMemory(Id1, sizeof(Id1)); 365a97c6e0aSVictor Perevertkin Offset = 0; 366a97c6e0aSVictor Perevertkin Offset = sprintf(&Id1[Offset], "SCSI\\"); 367a97c6e0aSVictor Perevertkin Offset += sprintf(&Id1[Offset], DeviceType); 368*e64984caSEric Kohl Offset += CopyField(InquiryData->VendorId, &Id1[Offset], 8, '_', FALSE); 369*e64984caSEric Kohl Offset += CopyField(InquiryData->ProductId, &Id1[Offset], 16, '_', FALSE); 370*e64984caSEric Kohl Offset += CopyField(InquiryData->ProductRevisionLevel, &Id1[Offset], 4, '_', FALSE); 371a97c6e0aSVictor Perevertkin Id1Length = strlen(Id1) + 1; 372a97c6e0aSVictor Perevertkin DPRINT("PdoHandleQueryHardwareId HardwareId1 %s\n", Id1); 373a97c6e0aSVictor Perevertkin 374a97c6e0aSVictor Perevertkin // generate id 2 375a97c6e0aSVictor Perevertkin // SCSI\SCSIType_VendorId(8)_ProductId(16) 376a97c6e0aSVictor Perevertkin RtlZeroMemory(Id2, sizeof(Id2)); 377a97c6e0aSVictor Perevertkin Offset = 0; 378a97c6e0aSVictor Perevertkin Offset = sprintf(&Id2[Offset], "SCSI\\"); 379a97c6e0aSVictor Perevertkin Offset += sprintf(&Id2[Offset], DeviceType); 380*e64984caSEric Kohl Offset += CopyField(InquiryData->VendorId, &Id2[Offset], 8, '_', FALSE); 381*e64984caSEric Kohl Offset += CopyField(InquiryData->ProductId, &Id2[Offset], 16, '_', FALSE); 382a97c6e0aSVictor Perevertkin Id2Length = strlen(Id2) + 1; 383a97c6e0aSVictor Perevertkin DPRINT("PdoHandleQueryHardwareId HardwareId2 %s\n", Id2); 384a97c6e0aSVictor Perevertkin 385a97c6e0aSVictor Perevertkin // generate id 3 386a97c6e0aSVictor Perevertkin // SCSI\SCSIType_VendorId(8) 387a97c6e0aSVictor Perevertkin RtlZeroMemory(Id3, sizeof(Id3)); 388a97c6e0aSVictor Perevertkin Offset = 0; 389a97c6e0aSVictor Perevertkin Offset = sprintf(&Id3[Offset], "SCSI\\"); 390a97c6e0aSVictor Perevertkin Offset += sprintf(&Id3[Offset], DeviceType); 391*e64984caSEric Kohl Offset += CopyField(InquiryData->VendorId, &Id3[Offset], 8, '_', FALSE); 392a97c6e0aSVictor Perevertkin Id3Length = strlen(Id3) + 1; 393a97c6e0aSVictor Perevertkin DPRINT("PdoHandleQueryHardwareId HardwareId3 %s\n", Id3); 394a97c6e0aSVictor Perevertkin 395a97c6e0aSVictor Perevertkin // generate id 4 3968ba87f97SEric Kohl // SCSI\VendorId(8)_ProductId(16)_Revision(1) 397a97c6e0aSVictor Perevertkin RtlZeroMemory(Id4, sizeof(Id4)); 398a97c6e0aSVictor Perevertkin Offset = 0; 399a97c6e0aSVictor Perevertkin Offset = sprintf(&Id4[Offset], "SCSI\\"); 400*e64984caSEric Kohl Offset += CopyField(InquiryData->VendorId, &Id4[Offset], 8, '_', FALSE); 401*e64984caSEric Kohl Offset += CopyField(InquiryData->ProductId, &Id4[Offset], 16, '_', FALSE); 402*e64984caSEric Kohl Offset += CopyField(InquiryData->ProductRevisionLevel, &Id4[Offset], 1, '_', FALSE); 403a97c6e0aSVictor Perevertkin Id4Length = strlen(Id4) + 1; 404a97c6e0aSVictor Perevertkin DPRINT("PdoHandleQueryHardwareId HardwareId4 %s\n", Id4); 405a97c6e0aSVictor Perevertkin 406a97c6e0aSVictor Perevertkin // generate id 5 4078ba87f97SEric Kohl // VendorId(8)_ProductId(16)_Revision(1) 408a97c6e0aSVictor Perevertkin RtlZeroMemory(Id5, sizeof(Id5)); 409a97c6e0aSVictor Perevertkin Offset = 0; 410*e64984caSEric Kohl Offset = CopyField(InquiryData->VendorId, &Id5[Offset], 8, '_', FALSE); 411*e64984caSEric Kohl Offset += CopyField(InquiryData->ProductId, &Id5[Offset], 16, '_', FALSE); 412*e64984caSEric Kohl Offset += CopyField(InquiryData->ProductRevisionLevel, &Id5[Offset], 1, '_', FALSE); 413a97c6e0aSVictor Perevertkin Id5Length = strlen(Id5) + 1; 414a97c6e0aSVictor Perevertkin DPRINT("PdoHandleQueryHardwareId HardwareId5 %s\n", Id5); 415a97c6e0aSVictor Perevertkin 416a97c6e0aSVictor Perevertkin // generate id 6 4178ba87f97SEric Kohl // SCSIType 418a97c6e0aSVictor Perevertkin RtlZeroMemory(Id6, sizeof(Id6)); 419a97c6e0aSVictor Perevertkin Offset = 0; 4208ba87f97SEric Kohl Offset = sprintf(&Id6[Offset], GenericType); 421a97c6e0aSVictor Perevertkin Id6Length = strlen(Id6) + 1; 422a97c6e0aSVictor Perevertkin DPRINT("PdoHandleQueryHardwareId HardwareId6 %s\n", Id6); 423a97c6e0aSVictor Perevertkin 4248ba87f97SEric Kohl TotalLength = Id1Length + Id2Length + Id3Length + Id4Length + Id5Length + Id6Length + 1; 425a97c6e0aSVictor Perevertkin 426a97c6e0aSVictor Perevertkin Buffer = ExAllocatePoolWithTag(PagedPool, TotalLength * sizeof(WCHAR), TAG_SCSIPORT); 427a97c6e0aSVictor Perevertkin if (!Buffer) 428a97c6e0aSVictor Perevertkin { 429a97c6e0aSVictor Perevertkin Irp->IoStatus.Information = 0; 430a97c6e0aSVictor Perevertkin return STATUS_INSUFFICIENT_RESOURCES; 431a97c6e0aSVictor Perevertkin } 432a97c6e0aSVictor Perevertkin 433a97c6e0aSVictor Perevertkin // reset offset 434a97c6e0aSVictor Perevertkin Offset = 0; 435a97c6e0aSVictor Perevertkin Length = TotalLength; 436a97c6e0aSVictor Perevertkin 437a97c6e0aSVictor Perevertkin ConvertToUnicodeString(Id1, Length, Offset, Buffer, &Offset); 438a97c6e0aSVictor Perevertkin ConvertToUnicodeString(Id2, Length, Offset, Buffer, &Offset); 439a97c6e0aSVictor Perevertkin ConvertToUnicodeString(Id3, Length, Offset, Buffer, &Offset); 440a97c6e0aSVictor Perevertkin ConvertToUnicodeString(Id4, Length, Offset, Buffer, &Offset); 441a97c6e0aSVictor Perevertkin ConvertToUnicodeString(Id5, Length, Offset, Buffer, &Offset); 442a97c6e0aSVictor Perevertkin ConvertToUnicodeString(Id6, Length, Offset, Buffer, &Offset); 443a97c6e0aSVictor Perevertkin 444a97c6e0aSVictor Perevertkin Buffer[Offset] = UNICODE_NULL; 445a97c6e0aSVictor Perevertkin 446a97c6e0aSVictor Perevertkin ASSERT(Offset + 1 == Length); 447a97c6e0aSVictor Perevertkin 448a97c6e0aSVictor Perevertkin Irp->IoStatus.Information = (ULONG_PTR)Buffer; 449a97c6e0aSVictor Perevertkin return STATUS_SUCCESS; 450a97c6e0aSVictor Perevertkin } 451a97c6e0aSVictor Perevertkin 452a97c6e0aSVictor Perevertkin static 453a97c6e0aSVictor Perevertkin NTSTATUS 454a97c6e0aSVictor Perevertkin PdoHandleQueryCompatibleId( 455a97c6e0aSVictor Perevertkin _In_ PDEVICE_OBJECT DeviceObject, 456a97c6e0aSVictor Perevertkin _Inout_ PIRP Irp) 457a97c6e0aSVictor Perevertkin { 458a97c6e0aSVictor Perevertkin PSCSI_PORT_LUN_EXTENSION PDODeviceExtension = DeviceObject->DeviceExtension; 459a97c6e0aSVictor Perevertkin CHAR Buffer[100] = {0}; 460a97c6e0aSVictor Perevertkin ULONG Length, Offset; 461a97c6e0aSVictor Perevertkin LPWSTR InstanceId; 462a97c6e0aSVictor Perevertkin LPCSTR DeviceType; 463a97c6e0aSVictor Perevertkin 464a97c6e0aSVictor Perevertkin DeviceType = GetDeviceType(&PDODeviceExtension->InquiryData); 465a97c6e0aSVictor Perevertkin 466a97c6e0aSVictor Perevertkin // format instance id 4675099f243SEric Kohl Length = sprintf(Buffer, "SCSI\\%s", DeviceType) + 1; 4685099f243SEric Kohl Length += sprintf(&Buffer[Length], "SCSI\\%s", "RAW") + 2; 469a97c6e0aSVictor Perevertkin 470a97c6e0aSVictor Perevertkin InstanceId = ExAllocatePoolWithTag(PagedPool, Length * sizeof(WCHAR), TAG_SCSIPORT); 471a97c6e0aSVictor Perevertkin if (!InstanceId) 472a97c6e0aSVictor Perevertkin { 473a97c6e0aSVictor Perevertkin Irp->IoStatus.Information = 0; 474a97c6e0aSVictor Perevertkin return STATUS_INSUFFICIENT_RESOURCES; 475a97c6e0aSVictor Perevertkin } 476a97c6e0aSVictor Perevertkin 477a97c6e0aSVictor Perevertkin ConvertToUnicodeString(Buffer, Length, 0, InstanceId, &Offset); 478a97c6e0aSVictor Perevertkin ConvertToUnicodeString(&Buffer[Offset], Length, Offset, InstanceId, &Offset); 479a97c6e0aSVictor Perevertkin 480a97c6e0aSVictor Perevertkin InstanceId[Offset] = UNICODE_NULL; 481a97c6e0aSVictor Perevertkin 482a97c6e0aSVictor Perevertkin DPRINT("PdoHandleQueryCompatibleId %S\n", InstanceId); 483a97c6e0aSVictor Perevertkin 484a97c6e0aSVictor Perevertkin Irp->IoStatus.Information = (ULONG_PTR)InstanceId; 485a97c6e0aSVictor Perevertkin return STATUS_SUCCESS; 486a97c6e0aSVictor Perevertkin } 487a97c6e0aSVictor Perevertkin 488a97c6e0aSVictor Perevertkin static 489a97c6e0aSVictor Perevertkin NTSTATUS 490a97c6e0aSVictor Perevertkin PdoHandleQueryInstanceId( 491a97c6e0aSVictor Perevertkin _In_ PDEVICE_OBJECT DeviceObject, 492a97c6e0aSVictor Perevertkin _Inout_ PIRP Irp) 493a97c6e0aSVictor Perevertkin { 494a97c6e0aSVictor Perevertkin PSCSI_PORT_LUN_EXTENSION lunExt = DeviceObject->DeviceExtension; 495a97c6e0aSVictor Perevertkin WCHAR Buffer[26]; 496a97c6e0aSVictor Perevertkin ULONG Length; 497a97c6e0aSVictor Perevertkin LPWSTR InstanceId; 498a97c6e0aSVictor Perevertkin 499a97c6e0aSVictor Perevertkin // use instance count and LUN 500a97c6e0aSVictor Perevertkin swprintf(Buffer, L"%x%x%x", lunExt->PathId, lunExt->TargetId, lunExt->Lun); 501a97c6e0aSVictor Perevertkin 502a97c6e0aSVictor Perevertkin Length = wcslen(Buffer) + 1; 503a97c6e0aSVictor Perevertkin 504a97c6e0aSVictor Perevertkin InstanceId = ExAllocatePoolWithTag(PagedPool, Length * sizeof(WCHAR), TAG_SCSIPORT); 505a97c6e0aSVictor Perevertkin if (!InstanceId) 506a97c6e0aSVictor Perevertkin { 507a97c6e0aSVictor Perevertkin Irp->IoStatus.Information = 0; 508a97c6e0aSVictor Perevertkin return STATUS_INSUFFICIENT_RESOURCES; 509a97c6e0aSVictor Perevertkin } 510a97c6e0aSVictor Perevertkin 511a97c6e0aSVictor Perevertkin wcscpy(InstanceId, Buffer); 512a97c6e0aSVictor Perevertkin 513a97c6e0aSVictor Perevertkin DPRINT("PdoHandleQueryInstanceId %S\n", InstanceId); 514a97c6e0aSVictor Perevertkin 515a97c6e0aSVictor Perevertkin Irp->IoStatus.Information = (ULONG_PTR)InstanceId; 516a97c6e0aSVictor Perevertkin return STATUS_SUCCESS; 517a97c6e0aSVictor Perevertkin } 518a97c6e0aSVictor Perevertkin 519a97c6e0aSVictor Perevertkin static 520a97c6e0aSVictor Perevertkin NTSTATUS 521a97c6e0aSVictor Perevertkin PdoHandleDeviceRelations( 522a97c6e0aSVictor Perevertkin _In_ PDEVICE_OBJECT DeviceObject, 523a97c6e0aSVictor Perevertkin _Inout_ PIRP Irp) 524a97c6e0aSVictor Perevertkin { 525a97c6e0aSVictor Perevertkin PDEVICE_RELATIONS deviceRelations; 526a97c6e0aSVictor Perevertkin PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp); 527a97c6e0aSVictor Perevertkin 528a97c6e0aSVictor Perevertkin // check if relation type is BusRelations 529a97c6e0aSVictor Perevertkin if (ioStack->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation) 530a97c6e0aSVictor Perevertkin { 531a97c6e0aSVictor Perevertkin // PDO handles only target device relation 532a97c6e0aSVictor Perevertkin return Irp->IoStatus.Status; 533a97c6e0aSVictor Perevertkin } 534a97c6e0aSVictor Perevertkin 535a97c6e0aSVictor Perevertkin deviceRelations = ExAllocatePoolWithTag(PagedPool, sizeof(DEVICE_RELATIONS), TAG_SCSIPORT); 536a97c6e0aSVictor Perevertkin if (!deviceRelations) 537a97c6e0aSVictor Perevertkin { 538a97c6e0aSVictor Perevertkin return STATUS_INSUFFICIENT_RESOURCES; 539a97c6e0aSVictor Perevertkin } 540a97c6e0aSVictor Perevertkin 541a97c6e0aSVictor Perevertkin // initialize device relations 542a97c6e0aSVictor Perevertkin deviceRelations->Count = 1; 543a97c6e0aSVictor Perevertkin deviceRelations->Objects[0] = DeviceObject; 544a97c6e0aSVictor Perevertkin ObReferenceObject(DeviceObject); 545a97c6e0aSVictor Perevertkin 546a97c6e0aSVictor Perevertkin Irp->IoStatus.Information = (ULONG_PTR)deviceRelations; 547a97c6e0aSVictor Perevertkin return STATUS_SUCCESS; 548a97c6e0aSVictor Perevertkin } 549a97c6e0aSVictor Perevertkin 550a97c6e0aSVictor Perevertkin NTSTATUS 551a97c6e0aSVictor Perevertkin PdoDispatchPnp( 552a97c6e0aSVictor Perevertkin _In_ PDEVICE_OBJECT DeviceObject, 553a97c6e0aSVictor Perevertkin _Inout_ PIRP Irp) 554a97c6e0aSVictor Perevertkin { 555a97c6e0aSVictor Perevertkin PIO_STACK_LOCATION ioStack = IoGetCurrentIrpStackLocation(Irp); 556a97c6e0aSVictor Perevertkin PSCSI_PORT_LUN_EXTENSION lunExt = DeviceObject->DeviceExtension; 557a97c6e0aSVictor Perevertkin NTSTATUS status; 558a97c6e0aSVictor Perevertkin 559a97c6e0aSVictor Perevertkin DPRINT("PDO PnP request %s\n", GetIRPMinorFunctionString(ioStack->MinorFunction)); 560a97c6e0aSVictor Perevertkin 561a97c6e0aSVictor Perevertkin ASSERT(!lunExt->Common.IsFDO); 562a97c6e0aSVictor Perevertkin 563a97c6e0aSVictor Perevertkin switch (ioStack->MinorFunction) 564a97c6e0aSVictor Perevertkin { 565a97c6e0aSVictor Perevertkin case IRP_MN_START_DEVICE: 566a97c6e0aSVictor Perevertkin { 567a97c6e0aSVictor Perevertkin RegistryInitLunKey(lunExt); 568a97c6e0aSVictor Perevertkin status = STATUS_SUCCESS; 569a97c6e0aSVictor Perevertkin break; 570a97c6e0aSVictor Perevertkin } 571a97c6e0aSVictor Perevertkin case IRP_MN_REMOVE_DEVICE: 572a97c6e0aSVictor Perevertkin case IRP_MN_QUERY_CAPABILITIES: 573a97c6e0aSVictor Perevertkin case IRP_MN_QUERY_REMOVE_DEVICE: 574a97c6e0aSVictor Perevertkin case IRP_MN_QUERY_STOP_DEVICE: 575a97c6e0aSVictor Perevertkin case IRP_MN_SURPRISE_REMOVAL: 576a97c6e0aSVictor Perevertkin { 577a97c6e0aSVictor Perevertkin status = STATUS_SUCCESS; 578a97c6e0aSVictor Perevertkin break; 579a97c6e0aSVictor Perevertkin } 580a97c6e0aSVictor Perevertkin case IRP_MN_QUERY_DEVICE_RELATIONS: 581a97c6e0aSVictor Perevertkin { 582a97c6e0aSVictor Perevertkin status = PdoHandleDeviceRelations(DeviceObject, Irp); 583a97c6e0aSVictor Perevertkin break; 584a97c6e0aSVictor Perevertkin } 585a97c6e0aSVictor Perevertkin case IRP_MN_QUERY_DEVICE_TEXT: 586a97c6e0aSVictor Perevertkin { 587a97c6e0aSVictor Perevertkin status = PdoHandleQueryDeviceText(DeviceObject, Irp); 588a97c6e0aSVictor Perevertkin break; 589a97c6e0aSVictor Perevertkin } 590a97c6e0aSVictor Perevertkin case IRP_MN_QUERY_ID: 591a97c6e0aSVictor Perevertkin { 592a97c6e0aSVictor Perevertkin DPRINT("IRP_MN_QUERY_ID IdType %s\n", 593a97c6e0aSVictor Perevertkin DbgGetDeviceIDString(ioStack->Parameters.QueryId.IdType)); 594a97c6e0aSVictor Perevertkin 595a97c6e0aSVictor Perevertkin if (ioStack->Parameters.QueryId.IdType == BusQueryDeviceID) 596a97c6e0aSVictor Perevertkin { 597a97c6e0aSVictor Perevertkin status = PdoHandleQueryDeviceId(DeviceObject, Irp); 598a97c6e0aSVictor Perevertkin break; 599a97c6e0aSVictor Perevertkin } 600a97c6e0aSVictor Perevertkin else if (ioStack->Parameters.QueryId.IdType == BusQueryHardwareIDs) 601a97c6e0aSVictor Perevertkin { 602a97c6e0aSVictor Perevertkin status = PdoHandleQueryHardwareId(DeviceObject, Irp); 603a97c6e0aSVictor Perevertkin break; 604a97c6e0aSVictor Perevertkin } 605a97c6e0aSVictor Perevertkin else if (ioStack->Parameters.QueryId.IdType == BusQueryInstanceID) 606a97c6e0aSVictor Perevertkin { 607a97c6e0aSVictor Perevertkin status = PdoHandleQueryInstanceId(DeviceObject, Irp); 608a97c6e0aSVictor Perevertkin break; 609a97c6e0aSVictor Perevertkin } 610a97c6e0aSVictor Perevertkin else if (ioStack->Parameters.QueryId.IdType == BusQueryCompatibleIDs) 611a97c6e0aSVictor Perevertkin { 612a97c6e0aSVictor Perevertkin status = PdoHandleQueryCompatibleId(DeviceObject, Irp); 613a97c6e0aSVictor Perevertkin break; 614a97c6e0aSVictor Perevertkin } 615a97c6e0aSVictor Perevertkin 616a97c6e0aSVictor Perevertkin // fallthrough 617a97c6e0aSVictor Perevertkin } 618a97c6e0aSVictor Perevertkin default: 619a97c6e0aSVictor Perevertkin { 620a97c6e0aSVictor Perevertkin // do nothing 621a97c6e0aSVictor Perevertkin status = Irp->IoStatus.Status; 622a97c6e0aSVictor Perevertkin } 623a97c6e0aSVictor Perevertkin } 624a97c6e0aSVictor Perevertkin 625a97c6e0aSVictor Perevertkin if (status != STATUS_PENDING) 626a97c6e0aSVictor Perevertkin { 627a97c6e0aSVictor Perevertkin Irp->IoStatus.Status = status; 628a97c6e0aSVictor Perevertkin IoCompleteRequest(Irp, IO_NO_INCREMENT); 629a97c6e0aSVictor Perevertkin } 630a97c6e0aSVictor Perevertkin 631a97c6e0aSVictor Perevertkin return status; 632a97c6e0aSVictor Perevertkin } 633