1c2c66affSColin Finck /* 2c2c66affSColin Finck * PROJECT: ReactOS Universal Serial Bus Bulk Storage Driver 3d17d15abSVictor Perevertkin * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4c2c66affSColin Finck * PURPOSE: USB block storage device driver. 5d17d15abSVictor Perevertkin * COPYRIGHT: 2005-2006 James Tabor 6d17d15abSVictor Perevertkin * 2011-2012 Michael Martin (michael.martin@reactos.org) 7d17d15abSVictor Perevertkin * 2011-2013 Johannes Anderwald (johannes.anderwald@reactos.org) 8f3fd12b9SVictor Perevertkin * 2017 Vadim Galyant 9f3fd12b9SVictor Perevertkin * 2019 Victor Perevertkin (victor.perevertkin@reactos.org) 10c2c66affSColin Finck */ 11c2c66affSColin Finck 12c2c66affSColin Finck #include "usbstor.h" 13c2c66affSColin Finck 14c2c66affSColin Finck #define NDEBUG 15c2c66affSColin Finck #include <debug.h> 16c2c66affSColin Finck 17d17d15abSVictor Perevertkin 18c2c66affSColin Finck LPCSTR 19c2c66affSColin Finck USBSTOR_GetDeviceType( 20f3fd12b9SVictor Perevertkin IN PINQUIRYDATA InquiryData, 21c2c66affSColin Finck IN UCHAR IsFloppy) 22c2c66affSColin Finck { 23c2c66affSColin Finck if (InquiryData->DeviceType == 0) 24c2c66affSColin Finck { 25c2c66affSColin Finck if (IsFloppy) 26c2c66affSColin Finck { 27c2c66affSColin Finck // floppy device 28c2c66affSColin Finck return "SFloppy"; 29c2c66affSColin Finck } 30c2c66affSColin Finck 31c2c66affSColin Finck // direct access device 32c2c66affSColin Finck return "Disk"; 33c2c66affSColin Finck } 34c2c66affSColin Finck 35c2c66affSColin Finck switch (InquiryData->DeviceType) 36c2c66affSColin Finck { 37c2c66affSColin Finck case 1: 38c2c66affSColin Finck { 39c2c66affSColin Finck // sequential device, i.e magnetic tape 40c2c66affSColin Finck return "Sequential"; 41c2c66affSColin Finck } 42c2c66affSColin Finck case 4: 43c2c66affSColin Finck { 44c2c66affSColin Finck // write once device 45c2c66affSColin Finck return "Worm"; 46c2c66affSColin Finck } 47c2c66affSColin Finck case 5: 48c2c66affSColin Finck { 49c2c66affSColin Finck // CDROM device 50c2c66affSColin Finck return "CdRom"; 51c2c66affSColin Finck } 52c2c66affSColin Finck case 7: 53c2c66affSColin Finck { 54c2c66affSColin Finck // optical memory device 55c2c66affSColin Finck return "Optical"; 56c2c66affSColin Finck } 57c2c66affSColin Finck case 8: 58c2c66affSColin Finck { 59c2c66affSColin Finck // medium change device 60c2c66affSColin Finck return "Changer"; 61c2c66affSColin Finck } 62c2c66affSColin Finck default: 63c2c66affSColin Finck { 64c2c66affSColin Finck // other device 65c2c66affSColin Finck return "Other"; 66c2c66affSColin Finck } 67c2c66affSColin Finck } 68c2c66affSColin Finck } 69c2c66affSColin Finck 70c2c66affSColin Finck LPCSTR 71c2c66affSColin Finck USBSTOR_GetGenericType( 72f3fd12b9SVictor Perevertkin IN PINQUIRYDATA InquiryData, 73c2c66affSColin Finck IN UCHAR IsFloppy) 74c2c66affSColin Finck { 75c2c66affSColin Finck if (InquiryData->DeviceType == 0) 76c2c66affSColin Finck { 77c2c66affSColin Finck if (IsFloppy) 78c2c66affSColin Finck { 79c2c66affSColin Finck // floppy device 80c2c66affSColin Finck return "GenSFloppy"; 81c2c66affSColin Finck } 82c2c66affSColin Finck 83c2c66affSColin Finck // direct access device 84c2c66affSColin Finck return "GenDisk"; 85c2c66affSColin Finck } 86c2c66affSColin Finck 87c2c66affSColin Finck switch (InquiryData->DeviceType) 88c2c66affSColin Finck { 89c2c66affSColin Finck case 1: 90c2c66affSColin Finck { 91c2c66affSColin Finck // sequential device, i.e magnetic tape 92c2c66affSColin Finck return "GenSequential"; 93c2c66affSColin Finck } 94c2c66affSColin Finck case 4: 95c2c66affSColin Finck { 96c2c66affSColin Finck // write once device 97c2c66affSColin Finck return "GenWorm"; 98c2c66affSColin Finck } 99c2c66affSColin Finck case 5: 100c2c66affSColin Finck { 101c2c66affSColin Finck // CDROM device 102c2c66affSColin Finck return "GenCdRom"; 103c2c66affSColin Finck } 104c2c66affSColin Finck case 7: 105c2c66affSColin Finck { 106c2c66affSColin Finck // optical memory device 107c2c66affSColin Finck return "GenOptical"; 108c2c66affSColin Finck } 109c2c66affSColin Finck case 8: 110c2c66affSColin Finck { 111c2c66affSColin Finck // medium change device 112c2c66affSColin Finck return "GenChanger"; 113c2c66affSColin Finck } 114c2c66affSColin Finck default: 115c2c66affSColin Finck { 116c2c66affSColin Finck // other device 117c2c66affSColin Finck return "UsbstorOther"; 118c2c66affSColin Finck } 119c2c66affSColin Finck } 120c2c66affSColin Finck } 121c2c66affSColin Finck 122*126abaf8SVictor Perevertkin static 123c2c66affSColin Finck ULONG 124c2c66affSColin Finck CopyField( 125c2c66affSColin Finck IN PUCHAR Name, 126c2c66affSColin Finck IN PCHAR Buffer, 127c2c66affSColin Finck IN ULONG MaxLength) 128c2c66affSColin Finck { 129c2c66affSColin Finck ULONG Index; 130c2c66affSColin Finck 131c2c66affSColin Finck for (Index = 0; Index < MaxLength; Index++) 132c2c66affSColin Finck { 133c2c66affSColin Finck if (Name[Index] <= ' ' || Name[Index] >= 0x7F /* last printable ascii character */ || Name[Index] == ',') 134c2c66affSColin Finck { 135c2c66affSColin Finck // convert to underscore 136c2c66affSColin Finck Buffer[Index] = '_'; 137c2c66affSColin Finck } 138c2c66affSColin Finck else 139c2c66affSColin Finck { 140c2c66affSColin Finck // just copy character 141c2c66affSColin Finck Buffer[Index] = Name[Index]; 142c2c66affSColin Finck } 143c2c66affSColin Finck } 144c2c66affSColin Finck 145c2c66affSColin Finck return MaxLength; 146c2c66affSColin Finck } 147c2c66affSColin Finck 148*126abaf8SVictor Perevertkin static 149*126abaf8SVictor Perevertkin ULONG 150*126abaf8SVictor Perevertkin CopyFieldTruncate( 151*126abaf8SVictor Perevertkin IN PUCHAR Name, 152*126abaf8SVictor Perevertkin IN PCHAR Buffer, 153*126abaf8SVictor Perevertkin IN ULONG MaxLength) 154*126abaf8SVictor Perevertkin { 155*126abaf8SVictor Perevertkin ULONG Index; 156*126abaf8SVictor Perevertkin 157*126abaf8SVictor Perevertkin for (Index = 0; Index < MaxLength; Index++) 158*126abaf8SVictor Perevertkin { 159*126abaf8SVictor Perevertkin if (Name[Index] == '\0') 160*126abaf8SVictor Perevertkin { 161*126abaf8SVictor Perevertkin break; 162*126abaf8SVictor Perevertkin } 163*126abaf8SVictor Perevertkin else if (Name[Index] <= ' ' || Name[Index] >= 0x7F /* last printable ascii character */ || Name[Index] == ',') 164*126abaf8SVictor Perevertkin { 165*126abaf8SVictor Perevertkin // convert to underscore 166*126abaf8SVictor Perevertkin Buffer[Index] = ' '; 167*126abaf8SVictor Perevertkin } 168*126abaf8SVictor Perevertkin else 169*126abaf8SVictor Perevertkin { 170*126abaf8SVictor Perevertkin // just copy character 171*126abaf8SVictor Perevertkin Buffer[Index] = Name[Index]; 172*126abaf8SVictor Perevertkin } 173*126abaf8SVictor Perevertkin } 174*126abaf8SVictor Perevertkin 175*126abaf8SVictor Perevertkin return Index; 176*126abaf8SVictor Perevertkin } 177*126abaf8SVictor Perevertkin 178c2c66affSColin Finck NTSTATUS 179c2c66affSColin Finck USBSTOR_PdoHandleQueryDeviceText( 180c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject, 181c2c66affSColin Finck IN PIRP Irp) 182c2c66affSColin Finck { 183*126abaf8SVictor Perevertkin PPDO_DEVICE_EXTENSION DeviceExtension; 184c2c66affSColin Finck PIO_STACK_LOCATION IoStack; 185*126abaf8SVictor Perevertkin CHAR LocalBuffer[26]; 186*126abaf8SVictor Perevertkin UINT32 Offset = 0; 187*126abaf8SVictor Perevertkin PINQUIRYDATA InquiryData; 188*126abaf8SVictor Perevertkin ANSI_STRING AnsiString; 189*126abaf8SVictor Perevertkin UNICODE_STRING DeviceDescription; 190c2c66affSColin Finck 191c2c66affSColin Finck IoStack = IoGetCurrentIrpStackLocation(Irp); 192c2c66affSColin Finck 193*126abaf8SVictor Perevertkin DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 194*126abaf8SVictor Perevertkin ASSERT(DeviceExtension->InquiryData); 195*126abaf8SVictor Perevertkin InquiryData = DeviceExtension->InquiryData; 196c2c66affSColin Finck 197*126abaf8SVictor Perevertkin switch (IoStack->Parameters.QueryDeviceText.DeviceTextType) 198*126abaf8SVictor Perevertkin { 199*126abaf8SVictor Perevertkin case DeviceTextDescription: 200*126abaf8SVictor Perevertkin case DeviceTextLocationInformation: 201*126abaf8SVictor Perevertkin { 202*126abaf8SVictor Perevertkin DPRINT("USBSTOR_PdoHandleQueryDeviceText\n"); 203*126abaf8SVictor Perevertkin 204*126abaf8SVictor Perevertkin Offset += CopyFieldTruncate(InquiryData->VendorId, &LocalBuffer[Offset], sizeof(InquiryData->VendorId)); 205*126abaf8SVictor Perevertkin LocalBuffer[Offset++] = ' '; 206*126abaf8SVictor Perevertkin Offset += CopyFieldTruncate(InquiryData->ProductId, &LocalBuffer[Offset], sizeof(InquiryData->ProductId)); 207*126abaf8SVictor Perevertkin LocalBuffer[Offset++] = '\0'; 208*126abaf8SVictor Perevertkin 209*126abaf8SVictor Perevertkin RtlInitAnsiString(&AnsiString, (PCSZ)&LocalBuffer); 210*126abaf8SVictor Perevertkin 211*126abaf8SVictor Perevertkin DeviceDescription.Length = 0; 212*126abaf8SVictor Perevertkin DeviceDescription.MaximumLength = (USHORT)(Offset * sizeof(WCHAR)); 213*126abaf8SVictor Perevertkin DeviceDescription.Buffer = (LPWSTR)AllocateItem(PagedPool, DeviceDescription.MaximumLength); 214*126abaf8SVictor Perevertkin if (!DeviceDescription.Buffer) 215c2c66affSColin Finck { 216c2c66affSColin Finck Irp->IoStatus.Information = 0; 217c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES; 218c2c66affSColin Finck } 219c2c66affSColin Finck 220*126abaf8SVictor Perevertkin RtlAnsiStringToUnicodeString(&DeviceDescription, &AnsiString, FALSE); 221c2c66affSColin Finck 222*126abaf8SVictor Perevertkin Irp->IoStatus.Information = (ULONG_PTR)DeviceDescription.Buffer; 223c2c66affSColin Finck return STATUS_SUCCESS; 224c2c66affSColin Finck } 225*126abaf8SVictor Perevertkin default: 226c2c66affSColin Finck { 227c2c66affSColin Finck Irp->IoStatus.Information = 0; 228*126abaf8SVictor Perevertkin return Irp->IoStatus.Status; 229c2c66affSColin Finck } 230c2c66affSColin Finck } 231c2c66affSColin Finck } 232c2c66affSColin Finck 233c2c66affSColin Finck NTSTATUS 234c2c66affSColin Finck USBSTOR_PdoHandleQueryDeviceId( 235c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject, 236c2c66affSColin Finck IN PIRP Irp) 237c2c66affSColin Finck { 238c2c66affSColin Finck PPDO_DEVICE_EXTENSION DeviceExtension; 239c2c66affSColin Finck NTSTATUS Status; 240d17d15abSVictor Perevertkin CHAR Buffer[100] = {0}; 241c2c66affSColin Finck LPCSTR DeviceType; 242c2c66affSColin Finck ULONG Offset = 0; 243f3fd12b9SVictor Perevertkin PINQUIRYDATA InquiryData; 244c2c66affSColin Finck ANSI_STRING AnsiString; 245c2c66affSColin Finck UNICODE_STRING DeviceId; 246c2c66affSColin Finck 247c2c66affSColin Finck DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 248c2c66affSColin Finck ASSERT(DeviceExtension->InquiryData); 249f3fd12b9SVictor Perevertkin InquiryData = DeviceExtension->InquiryData; 250c2c66affSColin Finck 251c2c66affSColin Finck DeviceType = USBSTOR_GetDeviceType(InquiryData, DeviceExtension->IsFloppy); 252c2c66affSColin Finck 253c2c66affSColin Finck // lets create device string 254c2c66affSColin Finck Offset = sprintf(&Buffer[Offset], "USBSTOR\\"); 255c2c66affSColin Finck Offset += sprintf(&Buffer[Offset], DeviceType); 256c2c66affSColin Finck Offset += sprintf(&Buffer[Offset], "&Ven_"); 257f3fd12b9SVictor Perevertkin Offset += CopyField(InquiryData->VendorId, &Buffer[Offset], 8); 258c2c66affSColin Finck Offset += sprintf(&Buffer[Offset], "&Prod_"); 259f3fd12b9SVictor Perevertkin Offset += CopyField(InquiryData->ProductId, &Buffer[Offset], 16); 260c2c66affSColin Finck Offset += sprintf(&Buffer[Offset], "&Rev_"); 261f3fd12b9SVictor Perevertkin Offset += CopyField(InquiryData->ProductRevisionLevel, &Buffer[Offset], 4); 262c2c66affSColin Finck 263c2c66affSColin Finck RtlInitAnsiString(&AnsiString, (PCSZ)Buffer); 264c2c66affSColin Finck 265c2c66affSColin Finck // allocate DeviceId string 266c2c66affSColin Finck DeviceId.Length = 0; 267f3fd12b9SVictor Perevertkin DeviceId.MaximumLength = (USHORT)((strlen((PCHAR)Buffer) + 1) * sizeof(WCHAR)); 268c2c66affSColin Finck DeviceId.Buffer = (LPWSTR)AllocateItem(PagedPool, DeviceId.MaximumLength); 269c2c66affSColin Finck if (!DeviceId.Buffer) 270c2c66affSColin Finck { 271c2c66affSColin Finck Irp->IoStatus.Information = 0; 272c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES; 273c2c66affSColin Finck } 274c2c66affSColin Finck 275c2c66affSColin Finck Status = RtlAnsiStringToUnicodeString(&DeviceId, &AnsiString, FALSE); 276c2c66affSColin Finck 277c2c66affSColin Finck if (NT_SUCCESS(Status)) 278c2c66affSColin Finck { 279c2c66affSColin Finck Irp->IoStatus.Information = (ULONG_PTR)DeviceId.Buffer; 280c2c66affSColin Finck } 281c2c66affSColin Finck 282c2c66affSColin Finck DPRINT("DeviceId %wZ Status %x\n", &DeviceId, Status); 283c2c66affSColin Finck 284c2c66affSColin Finck return Status; 285c2c66affSColin Finck } 286c2c66affSColin Finck 287c2c66affSColin Finck VOID 288c2c66affSColin Finck USBSTOR_ConvertToUnicodeString( 289c2c66affSColin Finck IN CHAR * Buffer, 290c2c66affSColin Finck IN ULONG ResultBufferLength, 291c2c66affSColin Finck IN ULONG ResultBufferOffset, 292c2c66affSColin Finck OUT LPWSTR ResultBuffer, 293c2c66affSColin Finck OUT PULONG NewResultBufferOffset) 294c2c66affSColin Finck { 295c2c66affSColin Finck UNICODE_STRING DeviceString; 296c2c66affSColin Finck ANSI_STRING AnsiString; 297c2c66affSColin Finck NTSTATUS Status; 298c2c66affSColin Finck 299c2c66affSColin Finck ASSERT(ResultBufferLength); 300c2c66affSColin Finck ASSERT(ResultBufferLength > ResultBufferOffset); 301c2c66affSColin Finck 302c2c66affSColin Finck DPRINT("ResultBufferOffset %lu ResultBufferLength %lu Buffer %s Length %lu\n", ResultBufferOffset, ResultBufferLength, Buffer, strlen(Buffer)); 303c2c66affSColin Finck 304c2c66affSColin Finck // construct destination string 305c2c66affSColin Finck DeviceString.Buffer = &ResultBuffer[ResultBufferOffset]; 306c2c66affSColin Finck DeviceString.Length = 0; 307c2c66affSColin Finck DeviceString.MaximumLength = (ResultBufferLength - ResultBufferOffset) * sizeof(WCHAR); 308c2c66affSColin Finck 309c2c66affSColin Finck // initialize source string 310c2c66affSColin Finck RtlInitAnsiString(&AnsiString, Buffer); 311c2c66affSColin Finck 312c2c66affSColin Finck Status = RtlAnsiStringToUnicodeString(&DeviceString, &AnsiString, FALSE); 313c2c66affSColin Finck ASSERT(Status == STATUS_SUCCESS); 314c2c66affSColin Finck 315c2c66affSColin Finck // subtract consumed bytes 316c2c66affSColin Finck ResultBufferLength -= (DeviceString.Length + sizeof(WCHAR)) / sizeof(WCHAR); 317c2c66affSColin Finck ResultBufferOffset += (DeviceString.Length + sizeof(WCHAR)) / sizeof(WCHAR); 318c2c66affSColin Finck 319c2c66affSColin Finck *NewResultBufferOffset = ResultBufferOffset; 320c2c66affSColin Finck } 321c2c66affSColin Finck 322c2c66affSColin Finck NTSTATUS 323c2c66affSColin Finck USBSTOR_PdoHandleQueryHardwareId( 324c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject, 325c2c66affSColin Finck IN OUT PIRP Irp) 326c2c66affSColin Finck { 327c2c66affSColin Finck PPDO_DEVICE_EXTENSION PDODeviceExtension; 328c2c66affSColin Finck PFDO_DEVICE_EXTENSION FDODeviceExtension; 329c2c66affSColin Finck LPCSTR GenericType, DeviceType; 330c2c66affSColin Finck LPWSTR Buffer; 331c2c66affSColin Finck CHAR Id1[50], Id2[50], Id3[50], Id4[50], Id5[50], Id6[50]; 332c2c66affSColin Finck ULONG Id1Length, Id2Length, Id3Length, Id4Length, Id5Length,Id6Length; 333c2c66affSColin Finck ULONG Offset, TotalLength, Length; 334f3fd12b9SVictor Perevertkin PINQUIRYDATA InquiryData; 335c2c66affSColin Finck 336c2c66affSColin Finck PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 337c2c66affSColin Finck FDODeviceExtension = (PFDO_DEVICE_EXTENSION)PDODeviceExtension->LowerDeviceObject->DeviceExtension; 338c2c66affSColin Finck ASSERT(FDODeviceExtension->DeviceDescriptor); 339f3fd12b9SVictor Perevertkin InquiryData = PDODeviceExtension->InquiryData; 340c2c66affSColin Finck 341c2c66affSColin Finck DeviceType = USBSTOR_GetDeviceType(InquiryData, PDODeviceExtension->IsFloppy); 342c2c66affSColin Finck GenericType = USBSTOR_GetGenericType(InquiryData, PDODeviceExtension->IsFloppy); 343c2c66affSColin Finck 344c2c66affSColin Finck ASSERT(GenericType); 345c2c66affSColin Finck 346c2c66affSColin Finck // generate id 1 347f3fd12b9SVictor Perevertkin // USBSTOR\SCSIType_VendorId(8)_ProductId(16)_Revision(4) 348c2c66affSColin Finck RtlZeroMemory(Id1, sizeof(Id1)); 349c2c66affSColin Finck Offset = 0; 350c2c66affSColin Finck Offset = sprintf(&Id1[Offset], "USBSTOR\\"); 351c2c66affSColin Finck Offset += sprintf(&Id1[Offset], DeviceType); 352f3fd12b9SVictor Perevertkin Offset += CopyField(InquiryData->VendorId, &Id1[Offset], 8); 353f3fd12b9SVictor Perevertkin Offset += CopyField(InquiryData->ProductId, &Id1[Offset], 16); 354f3fd12b9SVictor Perevertkin Offset += CopyField(InquiryData->ProductRevisionLevel, &Id1[Offset], 4); 355c2c66affSColin Finck Id1Length = strlen(Id1) + 1; 356c2c66affSColin Finck DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId1 %s\n", Id1); 357c2c66affSColin Finck 358c2c66affSColin Finck // generate id 2 359f3fd12b9SVictor Perevertkin // USBSTOR\SCSIType_VendorId(8)_ProductId(16) 360c2c66affSColin Finck RtlZeroMemory(Id2, sizeof(Id2)); 361c2c66affSColin Finck Offset = 0; 362c2c66affSColin Finck Offset = sprintf(&Id2[Offset], "USBSTOR\\"); 363c2c66affSColin Finck Offset += sprintf(&Id2[Offset], DeviceType); 364f3fd12b9SVictor Perevertkin Offset += CopyField(InquiryData->VendorId, &Id2[Offset], 8); 365f3fd12b9SVictor Perevertkin Offset += CopyField(InquiryData->ProductId, &Id2[Offset], 16); 366c2c66affSColin Finck Id2Length = strlen(Id2) + 1; 367c2c66affSColin Finck DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId2 %s\n", Id2); 368c2c66affSColin Finck 369c2c66affSColin Finck // generate id 3 370f3fd12b9SVictor Perevertkin // USBSTOR\SCSIType_VendorId(8) 371c2c66affSColin Finck RtlZeroMemory(Id3, sizeof(Id3)); 372c2c66affSColin Finck Offset = 0; 373c2c66affSColin Finck Offset = sprintf(&Id3[Offset], "USBSTOR\\"); 374c2c66affSColin Finck Offset += sprintf(&Id3[Offset], DeviceType); 375f3fd12b9SVictor Perevertkin Offset += CopyField(InquiryData->VendorId, &Id3[Offset], 8); 376c2c66affSColin Finck Id3Length = strlen(Id3) + 1; 377c2c66affSColin Finck DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId3 %s\n", Id3); 378c2c66affSColin Finck 379c2c66affSColin Finck // generate id 4 380f3fd12b9SVictor Perevertkin // USBSTOR\SCSIType_VendorId(8)_ProductId(16)_Revision(1) 381c2c66affSColin Finck RtlZeroMemory(Id4, sizeof(Id4)); 382c2c66affSColin Finck Offset = 0; 383c2c66affSColin Finck Offset = sprintf(&Id4[Offset], "USBSTOR\\"); 384c2c66affSColin Finck Offset += sprintf(&Id4[Offset], DeviceType); 385f3fd12b9SVictor Perevertkin Offset += CopyField(InquiryData->VendorId, &Id4[Offset], 8); 386f3fd12b9SVictor Perevertkin Offset += CopyField(InquiryData->ProductId, &Id4[Offset], 16); 387f3fd12b9SVictor Perevertkin Offset += CopyField(InquiryData->ProductRevisionLevel, &Id4[Offset], 1); 388c2c66affSColin Finck Id4Length = strlen(Id4) + 1; 389c2c66affSColin Finck DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId4 %s\n", Id4); 390c2c66affSColin Finck 391c2c66affSColin Finck // generate id 5 392c2c66affSColin Finck // USBSTOR\SCSIType 393c2c66affSColin Finck RtlZeroMemory(Id5, sizeof(Id5)); 394c2c66affSColin Finck Offset = 0; 395c2c66affSColin Finck Offset = sprintf(&Id5[Offset], "USBSTOR\\"); 396c2c66affSColin Finck Offset += sprintf(&Id5[Offset], GenericType); 397c2c66affSColin Finck Id5Length = strlen(Id5) + 1; 398c2c66affSColin Finck DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId5 %s\n", Id5); 399c2c66affSColin Finck 400c2c66affSColin Finck // generate id 6 401c2c66affSColin Finck // SCSIType 402c2c66affSColin Finck RtlZeroMemory(Id6, sizeof(Id6)); 403c2c66affSColin Finck Offset = 0; 404c2c66affSColin Finck Offset = sprintf(&Id6[Offset], GenericType); 405c2c66affSColin Finck Id6Length = strlen(Id6) + 1; 406c2c66affSColin Finck DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId6 %s\n", Id6); 407c2c66affSColin Finck 408c2c66affSColin Finck TotalLength = Id1Length + Id2Length + Id3Length + Id4Length + Id5Length + Id6Length + 1; 409c2c66affSColin Finck 410c2c66affSColin Finck Buffer = (LPWSTR)AllocateItem(PagedPool, TotalLength * sizeof(WCHAR)); 411c2c66affSColin Finck if (!Buffer) 412c2c66affSColin Finck { 413c2c66affSColin Finck Irp->IoStatus.Information = 0; 414c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES; 415c2c66affSColin Finck } 416c2c66affSColin Finck 417c2c66affSColin Finck // reset offset 418c2c66affSColin Finck Offset = 0; 419c2c66affSColin Finck Length = TotalLength; 420c2c66affSColin Finck 421c2c66affSColin Finck USBSTOR_ConvertToUnicodeString(Id1, Length, Offset, Buffer, &Offset); 422c2c66affSColin Finck USBSTOR_ConvertToUnicodeString(Id2, Length, Offset, Buffer, &Offset); 423c2c66affSColin Finck USBSTOR_ConvertToUnicodeString(Id3, Length, Offset, Buffer, &Offset); 424c2c66affSColin Finck USBSTOR_ConvertToUnicodeString(Id4, Length, Offset, Buffer, &Offset); 425c2c66affSColin Finck USBSTOR_ConvertToUnicodeString(Id5, Length, Offset, Buffer, &Offset); 426c2c66affSColin Finck USBSTOR_ConvertToUnicodeString(Id6, Length, Offset, Buffer, &Offset); 427c2c66affSColin Finck 428c2c66affSColin Finck ASSERT(Offset + 1 == Length); 429c2c66affSColin Finck 430c2c66affSColin Finck Irp->IoStatus.Information = (ULONG_PTR)Buffer; 431c2c66affSColin Finck return STATUS_SUCCESS; 432c2c66affSColin Finck } 433c2c66affSColin Finck 434c2c66affSColin Finck NTSTATUS 435c2c66affSColin Finck USBSTOR_PdoHandleQueryCompatibleId( 436c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject, 437c2c66affSColin Finck IN OUT PIRP Irp) 438c2c66affSColin Finck { 439c2c66affSColin Finck PPDO_DEVICE_EXTENSION PDODeviceExtension; 440c2c66affSColin Finck PFDO_DEVICE_EXTENSION FDODeviceExtension; 441d17d15abSVictor Perevertkin CHAR Buffer[100] = {0}; 442c2c66affSColin Finck ULONG Length, Offset; 443c2c66affSColin Finck LPWSTR InstanceId; 444c2c66affSColin Finck LPCSTR DeviceType; 445c2c66affSColin Finck 446c2c66affSColin Finck PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 447c2c66affSColin Finck FDODeviceExtension = (PFDO_DEVICE_EXTENSION)PDODeviceExtension->LowerDeviceObject->DeviceExtension; 448c2c66affSColin Finck ASSERT(FDODeviceExtension->DeviceDescriptor); 449f3fd12b9SVictor Perevertkin DeviceType = USBSTOR_GetDeviceType(PDODeviceExtension->InquiryData, PDODeviceExtension->IsFloppy); 450c2c66affSColin Finck 451c2c66affSColin Finck // format instance id 452c2c66affSColin Finck Length = sprintf(Buffer, "USBSTOR\\%s", DeviceType) + 1; 453c2c66affSColin Finck Length += sprintf(&Buffer[Length], "USBSTOR\\%s", "RAW") + 2; 454c2c66affSColin Finck 455c2c66affSColin Finck InstanceId = (LPWSTR)AllocateItem(PagedPool, Length * sizeof(WCHAR)); 456c2c66affSColin Finck if (!InstanceId) 457c2c66affSColin Finck { 458c2c66affSColin Finck Irp->IoStatus.Information = 0; 459c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES; 460c2c66affSColin Finck } 461c2c66affSColin Finck 462c2c66affSColin Finck USBSTOR_ConvertToUnicodeString(Buffer, Length, 0, InstanceId, &Offset); 463c2c66affSColin Finck USBSTOR_ConvertToUnicodeString(&Buffer[Offset], Length, Offset, InstanceId, &Offset); 464c2c66affSColin Finck 465c2c66affSColin Finck DPRINT("USBSTOR_PdoHandleQueryCompatibleId %S\n", InstanceId); 466c2c66affSColin Finck 467c2c66affSColin Finck Irp->IoStatus.Information = (ULONG_PTR)InstanceId; 468c2c66affSColin Finck return STATUS_SUCCESS; 469c2c66affSColin Finck } 470c2c66affSColin Finck 471c2c66affSColin Finck NTSTATUS 472c2c66affSColin Finck USBSTOR_PdoHandleQueryInstanceId( 473c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject, 474c2c66affSColin Finck IN OUT PIRP Irp) 475c2c66affSColin Finck { 476c2c66affSColin Finck PPDO_DEVICE_EXTENSION PDODeviceExtension; 477c2c66affSColin Finck PFDO_DEVICE_EXTENSION FDODeviceExtension; 478c2c66affSColin Finck WCHAR Buffer[100]; 479c2c66affSColin Finck ULONG Length; 480c2c66affSColin Finck LPWSTR InstanceId; 481c2c66affSColin Finck 482c2c66affSColin Finck PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 483c2c66affSColin Finck FDODeviceExtension = (PFDO_DEVICE_EXTENSION)PDODeviceExtension->LowerDeviceObject->DeviceExtension; 484c2c66affSColin Finck 485c2c66affSColin Finck // format instance id 486c2c66affSColin Finck if (FDODeviceExtension->SerialNumber) 487c2c66affSColin Finck { 488c2c66affSColin Finck // using serial number from device 489c2c66affSColin Finck swprintf(Buffer, L"%s&%c", FDODeviceExtension->SerialNumber->bString, PDODeviceExtension->LUN); 490c2c66affSColin Finck } 491c2c66affSColin Finck else 492c2c66affSColin Finck { 493c2c66affSColin Finck // use instance count and LUN 494c2c66affSColin Finck swprintf(Buffer, L"%04lu&%c", FDODeviceExtension->InstanceCount, PDODeviceExtension->LUN); 495c2c66affSColin Finck } 496c2c66affSColin Finck 497c2c66affSColin Finck Length = wcslen(Buffer) + 1; 498c2c66affSColin Finck 499c2c66affSColin Finck InstanceId = (LPWSTR)AllocateItem(PagedPool, Length * sizeof(WCHAR)); 500c2c66affSColin Finck if (!InstanceId) 501c2c66affSColin Finck { 502c2c66affSColin Finck Irp->IoStatus.Information = 0; 503c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES; 504c2c66affSColin Finck } 505c2c66affSColin Finck 506c2c66affSColin Finck wcscpy(InstanceId, Buffer); 507c2c66affSColin Finck 508c2c66affSColin Finck DPRINT("USBSTOR_PdoHandleQueryInstanceId %S\n", InstanceId); 509c2c66affSColin Finck 510c2c66affSColin Finck Irp->IoStatus.Information = (ULONG_PTR)InstanceId; 511c2c66affSColin Finck return STATUS_SUCCESS; 512c2c66affSColin Finck } 513c2c66affSColin Finck 514c2c66affSColin Finck NTSTATUS 515c2c66affSColin Finck USBSTOR_PdoHandleDeviceRelations( 516c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject, 517c2c66affSColin Finck IN OUT PIRP Irp) 518c2c66affSColin Finck { 519c2c66affSColin Finck PDEVICE_RELATIONS DeviceRelations; 520c2c66affSColin Finck PIO_STACK_LOCATION IoStack; 521c2c66affSColin Finck 522c2c66affSColin Finck DPRINT("USBSTOR_PdoHandleDeviceRelations\n"); 523c2c66affSColin Finck 524c2c66affSColin Finck IoStack = IoGetCurrentIrpStackLocation(Irp); 525c2c66affSColin Finck 526c2c66affSColin Finck // check if relation type is BusRelations 527c2c66affSColin Finck if (IoStack->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation) 528c2c66affSColin Finck { 529c2c66affSColin Finck // PDO handles only target device relation 530c2c66affSColin Finck return Irp->IoStatus.Status; 531c2c66affSColin Finck } 532c2c66affSColin Finck 533c2c66affSColin Finck DeviceRelations = (PDEVICE_RELATIONS)AllocateItem(PagedPool, sizeof(DEVICE_RELATIONS)); 534c2c66affSColin Finck if (!DeviceRelations) 535c2c66affSColin Finck { 536c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES; 537c2c66affSColin Finck } 538c2c66affSColin Finck 539c2c66affSColin Finck // initialize device relations 540c2c66affSColin Finck DeviceRelations->Count = 1; 541c2c66affSColin Finck DeviceRelations->Objects[0] = DeviceObject; 542c2c66affSColin Finck ObReferenceObject(DeviceObject); 543c2c66affSColin Finck 544c2c66affSColin Finck Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations; 545c2c66affSColin Finck return STATUS_SUCCESS; 546c2c66affSColin Finck } 547c2c66affSColin Finck 548c2c66affSColin Finck NTSTATUS 549c2c66affSColin Finck USBSTOR_PdoHandlePnp( 550c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject, 551c2c66affSColin Finck IN OUT PIRP Irp) 552c2c66affSColin Finck { 553c2c66affSColin Finck PIO_STACK_LOCATION IoStack; 554c2c66affSColin Finck PPDO_DEVICE_EXTENSION DeviceExtension; 555c2c66affSColin Finck NTSTATUS Status; 556c2c66affSColin Finck PDEVICE_CAPABILITIES Caps; 557c2c66affSColin Finck ULONG bDelete; 558c2c66affSColin Finck 559c2c66affSColin Finck IoStack = IoGetCurrentIrpStackLocation(Irp); 560c2c66affSColin Finck DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 561c2c66affSColin Finck ASSERT(DeviceExtension->Common.IsFDO == FALSE); 562c2c66affSColin Finck 563c2c66affSColin Finck switch(IoStack->MinorFunction) 564c2c66affSColin Finck { 565c2c66affSColin Finck case IRP_MN_QUERY_DEVICE_RELATIONS: 566c2c66affSColin Finck { 567c2c66affSColin Finck Status = USBSTOR_PdoHandleDeviceRelations(DeviceObject, Irp); 568c2c66affSColin Finck break; 569c2c66affSColin Finck } 570c2c66affSColin Finck case IRP_MN_QUERY_DEVICE_TEXT: 571c2c66affSColin Finck { 572c2c66affSColin Finck Status = USBSTOR_PdoHandleQueryDeviceText(DeviceObject, Irp); 573c2c66affSColin Finck break; 574c2c66affSColin Finck } 575c2c66affSColin Finck case IRP_MN_QUERY_ID: 576c2c66affSColin Finck { 577c2c66affSColin Finck if (IoStack->Parameters.QueryId.IdType == BusQueryDeviceID) 578c2c66affSColin Finck { 579c2c66affSColin Finck Status = USBSTOR_PdoHandleQueryDeviceId(DeviceObject, Irp); 580c2c66affSColin Finck break; 581c2c66affSColin Finck } 582c2c66affSColin Finck else if (IoStack->Parameters.QueryId.IdType == BusQueryHardwareIDs) 583c2c66affSColin Finck { 584c2c66affSColin Finck Status = USBSTOR_PdoHandleQueryHardwareId(DeviceObject, Irp); 585c2c66affSColin Finck break; 586c2c66affSColin Finck } 587c2c66affSColin Finck else if (IoStack->Parameters.QueryId.IdType == BusQueryInstanceID) 588c2c66affSColin Finck { 589c2c66affSColin Finck Status = USBSTOR_PdoHandleQueryInstanceId(DeviceObject, Irp); 590c2c66affSColin Finck break; 591c2c66affSColin Finck } 592c2c66affSColin Finck else if (IoStack->Parameters.QueryId.IdType == BusQueryCompatibleIDs) 593c2c66affSColin Finck { 594c2c66affSColin Finck Status = USBSTOR_PdoHandleQueryCompatibleId(DeviceObject, Irp); 595c2c66affSColin Finck break; 596c2c66affSColin Finck } 597c2c66affSColin Finck 598c2c66affSColin Finck DPRINT1("USBSTOR_PdoHandlePnp: IRP_MN_QUERY_ID IdType %x unimplemented\n", IoStack->Parameters.QueryId.IdType); 599c2c66affSColin Finck Status = STATUS_NOT_SUPPORTED; 600c2c66affSColin Finck Irp->IoStatus.Information = 0; 601c2c66affSColin Finck break; 602c2c66affSColin Finck } 603c2c66affSColin Finck case IRP_MN_REMOVE_DEVICE: 604c2c66affSColin Finck { 605c2c66affSColin Finck DPRINT("IRP_MN_REMOVE_DEVICE\n"); 606c2c66affSColin Finck 607c2c66affSColin Finck if(*DeviceExtension->PDODeviceObject != NULL) 608c2c66affSColin Finck { 609c2c66affSColin Finck *DeviceExtension->PDODeviceObject = NULL; 610c2c66affSColin Finck bDelete = TRUE; 611c2c66affSColin Finck } 612c2c66affSColin Finck else 613c2c66affSColin Finck { 614c2c66affSColin Finck // device object already marked for deletion 615c2c66affSColin Finck bDelete = FALSE; 616c2c66affSColin Finck } 617c2c66affSColin Finck 61840b25634SVictor Perevertkin // clean up the device extension 61940b25634SVictor Perevertkin ASSERT(DeviceExtension->InquiryData); 62040b25634SVictor Perevertkin ExFreePoolWithTag(DeviceExtension->InquiryData, USB_STOR_TAG); 62140b25634SVictor Perevertkin 622c2c66affSColin Finck Irp->IoStatus.Status = STATUS_SUCCESS; 623c2c66affSColin Finck IoCompleteRequest(Irp, IO_NO_INCREMENT); 624c2c66affSColin Finck 625c2c66affSColin Finck if (bDelete) 626c2c66affSColin Finck { 627c2c66affSColin Finck IoDeleteDevice(DeviceObject); 628c2c66affSColin Finck } 629c2c66affSColin Finck return STATUS_SUCCESS; 630c2c66affSColin Finck } 631c2c66affSColin Finck case IRP_MN_QUERY_CAPABILITIES: 632c2c66affSColin Finck { 633c2c66affSColin Finck // just forward irp to lower device 634c2c66affSColin Finck Status = USBSTOR_SyncForwardIrp(DeviceExtension->LowerDeviceObject, Irp); 635c2c66affSColin Finck ASSERT(Status == STATUS_SUCCESS); 636c2c66affSColin Finck 637c2c66affSColin Finck if (NT_SUCCESS(Status)) 638c2c66affSColin Finck { 639c2c66affSColin Finck // check if no unique id 640c2c66affSColin Finck Caps = (PDEVICE_CAPABILITIES)IoStack->Parameters.DeviceCapabilities.Capabilities; 641c2c66affSColin Finck Caps->UniqueID = FALSE; // no unique id is supported 642c2c66affSColin Finck Caps->Removable = TRUE; //FIXME 643c2c66affSColin Finck } 644c2c66affSColin Finck break; 645c2c66affSColin Finck } 646c2c66affSColin Finck case IRP_MN_QUERY_REMOVE_DEVICE: 647c2c66affSColin Finck case IRP_MN_QUERY_STOP_DEVICE: 648c2c66affSColin Finck { 649c2c66affSColin Finck #if 0 650c2c66affSColin Finck // 651c2c66affSColin Finck // if we're not claimed it's ok 652c2c66affSColin Finck // 653c2c66affSColin Finck if (DeviceExtension->Claimed) 654c2c66affSColin Finck #else 655c2c66affSColin Finck if (TRUE) 656c2c66affSColin Finck #endif 657c2c66affSColin Finck { 658c2c66affSColin Finck Status = STATUS_UNSUCCESSFUL; 659c2c66affSColin Finck DPRINT1("[USBSTOR] Request %x fails because device is still claimed\n", IoStack->MinorFunction); 660c2c66affSColin Finck } 661c2c66affSColin Finck else 662c2c66affSColin Finck Status = STATUS_SUCCESS; 663c2c66affSColin Finck break; 664c2c66affSColin Finck } 665c2c66affSColin Finck case IRP_MN_START_DEVICE: 666c2c66affSColin Finck { 667c2c66affSColin Finck // no-op for PDO 668c2c66affSColin Finck Status = STATUS_SUCCESS; 669c2c66affSColin Finck break; 670c2c66affSColin Finck } 671c2c66affSColin Finck case IRP_MN_SURPRISE_REMOVAL: 672c2c66affSColin Finck { 673c2c66affSColin Finck Status = STATUS_SUCCESS; 674c2c66affSColin Finck break; 675c2c66affSColin Finck } 676c2c66affSColin Finck default: 677c2c66affSColin Finck { 678c2c66affSColin Finck // do nothing 679c2c66affSColin Finck Status = Irp->IoStatus.Status; 680c2c66affSColin Finck } 681c2c66affSColin Finck } 682c2c66affSColin Finck 683c2c66affSColin Finck if (Status != STATUS_PENDING) 684c2c66affSColin Finck { 685c2c66affSColin Finck Irp->IoStatus.Status = Status; 686c2c66affSColin Finck IoCompleteRequest(Irp, IO_NO_INCREMENT); 687c2c66affSColin Finck } 688c2c66affSColin Finck 689c2c66affSColin Finck return Status; 690c2c66affSColin Finck } 691c2c66affSColin Finck 692c2c66affSColin Finck NTSTATUS 693c2c66affSColin Finck NTAPI 694f3fd12b9SVictor Perevertkin USBSTOR_SyncCompletionRoutine( 695c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject, 696c2c66affSColin Finck IN PIRP Irp, 697c2c66affSColin Finck IN PVOID Ctx) 698c2c66affSColin Finck { 699f3fd12b9SVictor Perevertkin KeSetEvent((PKEVENT)Ctx, IO_NO_INCREMENT, FALSE); 700c2c66affSColin Finck return STATUS_MORE_PROCESSING_REQUIRED; 701c2c66affSColin Finck } 702c2c66affSColin Finck 703f3fd12b9SVictor Perevertkin /* 704f3fd12b9SVictor Perevertkin * @name USBSTOR_SendInternalCdb 705f3fd12b9SVictor Perevertkin * 706f3fd12b9SVictor Perevertkin * Issues an internal SCSI request to device. 707f3fd12b9SVictor Perevertkin * The request is sent in a synchronous way. 708f3fd12b9SVictor Perevertkin */ 709f3fd12b9SVictor Perevertkin static 710c2c66affSColin Finck NTSTATUS 711f3fd12b9SVictor Perevertkin USBSTOR_SendInternalCdb( 712f3fd12b9SVictor Perevertkin IN PDEVICE_OBJECT PdoDevice, 713f3fd12b9SVictor Perevertkin IN PCDB Cdb, 714f3fd12b9SVictor Perevertkin IN UCHAR CdbLength, 715f3fd12b9SVictor Perevertkin IN ULONG TimeOutValue, 716f3fd12b9SVictor Perevertkin OUT PVOID OutDataBuffer, 717f3fd12b9SVictor Perevertkin OUT PULONG OutDataTransferLength) 718c2c66affSColin Finck { 719f3fd12b9SVictor Perevertkin PSCSI_REQUEST_BLOCK Srb; 720f3fd12b9SVictor Perevertkin PSENSE_DATA SenseBuffer; 721c2c66affSColin Finck PIO_STACK_LOCATION IoStack; 722f3fd12b9SVictor Perevertkin KEVENT Event; 723f3fd12b9SVictor Perevertkin PIRP Irp = NULL; 724f3fd12b9SVictor Perevertkin PMDL Mdl = NULL; 725f3fd12b9SVictor Perevertkin ULONG ix = 0; 726f3fd12b9SVictor Perevertkin NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES; 727f3fd12b9SVictor Perevertkin UCHAR SrbStatus; 728c2c66affSColin Finck 729f3fd12b9SVictor Perevertkin DPRINT("USBSTOR_SendInternalCdb SCSIOP %x\n", Cdb->CDB6GENERIC.OperationCode); 730f3fd12b9SVictor Perevertkin 731f3fd12b9SVictor Perevertkin Srb = ExAllocatePoolWithTag(NonPagedPool, 732f3fd12b9SVictor Perevertkin sizeof(SCSI_REQUEST_BLOCK), 733f3fd12b9SVictor Perevertkin USB_STOR_TAG); 734f3fd12b9SVictor Perevertkin 735f3fd12b9SVictor Perevertkin if (Srb) 736f3fd12b9SVictor Perevertkin { 737f3fd12b9SVictor Perevertkin SenseBuffer = ExAllocatePoolWithTag(NonPagedPool, 738f3fd12b9SVictor Perevertkin SENSE_BUFFER_SIZE, 739f3fd12b9SVictor Perevertkin USB_STOR_TAG); 740f3fd12b9SVictor Perevertkin 741f3fd12b9SVictor Perevertkin if (SenseBuffer) 742f3fd12b9SVictor Perevertkin { 743f3fd12b9SVictor Perevertkin Mdl = IoAllocateMdl(OutDataBuffer, 744f3fd12b9SVictor Perevertkin *OutDataTransferLength, 745f3fd12b9SVictor Perevertkin FALSE, 746f3fd12b9SVictor Perevertkin FALSE, 747f3fd12b9SVictor Perevertkin NULL); 748f3fd12b9SVictor Perevertkin 749f3fd12b9SVictor Perevertkin if (!Mdl) 750f3fd12b9SVictor Perevertkin { 751f3fd12b9SVictor Perevertkin ExFreePoolWithTag(SenseBuffer, USB_STOR_TAG); 752f3fd12b9SVictor Perevertkin ExFreePoolWithTag(Srb, USB_STOR_TAG); 753f3fd12b9SVictor Perevertkin return Status; 754f3fd12b9SVictor Perevertkin } 755f3fd12b9SVictor Perevertkin 756f3fd12b9SVictor Perevertkin MmBuildMdlForNonPagedPool(Mdl); 757f3fd12b9SVictor Perevertkin 758f3fd12b9SVictor Perevertkin // make 3 attempts - the device may be in STALL state after the first one 759f3fd12b9SVictor Perevertkin do 760f3fd12b9SVictor Perevertkin { 761f3fd12b9SVictor Perevertkin Irp = IoAllocateIrp(PdoDevice->StackSize, FALSE); 762f3fd12b9SVictor Perevertkin 763c2c66affSColin Finck if (!Irp) 764c2c66affSColin Finck { 765f3fd12b9SVictor Perevertkin break; 766c2c66affSColin Finck } 767c2c66affSColin Finck 768c2c66affSColin Finck IoStack = IoGetNextIrpStackLocation(Irp); 769c2c66affSColin Finck IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL; 770f3fd12b9SVictor Perevertkin IoStack->Parameters.Scsi.Srb = Srb; 771c2c66affSColin Finck 772f3fd12b9SVictor Perevertkin RtlZeroMemory(Srb, sizeof(SCSI_REQUEST_BLOCK)); 773c2c66affSColin Finck 774f3fd12b9SVictor Perevertkin Srb->Length = sizeof(SCSI_REQUEST_BLOCK); 775f3fd12b9SVictor Perevertkin Srb->Function = SRB_FUNCTION_EXECUTE_SCSI; 776f3fd12b9SVictor Perevertkin Srb->CdbLength = CdbLength; 777f3fd12b9SVictor Perevertkin Srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE; 778f3fd12b9SVictor Perevertkin Srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_NO_QUEUE_FREEZE; 779f3fd12b9SVictor Perevertkin Srb->DataTransferLength = *OutDataTransferLength; 780f3fd12b9SVictor Perevertkin Srb->TimeOutValue = TimeOutValue; 781f3fd12b9SVictor Perevertkin Srb->DataBuffer = OutDataBuffer; 782f3fd12b9SVictor Perevertkin Srb->SenseInfoBuffer = SenseBuffer; 783c2c66affSColin Finck 784f3fd12b9SVictor Perevertkin RtlCopyMemory(Srb->Cdb, Cdb, CdbLength); 785f3fd12b9SVictor Perevertkin 786f3fd12b9SVictor Perevertkin Irp->MdlAddress = Mdl; 787f3fd12b9SVictor Perevertkin 788f3fd12b9SVictor Perevertkin KeInitializeEvent(&Event, SynchronizationEvent, FALSE); 789f3fd12b9SVictor Perevertkin 790f3fd12b9SVictor Perevertkin IoSetCompletionRoutine(Irp, 791f3fd12b9SVictor Perevertkin USBSTOR_SyncCompletionRoutine, 792f3fd12b9SVictor Perevertkin &Event, 793f3fd12b9SVictor Perevertkin TRUE, 794f3fd12b9SVictor Perevertkin TRUE, 795f3fd12b9SVictor Perevertkin TRUE); 796f3fd12b9SVictor Perevertkin 797f3fd12b9SVictor Perevertkin if (IoCallDriver(PdoDevice, Irp) == STATUS_PENDING) 798f3fd12b9SVictor Perevertkin { 799f3fd12b9SVictor Perevertkin KeWaitForSingleObject(&Event, 800f3fd12b9SVictor Perevertkin Executive, 801f3fd12b9SVictor Perevertkin KernelMode, 802f3fd12b9SVictor Perevertkin FALSE, 803f3fd12b9SVictor Perevertkin NULL); 804c2c66affSColin Finck } 805c2c66affSColin Finck 806f3fd12b9SVictor Perevertkin SrbStatus = SRB_STATUS(Srb->SrbStatus); 807c2c66affSColin Finck 808c2c66affSColin Finck IoFreeIrp(Irp); 809f3fd12b9SVictor Perevertkin Irp = NULL; 810f3fd12b9SVictor Perevertkin 811f3fd12b9SVictor Perevertkin if (SrbStatus == SRB_STATUS_SUCCESS || 812f3fd12b9SVictor Perevertkin SrbStatus == SRB_STATUS_DATA_OVERRUN) 813f3fd12b9SVictor Perevertkin { 814f3fd12b9SVictor Perevertkin Status = STATUS_SUCCESS; 815f3fd12b9SVictor Perevertkin *OutDataTransferLength = Srb->DataTransferLength; 816f3fd12b9SVictor Perevertkin break; 817f3fd12b9SVictor Perevertkin } 818f3fd12b9SVictor Perevertkin 819f3fd12b9SVictor Perevertkin Status = STATUS_UNSUCCESSFUL; 820f3fd12b9SVictor Perevertkin 821f3fd12b9SVictor Perevertkin ++ix; 822f3fd12b9SVictor Perevertkin } while (ix < 3); 823f3fd12b9SVictor Perevertkin 824f3fd12b9SVictor Perevertkin if (Mdl) 825f3fd12b9SVictor Perevertkin { 826f3fd12b9SVictor Perevertkin IoFreeMdl(Mdl); 827f3fd12b9SVictor Perevertkin } 828f3fd12b9SVictor Perevertkin 829f3fd12b9SVictor Perevertkin ExFreePoolWithTag(SenseBuffer, USB_STOR_TAG); 830f3fd12b9SVictor Perevertkin } 831f3fd12b9SVictor Perevertkin 832f3fd12b9SVictor Perevertkin ExFreePoolWithTag(Srb, USB_STOR_TAG); 833f3fd12b9SVictor Perevertkin } 834f3fd12b9SVictor Perevertkin 835c2c66affSColin Finck return Status; 836c2c66affSColin Finck } 837c2c66affSColin Finck 838f3fd12b9SVictor Perevertkin /* 839f3fd12b9SVictor Perevertkin * @name USBSTOR_FillInquiryData 840f3fd12b9SVictor Perevertkin * 841f3fd12b9SVictor Perevertkin * Sends a SCSI Inquiry request and fills in the PDODeviceExtension->InquiryData field with a result. 842f3fd12b9SVictor Perevertkin */ 843f3fd12b9SVictor Perevertkin static 844c2c66affSColin Finck NTSTATUS 845f3fd12b9SVictor Perevertkin USBSTOR_FillInquiryData( 846c2c66affSColin Finck IN PDEVICE_OBJECT PDODeviceObject) 847c2c66affSColin Finck { 848f3fd12b9SVictor Perevertkin NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES; 849c2c66affSColin Finck PPDO_DEVICE_EXTENSION PDODeviceExtension; 850f3fd12b9SVictor Perevertkin CDB Cdb; 851f3fd12b9SVictor Perevertkin ULONG DataTransferLength = INQUIRYDATABUFFERSIZE; 852f3fd12b9SVictor Perevertkin PINQUIRYDATA InquiryData; 853c2c66affSColin Finck 854c2c66affSColin Finck PDODeviceExtension = (PPDO_DEVICE_EXTENSION)PDODeviceObject->DeviceExtension; 855f3fd12b9SVictor Perevertkin InquiryData = ExAllocatePoolWithTag(NonPagedPool, INQUIRYDATABUFFERSIZE, USB_STOR_TAG); 856c2c66affSColin Finck 857f3fd12b9SVictor Perevertkin if (!InquiryData) 858f3fd12b9SVictor Perevertkin { 859f3fd12b9SVictor Perevertkin DPRINT1("USBSTOR_FillInquiryData failed with %x\n", Status); 860f3fd12b9SVictor Perevertkin return Status; 861f3fd12b9SVictor Perevertkin } 862f3fd12b9SVictor Perevertkin 863f3fd12b9SVictor Perevertkin RtlZeroMemory(&Cdb, sizeof(Cdb)); 864f3fd12b9SVictor Perevertkin Cdb.CDB6INQUIRY.OperationCode = SCSIOP_INQUIRY; 865f3fd12b9SVictor Perevertkin Cdb.CDB6INQUIRY.AllocationLength = INQUIRYDATABUFFERSIZE; 866f3fd12b9SVictor Perevertkin 867f3fd12b9SVictor Perevertkin Status = USBSTOR_SendInternalCdb(PDODeviceObject, &Cdb, CDB6GENERIC_LENGTH, 20, InquiryData, &DataTransferLength); 868f3fd12b9SVictor Perevertkin 869c2c66affSColin Finck if (!NT_SUCCESS(Status)) 870c2c66affSColin Finck { 871f3fd12b9SVictor Perevertkin DPRINT1("USBSTOR_FillInquiryData failed with %x\n", Status); 872f3fd12b9SVictor Perevertkin ExFreePoolWithTag(InquiryData, USB_STOR_TAG); 873c2c66affSColin Finck return Status; 874c2c66affSColin Finck } 875c2c66affSColin Finck 876f3fd12b9SVictor Perevertkin DPRINT("DeviceType %x\n", InquiryData->DeviceType); 877f3fd12b9SVictor Perevertkin DPRINT("DeviceTypeModifier %x\n", InquiryData->DeviceTypeModifier); 878f3fd12b9SVictor Perevertkin DPRINT("RemovableMedia %x\n", InquiryData->RemovableMedia); 879f3fd12b9SVictor Perevertkin DPRINT("Version %x\n", InquiryData->Versions); 880f3fd12b9SVictor Perevertkin DPRINT("Format %x\n", InquiryData->ResponseDataFormat); 881f3fd12b9SVictor Perevertkin DPRINT("Length %x\n", InquiryData->AdditionalLength); 882f3fd12b9SVictor Perevertkin DPRINT("Reserved %p\n", InquiryData->Reserved); 883f3fd12b9SVictor Perevertkin DPRINT("VendorId %c%c%c%c%c%c%c%c\n", InquiryData->VendorId[0], InquiryData->VendorId[1], InquiryData->VendorId[2], InquiryData->VendorId[3], InquiryData->VendorId[4], InquiryData->VendorId[5], InquiryData->VendorId[6], InquiryData->VendorId[7]); 884f3fd12b9SVictor Perevertkin DPRINT("ProductId %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n", InquiryData->ProductId[0], InquiryData->ProductId[1], InquiryData->ProductId[2], InquiryData->ProductId[3], 885f3fd12b9SVictor Perevertkin InquiryData->ProductId[4], InquiryData->ProductId[5], InquiryData->ProductId[6], InquiryData->ProductId[7], 886f3fd12b9SVictor Perevertkin InquiryData->ProductId[8], InquiryData->ProductId[9], InquiryData->ProductId[10], InquiryData->ProductId[11], 887f3fd12b9SVictor Perevertkin InquiryData->ProductId[12], InquiryData->ProductId[13], InquiryData->ProductId[14], InquiryData->ProductId[15]); 888c2c66affSColin Finck 889f3fd12b9SVictor Perevertkin DPRINT("Revision %c%c%c%c\n", InquiryData->ProductRevisionLevel[0], InquiryData->ProductRevisionLevel[1], InquiryData->ProductRevisionLevel[2], InquiryData->ProductRevisionLevel[3]); 890c2c66affSColin Finck 891f3fd12b9SVictor Perevertkin PDODeviceExtension->InquiryData = InquiryData; 892c2c66affSColin Finck return Status; 893c2c66affSColin Finck } 894c2c66affSColin Finck 895c2c66affSColin Finck NTSTATUS 896c2c66affSColin Finck USBSTOR_CreatePDO( 897c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject, 898c2c66affSColin Finck IN UCHAR LUN) 899c2c66affSColin Finck { 900c2c66affSColin Finck PDEVICE_OBJECT PDO; 901c2c66affSColin Finck NTSTATUS Status; 902c2c66affSColin Finck PPDO_DEVICE_EXTENSION PDODeviceExtension; 903c2c66affSColin Finck PFDO_DEVICE_EXTENSION FDODeviceExtension; 904c2c66affSColin Finck 905c2c66affSColin Finck FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension; 906c2c66affSColin Finck 907c2c66affSColin Finck // create child device object 908c2c66affSColin Finck Status = IoCreateDevice(DeviceObject->DriverObject, sizeof(PDO_DEVICE_EXTENSION), NULL, FILE_DEVICE_MASS_STORAGE, FILE_AUTOGENERATED_DEVICE_NAME | FILE_DEVICE_SECURE_OPEN, FALSE, &PDO); 909c2c66affSColin Finck if (!NT_SUCCESS(Status)) 910c2c66affSColin Finck { 911f3fd12b9SVictor Perevertkin DPRINT1("Failed to create PDO, status %x\n", Status); 912c2c66affSColin Finck return Status; 913c2c66affSColin Finck } 914c2c66affSColin Finck 915c2c66affSColin Finck // patch the stack size 916c2c66affSColin Finck PDO->StackSize = DeviceObject->StackSize; 917c2c66affSColin Finck 918c2c66affSColin Finck PDODeviceExtension = (PPDO_DEVICE_EXTENSION)PDO->DeviceExtension; 919c2c66affSColin Finck 920c2c66affSColin Finck // initialize device extension 921c2c66affSColin Finck RtlZeroMemory(PDODeviceExtension, sizeof(PDO_DEVICE_EXTENSION)); 922c2c66affSColin Finck PDODeviceExtension->Common.IsFDO = FALSE; 923c2c66affSColin Finck PDODeviceExtension->LowerDeviceObject = DeviceObject; 924c2c66affSColin Finck PDODeviceExtension->PDODeviceObject = &FDODeviceExtension->ChildPDO[LUN]; 925c2c66affSColin Finck PDODeviceExtension->Self = PDO; 926c2c66affSColin Finck PDODeviceExtension->LUN = LUN; 927c2c66affSColin Finck 928f3fd12b9SVictor Perevertkin PDO->Flags |= DO_DIRECT_IO; 929c2c66affSColin Finck 930c2c66affSColin Finck // device is initialized 931c2c66affSColin Finck PDO->Flags &= ~DO_DEVICE_INITIALIZING; 932c2c66affSColin Finck 933c2c66affSColin Finck // output device object 934c2c66affSColin Finck FDODeviceExtension->ChildPDO[LUN] = PDO; 935c2c66affSColin Finck 936c2c66affSColin Finck // send inquiry command by irp 937f3fd12b9SVictor Perevertkin Status = USBSTOR_FillInquiryData(PDO); 938c2c66affSColin Finck 939f3fd12b9SVictor Perevertkin if (!NT_SUCCESS(Status)) 940c2c66affSColin Finck { 941f3fd12b9SVictor Perevertkin return Status; 942f3fd12b9SVictor Perevertkin } 943c2c66affSColin Finck 944b7de5870SVictor Perevertkin if (PDODeviceExtension->InquiryData->DeviceType == DIRECT_ACCESS_DEVICE || PDODeviceExtension->InquiryData->DeviceType == READ_ONLY_DIRECT_ACCESS_DEVICE) 945f3fd12b9SVictor Perevertkin { 946f3fd12b9SVictor Perevertkin PDODeviceExtension->IsFloppy = FALSE; // TODO: implement the actual check 947f3fd12b9SVictor Perevertkin } 948f3fd12b9SVictor Perevertkin else 949f3fd12b9SVictor Perevertkin { 950f3fd12b9SVictor Perevertkin // we work only with DIRECT_ACCESS_DEVICE for now 951f3fd12b9SVictor Perevertkin return STATUS_NOT_SUPPORTED; 952c2c66affSColin Finck } 953c2c66affSColin Finck 954c2c66affSColin Finck return Status; 955c2c66affSColin Finck } 956