Reactos
1/*
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)
8 * 2017 Vadim Galyant
9 */
10
11#include "usbstor.h"
12#include <sptilib.h>
13
14#define NDEBUG
15#include <debug.h>
16
17// See CORE-10515 and CORE-10755
18#define USBSTOR_DEFAULT_MAX_PHYS_PAGES (USBSTOR_DEFAULT_MAX_TRANSFER_LENGTH / PAGE_SIZE + 1)
19
20static
21BOOLEAN
22IsRequestValid(PIRP Irp)
23{
24 ULONG TransferLength;
25 PIO_STACK_LOCATION IoStack;
26 PSCSI_REQUEST_BLOCK Srb;
27
28 IoStack = IoGetCurrentIrpStackLocation(Irp);
29 Srb = IoStack->Parameters.Scsi.Srb;
30
31 if (Srb->SrbFlags & (SRB_FLAGS_DATA_IN | SRB_FLAGS_DATA_OUT))
32 {
33 if ((Srb->SrbFlags & SRB_FLAGS_UNSPECIFIED_DIRECTION) == SRB_FLAGS_UNSPECIFIED_DIRECTION)
34 {
35 DPRINT1("IsRequestValid: Invalid Srb. Srb->SrbFlags - %X\n", Srb->SrbFlags);
36 return FALSE;
37 }
38
39 TransferLength = Srb->DataTransferLength;
40
41 if (Irp->MdlAddress == NULL)
42 {
43 DPRINT1("IsRequestValid: Invalid Srb. Irp->MdlAddress == NULL\n");
44 return FALSE;
45 }
46
47 if (TransferLength == 0)
48 {
49 DPRINT1("IsRequestValid: Invalid Srb. TransferLength == 0\n");
50 return FALSE;
51 }
52
53 if (TransferLength > USBSTOR_DEFAULT_MAX_TRANSFER_LENGTH)
54 {
55 DPRINT1("IsRequestValid: Invalid Srb. TransferLength > 0x10000\n");
56 return FALSE;
57 }
58 }
59 else
60 {
61 if (Srb->DataTransferLength)
62 {
63 DPRINT1("IsRequestValid: Invalid Srb. Srb->DataTransferLength != 0\n");
64 return FALSE;
65 }
66
67 if (Srb->DataBuffer)
68 {
69 DPRINT1("IsRequestValid: Invalid Srb. Srb->DataBuffer != NULL\n");
70 return FALSE;
71 }
72
73 if (Irp->MdlAddress)
74 {
75 DPRINT1("IsRequestValid: Invalid Srb. Irp->MdlAddress != NULL\n");
76 return FALSE;
77 }
78 }
79
80 return TRUE;
81}
82
83NTSTATUS
84USBSTOR_HandleInternalDeviceControl(
85 IN PDEVICE_OBJECT DeviceObject,
86 IN PIRP Irp)
87{
88 PIO_STACK_LOCATION IoStack;
89 PSCSI_REQUEST_BLOCK Request;
90 PPDO_DEVICE_EXTENSION PDODeviceExtension;
91 NTSTATUS Status;
92
93 IoStack = IoGetCurrentIrpStackLocation(Irp);
94 Request = (PSCSI_REQUEST_BLOCK)IoStack->Parameters.Others.Argument1;
95 ASSERT(Request);
96 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
97 ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
98
99 switch(Request->Function)
100 {
101 case SRB_FUNCTION_EXECUTE_SCSI:
102 {
103 DPRINT("SRB_FUNCTION_EXECUTE_SCSI\n");
104
105 if (!IsRequestValid(Irp))
106 {
107 Status = STATUS_INVALID_PARAMETER;
108 break;
109 }
110
111 if (Request->Cdb[0] == SCSIOP_MODE_SENSE)
112 {
113 DPRINT("USBSTOR_Scsi: SRB_FUNCTION_EXECUTE_SCSI - FIXME SCSIOP_MODE_SENSE\n");
114 // FIXME Get from registry WriteProtect for StorageDevicePolicies;
115 // L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\StorageDevicePolicies"
116 // QueryTable[0].Name = L"WriteProtect"
117 }
118
119 IoMarkIrpPending(Irp);
120 Request->SrbStatus = SRB_STATUS_PENDING;
121
122 // add the request
123 if (!USBSTOR_QueueAddIrp(PDODeviceExtension->LowerDeviceObject, Irp))
124 {
125 IoStartPacket(PDODeviceExtension->LowerDeviceObject, Irp, &Request->QueueSortKey, USBSTOR_CancelIo);
126 }
127
128 return STATUS_PENDING;
129 }
130 case SRB_FUNCTION_RELEASE_DEVICE:
131 {
132 DPRINT1("SRB_FUNCTION_RELEASE_DEVICE\n");
133 ASSERT(PDODeviceExtension->Claimed == TRUE);
134
135 // release claim
136 PDODeviceExtension->Claimed = FALSE;
137 Status = STATUS_SUCCESS;
138 break;
139 }
140 case SRB_FUNCTION_CLAIM_DEVICE:
141 {
142 DPRINT1("SRB_FUNCTION_CLAIM_DEVICE\n");
143
144 // check if the device has been claimed
145 if (PDODeviceExtension->Claimed)
146 {
147 // device has already been claimed
148 Status = STATUS_DEVICE_BUSY;
149 Request->SrbStatus = SRB_STATUS_BUSY;
150 break;
151 }
152
153 // claim device
154 PDODeviceExtension->Claimed = TRUE;
155
156 // output device object
157 Request->DataBuffer = DeviceObject;
158
159 Status = STATUS_SUCCESS;
160 break;
161 }
162 case SRB_FUNCTION_RELEASE_QUEUE:
163 {
164 DPRINT1("SRB_FUNCTION_RELEASE_QUEUE\n");
165
166 USBSTOR_QueueRelease(PDODeviceExtension->LowerDeviceObject);
167
168 Request->SrbStatus = SRB_STATUS_SUCCESS;
169 Status = STATUS_SUCCESS;
170 break;
171 }
172
173 case SRB_FUNCTION_SHUTDOWN:
174 case SRB_FUNCTION_FLUSH:
175 case SRB_FUNCTION_FLUSH_QUEUE:
176 {
177 DPRINT1("SRB_FUNCTION_FLUSH / SRB_FUNCTION_FLUSH_QUEUE / SRB_FUNCTION_SHUTDOWN\n");
178
179 // wait for pending requests to finish
180 USBSTOR_QueueWaitForPendingRequests(PDODeviceExtension->LowerDeviceObject);
181
182 Request->SrbStatus = SRB_STATUS_SUCCESS;
183 Status = STATUS_SUCCESS;
184 break;
185 }
186 default:
187 {
188 //
189 // not supported
190 //
191 Status = STATUS_NOT_SUPPORTED;
192 Request->SrbStatus = SRB_STATUS_ERROR;
193 }
194 }
195
196 Irp->IoStatus.Status = Status;
197 IoCompleteRequest(Irp, IO_NO_INCREMENT);
198 return Status;
199}
200
201ULONG
202USBSTOR_GetFieldLength(
203 IN PUCHAR Name,
204 IN ULONG MaxLength)
205{
206 ULONG Index;
207 ULONG LastCharacterPosition = 0;
208
209 // scan the field and return last position which contains a valid character
210 for(Index = 0; Index < MaxLength; Index++)
211 {
212 if (Name[Index] != ' ')
213 {
214 // trim white spaces from field
215 LastCharacterPosition = Index;
216 }
217 }
218
219 // convert from zero based index to length
220 return LastCharacterPosition + 1;
221}
222
223NTSTATUS
224USBSTOR_HandleQueryProperty(
225 IN PDEVICE_OBJECT DeviceObject,
226 IN PIRP Irp)
227{
228 PIO_STACK_LOCATION IoStack;
229 PSTORAGE_PROPERTY_QUERY PropertyQuery;
230 PSTORAGE_DESCRIPTOR_HEADER DescriptorHeader;
231 PSTORAGE_ADAPTER_DESCRIPTOR_WIN8 AdapterDescriptor;
232 ULONG FieldLengthVendor, FieldLengthProduct, FieldLengthRevision, TotalLength, FieldLengthSerialNumber;
233 PPDO_DEVICE_EXTENSION PDODeviceExtension;
234 PINQUIRYDATA InquiryData;
235 PSTORAGE_DEVICE_DESCRIPTOR DeviceDescriptor;
236 PUCHAR Buffer;
237 PFDO_DEVICE_EXTENSION FDODeviceExtension;
238 UNICODE_STRING SerialNumber;
239 ANSI_STRING AnsiString;
240 NTSTATUS Status;
241
242 DPRINT("USBSTOR_HandleQueryProperty\n");
243
244 IoStack = IoGetCurrentIrpStackLocation(Irp);
245 ASSERT(IoStack->Parameters.DeviceIoControl.InputBufferLength >= sizeof(STORAGE_PROPERTY_QUERY));
246 ASSERT(Irp->AssociatedIrp.SystemBuffer);
247
248 PropertyQuery = (PSTORAGE_PROPERTY_QUERY)Irp->AssociatedIrp.SystemBuffer;
249
250 // check property type
251 if (PropertyQuery->PropertyId != StorageDeviceProperty &&
252 PropertyQuery->PropertyId != StorageAdapterProperty)
253 {
254 // only device property / adapter property are supported
255 return STATUS_INVALID_PARAMETER_1;
256 }
257
258 // check query type
259 if (PropertyQuery->QueryType == PropertyExistsQuery)
260 {
261 // device property / adapter property is supported
262 return STATUS_SUCCESS;
263 }
264
265 if (PropertyQuery->QueryType != PropertyStandardQuery)
266 {
267 // only standard query and exists query are supported
268 return STATUS_INVALID_PARAMETER_2;
269 }
270
271 // check if it is a device property
272 if (PropertyQuery->PropertyId == StorageDeviceProperty)
273 {
274 DPRINT("USBSTOR_HandleQueryProperty StorageDeviceProperty OutputBufferLength %lu\n", IoStack->Parameters.DeviceIoControl.OutputBufferLength);
275
276 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
277 ASSERT(PDODeviceExtension);
278 ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
279
280 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)PDODeviceExtension->LowerDeviceObject->DeviceExtension;
281 ASSERT(FDODeviceExtension);
282 ASSERT(FDODeviceExtension->Common.IsFDO);
283
284 InquiryData = (PINQUIRYDATA)&PDODeviceExtension->InquiryData;
285
286 // compute extra parameters length
287 FieldLengthVendor = USBSTOR_GetFieldLength(InquiryData->VendorId, 8);
288 FieldLengthProduct = USBSTOR_GetFieldLength(InquiryData->ProductId, 16);
289 FieldLengthRevision = USBSTOR_GetFieldLength(InquiryData->ProductRevisionLevel, 4);
290
291 if (FDODeviceExtension->SerialNumber)
292 {
293 FieldLengthSerialNumber = wcslen(FDODeviceExtension->SerialNumber->bString);
294 }
295 else
296 {
297 FieldLengthSerialNumber = 0;
298 }
299
300 // total length required is sizeof(STORAGE_DEVICE_DESCRIPTOR) + FieldLength + 4 extra null bytes - 1
301 // -1 due STORAGE_DEVICE_DESCRIPTOR contains one byte length of parameter data
302 TotalLength = sizeof(STORAGE_DEVICE_DESCRIPTOR) + FieldLengthVendor + FieldLengthProduct + FieldLengthRevision + FieldLengthSerialNumber + 3;
303
304 // check if output buffer is long enough
305 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < TotalLength)
306 {
307 // buffer too small
308 DescriptorHeader = (PSTORAGE_DESCRIPTOR_HEADER)Irp->AssociatedIrp.SystemBuffer;
309 ASSERT(IoStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(STORAGE_DESCRIPTOR_HEADER));
310
311 // return required size
312 DescriptorHeader->Version = TotalLength;
313 DescriptorHeader->Size = TotalLength;
314
315 Irp->IoStatus.Information = sizeof(STORAGE_DESCRIPTOR_HEADER);
316 return STATUS_SUCCESS;
317 }
318
319 // initialize the device descriptor
320 DeviceDescriptor = (PSTORAGE_DEVICE_DESCRIPTOR)Irp->AssociatedIrp.SystemBuffer;
321
322 DeviceDescriptor->Version = sizeof(STORAGE_DEVICE_DESCRIPTOR);
323 DeviceDescriptor->Size = TotalLength;
324 DeviceDescriptor->DeviceType = InquiryData->DeviceType;
325 DeviceDescriptor->DeviceTypeModifier = InquiryData->DeviceTypeModifier;
326 DeviceDescriptor->RemovableMedia = InquiryData->RemovableMedia;
327 DeviceDescriptor->CommandQueueing = FALSE;
328 DeviceDescriptor->BusType = BusTypeUsb;
329 DeviceDescriptor->VendorIdOffset = sizeof(STORAGE_DEVICE_DESCRIPTOR) - sizeof(UCHAR);
330 DeviceDescriptor->ProductIdOffset = DeviceDescriptor->VendorIdOffset + FieldLengthVendor + 1;
331 DeviceDescriptor->ProductRevisionOffset = DeviceDescriptor->ProductIdOffset + FieldLengthProduct + 1;
332 DeviceDescriptor->SerialNumberOffset = (FieldLengthSerialNumber > 0 ? DeviceDescriptor->ProductRevisionOffset + FieldLengthRevision + 1 : 0);
333 DeviceDescriptor->RawPropertiesLength = FieldLengthVendor + FieldLengthProduct + FieldLengthRevision + FieldLengthSerialNumber + 3 + (FieldLengthSerialNumber > 0 ? + 1 : 0);
334
335 // copy descriptors
336 Buffer = (PUCHAR)((ULONG_PTR)DeviceDescriptor + sizeof(STORAGE_DEVICE_DESCRIPTOR) - sizeof(UCHAR));
337
338 RtlCopyMemory(Buffer, InquiryData->VendorId, FieldLengthVendor);
339 Buffer[FieldLengthVendor] = '\0';
340 Buffer += FieldLengthVendor + 1;
341
342 RtlCopyMemory(Buffer, InquiryData->ProductId, FieldLengthProduct);
343 Buffer[FieldLengthProduct] = '\0';
344 Buffer += FieldLengthProduct + 1;
345
346 RtlCopyMemory(Buffer, InquiryData->ProductRevisionLevel, FieldLengthRevision);
347 Buffer[FieldLengthRevision] = '\0';
348 Buffer += FieldLengthRevision + 1;
349
350 if (FieldLengthSerialNumber)
351 {
352 RtlInitUnicodeString(&SerialNumber, FDODeviceExtension->SerialNumber->bString);
353
354 AnsiString.Buffer = (PCHAR)Buffer;
355 AnsiString.Length = 0;
356 AnsiString.MaximumLength = FieldLengthSerialNumber * sizeof(WCHAR);
357
358 Status = RtlUnicodeStringToAnsiString(&AnsiString, &SerialNumber, FALSE);
359 ASSERT(Status == STATUS_SUCCESS);
360 }
361
362 DPRINT("Vendor %s\n", (LPCSTR)((ULONG_PTR)DeviceDescriptor + DeviceDescriptor->VendorIdOffset));
363 DPRINT("Product %s\n", (LPCSTR)((ULONG_PTR)DeviceDescriptor + DeviceDescriptor->ProductIdOffset));
364 DPRINT("Revision %s\n", (LPCSTR)((ULONG_PTR)DeviceDescriptor + DeviceDescriptor->ProductRevisionOffset));
365 DPRINT("Serial %s\n", (LPCSTR)((ULONG_PTR)DeviceDescriptor + DeviceDescriptor->SerialNumberOffset));
366
367 Irp->IoStatus.Information = TotalLength;
368 return STATUS_SUCCESS;
369 }
370 else
371 {
372 // adapter property query request
373
374 DPRINT("USBSTOR_HandleQueryProperty StorageAdapterProperty OutputBufferLength %lu\n", IoStack->Parameters.DeviceIoControl.OutputBufferLength);
375
376 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(STORAGE_ADAPTER_DESCRIPTOR_WIN8))
377 {
378 // buffer too small
379 DescriptorHeader = (PSTORAGE_DESCRIPTOR_HEADER)Irp->AssociatedIrp.SystemBuffer;
380 ASSERT(IoStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(STORAGE_DESCRIPTOR_HEADER));
381
382 // return required size
383 DescriptorHeader->Version = sizeof(STORAGE_ADAPTER_DESCRIPTOR_WIN8);
384 DescriptorHeader->Size = sizeof(STORAGE_ADAPTER_DESCRIPTOR_WIN8);
385
386 Irp->IoStatus.Information = sizeof(STORAGE_DESCRIPTOR_HEADER);
387 return STATUS_SUCCESS;
388 }
389
390 // get adapter descriptor, information is returned in the same buffer
391 AdapterDescriptor = Irp->AssociatedIrp.SystemBuffer;
392
393 // fill out descriptor
394 // NOTE: STORAGE_ADAPTER_DESCRIPTOR_WIN8 may vary in size, so it's important to zero out
395 // all unused fields
396 *AdapterDescriptor = (STORAGE_ADAPTER_DESCRIPTOR_WIN8) {
397 .Version = sizeof(STORAGE_ADAPTER_DESCRIPTOR_WIN8),
398 .Size = sizeof(STORAGE_ADAPTER_DESCRIPTOR_WIN8),
399 .MaximumTransferLength = USBSTOR_DEFAULT_MAX_TRANSFER_LENGTH,
400 .MaximumPhysicalPages = USBSTOR_DEFAULT_MAX_PHYS_PAGES,
401 .BusType = BusTypeUsb,
402 .BusMajorVersion = 2, //FIXME verify
403 .BusMinorVersion = 0 //FIXME
404 };
405
406 // __debugbreak();
407
408 // store returned length
409 Irp->IoStatus.Information = sizeof(STORAGE_ADAPTER_DESCRIPTOR_WIN8);
410
411 return STATUS_SUCCESS;
412 }
413}
414
415NTSTATUS
416USBSTOR_HandleDeviceControl(
417 IN PDEVICE_OBJECT DeviceObject,
418 IN PIRP Irp)
419{
420 PIO_STACK_LOCATION IoStack;
421 NTSTATUS Status;
422 PPDO_DEVICE_EXTENSION PDODeviceExtension;
423 PSCSI_ADAPTER_BUS_INFO BusInfo;
424 PSCSI_INQUIRY_DATA ScsiInquiryData;
425 PINQUIRYDATA InquiryData;
426
427 IoStack = IoGetCurrentIrpStackLocation(Irp);
428
429 switch (IoStack->Parameters.DeviceIoControl.IoControlCode)
430 {
431 case IOCTL_STORAGE_QUERY_PROPERTY:
432 Status = USBSTOR_HandleQueryProperty(DeviceObject, Irp);
433 break;
434 case IOCTL_SCSI_PASS_THROUGH:
435 case IOCTL_SCSI_PASS_THROUGH_DIRECT:
436 {
437 PDODeviceExtension = DeviceObject->DeviceExtension;
438
439 ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
440 ASSERT(PDODeviceExtension);
441 ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
442
443 /* Skip requests that bypassed the class driver. See also cdrom!RequestHandleScsiPassThrough */
444 if ((IoGetCurrentIrpStackLocation(Irp)->MinorFunction == 0) && PDODeviceExtension->Claimed)
445 {
446 Status = STATUS_INVALID_DEVICE_REQUEST;
447 break;
448 }
449
450 Status = SptiHandleScsiPassthru(DeviceObject,
451 Irp,
452 USBSTOR_DEFAULT_MAX_TRANSFER_LENGTH,
453 USBSTOR_DEFAULT_MAX_PHYS_PAGES);
454 break;
455 }
456 case IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER:
457 DPRINT1("USBSTOR_HandleDeviceControl IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER NOT implemented\n");
458 Status = STATUS_NOT_SUPPORTED;
459 break;
460 case IOCTL_SCSI_GET_CAPABILITIES:
461 {
462 PIO_SCSI_CAPABILITIES Capabilities;
463
464 // Legacy port capability query
465 if (IoStack->Parameters.DeviceIoControl.OutputBufferLength == sizeof(PVOID))
466 {
467 Capabilities = *((PVOID *)Irp->AssociatedIrp.SystemBuffer) = ExAllocatePoolWithTag(NonPagedPool,
468 sizeof(IO_SCSI_CAPABILITIES),
469 USB_STOR_TAG);
470 Irp->IoStatus.Information = sizeof(PVOID);
471 }
472 else
473 {
474 Capabilities = Irp->AssociatedIrp.SystemBuffer;
475 Irp->IoStatus.Information = sizeof(IO_SCSI_CAPABILITIES);
476 }
477
478 if (Capabilities)
479 {
480 Capabilities->MaximumTransferLength = USBSTOR_DEFAULT_MAX_TRANSFER_LENGTH;
481 Capabilities->MaximumPhysicalPages = USBSTOR_DEFAULT_MAX_PHYS_PAGES;
482 Capabilities->SupportedAsynchronousEvents = 0;
483 Capabilities->AlignmentMask = 0;
484 Capabilities->TaggedQueuing = FALSE;
485 Capabilities->AdapterScansDown = FALSE;
486 Capabilities->AdapterUsesPio = FALSE;
487 Status = STATUS_SUCCESS;
488 }
489 else
490 {
491 Status = STATUS_INSUFFICIENT_RESOURCES;
492 }
493
494 break;
495 }
496 case IOCTL_SCSI_GET_INQUIRY_DATA:
497 {
498 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
499 ASSERT(PDODeviceExtension);
500 ASSERT(PDODeviceExtension->Common.IsFDO == FALSE);
501
502 // get parameters
503 BusInfo = Irp->AssociatedIrp.SystemBuffer;
504 ScsiInquiryData = (PSCSI_INQUIRY_DATA)(BusInfo + 1);
505 InquiryData = (PINQUIRYDATA)ScsiInquiryData->InquiryData;
506
507
508 BusInfo->NumberOfBuses = 1;
509 BusInfo->BusData[0].NumberOfLogicalUnits = 1; //FIXME
510 BusInfo->BusData[0].InitiatorBusId = 0;
511 BusInfo->BusData[0].InquiryDataOffset = sizeof(SCSI_ADAPTER_BUS_INFO);
512
513 ScsiInquiryData->PathId = 0;
514 ScsiInquiryData->TargetId = 0;
515 ScsiInquiryData->Lun = PDODeviceExtension->LUN & MAX_LUN;
516 ScsiInquiryData->DeviceClaimed = PDODeviceExtension->Claimed;
517 ScsiInquiryData->InquiryDataLength = sizeof(INQUIRYDATA);
518 ScsiInquiryData->NextInquiryDataOffset = 0;
519
520 // Note: INQUIRYDATA structure is larger than INQUIRYDATABUFFERSIZE
521 RtlZeroMemory(InquiryData, sizeof(INQUIRYDATA));
522 RtlCopyMemory(InquiryData, &PDODeviceExtension->InquiryData, sizeof(PDODeviceExtension->InquiryData));
523
524 InquiryData->Versions = 0x04;
525 InquiryData->ResponseDataFormat = 0x02; // some devices set this to 1
526
527 Irp->IoStatus.Information = sizeof(SCSI_ADAPTER_BUS_INFO) + sizeof(SCSI_INQUIRY_DATA) + sizeof(INQUIRYDATA) - 1;
528 Status = STATUS_SUCCESS;
529
530 break;
531 }
532 case IOCTL_SCSI_GET_ADDRESS:
533 {
534 PSCSI_ADDRESS Address = Irp->AssociatedIrp.SystemBuffer;
535
536 Address->Length = sizeof(SCSI_ADDRESS);
537 Address->PortNumber = 0;
538 Address->PathId = 0;
539 Address->TargetId = 0;
540 Address->Lun = (((PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension)->LUN & MAX_LUN);
541 Irp->IoStatus.Information = sizeof(SCSI_ADDRESS);
542
543 Status = STATUS_SUCCESS;
544
545 break;
546 }
547 default:
548 DPRINT("USBSTOR_HandleDeviceControl IoControl %x not supported\n", IoStack->Parameters.DeviceIoControl.IoControlCode);
549 Status = STATUS_NOT_SUPPORTED;
550 break;
551 }
552
553 return Status;
554}