2 * PROJECT: ReactOS Universal Serial Bus Bulk Storage Driver
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: USB block storage device driver.
5 * COPYRIGHT: 2005-2006 James Tabor
6 * 2011-2012 Michael Martin (michael.martin@reactos.org)
7 * 2011-2013 Johannes Anderwald (johannes.anderwald@reactos.org)
9 * 2019 Victor Perevertkin (victor.perevertkin@reactos.org)
20 USBSTOR_GetDeviceType(
21 IN PINQUIRYDATA InquiryData
)
23 switch (InquiryData
->DeviceType
)
25 case DIRECT_ACCESS_DEVICE
:
27 case SEQUENTIAL_ACCESS_DEVICE
:
28 // sequential device, i.e magnetic tape
30 case WRITE_ONCE_READ_MULTIPLE_DEVICE
:
32 case READ_ONLY_DIRECT_ACCESS_DEVICE
:
45 USBSTOR_GetGenericType(
46 IN PINQUIRYDATA InquiryData
)
48 switch (InquiryData
->DeviceType
)
50 case DIRECT_ACCESS_DEVICE
:
52 case SEQUENTIAL_ACCESS_DEVICE
:
53 // sequential device, i.e magnetic tape
54 return "GenSequential";
55 case WRITE_ONCE_READ_MULTIPLE_DEVICE
:
57 case READ_ONLY_DIRECT_ACCESS_DEVICE
:
64 return "UsbstorOther";
77 for (Index
= 0; Index
< MaxLength
; Index
++)
79 if (Name
[Index
] <= ' ' || Name
[Index
] >= 0x7F /* last printable ascii character */ || Name
[Index
] == ',')
81 // convert to underscore
86 // just copy character
87 Buffer
[Index
] = Name
[Index
];
103 for (Index
= 0; Index
< MaxLength
; Index
++)
105 if (Name
[Index
] == '\0')
109 else if (Name
[Index
] <= ' ' || Name
[Index
] >= 0x7F /* last printable ascii character */ || Name
[Index
] == ',')
111 // convert to underscore
116 // just copy character
117 Buffer
[Index
] = Name
[Index
];
125 USBSTOR_PdoHandleQueryDeviceText(
126 IN PDEVICE_OBJECT DeviceObject
,
129 PPDO_DEVICE_EXTENSION DeviceExtension
;
130 PIO_STACK_LOCATION IoStack
;
131 CHAR LocalBuffer
[26];
133 PINQUIRYDATA InquiryData
;
134 ANSI_STRING AnsiString
;
135 UNICODE_STRING DeviceDescription
;
137 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
139 DeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
140 InquiryData
= (PINQUIRYDATA
)&DeviceExtension
->InquiryData
;
142 switch (IoStack
->Parameters
.QueryDeviceText
.DeviceTextType
)
144 case DeviceTextDescription
:
145 case DeviceTextLocationInformation
:
147 DPRINT("USBSTOR_PdoHandleQueryDeviceText\n");
149 Offset
+= CopyFieldTruncate(InquiryData
->VendorId
, &LocalBuffer
[Offset
], sizeof(InquiryData
->VendorId
));
150 LocalBuffer
[Offset
++] = ' ';
151 Offset
+= CopyFieldTruncate(InquiryData
->ProductId
, &LocalBuffer
[Offset
], sizeof(InquiryData
->ProductId
));
152 LocalBuffer
[Offset
++] = '\0';
154 RtlInitAnsiString(&AnsiString
, (PCSZ
)&LocalBuffer
);
156 DeviceDescription
.Length
= 0;
157 DeviceDescription
.MaximumLength
= (USHORT
)(Offset
* sizeof(WCHAR
));
158 DeviceDescription
.Buffer
= ExAllocatePoolWithTag(PagedPool
, DeviceDescription
.MaximumLength
, USB_STOR_TAG
);
159 if (!DeviceDescription
.Buffer
)
161 Irp
->IoStatus
.Information
= 0;
162 return STATUS_INSUFFICIENT_RESOURCES
;
165 RtlAnsiStringToUnicodeString(&DeviceDescription
, &AnsiString
, FALSE
);
167 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceDescription
.Buffer
;
168 return STATUS_SUCCESS
;
172 Irp
->IoStatus
.Information
= 0;
173 return Irp
->IoStatus
.Status
;
179 USBSTOR_PdoHandleQueryDeviceId(
180 IN PDEVICE_OBJECT DeviceObject
,
183 PPDO_DEVICE_EXTENSION DeviceExtension
;
185 CHAR Buffer
[100] = {0};
188 PINQUIRYDATA InquiryData
;
189 ANSI_STRING AnsiString
;
190 UNICODE_STRING DeviceId
;
192 DeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
193 InquiryData
= (PINQUIRYDATA
)&DeviceExtension
->InquiryData
;
195 DeviceType
= USBSTOR_GetDeviceType(InquiryData
);
197 // lets create device string
198 Offset
= sprintf(&Buffer
[Offset
], "USBSTOR\\");
199 Offset
+= sprintf(&Buffer
[Offset
], DeviceType
);
200 Offset
+= sprintf(&Buffer
[Offset
], "&Ven_");
201 Offset
+= CopyField(InquiryData
->VendorId
, &Buffer
[Offset
], 8);
202 Offset
+= sprintf(&Buffer
[Offset
], "&Prod_");
203 Offset
+= CopyField(InquiryData
->ProductId
, &Buffer
[Offset
], 16);
204 Offset
+= sprintf(&Buffer
[Offset
], "&Rev_");
205 Offset
+= CopyField(InquiryData
->ProductRevisionLevel
, &Buffer
[Offset
], 4);
207 RtlInitAnsiString(&AnsiString
, (PCSZ
)Buffer
);
209 // allocate DeviceId string
211 DeviceId
.MaximumLength
= (USHORT
)((strlen((PCHAR
)Buffer
) + 1) * sizeof(WCHAR
));
212 DeviceId
.Buffer
= ExAllocatePoolWithTag(PagedPool
, DeviceId
.MaximumLength
, USB_STOR_TAG
);
213 if (!DeviceId
.Buffer
)
215 Irp
->IoStatus
.Information
= 0;
216 return STATUS_INSUFFICIENT_RESOURCES
;
219 Status
= RtlAnsiStringToUnicodeString(&DeviceId
, &AnsiString
, FALSE
);
221 if (NT_SUCCESS(Status
))
223 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceId
.Buffer
;
226 DPRINT("DeviceId %wZ Status %x\n", &DeviceId
, Status
);
232 USBSTOR_ConvertToUnicodeString(
234 IN ULONG ResultBufferLength
,
235 IN ULONG ResultBufferOffset
,
236 OUT LPWSTR ResultBuffer
,
237 OUT PULONG NewResultBufferOffset
)
239 UNICODE_STRING DeviceString
;
240 ANSI_STRING AnsiString
;
243 ASSERT(ResultBufferLength
);
244 ASSERT(ResultBufferLength
> ResultBufferOffset
);
246 DPRINT("ResultBufferOffset %lu ResultBufferLength %lu Buffer %s Length %lu\n", ResultBufferOffset
, ResultBufferLength
, Buffer
, strlen(Buffer
));
248 // construct destination string
249 DeviceString
.Buffer
= &ResultBuffer
[ResultBufferOffset
];
250 DeviceString
.Length
= 0;
251 DeviceString
.MaximumLength
= (ResultBufferLength
- ResultBufferOffset
) * sizeof(WCHAR
);
253 // initialize source string
254 RtlInitAnsiString(&AnsiString
, Buffer
);
256 Status
= RtlAnsiStringToUnicodeString(&DeviceString
, &AnsiString
, FALSE
);
257 ASSERT(Status
== STATUS_SUCCESS
);
259 // subtract consumed bytes
260 ResultBufferLength
-= (DeviceString
.Length
+ sizeof(WCHAR
)) / sizeof(WCHAR
);
261 ResultBufferOffset
+= (DeviceString
.Length
+ sizeof(WCHAR
)) / sizeof(WCHAR
);
263 *NewResultBufferOffset
= ResultBufferOffset
;
267 USBSTOR_PdoHandleQueryHardwareId(
268 IN PDEVICE_OBJECT DeviceObject
,
271 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
272 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
273 LPCSTR GenericType
, DeviceType
;
275 CHAR Id1
[50], Id2
[50], Id3
[50], Id4
[50], Id5
[50], Id6
[50], Id7
[50];
276 ULONG Id1Length
, Id2Length
, Id3Length
, Id4Length
, Id5Length
, Id6Length
, Id7Length
;
277 ULONG Offset
, TotalLength
, Length
;
278 PINQUIRYDATA InquiryData
;
280 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
281 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)PDODeviceExtension
->LowerDeviceObject
->DeviceExtension
;
282 ASSERT(FDODeviceExtension
->DeviceDescriptor
);
283 InquiryData
= (PINQUIRYDATA
)&PDODeviceExtension
->InquiryData
;
285 DeviceType
= USBSTOR_GetDeviceType(InquiryData
);
286 GenericType
= USBSTOR_GetGenericType(InquiryData
);
291 // USBSTOR\SCSIType_VendorId(8)_ProductId(16)_Revision(4)
292 RtlZeroMemory(Id1
, sizeof(Id1
));
294 Offset
= sprintf(&Id1
[Offset
], "USBSTOR\\");
295 Offset
+= sprintf(&Id1
[Offset
], DeviceType
);
296 Offset
+= CopyField(InquiryData
->VendorId
, &Id1
[Offset
], 8);
297 Offset
+= CopyField(InquiryData
->ProductId
, &Id1
[Offset
], 16);
298 Offset
+= CopyField(InquiryData
->ProductRevisionLevel
, &Id1
[Offset
], 4);
299 Id1Length
= strlen(Id1
) + 1;
300 DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId1 %s\n", Id1
);
303 // USBSTOR\SCSIType_VendorId(8)_ProductId(16)
304 RtlZeroMemory(Id2
, sizeof(Id2
));
306 Offset
= sprintf(&Id2
[Offset
], "USBSTOR\\");
307 Offset
+= sprintf(&Id2
[Offset
], DeviceType
);
308 Offset
+= CopyField(InquiryData
->VendorId
, &Id2
[Offset
], 8);
309 Offset
+= CopyField(InquiryData
->ProductId
, &Id2
[Offset
], 16);
310 Id2Length
= strlen(Id2
) + 1;
311 DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId2 %s\n", Id2
);
314 // USBSTOR\SCSIType_VendorId(8)
315 RtlZeroMemory(Id3
, sizeof(Id3
));
317 Offset
= sprintf(&Id3
[Offset
], "USBSTOR\\");
318 Offset
+= sprintf(&Id3
[Offset
], DeviceType
);
319 Offset
+= CopyField(InquiryData
->VendorId
, &Id3
[Offset
], 8);
320 Id3Length
= strlen(Id3
) + 1;
321 DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId3 %s\n", Id3
);
324 // USBSTOR\SCSIType_VendorId(8)_ProductId(16)_Revision(1)
325 RtlZeroMemory(Id4
, sizeof(Id4
));
327 Offset
= sprintf(&Id4
[Offset
], "USBSTOR\\");
328 Offset
+= sprintf(&Id4
[Offset
], DeviceType
);
329 Offset
+= CopyField(InquiryData
->VendorId
, &Id4
[Offset
], 8);
330 Offset
+= CopyField(InquiryData
->ProductId
, &Id4
[Offset
], 16);
331 Offset
+= CopyField(InquiryData
->ProductRevisionLevel
, &Id4
[Offset
], 1);
332 Id4Length
= strlen(Id4
) + 1;
333 DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId4 %s\n", Id4
);
336 // SCSIType_VendorId(8)_ProductId(16)_Revision(1)
337 RtlZeroMemory(Id5
, sizeof(Id5
));
339 Offset
= sprintf(&Id5
[Offset
], DeviceType
);
340 Offset
+= CopyField(InquiryData
->VendorId
, &Id5
[Offset
], 8);
341 Offset
+= CopyField(InquiryData
->ProductId
, &Id5
[Offset
], 16);
342 Offset
+= CopyField(InquiryData
->ProductRevisionLevel
, &Id5
[Offset
], 1);
343 Id5Length
= strlen(Id5
) + 1;
344 DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId5 %s\n", Id5
);
348 RtlZeroMemory(Id6
, sizeof(Id6
));
350 Offset
= sprintf(&Id6
[Offset
], "USBSTOR\\");
351 Offset
+= sprintf(&Id6
[Offset
], GenericType
);
352 Id6Length
= strlen(Id6
) + 1;
353 DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId6 %s\n", Id6
);
357 RtlZeroMemory(Id7
, sizeof(Id7
));
359 Offset
= sprintf(&Id7
[Offset
], GenericType
);
360 Id7Length
= strlen(Id7
) + 1;
361 DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId7 %s\n", Id7
);
363 // last +1 is for terminating \0 of REG_MULTI_SZ
364 TotalLength
= Id1Length
+ Id2Length
+ Id3Length
+ Id4Length
+ Id5Length
+ Id6Length
+ Id7Length
+ 1;
366 Buffer
= ExAllocatePoolWithTag(PagedPool
, TotalLength
* sizeof(WCHAR
), USB_STOR_TAG
);
369 Irp
->IoStatus
.Information
= 0;
370 return STATUS_INSUFFICIENT_RESOURCES
;
375 Length
= TotalLength
;
377 USBSTOR_ConvertToUnicodeString(Id1
, Length
, Offset
, Buffer
, &Offset
);
378 USBSTOR_ConvertToUnicodeString(Id2
, Length
, Offset
, Buffer
, &Offset
);
379 USBSTOR_ConvertToUnicodeString(Id3
, Length
, Offset
, Buffer
, &Offset
);
380 USBSTOR_ConvertToUnicodeString(Id4
, Length
, Offset
, Buffer
, &Offset
);
381 USBSTOR_ConvertToUnicodeString(Id5
, Length
, Offset
, Buffer
, &Offset
);
382 USBSTOR_ConvertToUnicodeString(Id6
, Length
, Offset
, Buffer
, &Offset
);
383 USBSTOR_ConvertToUnicodeString(Id7
, Length
, Offset
, Buffer
, &Offset
);
385 Buffer
[Offset
] = UNICODE_NULL
; // finish the REG_MULTI_SZ
387 ASSERT(Offset
+ 1 == Length
);
389 Irp
->IoStatus
.Information
= (ULONG_PTR
)Buffer
;
390 return STATUS_SUCCESS
;
394 USBSTOR_PdoHandleQueryCompatibleId(
395 IN PDEVICE_OBJECT DeviceObject
,
398 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
399 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
400 CHAR Buffer
[100] = {0};
401 ULONG Length
, Offset
;
405 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
406 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)PDODeviceExtension
->LowerDeviceObject
->DeviceExtension
;
407 ASSERT(FDODeviceExtension
->DeviceDescriptor
);
408 DeviceType
= USBSTOR_GetDeviceType((PINQUIRYDATA
)&PDODeviceExtension
->InquiryData
);
410 // format instance id
411 Length
= sprintf(Buffer
, "USBSTOR\\%s", DeviceType
) + 1;
412 // +1 for terminating \0 and another +1 for \0 at the end of REG_MULTI_SZ
413 Length
+= sprintf(&Buffer
[Length
], "USBSTOR\\%s", "RAW") + 2;
415 InstanceId
= ExAllocatePoolWithTag(PagedPool
, Length
* sizeof(WCHAR
), USB_STOR_TAG
);
418 Irp
->IoStatus
.Information
= 0;
419 return STATUS_INSUFFICIENT_RESOURCES
;
422 USBSTOR_ConvertToUnicodeString(Buffer
, Length
, 0, InstanceId
, &Offset
);
423 USBSTOR_ConvertToUnicodeString(&Buffer
[Offset
], Length
, Offset
, InstanceId
, &Offset
);
425 InstanceId
[Offset
] = UNICODE_NULL
; // finish the REG_MULTI_SZ
427 DPRINT("USBSTOR_PdoHandleQueryCompatibleId %S\n", InstanceId
);
429 Irp
->IoStatus
.Information
= (ULONG_PTR
)InstanceId
;
430 return STATUS_SUCCESS
;
434 USBSTOR_PdoHandleQueryInstanceId(
435 IN PDEVICE_OBJECT DeviceObject
,
438 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
439 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
440 PUSB_STRING_DESCRIPTOR Descriptor
;
445 PDODeviceExtension
= DeviceObject
->DeviceExtension
;
446 FDODeviceExtension
= PDODeviceExtension
->LowerDeviceObject
->DeviceExtension
;
448 Descriptor
= FDODeviceExtension
->SerialNumber
;
449 if (Descriptor
&& (Descriptor
->bLength
>= sizeof(USB_COMMON_DESCRIPTOR
) + sizeof(WCHAR
)))
451 /* Format the serial number descriptor only if supported by the device */
452 CharCount
= (Descriptor
->bLength
- sizeof(USB_COMMON_DESCRIPTOR
)) / sizeof(WCHAR
) +
454 (sizeof("F") - 1) + // LUN: 1 char (MAX_LUN)
459 /* Use the instance count and LUN as a fallback */
460 CharCount
= (sizeof("99999999") - 1) + // Instance Count: 8 chars
462 (sizeof("F") - 1) + // LUN: 1 char (MAX_LUN)
466 InstanceId
= ExAllocatePoolUninitialized(PagedPool
, CharCount
* sizeof(WCHAR
), USB_STOR_TAG
);
469 Irp
->IoStatus
.Information
= 0;
470 return STATUS_INSUFFICIENT_RESOURCES
;
473 if (Descriptor
&& (Descriptor
->bLength
>= sizeof(USB_COMMON_DESCRIPTOR
) + sizeof(WCHAR
)))
475 Status
= RtlStringCchPrintfW(InstanceId
,
479 PDODeviceExtension
->LUN
);
483 Status
= RtlStringCchPrintfW(InstanceId
,
486 FDODeviceExtension
->InstanceCount
,
487 PDODeviceExtension
->LUN
);
490 /* This should not happen */
491 ASSERT(NT_SUCCESS(Status
));
493 DPRINT("USBSTOR_PdoHandleQueryInstanceId '%S'\n", InstanceId
);
495 Irp
->IoStatus
.Information
= (ULONG_PTR
)InstanceId
;
496 return STATUS_SUCCESS
;
500 USBSTOR_PdoHandleDeviceRelations(
501 IN PDEVICE_OBJECT DeviceObject
,
504 PDEVICE_RELATIONS DeviceRelations
;
505 PIO_STACK_LOCATION IoStack
;
507 DPRINT("USBSTOR_PdoHandleDeviceRelations\n");
509 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
511 // check if relation type is BusRelations
512 if (IoStack
->Parameters
.QueryDeviceRelations
.Type
!= TargetDeviceRelation
)
514 // PDO handles only target device relation
515 return Irp
->IoStatus
.Status
;
518 DeviceRelations
= ExAllocatePoolWithTag(PagedPool
, sizeof(DEVICE_RELATIONS
), USB_STOR_TAG
);
519 if (!DeviceRelations
)
521 return STATUS_INSUFFICIENT_RESOURCES
;
524 // initialize device relations
525 DeviceRelations
->Count
= 1;
526 DeviceRelations
->Objects
[0] = DeviceObject
;
527 ObReferenceObject(DeviceObject
);
529 Irp
->IoStatus
.Information
= (ULONG_PTR
)DeviceRelations
;
530 return STATUS_SUCCESS
;
534 USBSTOR_PdoHandlePnp(
535 IN PDEVICE_OBJECT DeviceObject
,
538 PIO_STACK_LOCATION IoStack
;
539 PPDO_DEVICE_EXTENSION DeviceExtension
;
541 PDEVICE_CAPABILITIES Caps
;
544 IoStack
= IoGetCurrentIrpStackLocation(Irp
);
545 DeviceExtension
= (PPDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
546 ASSERT(DeviceExtension
->Common
.IsFDO
== FALSE
);
548 switch(IoStack
->MinorFunction
)
550 case IRP_MN_QUERY_DEVICE_RELATIONS
:
552 Status
= USBSTOR_PdoHandleDeviceRelations(DeviceObject
, Irp
);
555 case IRP_MN_QUERY_DEVICE_TEXT
:
557 Status
= USBSTOR_PdoHandleQueryDeviceText(DeviceObject
, Irp
);
560 case IRP_MN_QUERY_ID
:
562 if (IoStack
->Parameters
.QueryId
.IdType
== BusQueryDeviceID
)
564 Status
= USBSTOR_PdoHandleQueryDeviceId(DeviceObject
, Irp
);
567 else if (IoStack
->Parameters
.QueryId
.IdType
== BusQueryHardwareIDs
)
569 Status
= USBSTOR_PdoHandleQueryHardwareId(DeviceObject
, Irp
);
572 else if (IoStack
->Parameters
.QueryId
.IdType
== BusQueryInstanceID
)
574 Status
= USBSTOR_PdoHandleQueryInstanceId(DeviceObject
, Irp
);
577 else if (IoStack
->Parameters
.QueryId
.IdType
== BusQueryCompatibleIDs
)
579 Status
= USBSTOR_PdoHandleQueryCompatibleId(DeviceObject
, Irp
);
583 DPRINT1("USBSTOR_PdoHandlePnp: IRP_MN_QUERY_ID IdType %x unimplemented\n", IoStack
->Parameters
.QueryId
.IdType
);
584 Status
= STATUS_NOT_SUPPORTED
;
585 Irp
->IoStatus
.Information
= 0;
588 case IRP_MN_REMOVE_DEVICE
:
590 DPRINT("IRP_MN_REMOVE_DEVICE\n");
592 if(*DeviceExtension
->PDODeviceObject
!= NULL
)
594 *DeviceExtension
->PDODeviceObject
= NULL
;
599 // device object already marked for deletion
603 Irp
->IoStatus
.Status
= STATUS_SUCCESS
;
604 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
608 IoDeleteDevice(DeviceObject
);
610 return STATUS_SUCCESS
;
612 case IRP_MN_QUERY_CAPABILITIES
:
614 // just forward irp to lower device
615 Status
= STATUS_UNSUCCESSFUL
;
617 if (IoForwardIrpSynchronously(DeviceExtension
->LowerDeviceObject
, Irp
))
619 Status
= Irp
->IoStatus
.Status
;
620 ASSERT(Status
== STATUS_SUCCESS
);
622 if (NT_SUCCESS(Status
))
624 // check if no unique id
625 Caps
= (PDEVICE_CAPABILITIES
)IoStack
->Parameters
.DeviceCapabilities
.Capabilities
;
626 Caps
->UniqueID
= FALSE
; // no unique id is supported
627 Caps
->Removable
= TRUE
; //FIXME
632 case IRP_MN_QUERY_REMOVE_DEVICE
:
633 case IRP_MN_QUERY_STOP_DEVICE
:
635 if (DeviceExtension
->Claimed
)
637 Status
= STATUS_UNSUCCESSFUL
;
638 DPRINT1("[USBSTOR] Request %x fails because device is still claimed\n", IoStack
->MinorFunction
);
641 Status
= STATUS_SUCCESS
;
644 case IRP_MN_START_DEVICE
:
647 Status
= STATUS_SUCCESS
;
650 case IRP_MN_SURPRISE_REMOVAL
:
652 Status
= STATUS_SUCCESS
;
658 Status
= Irp
->IoStatus
.Status
;
662 if (Status
!= STATUS_PENDING
)
664 Irp
->IoStatus
.Status
= Status
;
665 IoCompleteRequest(Irp
, IO_NO_INCREMENT
);
673 USBSTOR_SyncCompletionRoutine(
674 IN PDEVICE_OBJECT DeviceObject
,
678 KeSetEvent((PKEVENT
)Ctx
, IO_NO_INCREMENT
, FALSE
);
679 return STATUS_MORE_PROCESSING_REQUIRED
;
683 * @name USBSTOR_SendInternalCdb
685 * Issues an internal SCSI request to device.
686 * The request is sent in a synchronous way.
690 USBSTOR_SendInternalCdb(
691 IN PDEVICE_OBJECT PdoDevice
,
694 IN ULONG TimeOutValue
,
695 OUT PVOID OutDataBuffer
,
696 OUT PULONG OutDataTransferLength
)
698 PSCSI_REQUEST_BLOCK Srb
;
699 PSENSE_DATA SenseBuffer
;
700 PIO_STACK_LOCATION IoStack
;
705 NTSTATUS Status
= STATUS_INSUFFICIENT_RESOURCES
;
708 DPRINT("USBSTOR_SendInternalCdb SCSIOP %x\n", Cdb
->CDB6GENERIC
.OperationCode
);
710 Srb
= ExAllocatePoolWithTag(NonPagedPool
,
711 sizeof(SCSI_REQUEST_BLOCK
),
716 SenseBuffer
= ExAllocatePoolWithTag(NonPagedPool
,
722 Mdl
= IoAllocateMdl(OutDataBuffer
,
723 *OutDataTransferLength
,
730 ExFreePoolWithTag(SenseBuffer
, USB_STOR_TAG
);
731 ExFreePoolWithTag(Srb
, USB_STOR_TAG
);
735 MmBuildMdlForNonPagedPool(Mdl
);
737 // make 3 attempts - the device may be in STALL state after the first one
740 Irp
= IoAllocateIrp(PdoDevice
->StackSize
, FALSE
);
747 IoStack
= IoGetNextIrpStackLocation(Irp
);
748 IoStack
->MajorFunction
= IRP_MJ_INTERNAL_DEVICE_CONTROL
;
749 IoStack
->Parameters
.Scsi
.Srb
= Srb
;
751 RtlZeroMemory(Srb
, sizeof(SCSI_REQUEST_BLOCK
));
753 Srb
->Length
= sizeof(SCSI_REQUEST_BLOCK
);
754 Srb
->Function
= SRB_FUNCTION_EXECUTE_SCSI
;
755 Srb
->CdbLength
= CdbLength
;
756 Srb
->SenseInfoBufferLength
= SENSE_BUFFER_SIZE
;
757 Srb
->SrbFlags
= SRB_FLAGS_DATA_IN
| SRB_FLAGS_NO_QUEUE_FREEZE
;
758 Srb
->DataTransferLength
= *OutDataTransferLength
;
759 Srb
->TimeOutValue
= TimeOutValue
;
760 Srb
->DataBuffer
= OutDataBuffer
;
761 Srb
->SenseInfoBuffer
= SenseBuffer
;
763 RtlCopyMemory(Srb
->Cdb
, Cdb
, CdbLength
);
765 Irp
->MdlAddress
= Mdl
;
767 KeInitializeEvent(&Event
, SynchronizationEvent
, FALSE
);
769 IoSetCompletionRoutine(Irp
,
770 USBSTOR_SyncCompletionRoutine
,
776 if (IoCallDriver(PdoDevice
, Irp
) == STATUS_PENDING
)
778 KeWaitForSingleObject(&Event
,
785 SrbStatus
= SRB_STATUS(Srb
->SrbStatus
);
790 if (SrbStatus
== SRB_STATUS_SUCCESS
||
791 SrbStatus
== SRB_STATUS_DATA_OVERRUN
)
793 Status
= STATUS_SUCCESS
;
794 *OutDataTransferLength
= Srb
->DataTransferLength
;
798 Status
= STATUS_UNSUCCESSFUL
;
808 ExFreePoolWithTag(SenseBuffer
, USB_STOR_TAG
);
811 ExFreePoolWithTag(Srb
, USB_STOR_TAG
);
818 * @name USBSTOR_FillInquiryData
820 * Sends a SCSI Inquiry request and fills in the PDODeviceExtension->InquiryData field with a result.
824 USBSTOR_FillInquiryData(
825 IN PDEVICE_OBJECT PDODeviceObject
)
827 NTSTATUS Status
= STATUS_INSUFFICIENT_RESOURCES
;
828 PPDO_DEVICE_EXTENSION PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)PDODeviceObject
->DeviceExtension
;
830 ULONG DataTransferLength
= INQUIRYDATABUFFERSIZE
;
831 PINQUIRYDATA InquiryData
= (PINQUIRYDATA
)&PDODeviceExtension
->InquiryData
;
833 RtlZeroMemory(&Cdb
, sizeof(Cdb
));
834 Cdb
.CDB6INQUIRY
.OperationCode
= SCSIOP_INQUIRY
;
835 Cdb
.CDB6INQUIRY
.AllocationLength
= INQUIRYDATABUFFERSIZE
;
837 Status
= USBSTOR_SendInternalCdb(PDODeviceObject
, &Cdb
, CDB6GENERIC_LENGTH
, 20, InquiryData
, &DataTransferLength
);
839 if (!NT_SUCCESS(Status
))
841 DPRINT1("USBSTOR_FillInquiryData failed with %x\n", Status
);
845 DPRINT("DeviceType %x\n", InquiryData
->DeviceType
);
846 DPRINT("DeviceTypeModifier %x\n", InquiryData
->DeviceTypeModifier
);
847 DPRINT("RemovableMedia %x\n", InquiryData
->RemovableMedia
);
848 DPRINT("Version %x\n", InquiryData
->Versions
);
849 DPRINT("Format %x\n", InquiryData
->ResponseDataFormat
);
850 DPRINT("Length %x\n", InquiryData
->AdditionalLength
);
851 DPRINT("Reserved %p\n", InquiryData
->Reserved
);
852 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]);
853 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],
854 InquiryData
->ProductId
[4], InquiryData
->ProductId
[5], InquiryData
->ProductId
[6], InquiryData
->ProductId
[7],
855 InquiryData
->ProductId
[8], InquiryData
->ProductId
[9], InquiryData
->ProductId
[10], InquiryData
->ProductId
[11],
856 InquiryData
->ProductId
[12], InquiryData
->ProductId
[13], InquiryData
->ProductId
[14], InquiryData
->ProductId
[15]);
858 DPRINT("Revision %c%c%c%c\n", InquiryData
->ProductRevisionLevel
[0], InquiryData
->ProductRevisionLevel
[1], InquiryData
->ProductRevisionLevel
[2], InquiryData
->ProductRevisionLevel
[3]);
865 IN PDEVICE_OBJECT DeviceObject
,
870 PPDO_DEVICE_EXTENSION PDODeviceExtension
;
871 PFDO_DEVICE_EXTENSION FDODeviceExtension
;
872 PINQUIRYDATA InquiryData
;
874 FDODeviceExtension
= (PFDO_DEVICE_EXTENSION
)DeviceObject
->DeviceExtension
;
876 // create child device object
877 Status
= IoCreateDevice(DeviceObject
->DriverObject
, sizeof(PDO_DEVICE_EXTENSION
), NULL
, FILE_DEVICE_MASS_STORAGE
, FILE_AUTOGENERATED_DEVICE_NAME
| FILE_DEVICE_SECURE_OPEN
, FALSE
, &PDO
);
878 if (!NT_SUCCESS(Status
))
880 DPRINT1("Failed to create PDO, status %x\n", Status
);
884 // patch the stack size
885 PDO
->StackSize
= DeviceObject
->StackSize
;
887 PDODeviceExtension
= (PPDO_DEVICE_EXTENSION
)PDO
->DeviceExtension
;
888 InquiryData
= (PINQUIRYDATA
)&PDODeviceExtension
->InquiryData
;
890 // initialize device extension
891 RtlZeroMemory(PDODeviceExtension
, sizeof(PDO_DEVICE_EXTENSION
));
892 PDODeviceExtension
->Common
.IsFDO
= FALSE
;
893 PDODeviceExtension
->LowerDeviceObject
= DeviceObject
;
894 PDODeviceExtension
->PDODeviceObject
= &FDODeviceExtension
->ChildPDO
[LUN
];
895 PDODeviceExtension
->Self
= PDO
;
896 PDODeviceExtension
->LUN
= LUN
;
898 PDO
->Flags
|= DO_DIRECT_IO
;
900 // device is initialized
901 PDO
->Flags
&= ~DO_DEVICE_INITIALIZING
;
903 // output device object
904 FDODeviceExtension
->ChildPDO
[LUN
] = PDO
;
906 // send inquiry command by irp
907 Status
= USBSTOR_FillInquiryData(PDO
);
909 if (!NT_SUCCESS(Status
))
914 if (InquiryData
->DeviceType
!= DIRECT_ACCESS_DEVICE
&&
915 InquiryData
->DeviceType
!= READ_ONLY_DIRECT_ACCESS_DEVICE
)
917 return STATUS_NOT_SUPPORTED
;