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
18a9b97aedSVictor Perevertkin static
19c2c66affSColin Finck LPCSTR
USBSTOR_GetDeviceType(IN PINQUIRYDATA InquiryData)20c2c66affSColin Finck USBSTOR_GetDeviceType(
21a9b97aedSVictor Perevertkin IN PINQUIRYDATA InquiryData)
22c2c66affSColin Finck {
23c2c66affSColin Finck switch (InquiryData->DeviceType)
24c2c66affSColin Finck {
25a9b97aedSVictor Perevertkin case DIRECT_ACCESS_DEVICE:
26a9b97aedSVictor Perevertkin return "Disk";
27a9b97aedSVictor Perevertkin case SEQUENTIAL_ACCESS_DEVICE:
28c2c66affSColin Finck // sequential device, i.e magnetic tape
29c2c66affSColin Finck return "Sequential";
30a9b97aedSVictor Perevertkin case WRITE_ONCE_READ_MULTIPLE_DEVICE:
31c2c66affSColin Finck return "Worm";
32a9b97aedSVictor Perevertkin case READ_ONLY_DIRECT_ACCESS_DEVICE:
33c2c66affSColin Finck return "CdRom";
34a9b97aedSVictor Perevertkin case OPTICAL_DEVICE:
35c2c66affSColin Finck return "Optical";
36a9b97aedSVictor Perevertkin case MEDIUM_CHANGER:
37c2c66affSColin Finck return "Changer";
38c2c66affSColin Finck default:
39c2c66affSColin Finck return "Other";
40c2c66affSColin Finck }
41c2c66affSColin Finck }
42c2c66affSColin Finck
43a9b97aedSVictor Perevertkin static
44c2c66affSColin Finck LPCSTR
USBSTOR_GetGenericType(IN PINQUIRYDATA InquiryData)45c2c66affSColin Finck USBSTOR_GetGenericType(
46a9b97aedSVictor Perevertkin IN PINQUIRYDATA InquiryData)
47c2c66affSColin Finck {
48c2c66affSColin Finck switch (InquiryData->DeviceType)
49c2c66affSColin Finck {
50a9b97aedSVictor Perevertkin case DIRECT_ACCESS_DEVICE:
51a9b97aedSVictor Perevertkin return "GenDisk";
52a9b97aedSVictor Perevertkin case SEQUENTIAL_ACCESS_DEVICE:
53c2c66affSColin Finck // sequential device, i.e magnetic tape
54c2c66affSColin Finck return "GenSequential";
55a9b97aedSVictor Perevertkin case WRITE_ONCE_READ_MULTIPLE_DEVICE:
56c2c66affSColin Finck return "GenWorm";
57a9b97aedSVictor Perevertkin case READ_ONLY_DIRECT_ACCESS_DEVICE:
58c2c66affSColin Finck return "GenCdRom";
59a9b97aedSVictor Perevertkin case OPTICAL_DEVICE:
60c2c66affSColin Finck return "GenOptical";
61a9b97aedSVictor Perevertkin case MEDIUM_CHANGER:
62c2c66affSColin Finck return "GenChanger";
63c2c66affSColin Finck default:
64c2c66affSColin Finck return "UsbstorOther";
65c2c66affSColin Finck }
66c2c66affSColin Finck }
67c2c66affSColin Finck
68126abaf8SVictor Perevertkin static
69c2c66affSColin Finck ULONG
CopyField(IN PUCHAR Name,IN PCHAR Buffer,IN ULONG MaxLength)70c2c66affSColin Finck CopyField(
71c2c66affSColin Finck IN PUCHAR Name,
72c2c66affSColin Finck IN PCHAR Buffer,
73c2c66affSColin Finck IN ULONG MaxLength)
74c2c66affSColin Finck {
75c2c66affSColin Finck ULONG Index;
76c2c66affSColin Finck
77c2c66affSColin Finck for (Index = 0; Index < MaxLength; Index++)
78c2c66affSColin Finck {
79c2c66affSColin Finck if (Name[Index] <= ' ' || Name[Index] >= 0x7F /* last printable ascii character */ || Name[Index] == ',')
80c2c66affSColin Finck {
81c2c66affSColin Finck // convert to underscore
82c2c66affSColin Finck Buffer[Index] = '_';
83c2c66affSColin Finck }
84c2c66affSColin Finck else
85c2c66affSColin Finck {
86c2c66affSColin Finck // just copy character
87c2c66affSColin Finck Buffer[Index] = Name[Index];
88c2c66affSColin Finck }
89c2c66affSColin Finck }
90c2c66affSColin Finck
91c2c66affSColin Finck return MaxLength;
92c2c66affSColin Finck }
93c2c66affSColin Finck
94126abaf8SVictor Perevertkin static
95126abaf8SVictor Perevertkin ULONG
CopyFieldTruncate(IN PUCHAR Name,IN PCHAR Buffer,IN ULONG MaxLength)96126abaf8SVictor Perevertkin CopyFieldTruncate(
97126abaf8SVictor Perevertkin IN PUCHAR Name,
98126abaf8SVictor Perevertkin IN PCHAR Buffer,
99126abaf8SVictor Perevertkin IN ULONG MaxLength)
100126abaf8SVictor Perevertkin {
101126abaf8SVictor Perevertkin ULONG Index;
102126abaf8SVictor Perevertkin
103126abaf8SVictor Perevertkin for (Index = 0; Index < MaxLength; Index++)
104126abaf8SVictor Perevertkin {
105126abaf8SVictor Perevertkin if (Name[Index] == '\0')
106126abaf8SVictor Perevertkin {
107126abaf8SVictor Perevertkin break;
108126abaf8SVictor Perevertkin }
109126abaf8SVictor Perevertkin else if (Name[Index] <= ' ' || Name[Index] >= 0x7F /* last printable ascii character */ || Name[Index] == ',')
110126abaf8SVictor Perevertkin {
111126abaf8SVictor Perevertkin // convert to underscore
112126abaf8SVictor Perevertkin Buffer[Index] = ' ';
113126abaf8SVictor Perevertkin }
114126abaf8SVictor Perevertkin else
115126abaf8SVictor Perevertkin {
116126abaf8SVictor Perevertkin // just copy character
117126abaf8SVictor Perevertkin Buffer[Index] = Name[Index];
118126abaf8SVictor Perevertkin }
119126abaf8SVictor Perevertkin }
120126abaf8SVictor Perevertkin
121126abaf8SVictor Perevertkin return Index;
122126abaf8SVictor Perevertkin }
123126abaf8SVictor Perevertkin
124c2c66affSColin Finck NTSTATUS
USBSTOR_PdoHandleQueryDeviceText(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)125c2c66affSColin Finck USBSTOR_PdoHandleQueryDeviceText(
126c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject,
127c2c66affSColin Finck IN PIRP Irp)
128c2c66affSColin Finck {
129126abaf8SVictor Perevertkin PPDO_DEVICE_EXTENSION DeviceExtension;
130c2c66affSColin Finck PIO_STACK_LOCATION IoStack;
131126abaf8SVictor Perevertkin CHAR LocalBuffer[26];
132126abaf8SVictor Perevertkin UINT32 Offset = 0;
133126abaf8SVictor Perevertkin PINQUIRYDATA InquiryData;
134126abaf8SVictor Perevertkin ANSI_STRING AnsiString;
135126abaf8SVictor Perevertkin UNICODE_STRING DeviceDescription;
136c2c66affSColin Finck
137c2c66affSColin Finck IoStack = IoGetCurrentIrpStackLocation(Irp);
138c2c66affSColin Finck
139126abaf8SVictor Perevertkin DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
14094e61c30SVictor Perevertkin InquiryData = (PINQUIRYDATA)&DeviceExtension->InquiryData;
141c2c66affSColin Finck
142126abaf8SVictor Perevertkin switch (IoStack->Parameters.QueryDeviceText.DeviceTextType)
143126abaf8SVictor Perevertkin {
144126abaf8SVictor Perevertkin case DeviceTextDescription:
145126abaf8SVictor Perevertkin case DeviceTextLocationInformation:
146126abaf8SVictor Perevertkin {
147126abaf8SVictor Perevertkin DPRINT("USBSTOR_PdoHandleQueryDeviceText\n");
148126abaf8SVictor Perevertkin
149126abaf8SVictor Perevertkin Offset += CopyFieldTruncate(InquiryData->VendorId, &LocalBuffer[Offset], sizeof(InquiryData->VendorId));
150126abaf8SVictor Perevertkin LocalBuffer[Offset++] = ' ';
151126abaf8SVictor Perevertkin Offset += CopyFieldTruncate(InquiryData->ProductId, &LocalBuffer[Offset], sizeof(InquiryData->ProductId));
152126abaf8SVictor Perevertkin LocalBuffer[Offset++] = '\0';
153126abaf8SVictor Perevertkin
154126abaf8SVictor Perevertkin RtlInitAnsiString(&AnsiString, (PCSZ)&LocalBuffer);
155126abaf8SVictor Perevertkin
156126abaf8SVictor Perevertkin DeviceDescription.Length = 0;
157126abaf8SVictor Perevertkin DeviceDescription.MaximumLength = (USHORT)(Offset * sizeof(WCHAR));
158a9b97aedSVictor Perevertkin DeviceDescription.Buffer = ExAllocatePoolWithTag(PagedPool, DeviceDescription.MaximumLength, USB_STOR_TAG);
159126abaf8SVictor Perevertkin if (!DeviceDescription.Buffer)
160c2c66affSColin Finck {
161c2c66affSColin Finck Irp->IoStatus.Information = 0;
162c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES;
163c2c66affSColin Finck }
164c2c66affSColin Finck
165126abaf8SVictor Perevertkin RtlAnsiStringToUnicodeString(&DeviceDescription, &AnsiString, FALSE);
166c2c66affSColin Finck
167126abaf8SVictor Perevertkin Irp->IoStatus.Information = (ULONG_PTR)DeviceDescription.Buffer;
168c2c66affSColin Finck return STATUS_SUCCESS;
169c2c66affSColin Finck }
170126abaf8SVictor Perevertkin default:
171c2c66affSColin Finck {
172c2c66affSColin Finck Irp->IoStatus.Information = 0;
173126abaf8SVictor Perevertkin return Irp->IoStatus.Status;
174c2c66affSColin Finck }
175c2c66affSColin Finck }
176c2c66affSColin Finck }
177c2c66affSColin Finck
178c2c66affSColin Finck NTSTATUS
USBSTOR_PdoHandleQueryDeviceId(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)179c2c66affSColin Finck USBSTOR_PdoHandleQueryDeviceId(
180c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject,
181c2c66affSColin Finck IN PIRP Irp)
182c2c66affSColin Finck {
183c2c66affSColin Finck PPDO_DEVICE_EXTENSION DeviceExtension;
184c2c66affSColin Finck NTSTATUS Status;
185d17d15abSVictor Perevertkin CHAR Buffer[100] = {0};
186c2c66affSColin Finck LPCSTR DeviceType;
187c2c66affSColin Finck ULONG Offset = 0;
188f3fd12b9SVictor Perevertkin PINQUIRYDATA InquiryData;
189c2c66affSColin Finck ANSI_STRING AnsiString;
190c2c66affSColin Finck UNICODE_STRING DeviceId;
191c2c66affSColin Finck
192c2c66affSColin Finck DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
19394e61c30SVictor Perevertkin InquiryData = (PINQUIRYDATA)&DeviceExtension->InquiryData;
194c2c66affSColin Finck
195a9b97aedSVictor Perevertkin DeviceType = USBSTOR_GetDeviceType(InquiryData);
196c2c66affSColin Finck
197c2c66affSColin Finck // lets create device string
198c2c66affSColin Finck Offset = sprintf(&Buffer[Offset], "USBSTOR\\");
199c2c66affSColin Finck Offset += sprintf(&Buffer[Offset], DeviceType);
200c2c66affSColin Finck Offset += sprintf(&Buffer[Offset], "&Ven_");
201f3fd12b9SVictor Perevertkin Offset += CopyField(InquiryData->VendorId, &Buffer[Offset], 8);
202c2c66affSColin Finck Offset += sprintf(&Buffer[Offset], "&Prod_");
203f3fd12b9SVictor Perevertkin Offset += CopyField(InquiryData->ProductId, &Buffer[Offset], 16);
204c2c66affSColin Finck Offset += sprintf(&Buffer[Offset], "&Rev_");
205f3fd12b9SVictor Perevertkin Offset += CopyField(InquiryData->ProductRevisionLevel, &Buffer[Offset], 4);
206c2c66affSColin Finck
207c2c66affSColin Finck RtlInitAnsiString(&AnsiString, (PCSZ)Buffer);
208c2c66affSColin Finck
209c2c66affSColin Finck // allocate DeviceId string
210c2c66affSColin Finck DeviceId.Length = 0;
211f3fd12b9SVictor Perevertkin DeviceId.MaximumLength = (USHORT)((strlen((PCHAR)Buffer) + 1) * sizeof(WCHAR));
212a9b97aedSVictor Perevertkin DeviceId.Buffer = ExAllocatePoolWithTag(PagedPool, DeviceId.MaximumLength, USB_STOR_TAG);
213c2c66affSColin Finck if (!DeviceId.Buffer)
214c2c66affSColin Finck {
215c2c66affSColin Finck Irp->IoStatus.Information = 0;
216c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES;
217c2c66affSColin Finck }
218c2c66affSColin Finck
219c2c66affSColin Finck Status = RtlAnsiStringToUnicodeString(&DeviceId, &AnsiString, FALSE);
220c2c66affSColin Finck
221c2c66affSColin Finck if (NT_SUCCESS(Status))
222c2c66affSColin Finck {
223c2c66affSColin Finck Irp->IoStatus.Information = (ULONG_PTR)DeviceId.Buffer;
224c2c66affSColin Finck }
225c2c66affSColin Finck
226c2c66affSColin Finck DPRINT("DeviceId %wZ Status %x\n", &DeviceId, Status);
227c2c66affSColin Finck
228c2c66affSColin Finck return Status;
229c2c66affSColin Finck }
230c2c66affSColin Finck
231c2c66affSColin Finck VOID
USBSTOR_ConvertToUnicodeString(IN CHAR * Buffer,IN ULONG ResultBufferLength,IN ULONG ResultBufferOffset,OUT LPWSTR ResultBuffer,OUT PULONG NewResultBufferOffset)232c2c66affSColin Finck USBSTOR_ConvertToUnicodeString(
233c2c66affSColin Finck IN CHAR * Buffer,
234c2c66affSColin Finck IN ULONG ResultBufferLength,
235c2c66affSColin Finck IN ULONG ResultBufferOffset,
236c2c66affSColin Finck OUT LPWSTR ResultBuffer,
237c2c66affSColin Finck OUT PULONG NewResultBufferOffset)
238c2c66affSColin Finck {
239c2c66affSColin Finck UNICODE_STRING DeviceString;
240c2c66affSColin Finck ANSI_STRING AnsiString;
241c2c66affSColin Finck NTSTATUS Status;
242c2c66affSColin Finck
243c2c66affSColin Finck ASSERT(ResultBufferLength);
244c2c66affSColin Finck ASSERT(ResultBufferLength > ResultBufferOffset);
245c2c66affSColin Finck
246c2c66affSColin Finck DPRINT("ResultBufferOffset %lu ResultBufferLength %lu Buffer %s Length %lu\n", ResultBufferOffset, ResultBufferLength, Buffer, strlen(Buffer));
247c2c66affSColin Finck
248c2c66affSColin Finck // construct destination string
249c2c66affSColin Finck DeviceString.Buffer = &ResultBuffer[ResultBufferOffset];
250c2c66affSColin Finck DeviceString.Length = 0;
251c2c66affSColin Finck DeviceString.MaximumLength = (ResultBufferLength - ResultBufferOffset) * sizeof(WCHAR);
252c2c66affSColin Finck
253c2c66affSColin Finck // initialize source string
254c2c66affSColin Finck RtlInitAnsiString(&AnsiString, Buffer);
255c2c66affSColin Finck
256c2c66affSColin Finck Status = RtlAnsiStringToUnicodeString(&DeviceString, &AnsiString, FALSE);
257c2c66affSColin Finck ASSERT(Status == STATUS_SUCCESS);
258c2c66affSColin Finck
259c2c66affSColin Finck // subtract consumed bytes
260c2c66affSColin Finck ResultBufferLength -= (DeviceString.Length + sizeof(WCHAR)) / sizeof(WCHAR);
261c2c66affSColin Finck ResultBufferOffset += (DeviceString.Length + sizeof(WCHAR)) / sizeof(WCHAR);
262c2c66affSColin Finck
263c2c66affSColin Finck *NewResultBufferOffset = ResultBufferOffset;
264c2c66affSColin Finck }
265c2c66affSColin Finck
266c2c66affSColin Finck NTSTATUS
USBSTOR_PdoHandleQueryHardwareId(IN PDEVICE_OBJECT DeviceObject,IN OUT PIRP Irp)267c2c66affSColin Finck USBSTOR_PdoHandleQueryHardwareId(
268c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject,
269c2c66affSColin Finck IN OUT PIRP Irp)
270c2c66affSColin Finck {
271c2c66affSColin Finck PPDO_DEVICE_EXTENSION PDODeviceExtension;
272c2c66affSColin Finck PFDO_DEVICE_EXTENSION FDODeviceExtension;
273c2c66affSColin Finck LPCSTR GenericType, DeviceType;
274c2c66affSColin Finck LPWSTR Buffer;
2757bef5b88SEric Kohl CHAR Id1[50], Id2[50], Id3[50], Id4[50], Id5[50], Id6[50], Id7[50];
2767bef5b88SEric Kohl ULONG Id1Length, Id2Length, Id3Length, Id4Length, Id5Length, Id6Length, Id7Length;
277c2c66affSColin Finck ULONG Offset, TotalLength, Length;
278f3fd12b9SVictor Perevertkin PINQUIRYDATA InquiryData;
279c2c66affSColin Finck
280c2c66affSColin Finck PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
281c2c66affSColin Finck FDODeviceExtension = (PFDO_DEVICE_EXTENSION)PDODeviceExtension->LowerDeviceObject->DeviceExtension;
282c2c66affSColin Finck ASSERT(FDODeviceExtension->DeviceDescriptor);
28394e61c30SVictor Perevertkin InquiryData = (PINQUIRYDATA)&PDODeviceExtension->InquiryData;
284c2c66affSColin Finck
285a9b97aedSVictor Perevertkin DeviceType = USBSTOR_GetDeviceType(InquiryData);
286a9b97aedSVictor Perevertkin GenericType = USBSTOR_GetGenericType(InquiryData);
287c2c66affSColin Finck
288c2c66affSColin Finck ASSERT(GenericType);
289c2c66affSColin Finck
290c2c66affSColin Finck // generate id 1
291f3fd12b9SVictor Perevertkin // USBSTOR\SCSIType_VendorId(8)_ProductId(16)_Revision(4)
292c2c66affSColin Finck RtlZeroMemory(Id1, sizeof(Id1));
293c2c66affSColin Finck Offset = 0;
294c2c66affSColin Finck Offset = sprintf(&Id1[Offset], "USBSTOR\\");
295c2c66affSColin Finck Offset += sprintf(&Id1[Offset], DeviceType);
296f3fd12b9SVictor Perevertkin Offset += CopyField(InquiryData->VendorId, &Id1[Offset], 8);
297f3fd12b9SVictor Perevertkin Offset += CopyField(InquiryData->ProductId, &Id1[Offset], 16);
298f3fd12b9SVictor Perevertkin Offset += CopyField(InquiryData->ProductRevisionLevel, &Id1[Offset], 4);
299c2c66affSColin Finck Id1Length = strlen(Id1) + 1;
300c2c66affSColin Finck DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId1 %s\n", Id1);
301c2c66affSColin Finck
302c2c66affSColin Finck // generate id 2
303f3fd12b9SVictor Perevertkin // USBSTOR\SCSIType_VendorId(8)_ProductId(16)
304c2c66affSColin Finck RtlZeroMemory(Id2, sizeof(Id2));
305c2c66affSColin Finck Offset = 0;
306c2c66affSColin Finck Offset = sprintf(&Id2[Offset], "USBSTOR\\");
307c2c66affSColin Finck Offset += sprintf(&Id2[Offset], DeviceType);
308f3fd12b9SVictor Perevertkin Offset += CopyField(InquiryData->VendorId, &Id2[Offset], 8);
309f3fd12b9SVictor Perevertkin Offset += CopyField(InquiryData->ProductId, &Id2[Offset], 16);
310c2c66affSColin Finck Id2Length = strlen(Id2) + 1;
311c2c66affSColin Finck DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId2 %s\n", Id2);
312c2c66affSColin Finck
313c2c66affSColin Finck // generate id 3
314f3fd12b9SVictor Perevertkin // USBSTOR\SCSIType_VendorId(8)
315c2c66affSColin Finck RtlZeroMemory(Id3, sizeof(Id3));
316c2c66affSColin Finck Offset = 0;
317c2c66affSColin Finck Offset = sprintf(&Id3[Offset], "USBSTOR\\");
318c2c66affSColin Finck Offset += sprintf(&Id3[Offset], DeviceType);
319f3fd12b9SVictor Perevertkin Offset += CopyField(InquiryData->VendorId, &Id3[Offset], 8);
320c2c66affSColin Finck Id3Length = strlen(Id3) + 1;
321c2c66affSColin Finck DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId3 %s\n", Id3);
322c2c66affSColin Finck
323c2c66affSColin Finck // generate id 4
324f3fd12b9SVictor Perevertkin // USBSTOR\SCSIType_VendorId(8)_ProductId(16)_Revision(1)
325c2c66affSColin Finck RtlZeroMemory(Id4, sizeof(Id4));
326c2c66affSColin Finck Offset = 0;
327c2c66affSColin Finck Offset = sprintf(&Id4[Offset], "USBSTOR\\");
328c2c66affSColin Finck Offset += sprintf(&Id4[Offset], DeviceType);
329f3fd12b9SVictor Perevertkin Offset += CopyField(InquiryData->VendorId, &Id4[Offset], 8);
330f3fd12b9SVictor Perevertkin Offset += CopyField(InquiryData->ProductId, &Id4[Offset], 16);
331f3fd12b9SVictor Perevertkin Offset += CopyField(InquiryData->ProductRevisionLevel, &Id4[Offset], 1);
332c2c66affSColin Finck Id4Length = strlen(Id4) + 1;
333c2c66affSColin Finck DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId4 %s\n", Id4);
334c2c66affSColin Finck
335c2c66affSColin Finck // generate id 5
3367bef5b88SEric Kohl // SCSIType_VendorId(8)_ProductId(16)_Revision(1)
337c2c66affSColin Finck RtlZeroMemory(Id5, sizeof(Id5));
338c2c66affSColin Finck Offset = 0;
3397bef5b88SEric Kohl Offset = sprintf(&Id5[Offset], DeviceType);
3407bef5b88SEric Kohl Offset += CopyField(InquiryData->VendorId, &Id5[Offset], 8);
3417bef5b88SEric Kohl Offset += CopyField(InquiryData->ProductId, &Id5[Offset], 16);
3427bef5b88SEric Kohl Offset += CopyField(InquiryData->ProductRevisionLevel, &Id5[Offset], 1);
343c2c66affSColin Finck Id5Length = strlen(Id5) + 1;
344c2c66affSColin Finck DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId5 %s\n", Id5);
345c2c66affSColin Finck
346c2c66affSColin Finck // generate id 6
3477bef5b88SEric Kohl // USBSTOR\SCSIType
348c2c66affSColin Finck RtlZeroMemory(Id6, sizeof(Id6));
349c2c66affSColin Finck Offset = 0;
3507bef5b88SEric Kohl Offset = sprintf(&Id6[Offset], "USBSTOR\\");
3517bef5b88SEric Kohl Offset += sprintf(&Id6[Offset], GenericType);
352c2c66affSColin Finck Id6Length = strlen(Id6) + 1;
353c2c66affSColin Finck DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId6 %s\n", Id6);
354c2c66affSColin Finck
3557bef5b88SEric Kohl // generate id 7
3567bef5b88SEric Kohl // SCSIType
3577bef5b88SEric Kohl RtlZeroMemory(Id7, sizeof(Id7));
3587bef5b88SEric Kohl Offset = 0;
3597bef5b88SEric Kohl Offset = sprintf(&Id7[Offset], GenericType);
3607bef5b88SEric Kohl Id7Length = strlen(Id7) + 1;
3617bef5b88SEric Kohl DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId7 %s\n", Id7);
3627bef5b88SEric Kohl
3631e512e29SVictor Perevertkin // last +1 is for terminating \0 of REG_MULTI_SZ
3647bef5b88SEric Kohl TotalLength = Id1Length + Id2Length + Id3Length + Id4Length + Id5Length + Id6Length + Id7Length + 1;
365c2c66affSColin Finck
366a9b97aedSVictor Perevertkin Buffer = ExAllocatePoolWithTag(PagedPool, TotalLength * sizeof(WCHAR), USB_STOR_TAG);
367c2c66affSColin Finck if (!Buffer)
368c2c66affSColin Finck {
369c2c66affSColin Finck Irp->IoStatus.Information = 0;
370c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES;
371c2c66affSColin Finck }
372c2c66affSColin Finck
373c2c66affSColin Finck // reset offset
374c2c66affSColin Finck Offset = 0;
375c2c66affSColin Finck Length = TotalLength;
376c2c66affSColin Finck
377c2c66affSColin Finck USBSTOR_ConvertToUnicodeString(Id1, Length, Offset, Buffer, &Offset);
378c2c66affSColin Finck USBSTOR_ConvertToUnicodeString(Id2, Length, Offset, Buffer, &Offset);
379c2c66affSColin Finck USBSTOR_ConvertToUnicodeString(Id3, Length, Offset, Buffer, &Offset);
380c2c66affSColin Finck USBSTOR_ConvertToUnicodeString(Id4, Length, Offset, Buffer, &Offset);
381c2c66affSColin Finck USBSTOR_ConvertToUnicodeString(Id5, Length, Offset, Buffer, &Offset);
382c2c66affSColin Finck USBSTOR_ConvertToUnicodeString(Id6, Length, Offset, Buffer, &Offset);
3837bef5b88SEric Kohl USBSTOR_ConvertToUnicodeString(Id7, Length, Offset, Buffer, &Offset);
384c2c66affSColin Finck
3851e512e29SVictor Perevertkin Buffer[Offset] = UNICODE_NULL; // finish the REG_MULTI_SZ
3861e512e29SVictor Perevertkin
387c2c66affSColin Finck ASSERT(Offset + 1 == Length);
388c2c66affSColin Finck
389c2c66affSColin Finck Irp->IoStatus.Information = (ULONG_PTR)Buffer;
390c2c66affSColin Finck return STATUS_SUCCESS;
391c2c66affSColin Finck }
392c2c66affSColin Finck
393c2c66affSColin Finck NTSTATUS
USBSTOR_PdoHandleQueryCompatibleId(IN PDEVICE_OBJECT DeviceObject,IN OUT PIRP Irp)394c2c66affSColin Finck USBSTOR_PdoHandleQueryCompatibleId(
395c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject,
396c2c66affSColin Finck IN OUT PIRP Irp)
397c2c66affSColin Finck {
398c2c66affSColin Finck PPDO_DEVICE_EXTENSION PDODeviceExtension;
399c2c66affSColin Finck PFDO_DEVICE_EXTENSION FDODeviceExtension;
400d17d15abSVictor Perevertkin CHAR Buffer[100] = {0};
401c2c66affSColin Finck ULONG Length, Offset;
402c2c66affSColin Finck LPWSTR InstanceId;
403c2c66affSColin Finck LPCSTR DeviceType;
404c2c66affSColin Finck
405c2c66affSColin Finck PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
406c2c66affSColin Finck FDODeviceExtension = (PFDO_DEVICE_EXTENSION)PDODeviceExtension->LowerDeviceObject->DeviceExtension;
407c2c66affSColin Finck ASSERT(FDODeviceExtension->DeviceDescriptor);
40894e61c30SVictor Perevertkin DeviceType = USBSTOR_GetDeviceType((PINQUIRYDATA)&PDODeviceExtension->InquiryData);
409c2c66affSColin Finck
410c2c66affSColin Finck // format instance id
411c2c66affSColin Finck Length = sprintf(Buffer, "USBSTOR\\%s", DeviceType) + 1;
4121e512e29SVictor Perevertkin // +1 for terminating \0 and another +1 for \0 at the end of REG_MULTI_SZ
413c2c66affSColin Finck Length += sprintf(&Buffer[Length], "USBSTOR\\%s", "RAW") + 2;
414c2c66affSColin Finck
415a9b97aedSVictor Perevertkin InstanceId = ExAllocatePoolWithTag(PagedPool, Length * sizeof(WCHAR), USB_STOR_TAG);
416c2c66affSColin Finck if (!InstanceId)
417c2c66affSColin Finck {
418c2c66affSColin Finck Irp->IoStatus.Information = 0;
419c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES;
420c2c66affSColin Finck }
421c2c66affSColin Finck
422c2c66affSColin Finck USBSTOR_ConvertToUnicodeString(Buffer, Length, 0, InstanceId, &Offset);
423c2c66affSColin Finck USBSTOR_ConvertToUnicodeString(&Buffer[Offset], Length, Offset, InstanceId, &Offset);
424c2c66affSColin Finck
4251e512e29SVictor Perevertkin InstanceId[Offset] = UNICODE_NULL; // finish the REG_MULTI_SZ
4261e512e29SVictor Perevertkin
427c2c66affSColin Finck DPRINT("USBSTOR_PdoHandleQueryCompatibleId %S\n", InstanceId);
428c2c66affSColin Finck
429c2c66affSColin Finck Irp->IoStatus.Information = (ULONG_PTR)InstanceId;
430c2c66affSColin Finck return STATUS_SUCCESS;
431c2c66affSColin Finck }
432c2c66affSColin Finck
433c2c66affSColin Finck NTSTATUS
USBSTOR_PdoHandleQueryInstanceId(IN PDEVICE_OBJECT DeviceObject,IN OUT PIRP Irp)434c2c66affSColin Finck USBSTOR_PdoHandleQueryInstanceId(
435c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject,
436c2c66affSColin Finck IN OUT PIRP Irp)
437c2c66affSColin Finck {
438c2c66affSColin Finck PPDO_DEVICE_EXTENSION PDODeviceExtension;
439c2c66affSColin Finck PFDO_DEVICE_EXTENSION FDODeviceExtension;
440*20efea8fSAdam Słaboń PUSB_STRING_DESCRIPTOR Descriptor;
441*20efea8fSAdam Słaboń ULONG CharCount;
442c2c66affSColin Finck LPWSTR InstanceId;
443*20efea8fSAdam Słaboń NTSTATUS Status;
444c2c66affSColin Finck
445*20efea8fSAdam Słaboń PDODeviceExtension = DeviceObject->DeviceExtension;
446*20efea8fSAdam Słaboń FDODeviceExtension = PDODeviceExtension->LowerDeviceObject->DeviceExtension;
447c2c66affSColin Finck
448*20efea8fSAdam Słaboń Descriptor = FDODeviceExtension->SerialNumber;
449*20efea8fSAdam Słaboń if (Descriptor && (Descriptor->bLength >= sizeof(USB_COMMON_DESCRIPTOR) + sizeof(WCHAR)))
450c2c66affSColin Finck {
451*20efea8fSAdam Słaboń /* Format the serial number descriptor only if supported by the device */
452*20efea8fSAdam Słaboń CharCount = (Descriptor->bLength - sizeof(USB_COMMON_DESCRIPTOR)) / sizeof(WCHAR) +
453*20efea8fSAdam Słaboń (sizeof("&") - 1) +
454*20efea8fSAdam Słaboń (sizeof("F") - 1) + // LUN: 1 char (MAX_LUN)
455*20efea8fSAdam Słaboń sizeof(ANSI_NULL);
456c2c66affSColin Finck }
457c2c66affSColin Finck else
458c2c66affSColin Finck {
459*20efea8fSAdam Słaboń /* Use the instance count and LUN as a fallback */
460*20efea8fSAdam Słaboń CharCount = (sizeof("99999999") - 1) + // Instance Count: 8 chars
461*20efea8fSAdam Słaboń (sizeof("&") - 1) +
462*20efea8fSAdam Słaboń (sizeof("F") - 1) + // LUN: 1 char (MAX_LUN)
463*20efea8fSAdam Słaboń sizeof(ANSI_NULL);
464c2c66affSColin Finck }
465c2c66affSColin Finck
466*20efea8fSAdam Słaboń InstanceId = ExAllocatePoolUninitialized(PagedPool, CharCount * sizeof(WCHAR), USB_STOR_TAG);
467c2c66affSColin Finck if (!InstanceId)
468c2c66affSColin Finck {
469c2c66affSColin Finck Irp->IoStatus.Information = 0;
470c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES;
471c2c66affSColin Finck }
472c2c66affSColin Finck
473*20efea8fSAdam Słaboń if (Descriptor && (Descriptor->bLength >= sizeof(USB_COMMON_DESCRIPTOR) + sizeof(WCHAR)))
474*20efea8fSAdam Słaboń {
475*20efea8fSAdam Słaboń Status = RtlStringCchPrintfW(InstanceId,
476*20efea8fSAdam Słaboń CharCount,
477*20efea8fSAdam Słaboń L"%s&%x",
478*20efea8fSAdam Słaboń Descriptor->bString,
479*20efea8fSAdam Słaboń PDODeviceExtension->LUN);
480*20efea8fSAdam Słaboń }
481*20efea8fSAdam Słaboń else
482*20efea8fSAdam Słaboń {
483*20efea8fSAdam Słaboń Status = RtlStringCchPrintfW(InstanceId,
484*20efea8fSAdam Słaboń CharCount,
485*20efea8fSAdam Słaboń L"%04lu&%x",
486*20efea8fSAdam Słaboń FDODeviceExtension->InstanceCount,
487*20efea8fSAdam Słaboń PDODeviceExtension->LUN);
488*20efea8fSAdam Słaboń }
489c2c66affSColin Finck
490*20efea8fSAdam Słaboń /* This should not happen */
491*20efea8fSAdam Słaboń ASSERT(NT_SUCCESS(Status));
492*20efea8fSAdam Słaboń
493*20efea8fSAdam Słaboń DPRINT("USBSTOR_PdoHandleQueryInstanceId '%S'\n", InstanceId);
494c2c66affSColin Finck
495c2c66affSColin Finck Irp->IoStatus.Information = (ULONG_PTR)InstanceId;
496c2c66affSColin Finck return STATUS_SUCCESS;
497c2c66affSColin Finck }
498c2c66affSColin Finck
499c2c66affSColin Finck NTSTATUS
USBSTOR_PdoHandleDeviceRelations(IN PDEVICE_OBJECT DeviceObject,IN OUT PIRP Irp)500c2c66affSColin Finck USBSTOR_PdoHandleDeviceRelations(
501c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject,
502c2c66affSColin Finck IN OUT PIRP Irp)
503c2c66affSColin Finck {
504c2c66affSColin Finck PDEVICE_RELATIONS DeviceRelations;
505c2c66affSColin Finck PIO_STACK_LOCATION IoStack;
506c2c66affSColin Finck
507c2c66affSColin Finck DPRINT("USBSTOR_PdoHandleDeviceRelations\n");
508c2c66affSColin Finck
509c2c66affSColin Finck IoStack = IoGetCurrentIrpStackLocation(Irp);
510c2c66affSColin Finck
511c2c66affSColin Finck // check if relation type is BusRelations
512c2c66affSColin Finck if (IoStack->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation)
513c2c66affSColin Finck {
514c2c66affSColin Finck // PDO handles only target device relation
515c2c66affSColin Finck return Irp->IoStatus.Status;
516c2c66affSColin Finck }
517c2c66affSColin Finck
518a9b97aedSVictor Perevertkin DeviceRelations = ExAllocatePoolWithTag(PagedPool, sizeof(DEVICE_RELATIONS), USB_STOR_TAG);
519c2c66affSColin Finck if (!DeviceRelations)
520c2c66affSColin Finck {
521c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES;
522c2c66affSColin Finck }
523c2c66affSColin Finck
524c2c66affSColin Finck // initialize device relations
525c2c66affSColin Finck DeviceRelations->Count = 1;
526c2c66affSColin Finck DeviceRelations->Objects[0] = DeviceObject;
527c2c66affSColin Finck ObReferenceObject(DeviceObject);
528c2c66affSColin Finck
529c2c66affSColin Finck Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
530c2c66affSColin Finck return STATUS_SUCCESS;
531c2c66affSColin Finck }
532c2c66affSColin Finck
533c2c66affSColin Finck NTSTATUS
USBSTOR_PdoHandlePnp(IN PDEVICE_OBJECT DeviceObject,IN OUT PIRP Irp)534c2c66affSColin Finck USBSTOR_PdoHandlePnp(
535c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject,
536c2c66affSColin Finck IN OUT PIRP Irp)
537c2c66affSColin Finck {
538c2c66affSColin Finck PIO_STACK_LOCATION IoStack;
539c2c66affSColin Finck PPDO_DEVICE_EXTENSION DeviceExtension;
540c2c66affSColin Finck NTSTATUS Status;
541c2c66affSColin Finck PDEVICE_CAPABILITIES Caps;
542c2c66affSColin Finck ULONG bDelete;
543c2c66affSColin Finck
544c2c66affSColin Finck IoStack = IoGetCurrentIrpStackLocation(Irp);
545c2c66affSColin Finck DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
546c2c66affSColin Finck ASSERT(DeviceExtension->Common.IsFDO == FALSE);
547c2c66affSColin Finck
548c2c66affSColin Finck switch(IoStack->MinorFunction)
549c2c66affSColin Finck {
550c2c66affSColin Finck case IRP_MN_QUERY_DEVICE_RELATIONS:
551c2c66affSColin Finck {
552c2c66affSColin Finck Status = USBSTOR_PdoHandleDeviceRelations(DeviceObject, Irp);
553c2c66affSColin Finck break;
554c2c66affSColin Finck }
555c2c66affSColin Finck case IRP_MN_QUERY_DEVICE_TEXT:
556c2c66affSColin Finck {
557c2c66affSColin Finck Status = USBSTOR_PdoHandleQueryDeviceText(DeviceObject, Irp);
558c2c66affSColin Finck break;
559c2c66affSColin Finck }
560c2c66affSColin Finck case IRP_MN_QUERY_ID:
561c2c66affSColin Finck {
562c2c66affSColin Finck if (IoStack->Parameters.QueryId.IdType == BusQueryDeviceID)
563c2c66affSColin Finck {
564c2c66affSColin Finck Status = USBSTOR_PdoHandleQueryDeviceId(DeviceObject, Irp);
565c2c66affSColin Finck break;
566c2c66affSColin Finck }
567c2c66affSColin Finck else if (IoStack->Parameters.QueryId.IdType == BusQueryHardwareIDs)
568c2c66affSColin Finck {
569c2c66affSColin Finck Status = USBSTOR_PdoHandleQueryHardwareId(DeviceObject, Irp);
570c2c66affSColin Finck break;
571c2c66affSColin Finck }
572c2c66affSColin Finck else if (IoStack->Parameters.QueryId.IdType == BusQueryInstanceID)
573c2c66affSColin Finck {
574c2c66affSColin Finck Status = USBSTOR_PdoHandleQueryInstanceId(DeviceObject, Irp);
575c2c66affSColin Finck break;
576c2c66affSColin Finck }
577c2c66affSColin Finck else if (IoStack->Parameters.QueryId.IdType == BusQueryCompatibleIDs)
578c2c66affSColin Finck {
579c2c66affSColin Finck Status = USBSTOR_PdoHandleQueryCompatibleId(DeviceObject, Irp);
580c2c66affSColin Finck break;
581c2c66affSColin Finck }
582c2c66affSColin Finck
583c2c66affSColin Finck DPRINT1("USBSTOR_PdoHandlePnp: IRP_MN_QUERY_ID IdType %x unimplemented\n", IoStack->Parameters.QueryId.IdType);
584c2c66affSColin Finck Status = STATUS_NOT_SUPPORTED;
585c2c66affSColin Finck Irp->IoStatus.Information = 0;
586c2c66affSColin Finck break;
587c2c66affSColin Finck }
588c2c66affSColin Finck case IRP_MN_REMOVE_DEVICE:
589c2c66affSColin Finck {
590c2c66affSColin Finck DPRINT("IRP_MN_REMOVE_DEVICE\n");
591c2c66affSColin Finck
592c2c66affSColin Finck if(*DeviceExtension->PDODeviceObject != NULL)
593c2c66affSColin Finck {
594c2c66affSColin Finck *DeviceExtension->PDODeviceObject = NULL;
595c2c66affSColin Finck bDelete = TRUE;
596c2c66affSColin Finck }
597c2c66affSColin Finck else
598c2c66affSColin Finck {
599c2c66affSColin Finck // device object already marked for deletion
600c2c66affSColin Finck bDelete = FALSE;
601c2c66affSColin Finck }
602c2c66affSColin Finck
603c2c66affSColin Finck Irp->IoStatus.Status = STATUS_SUCCESS;
604c2c66affSColin Finck IoCompleteRequest(Irp, IO_NO_INCREMENT);
605c2c66affSColin Finck
606c2c66affSColin Finck if (bDelete)
607c2c66affSColin Finck {
608c2c66affSColin Finck IoDeleteDevice(DeviceObject);
609c2c66affSColin Finck }
610c2c66affSColin Finck return STATUS_SUCCESS;
611c2c66affSColin Finck }
612c2c66affSColin Finck case IRP_MN_QUERY_CAPABILITIES:
613c2c66affSColin Finck {
614c2c66affSColin Finck // just forward irp to lower device
6157ed1883cSVictor Perevertkin Status = STATUS_UNSUCCESSFUL;
6167ed1883cSVictor Perevertkin
6177ed1883cSVictor Perevertkin if (IoForwardIrpSynchronously(DeviceExtension->LowerDeviceObject, Irp))
6187ed1883cSVictor Perevertkin {
6197ed1883cSVictor Perevertkin Status = Irp->IoStatus.Status;
620c2c66affSColin Finck ASSERT(Status == STATUS_SUCCESS);
621c2c66affSColin Finck
622c2c66affSColin Finck if (NT_SUCCESS(Status))
623c2c66affSColin Finck {
624c2c66affSColin Finck // check if no unique id
625c2c66affSColin Finck Caps = (PDEVICE_CAPABILITIES)IoStack->Parameters.DeviceCapabilities.Capabilities;
626c2c66affSColin Finck Caps->UniqueID = FALSE; // no unique id is supported
627c2c66affSColin Finck Caps->Removable = TRUE; //FIXME
628c2c66affSColin Finck }
6297ed1883cSVictor Perevertkin }
630c2c66affSColin Finck break;
631c2c66affSColin Finck }
632c2c66affSColin Finck case IRP_MN_QUERY_REMOVE_DEVICE:
633c2c66affSColin Finck case IRP_MN_QUERY_STOP_DEVICE:
634c2c66affSColin Finck {
635c2c66affSColin Finck if (DeviceExtension->Claimed)
636c2c66affSColin Finck {
637c2c66affSColin Finck Status = STATUS_UNSUCCESSFUL;
638c2c66affSColin Finck DPRINT1("[USBSTOR] Request %x fails because device is still claimed\n", IoStack->MinorFunction);
639c2c66affSColin Finck }
640c2c66affSColin Finck else
641c2c66affSColin Finck Status = STATUS_SUCCESS;
642c2c66affSColin Finck break;
643c2c66affSColin Finck }
644c2c66affSColin Finck case IRP_MN_START_DEVICE:
645c2c66affSColin Finck {
646c2c66affSColin Finck // no-op for PDO
647c2c66affSColin Finck Status = STATUS_SUCCESS;
648c2c66affSColin Finck break;
649c2c66affSColin Finck }
650c2c66affSColin Finck case IRP_MN_SURPRISE_REMOVAL:
651c2c66affSColin Finck {
652c2c66affSColin Finck Status = STATUS_SUCCESS;
653c2c66affSColin Finck break;
654c2c66affSColin Finck }
655c2c66affSColin Finck default:
656c2c66affSColin Finck {
657c2c66affSColin Finck // do nothing
658c2c66affSColin Finck Status = Irp->IoStatus.Status;
659c2c66affSColin Finck }
660c2c66affSColin Finck }
661c2c66affSColin Finck
662c2c66affSColin Finck if (Status != STATUS_PENDING)
663c2c66affSColin Finck {
664c2c66affSColin Finck Irp->IoStatus.Status = Status;
665c2c66affSColin Finck IoCompleteRequest(Irp, IO_NO_INCREMENT);
666c2c66affSColin Finck }
667c2c66affSColin Finck
668c2c66affSColin Finck return Status;
669c2c66affSColin Finck }
670c2c66affSColin Finck
671c2c66affSColin Finck NTSTATUS
672c2c66affSColin Finck NTAPI
USBSTOR_SyncCompletionRoutine(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp,IN PVOID Ctx)673f3fd12b9SVictor Perevertkin USBSTOR_SyncCompletionRoutine(
674c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject,
675c2c66affSColin Finck IN PIRP Irp,
676c2c66affSColin Finck IN PVOID Ctx)
677c2c66affSColin Finck {
678f3fd12b9SVictor Perevertkin KeSetEvent((PKEVENT)Ctx, IO_NO_INCREMENT, FALSE);
679c2c66affSColin Finck return STATUS_MORE_PROCESSING_REQUIRED;
680c2c66affSColin Finck }
681c2c66affSColin Finck
682f3fd12b9SVictor Perevertkin /*
683f3fd12b9SVictor Perevertkin * @name USBSTOR_SendInternalCdb
684f3fd12b9SVictor Perevertkin *
685f3fd12b9SVictor Perevertkin * Issues an internal SCSI request to device.
686f3fd12b9SVictor Perevertkin * The request is sent in a synchronous way.
687f3fd12b9SVictor Perevertkin */
688f3fd12b9SVictor Perevertkin static
689c2c66affSColin Finck NTSTATUS
USBSTOR_SendInternalCdb(IN PDEVICE_OBJECT PdoDevice,IN PCDB Cdb,IN UCHAR CdbLength,IN ULONG TimeOutValue,OUT PVOID OutDataBuffer,OUT PULONG OutDataTransferLength)690f3fd12b9SVictor Perevertkin USBSTOR_SendInternalCdb(
691f3fd12b9SVictor Perevertkin IN PDEVICE_OBJECT PdoDevice,
692f3fd12b9SVictor Perevertkin IN PCDB Cdb,
693f3fd12b9SVictor Perevertkin IN UCHAR CdbLength,
694f3fd12b9SVictor Perevertkin IN ULONG TimeOutValue,
695f3fd12b9SVictor Perevertkin OUT PVOID OutDataBuffer,
696f3fd12b9SVictor Perevertkin OUT PULONG OutDataTransferLength)
697c2c66affSColin Finck {
698f3fd12b9SVictor Perevertkin PSCSI_REQUEST_BLOCK Srb;
699f3fd12b9SVictor Perevertkin PSENSE_DATA SenseBuffer;
700c2c66affSColin Finck PIO_STACK_LOCATION IoStack;
701f3fd12b9SVictor Perevertkin KEVENT Event;
702f3fd12b9SVictor Perevertkin PIRP Irp = NULL;
703f3fd12b9SVictor Perevertkin PMDL Mdl = NULL;
704f3fd12b9SVictor Perevertkin ULONG ix = 0;
705f3fd12b9SVictor Perevertkin NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES;
706f3fd12b9SVictor Perevertkin UCHAR SrbStatus;
707c2c66affSColin Finck
708f3fd12b9SVictor Perevertkin DPRINT("USBSTOR_SendInternalCdb SCSIOP %x\n", Cdb->CDB6GENERIC.OperationCode);
709f3fd12b9SVictor Perevertkin
710f3fd12b9SVictor Perevertkin Srb = ExAllocatePoolWithTag(NonPagedPool,
711f3fd12b9SVictor Perevertkin sizeof(SCSI_REQUEST_BLOCK),
712f3fd12b9SVictor Perevertkin USB_STOR_TAG);
713f3fd12b9SVictor Perevertkin
714f3fd12b9SVictor Perevertkin if (Srb)
715f3fd12b9SVictor Perevertkin {
716f3fd12b9SVictor Perevertkin SenseBuffer = ExAllocatePoolWithTag(NonPagedPool,
717f3fd12b9SVictor Perevertkin SENSE_BUFFER_SIZE,
718f3fd12b9SVictor Perevertkin USB_STOR_TAG);
719f3fd12b9SVictor Perevertkin
720f3fd12b9SVictor Perevertkin if (SenseBuffer)
721f3fd12b9SVictor Perevertkin {
722f3fd12b9SVictor Perevertkin Mdl = IoAllocateMdl(OutDataBuffer,
723f3fd12b9SVictor Perevertkin *OutDataTransferLength,
724f3fd12b9SVictor Perevertkin FALSE,
725f3fd12b9SVictor Perevertkin FALSE,
726f3fd12b9SVictor Perevertkin NULL);
727f3fd12b9SVictor Perevertkin
728f3fd12b9SVictor Perevertkin if (!Mdl)
729f3fd12b9SVictor Perevertkin {
730f3fd12b9SVictor Perevertkin ExFreePoolWithTag(SenseBuffer, USB_STOR_TAG);
731f3fd12b9SVictor Perevertkin ExFreePoolWithTag(Srb, USB_STOR_TAG);
732f3fd12b9SVictor Perevertkin return Status;
733f3fd12b9SVictor Perevertkin }
734f3fd12b9SVictor Perevertkin
735f3fd12b9SVictor Perevertkin MmBuildMdlForNonPagedPool(Mdl);
736f3fd12b9SVictor Perevertkin
737f3fd12b9SVictor Perevertkin // make 3 attempts - the device may be in STALL state after the first one
738f3fd12b9SVictor Perevertkin do
739f3fd12b9SVictor Perevertkin {
740f3fd12b9SVictor Perevertkin Irp = IoAllocateIrp(PdoDevice->StackSize, FALSE);
741f3fd12b9SVictor Perevertkin
742c2c66affSColin Finck if (!Irp)
743c2c66affSColin Finck {
744f3fd12b9SVictor Perevertkin break;
745c2c66affSColin Finck }
746c2c66affSColin Finck
747c2c66affSColin Finck IoStack = IoGetNextIrpStackLocation(Irp);
748c2c66affSColin Finck IoStack->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
749f3fd12b9SVictor Perevertkin IoStack->Parameters.Scsi.Srb = Srb;
750c2c66affSColin Finck
751f3fd12b9SVictor Perevertkin RtlZeroMemory(Srb, sizeof(SCSI_REQUEST_BLOCK));
752c2c66affSColin Finck
753f3fd12b9SVictor Perevertkin Srb->Length = sizeof(SCSI_REQUEST_BLOCK);
754f3fd12b9SVictor Perevertkin Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
755f3fd12b9SVictor Perevertkin Srb->CdbLength = CdbLength;
756f3fd12b9SVictor Perevertkin Srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE;
757f3fd12b9SVictor Perevertkin Srb->SrbFlags = SRB_FLAGS_DATA_IN | SRB_FLAGS_NO_QUEUE_FREEZE;
758f3fd12b9SVictor Perevertkin Srb->DataTransferLength = *OutDataTransferLength;
759f3fd12b9SVictor Perevertkin Srb->TimeOutValue = TimeOutValue;
760f3fd12b9SVictor Perevertkin Srb->DataBuffer = OutDataBuffer;
761f3fd12b9SVictor Perevertkin Srb->SenseInfoBuffer = SenseBuffer;
762c2c66affSColin Finck
763f3fd12b9SVictor Perevertkin RtlCopyMemory(Srb->Cdb, Cdb, CdbLength);
764f3fd12b9SVictor Perevertkin
765f3fd12b9SVictor Perevertkin Irp->MdlAddress = Mdl;
766f3fd12b9SVictor Perevertkin
767f3fd12b9SVictor Perevertkin KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
768f3fd12b9SVictor Perevertkin
769f3fd12b9SVictor Perevertkin IoSetCompletionRoutine(Irp,
770f3fd12b9SVictor Perevertkin USBSTOR_SyncCompletionRoutine,
771f3fd12b9SVictor Perevertkin &Event,
772f3fd12b9SVictor Perevertkin TRUE,
773f3fd12b9SVictor Perevertkin TRUE,
774f3fd12b9SVictor Perevertkin TRUE);
775f3fd12b9SVictor Perevertkin
776f3fd12b9SVictor Perevertkin if (IoCallDriver(PdoDevice, Irp) == STATUS_PENDING)
777f3fd12b9SVictor Perevertkin {
778f3fd12b9SVictor Perevertkin KeWaitForSingleObject(&Event,
779f3fd12b9SVictor Perevertkin Executive,
780f3fd12b9SVictor Perevertkin KernelMode,
781f3fd12b9SVictor Perevertkin FALSE,
782f3fd12b9SVictor Perevertkin NULL);
783c2c66affSColin Finck }
784c2c66affSColin Finck
785f3fd12b9SVictor Perevertkin SrbStatus = SRB_STATUS(Srb->SrbStatus);
786c2c66affSColin Finck
787c2c66affSColin Finck IoFreeIrp(Irp);
788f3fd12b9SVictor Perevertkin Irp = NULL;
789f3fd12b9SVictor Perevertkin
790f3fd12b9SVictor Perevertkin if (SrbStatus == SRB_STATUS_SUCCESS ||
791f3fd12b9SVictor Perevertkin SrbStatus == SRB_STATUS_DATA_OVERRUN)
792f3fd12b9SVictor Perevertkin {
793f3fd12b9SVictor Perevertkin Status = STATUS_SUCCESS;
794f3fd12b9SVictor Perevertkin *OutDataTransferLength = Srb->DataTransferLength;
795f3fd12b9SVictor Perevertkin break;
796f3fd12b9SVictor Perevertkin }
797f3fd12b9SVictor Perevertkin
798f3fd12b9SVictor Perevertkin Status = STATUS_UNSUCCESSFUL;
799f3fd12b9SVictor Perevertkin
800f3fd12b9SVictor Perevertkin ++ix;
801f3fd12b9SVictor Perevertkin } while (ix < 3);
802f3fd12b9SVictor Perevertkin
803f3fd12b9SVictor Perevertkin if (Mdl)
804f3fd12b9SVictor Perevertkin {
805f3fd12b9SVictor Perevertkin IoFreeMdl(Mdl);
806f3fd12b9SVictor Perevertkin }
807f3fd12b9SVictor Perevertkin
808f3fd12b9SVictor Perevertkin ExFreePoolWithTag(SenseBuffer, USB_STOR_TAG);
809f3fd12b9SVictor Perevertkin }
810f3fd12b9SVictor Perevertkin
811f3fd12b9SVictor Perevertkin ExFreePoolWithTag(Srb, USB_STOR_TAG);
812f3fd12b9SVictor Perevertkin }
813f3fd12b9SVictor Perevertkin
814c2c66affSColin Finck return Status;
815c2c66affSColin Finck }
816c2c66affSColin Finck
817f3fd12b9SVictor Perevertkin /*
818f3fd12b9SVictor Perevertkin * @name USBSTOR_FillInquiryData
819f3fd12b9SVictor Perevertkin *
820f3fd12b9SVictor Perevertkin * Sends a SCSI Inquiry request and fills in the PDODeviceExtension->InquiryData field with a result.
821f3fd12b9SVictor Perevertkin */
822f3fd12b9SVictor Perevertkin static
823c2c66affSColin Finck NTSTATUS
USBSTOR_FillInquiryData(IN PDEVICE_OBJECT PDODeviceObject)824f3fd12b9SVictor Perevertkin USBSTOR_FillInquiryData(
825c2c66affSColin Finck IN PDEVICE_OBJECT PDODeviceObject)
826c2c66affSColin Finck {
827f3fd12b9SVictor Perevertkin NTSTATUS Status = STATUS_INSUFFICIENT_RESOURCES;
82894e61c30SVictor Perevertkin PPDO_DEVICE_EXTENSION PDODeviceExtension = (PPDO_DEVICE_EXTENSION)PDODeviceObject->DeviceExtension;
829f3fd12b9SVictor Perevertkin CDB Cdb;
830f3fd12b9SVictor Perevertkin ULONG DataTransferLength = INQUIRYDATABUFFERSIZE;
83194e61c30SVictor Perevertkin PINQUIRYDATA InquiryData = (PINQUIRYDATA)&PDODeviceExtension->InquiryData;
832f3fd12b9SVictor Perevertkin
833f3fd12b9SVictor Perevertkin RtlZeroMemory(&Cdb, sizeof(Cdb));
834f3fd12b9SVictor Perevertkin Cdb.CDB6INQUIRY.OperationCode = SCSIOP_INQUIRY;
835f3fd12b9SVictor Perevertkin Cdb.CDB6INQUIRY.AllocationLength = INQUIRYDATABUFFERSIZE;
836f3fd12b9SVictor Perevertkin
837f3fd12b9SVictor Perevertkin Status = USBSTOR_SendInternalCdb(PDODeviceObject, &Cdb, CDB6GENERIC_LENGTH, 20, InquiryData, &DataTransferLength);
838f3fd12b9SVictor Perevertkin
839c2c66affSColin Finck if (!NT_SUCCESS(Status))
840c2c66affSColin Finck {
841f3fd12b9SVictor Perevertkin DPRINT1("USBSTOR_FillInquiryData failed with %x\n", Status);
842c2c66affSColin Finck return Status;
843c2c66affSColin Finck }
844c2c66affSColin Finck
845f3fd12b9SVictor Perevertkin DPRINT("DeviceType %x\n", InquiryData->DeviceType);
846f3fd12b9SVictor Perevertkin DPRINT("DeviceTypeModifier %x\n", InquiryData->DeviceTypeModifier);
847f3fd12b9SVictor Perevertkin DPRINT("RemovableMedia %x\n", InquiryData->RemovableMedia);
848f3fd12b9SVictor Perevertkin DPRINT("Version %x\n", InquiryData->Versions);
849f3fd12b9SVictor Perevertkin DPRINT("Format %x\n", InquiryData->ResponseDataFormat);
850f3fd12b9SVictor Perevertkin DPRINT("Length %x\n", InquiryData->AdditionalLength);
851f3fd12b9SVictor Perevertkin DPRINT("Reserved %p\n", InquiryData->Reserved);
852f3fd12b9SVictor 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]);
853f3fd12b9SVictor 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],
854f3fd12b9SVictor Perevertkin InquiryData->ProductId[4], InquiryData->ProductId[5], InquiryData->ProductId[6], InquiryData->ProductId[7],
855f3fd12b9SVictor Perevertkin InquiryData->ProductId[8], InquiryData->ProductId[9], InquiryData->ProductId[10], InquiryData->ProductId[11],
856f3fd12b9SVictor Perevertkin InquiryData->ProductId[12], InquiryData->ProductId[13], InquiryData->ProductId[14], InquiryData->ProductId[15]);
857c2c66affSColin Finck
858f3fd12b9SVictor Perevertkin DPRINT("Revision %c%c%c%c\n", InquiryData->ProductRevisionLevel[0], InquiryData->ProductRevisionLevel[1], InquiryData->ProductRevisionLevel[2], InquiryData->ProductRevisionLevel[3]);
859c2c66affSColin Finck
860c2c66affSColin Finck return Status;
861c2c66affSColin Finck }
862c2c66affSColin Finck
863c2c66affSColin Finck NTSTATUS
USBSTOR_CreatePDO(IN PDEVICE_OBJECT DeviceObject,IN UCHAR LUN)864c2c66affSColin Finck USBSTOR_CreatePDO(
865c2c66affSColin Finck IN PDEVICE_OBJECT DeviceObject,
866c2c66affSColin Finck IN UCHAR LUN)
867c2c66affSColin Finck {
868c2c66affSColin Finck PDEVICE_OBJECT PDO;
869c2c66affSColin Finck NTSTATUS Status;
870c2c66affSColin Finck PPDO_DEVICE_EXTENSION PDODeviceExtension;
871c2c66affSColin Finck PFDO_DEVICE_EXTENSION FDODeviceExtension;
87294e61c30SVictor Perevertkin PINQUIRYDATA InquiryData;
873c2c66affSColin Finck
874c2c66affSColin Finck FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
875c2c66affSColin Finck
876c2c66affSColin Finck // create child device object
877c2c66affSColin Finck Status = IoCreateDevice(DeviceObject->DriverObject, sizeof(PDO_DEVICE_EXTENSION), NULL, FILE_DEVICE_MASS_STORAGE, FILE_AUTOGENERATED_DEVICE_NAME | FILE_DEVICE_SECURE_OPEN, FALSE, &PDO);
878c2c66affSColin Finck if (!NT_SUCCESS(Status))
879c2c66affSColin Finck {
880f3fd12b9SVictor Perevertkin DPRINT1("Failed to create PDO, status %x\n", Status);
881c2c66affSColin Finck return Status;
882c2c66affSColin Finck }
883c2c66affSColin Finck
884c2c66affSColin Finck // patch the stack size
885c2c66affSColin Finck PDO->StackSize = DeviceObject->StackSize;
886c2c66affSColin Finck
887c2c66affSColin Finck PDODeviceExtension = (PPDO_DEVICE_EXTENSION)PDO->DeviceExtension;
88894e61c30SVictor Perevertkin InquiryData = (PINQUIRYDATA)&PDODeviceExtension->InquiryData;
889c2c66affSColin Finck
890c2c66affSColin Finck // initialize device extension
891c2c66affSColin Finck RtlZeroMemory(PDODeviceExtension, sizeof(PDO_DEVICE_EXTENSION));
892c2c66affSColin Finck PDODeviceExtension->Common.IsFDO = FALSE;
893c2c66affSColin Finck PDODeviceExtension->LowerDeviceObject = DeviceObject;
894c2c66affSColin Finck PDODeviceExtension->PDODeviceObject = &FDODeviceExtension->ChildPDO[LUN];
895c2c66affSColin Finck PDODeviceExtension->Self = PDO;
896c2c66affSColin Finck PDODeviceExtension->LUN = LUN;
897c2c66affSColin Finck
898f3fd12b9SVictor Perevertkin PDO->Flags |= DO_DIRECT_IO;
899c2c66affSColin Finck
900c2c66affSColin Finck // device is initialized
901c2c66affSColin Finck PDO->Flags &= ~DO_DEVICE_INITIALIZING;
902c2c66affSColin Finck
903c2c66affSColin Finck // output device object
904c2c66affSColin Finck FDODeviceExtension->ChildPDO[LUN] = PDO;
905c2c66affSColin Finck
906c2c66affSColin Finck // send inquiry command by irp
907f3fd12b9SVictor Perevertkin Status = USBSTOR_FillInquiryData(PDO);
908c2c66affSColin Finck
909f3fd12b9SVictor Perevertkin if (!NT_SUCCESS(Status))
910c2c66affSColin Finck {
911f3fd12b9SVictor Perevertkin return Status;
912f3fd12b9SVictor Perevertkin }
913c2c66affSColin Finck
91494e61c30SVictor Perevertkin if (InquiryData->DeviceType != DIRECT_ACCESS_DEVICE &&
91594e61c30SVictor Perevertkin InquiryData->DeviceType != READ_ONLY_DIRECT_ACCESS_DEVICE)
916f3fd12b9SVictor Perevertkin {
917f3fd12b9SVictor Perevertkin return STATUS_NOT_SUPPORTED;
918c2c66affSColin Finck }
919c2c66affSColin Finck
920c2c66affSColin Finck return Status;
921c2c66affSColin Finck }
922