ReactOS  0.4.14-dev-614-gbfd8a84
pdo.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS Universal Serial Bus Bulk Storage Driver
3  * LICENSE: GPL - See COPYING in the top level directory
4  * FILE: drivers/usb/usbstor/pdo.c
5  * PURPOSE: USB block storage device driver.
6  * PROGRAMMERS:
7  * James Tabor
8  * Michael Martin (michael.martin@reactos.org)
9  * Johannes Anderwald (johannes.anderwald@reactos.org)
10  */
11 
12 #include "usbstor.h"
13 
14 #define NDEBUG
15 #include <debug.h>
16 
17 LPCSTR
19  IN PUFI_INQUIRY_RESPONSE InquiryData,
20  IN UCHAR IsFloppy)
21 {
22  //
23  // check if device type is zero
24  //
25  if (InquiryData->DeviceType == 0)
26  {
27  if (IsFloppy)
28  {
29  //
30  // floppy device
31  //
32  return "SFloppy";
33  }
34 
35  //
36  // direct access device
37  //
38  return "Disk";
39  }
40 
41  //
42  // FIXME: use constant - derived from http://en.wikipedia.org/wiki/SCSI_Peripheral_Device_Type
43  //
44  switch (InquiryData->DeviceType)
45  {
46  case 1:
47  {
48  //
49  // sequential device, i.e magnetic tape
50  //
51  return "Sequential";
52  }
53  case 4:
54  {
55  //
56  // write once device
57  //
58  return "Worm";
59  }
60  case 5:
61  {
62  //
63  // CDROM device
64  //
65  return "CdRom";
66  }
67  case 7:
68  {
69  //
70  // optical memory device
71  //
72  return "Optical";
73  }
74  case 8:
75  {
76  //
77  // medium change device
78  //
79  return "Changer";
80  }
81  default:
82  {
83  //
84  // other device
85  //
86  return "Other";
87  }
88  }
89 }
90 
91 LPCSTR
93  IN PUFI_INQUIRY_RESPONSE InquiryData,
94  IN UCHAR IsFloppy)
95 {
96  //
97  // check if device type is zero
98  //
99  if (InquiryData->DeviceType == 0)
100  {
101  if (IsFloppy)
102  {
103  //
104  // floppy device
105  //
106  return "GenSFloppy";
107  }
108 
109  //
110  // direct access device
111  //
112  return "GenDisk";
113  }
114 
115  //
116  // FIXME: use constant - derived from http://en.wikipedia.org/wiki/SCSI_Peripheral_Device_Type
117  //
118  switch (InquiryData->DeviceType)
119  {
120  case 1:
121  {
122  //
123  // sequential device, i.e magnetic tape
124  //
125  return "GenSequential";
126  }
127  case 4:
128  {
129  //
130  // write once device
131  //
132  return "GenWorm";
133  }
134  case 5:
135  {
136  //
137  // CDROM device
138  //
139  return "GenCdRom";
140  }
141  case 7:
142  {
143  //
144  // optical memory device
145  //
146  return "GenOptical";
147  }
148  case 8:
149  {
150  //
151  // medium change device
152  //
153  return "GenChanger";
154  }
155  default:
156  {
157  //
158  // other device
159  //
160  return "UsbstorOther";
161  }
162  }
163 }
164 
165 
166 ULONG
168  IN PUCHAR Name,
169  IN PCHAR Buffer,
170  IN ULONG MaxLength)
171 {
172  ULONG Index;
173 
174  for(Index = 0; Index < MaxLength; Index++)
175  {
176  if (Name[Index] <= ' ' || Name[Index] >= 0x7F /* last printable ascii character */ || Name[Index] == ',')
177  {
178  //
179  // convert to underscore
180  //
181  Buffer[Index] = '_';
182  }
183  else
184  {
185  //
186  // just copy character
187  //
188  Buffer[Index] = Name[Index];
189  }
190  }
191 
192  return MaxLength;
193 }
194 
195 NTSTATUS
198  IN PIRP Irp)
199 {
200  //PPDO_DEVICE_EXTENSION DeviceExtension;
201  PIO_STACK_LOCATION IoStack;
202  LPWSTR Buffer;
203  static WCHAR DeviceText[] = L"USB Mass Storage Device";
204 
205  //
206  // get current stack location
207  //
209 
210  if (IoStack->Parameters.QueryDeviceText.DeviceTextType == DeviceTextDescription)
211  {
212  DPRINT("USBSTOR_PdoHandleQueryDeviceText DeviceTextDescription\n");
213 
214  //
215  // allocate item
216  //
217  Buffer = (LPWSTR)AllocateItem(PagedPool, sizeof(DeviceText));
218  if (!Buffer)
219  {
220  //
221  // no memory
222  //
223  Irp->IoStatus.Information = 0;
225  }
226 
227  //
228  // copy buffer
229  //
230  wcscpy(Buffer, DeviceText);
231 
232  //
233  // save result
234  //
235  Irp->IoStatus.Information = (ULONG_PTR)Buffer;
236  return STATUS_SUCCESS;
237  }
238  else
239  {
240  DPRINT("USBSTOR_PdoHandleQueryDeviceText DeviceTextLocationInformation\n");
241 
242  //
243  // allocate item
244  //
245  Buffer = (LPWSTR)AllocateItem(PagedPool, sizeof(DeviceText));
246  if (!Buffer)
247  {
248  //
249  // no memory
250  //
251  Irp->IoStatus.Information = 0;
253  }
254 
255  //
256  // copy buffer
257  //
258  wcscpy(Buffer, DeviceText);
259 
260  //
261  // save result
262  //
263  Irp->IoStatus.Information = (ULONG_PTR)Buffer;
264  return STATUS_SUCCESS;
265  }
266 
267 }
268 
269 
270 NTSTATUS
273  IN PIRP Irp)
274 {
275  PPDO_DEVICE_EXTENSION DeviceExtension;
277  CHAR Buffer[100];
279  ULONG Offset = 0;
280  PUFI_INQUIRY_RESPONSE InquiryData;
282  UNICODE_STRING DeviceId;
283 
284  //
285  // get device extension
286  //
288 
289  //
290  // sanity check
291  //
292  ASSERT(DeviceExtension->InquiryData);
293 
294  //
295  // get inquiry data
296  //
297  InquiryData = (PUFI_INQUIRY_RESPONSE)DeviceExtension->InquiryData;
298 
299  //
300  // get device type
301  //
302  DeviceType = USBSTOR_GetDeviceType(InquiryData, DeviceExtension->IsFloppy);
303 
304  //
305  // zero buffer
306  //
307  RtlZeroMemory(Buffer, sizeof(Buffer));
308 
309  //
310  // lets create device string
311  //
312  Offset = sprintf(&Buffer[Offset], "USBSTOR\\");
314  Offset += sprintf(&Buffer[Offset], "&Ven_");
315  Offset += CopyField(InquiryData->Vendor, &Buffer[Offset], 8);
316  Offset += sprintf(&Buffer[Offset], "&Prod_");
317  Offset += CopyField(InquiryData->Product, &Buffer[Offset], 16);
318  Offset += sprintf(&Buffer[Offset], "&Rev_");
319  Offset += CopyField(InquiryData->Revision, &Buffer[Offset], 4);
320 
321  //
322  // now initialize ansi string
323  //
325 
326  //
327  // allocate DeviceId string
328  //
329  DeviceId.Length = 0;
330  DeviceId.MaximumLength = (strlen((PCHAR)Buffer) + 1) * sizeof(WCHAR);
331  DeviceId.Buffer = (LPWSTR)AllocateItem(PagedPool, DeviceId.MaximumLength);
332  if (!DeviceId.Buffer)
333  {
334  //
335  // no memory
336  //
337  Irp->IoStatus.Information = 0;
339  }
340 
341 
342  //
343  // convert to unicode
344  //
346 
347  if (NT_SUCCESS(Status))
348  {
349  //
350  // store result
351  //
352  Irp->IoStatus.Information = (ULONG_PTR)DeviceId.Buffer;
353  }
354 
355  DPRINT("DeviceId %wZ Status %x\n", &DeviceId, Status);
356 
357  //
358  // done
359  //
360  return Status;
361 }
362 
363 VOID
365  IN CHAR * Buffer,
366  IN ULONG ResultBufferLength,
367  IN ULONG ResultBufferOffset,
369  OUT PULONG NewResultBufferOffset)
370 {
371  UNICODE_STRING DeviceString;
374 
375  ASSERT(ResultBufferLength);
376  ASSERT(ResultBufferLength > ResultBufferOffset);
377 
378  DPRINT("ResultBufferOffset %lu ResultBufferLength %lu Buffer %s Length %lu\n", ResultBufferOffset, ResultBufferLength, Buffer, strlen(Buffer));
379 
380  //
381  // construct destination string
382  //
383  DeviceString.Buffer = &ResultBuffer[ResultBufferOffset];
384  DeviceString.Length = 0;
385  DeviceString.MaximumLength = (ResultBufferLength - ResultBufferOffset) * sizeof(WCHAR);
386 
387  //
388  // initialize source string
389  //
391 
392  //
393  // convert to unicode
394  //
397 
398  //
399  // subtract consumed bytes
400  //
401  ResultBufferLength -= (DeviceString.Length + sizeof(WCHAR)) / sizeof(WCHAR);
402  ResultBufferOffset += (DeviceString.Length + sizeof(WCHAR)) / sizeof(WCHAR);
403 
404  //
405  // store new offset
406  //
407  *NewResultBufferOffset = ResultBufferOffset;
408 }
409 
410 
411 
412 NTSTATUS
415  IN OUT PIRP Irp)
416 {
417  PPDO_DEVICE_EXTENSION PDODeviceExtension;
418  PFDO_DEVICE_EXTENSION FDODeviceExtension;
419  LPCSTR GenericType, DeviceType;
420  LPWSTR Buffer;
421  CHAR Id1[50], Id2[50], Id3[50], Id4[50], Id5[50], Id6[50];
422  ULONG Id1Length, Id2Length, Id3Length, Id4Length, Id5Length,Id6Length;
424  PUFI_INQUIRY_RESPONSE InquiryData;
425 
426  //
427  // get PDO device extension
428  //
429  PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
430 
431  //
432  // get FDO device extension
433  //
434  FDODeviceExtension = (PFDO_DEVICE_EXTENSION)PDODeviceExtension->LowerDeviceObject->DeviceExtension;
435 
436  //
437  // sanity check
438  //
439  ASSERT(FDODeviceExtension->DeviceDescriptor);
440 
441  //
442  // get inquiry data
443  //
444  InquiryData = (PUFI_INQUIRY_RESPONSE)PDODeviceExtension->InquiryData;
445 
446 
447  //
448  // get device type and generic type
449  //
450  DeviceType = USBSTOR_GetDeviceType(InquiryData, PDODeviceExtension->IsFloppy);
451  GenericType = USBSTOR_GetGenericType(InquiryData, PDODeviceExtension->IsFloppy);
452 
453  ASSERT(GenericType);
454 
455  //
456  // generate id 1
457  // USBSTOR\SCSIType_Vendor(8)_Product(16)_Revision(4)
458  //
459  RtlZeroMemory(Id1, sizeof(Id1));
460  Offset = 0;
461  Offset = sprintf(&Id1[Offset], "USBSTOR\\");
462  Offset += sprintf(&Id1[Offset], DeviceType);
463  Offset += CopyField(InquiryData->Vendor, &Id1[Offset], 8);
464  Offset += CopyField(InquiryData->Product, &Id1[Offset], 16);
465  Offset += CopyField(InquiryData->Revision, &Id1[Offset], 4);
466  Id1Length = strlen(Id1) + 1;
467  DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId1 %s\n", Id1);
468 
469  //
470  // generate id 2
471  // USBSTOR\SCSIType_VENDOR(8)_Product(16)
472  //
473  RtlZeroMemory(Id2, sizeof(Id2));
474  Offset = 0;
475  Offset = sprintf(&Id2[Offset], "USBSTOR\\");
476  Offset += sprintf(&Id2[Offset], DeviceType);
477  Offset += CopyField(InquiryData->Vendor, &Id2[Offset], 8);
478  Offset += CopyField(InquiryData->Product, &Id2[Offset], 16);
479  Id2Length = strlen(Id2) + 1;
480  DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId2 %s\n", Id2);
481 
482  //
483  // generate id 3
484  // USBSTOR\SCSIType_VENDOR(8)
485  //
486  RtlZeroMemory(Id3, sizeof(Id3));
487  Offset = 0;
488  Offset = sprintf(&Id3[Offset], "USBSTOR\\");
489  Offset += sprintf(&Id3[Offset], DeviceType);
490  Offset += CopyField(InquiryData->Vendor, &Id3[Offset], 8);
491  Id3Length = strlen(Id3) + 1;
492  DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId3 %s\n", Id3);
493 
494  //
495  // generate id 4
496  // USBSTOR\SCSIType_VENDOR(8)_Product(16)_Revision(1)
497  //
498  RtlZeroMemory(Id4, sizeof(Id4));
499  Offset = 0;
500  Offset = sprintf(&Id4[Offset], "USBSTOR\\");
501  Offset += sprintf(&Id4[Offset], DeviceType);
502  Offset += CopyField(InquiryData->Vendor, &Id4[Offset], 8);
503  Offset += CopyField(InquiryData->Product, &Id4[Offset], 16);
504  Offset += CopyField(InquiryData->Revision, &Id4[Offset], 1);
505  Id4Length = strlen(Id4) + 1;
506  DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId4 %s\n", Id4);
507 
508  //
509  // generate id 5
510  // USBSTOR\SCSIType
511  //
512  RtlZeroMemory(Id5, sizeof(Id5));
513  Offset = 0;
514  Offset = sprintf(&Id5[Offset], "USBSTOR\\");
515  Offset += sprintf(&Id5[Offset], GenericType);
516  Id5Length = strlen(Id5) + 1;
517  DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId5 %s\n", Id5);
518 
519  //
520  // generate id 6
521  // SCSIType
522  //
523  RtlZeroMemory(Id6, sizeof(Id6));
524  Offset = 0;
525  Offset = sprintf(&Id6[Offset], GenericType);
526  Id6Length = strlen(Id6) + 1;
527  DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId6 %s\n", Id6);
528 
529  //
530  // compute total length
531  //
532  TotalLength = Id1Length + Id2Length + Id3Length + Id4Length + Id5Length + Id6Length + 1;
533 
534  //
535  // allocate buffer
536  //
538  if (!Buffer)
539  {
540  //
541  // no memory
542  //
543  Irp->IoStatus.Information = 0;
545  }
546 
547  //
548  // reset offset
549  //
550  Offset = 0;
552 
559 
560  //
561  // sanity check
562  //
563  ASSERT(Offset + 1 == Length);
564 
565  //
566  // store result
567  //
568  Irp->IoStatus.Information = (ULONG_PTR)Buffer;
569 
570  //
571  // done
572  //
573  return STATUS_SUCCESS;
574 }
575 
576 NTSTATUS
579  IN OUT PIRP Irp)
580 {
581  PPDO_DEVICE_EXTENSION PDODeviceExtension;
582  PFDO_DEVICE_EXTENSION FDODeviceExtension;
583  CHAR Buffer[100];
587 
588  //
589  // get PDO device extension
590  //
591  PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
592 
593  //
594  // get FDO device extension
595  //
596  FDODeviceExtension = (PFDO_DEVICE_EXTENSION)PDODeviceExtension->LowerDeviceObject->DeviceExtension;
597 
598  //
599  // sanity check
600  //
601  ASSERT(FDODeviceExtension->DeviceDescriptor);
602 
603  //
604  // get target device type
605  //
606  DeviceType = USBSTOR_GetDeviceType((PUFI_INQUIRY_RESPONSE)PDODeviceExtension->InquiryData, PDODeviceExtension->IsFloppy);
607 
608  //
609  // zero memory
610  //
611  RtlZeroMemory(Buffer, sizeof(Buffer));
612 
613  //
614  // format instance id
615  //
616  Length = sprintf(Buffer, "USBSTOR\\%s", DeviceType) + 1;
617  Length += sprintf(&Buffer[Length], "USBSTOR\\%s", "RAW") + 2;
618 
619  //
620  // allocate instance id
621  //
623  if (!InstanceId)
624  {
625  //
626  // no memory
627  //
628  Irp->IoStatus.Information = 0;
630  }
631 
634 
635  DPRINT("USBSTOR_PdoHandleQueryCompatibleId %S\n", InstanceId);
636 
637  //
638  // store result
639  //
640  Irp->IoStatus.Information = (ULONG_PTR)InstanceId;
641 
642  //
643  // completed successfully
644  //
645  return STATUS_SUCCESS;
646 }
647 
648 NTSTATUS
651  IN OUT PIRP Irp)
652 {
653  PPDO_DEVICE_EXTENSION PDODeviceExtension;
654  PFDO_DEVICE_EXTENSION FDODeviceExtension;
655  WCHAR Buffer[100];
656  ULONG Length;
658 
659  //
660  // get PDO device extension
661  //
662  PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
663 
664  //
665  // get FDO device extension
666  //
667  FDODeviceExtension = (PFDO_DEVICE_EXTENSION)PDODeviceExtension->LowerDeviceObject->DeviceExtension;
668 
669  //
670  // format instance id
671  //
672  if (FDODeviceExtension->SerialNumber)
673  {
674  //
675  // using serial number from device
676  //
677  swprintf(Buffer, L"%s&%c", FDODeviceExtension->SerialNumber->bString, PDODeviceExtension->LUN);
678  }
679  else
680  {
681  //
682  // use instance count and LUN
683  //
684  swprintf(Buffer, L"%04lu&%c", FDODeviceExtension->InstanceCount, PDODeviceExtension->LUN);
685  }
686 
687  //
688  // calculate length
689  //
690  Length = wcslen(Buffer) + 1;
691 
692  //
693  // allocate instance id
694  //
696  if (!InstanceId)
697  {
698  //
699  // no memory
700  //
701  Irp->IoStatus.Information = 0;
703  }
704 
705  //
706  // copy instance id
707  //
709 
710  DPRINT("USBSTOR_PdoHandleQueryInstanceId %S\n", InstanceId);
711 
712  //
713  // store result
714  //
715  Irp->IoStatus.Information = (ULONG_PTR)InstanceId;
716 
717  //
718  // completed successfully
719  //
720  return STATUS_SUCCESS;
721 }
722 
723 NTSTATUS
726  IN OUT PIRP Irp)
727 {
728  PDEVICE_RELATIONS DeviceRelations;
729  PIO_STACK_LOCATION IoStack;
730 
731  DPRINT("USBSTOR_PdoHandleDeviceRelations\n");
732 
733  //
734  // get current irp stack location
735  //
737 
738  //
739  // check if relation type is BusRelations
740  //
741  if (IoStack->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation)
742  {
743  //
744  // PDO handles only target device relation
745  //
746  return Irp->IoStatus.Status;
747  }
748 
749  //
750  // allocate device relations
751  //
752  DeviceRelations = (PDEVICE_RELATIONS)AllocateItem(PagedPool, sizeof(DEVICE_RELATIONS));
753  if (!DeviceRelations)
754  {
755  //
756  // no memory
757  //
759  }
760 
761  //
762  // initialize device relations
763  //
764  DeviceRelations->Count = 1;
765  DeviceRelations->Objects[0] = DeviceObject;
767 
768  //
769  // store result
770  //
771  Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
772 
773  //
774  // completed successfully
775  //
776  return STATUS_SUCCESS;
777 }
778 
779 
780 NTSTATUS
783  IN OUT PIRP Irp)
784 {
785  PIO_STACK_LOCATION IoStack;
786  PPDO_DEVICE_EXTENSION DeviceExtension;
789  ULONG bDelete;
790 
791  //
792  // get current stack location
793  //
795 
796  //
797  // get device extension
798  //
800 
801  //
802  // sanity check
803  //
804  ASSERT(DeviceExtension->Common.IsFDO == FALSE);
805 
806  switch(IoStack->MinorFunction)
807  {
809  {
811  break;
812  }
814  {
816  break;
817  }
818  case IRP_MN_QUERY_ID:
819  {
820  if (IoStack->Parameters.QueryId.IdType == BusQueryDeviceID)
821  {
822  //
823  // handle query device id
824  //
826  break;
827  }
828  else if (IoStack->Parameters.QueryId.IdType == BusQueryHardwareIDs)
829  {
830  //
831  // handle instance id
832  //
834  break;
835  }
836  else if (IoStack->Parameters.QueryId.IdType == BusQueryInstanceID)
837  {
838  //
839  // handle instance id
840  //
842  break;
843  }
844  else if (IoStack->Parameters.QueryId.IdType == BusQueryCompatibleIDs)
845  {
846  //
847  // handle instance id
848  //
850  break;
851  }
852 
853  DPRINT1("USBSTOR_PdoHandlePnp: IRP_MN_QUERY_ID IdType %x unimplemented\n", IoStack->Parameters.QueryId.IdType);
855  Irp->IoStatus.Information = 0;
856  break;
857  }
859  {
860  DPRINT("IRP_MN_REMOVE_DEVICE\n");
861 
862  if(*DeviceExtension->PDODeviceObject != NULL)
863  {
864  //
865  // clear entry in FDO pdo list
866  //
867  *DeviceExtension->PDODeviceObject = NULL;
868  bDelete = TRUE;
869  }
870  else
871  {
872  //
873  // device object already marked for deletion
874  //
875  bDelete = FALSE;
876  }
877 
878  /* Complete the IRP */
879  Irp->IoStatus.Status = STATUS_SUCCESS;
881 
882  if (bDelete)
883  {
884  /* Delete the device object */
886  }
887  return STATUS_SUCCESS;
888  }
890  {
891  //
892  // just forward irp to lower device
893  //
894  Status = USBSTOR_SyncForwardIrp(DeviceExtension->LowerDeviceObject, Irp);
896 
897  if (NT_SUCCESS(Status))
898  {
899  //
900  // check if no unique id
901  //
902  Caps = (PDEVICE_CAPABILITIES)IoStack->Parameters.DeviceCapabilities.Capabilities;
903  Caps->UniqueID = FALSE; // no unique id is supported
904  Caps->Removable = TRUE; //FIXME
905  }
906  break;
907  }
910  {
911 #if 0
912  //
913  // if we're not claimed it's ok
914  //
915  if (DeviceExtension->Claimed)
916 #else
917  if (TRUE)
918 #endif
919  {
921  DPRINT1("[USBSTOR] Request %x fails because device is still claimed\n", IoStack->MinorFunction);
922  }
923  else
925  break;
926  }
927  case IRP_MN_START_DEVICE:
928  {
929  //
930  // no-op for PDO
931  //
933  break;
934  }
936  {
938  break;
939  }
940  default:
941  {
942  //
943  // do nothing
944  //
945  Status = Irp->IoStatus.Status;
946  }
947  }
948 
949  //
950  // complete request
951  //
952  if (Status != STATUS_PENDING)
953  {
954  //
955  // store result
956  //
957  Irp->IoStatus.Status = Status;
958 
959  //
960  // complete request
961  //
963  }
964 
965  //
966  // done processing
967  //
968  return Status;
969 }
970 
971 NTSTATUS
972 NTAPI
975  IN PIRP Irp,
976  IN PVOID Ctx)
977 {
978  PKEVENT Event = (PKEVENT)Ctx;
979 
980  //
981  // signal event
982  //
983  KeSetEvent(Event, 0, FALSE);
985 }
986 
987 NTSTATUS
990  IN ULONG DataTransferLength,
991  IN UCHAR OpCode,
992  IN PKEVENT Event,
993  OUT PSCSI_REQUEST_BLOCK *OutRequest,
994  OUT PIRP *OutIrp)
995 {
996  PIRP Irp;
997  PIO_STACK_LOCATION IoStack;
999  PCDB pCDB;
1000 
1001  //
1002  // allocate irp
1003  //
1005  if (!Irp)
1006  {
1007  //
1008  // no memory
1009  //
1011  }
1012 
1013  //
1014  // get next stack location
1015  //
1016  IoStack = IoGetNextIrpStackLocation(Irp);
1017 
1018  //
1019  // create scsi block
1020  //
1022  sizeof(SCSI_REQUEST_BLOCK),
1023  USB_STOR_TAG);
1024  if (!Request)
1025  {
1026  //
1027  // no memory
1028  //
1029  IoFreeIrp(Irp);
1031  }
1032 
1033  //
1034  // init request
1035  //
1037 
1038  //
1039  // allocate data transfer block
1040  //
1042  DataTransferLength,
1043  USB_STOR_TAG);
1044  if (!Request->DataBuffer)
1045  {
1046  //
1047  // no memory
1048  //
1049  IoFreeIrp(Irp);
1052  }
1053 
1054  //
1055  // allocate MDL
1056  //
1057  Irp->MdlAddress = IoAllocateMdl(Request->DataBuffer, DataTransferLength, FALSE, FALSE, NULL);
1058  if (!Irp->MdlAddress)
1059  {
1060  //
1061  // no memory
1062  //
1063  IoFreeIrp(Irp);
1064  ExFreePoolWithTag(Request->DataBuffer, USB_STOR_TAG);
1067  }
1068 
1069  //
1070  // non paged pool
1071  //
1072  MmBuildMdlForNonPagedPool(Irp->MdlAddress);
1073 
1074  //
1075  // init scsi block
1076  //
1077  Request->DataTransferLength = DataTransferLength;
1078  Request->Function = SRB_FUNCTION_EXECUTE_SCSI;
1079  Request->SrbFlags = SRB_FLAGS_DATA_IN;
1080 
1081  RtlZeroMemory(Request->DataBuffer, DataTransferLength);
1082 
1083 
1084  //
1085  // get SCSI command data block
1086  //
1087  pCDB = (PCDB)Request->Cdb;
1088 
1089  //
1090  // set op code
1091  //
1092  pCDB->AsByte[0] = OpCode;
1093 
1094  //
1095  // store result
1096  //
1098  IoStack->Parameters.Others.Argument1 = Request;
1099  IoStack->DeviceObject = DeviceObject;
1100 
1101  //
1102  // init event
1103  //
1105 
1106  //
1107  // lets setup a completion routine
1108  //
1110 
1111  //
1112  // output result
1113  //
1114  *OutIrp = Irp;
1115  *OutRequest = Request;
1116  return STATUS_SUCCESS;
1117 }
1118 
1119 NTSTATUS
1121  IN PDEVICE_OBJECT PDODeviceObject,
1122  IN ULONG DataTransferLength,
1123  IN UCHAR OpCode,
1124  OUT PVOID *OutData)
1125 {
1126  NTSTATUS Status;
1127  PIRP Irp;
1128  KEVENT Event;
1129  PPDO_DEVICE_EXTENSION PDODeviceExtension;
1131 
1132  //
1133  // let's allocate an irp
1134  //
1135  Status = USBSTOR_AllocateIrp(PDODeviceObject, DataTransferLength, OpCode, &Event, &Request, &Irp);
1136  if (!NT_SUCCESS(Status))
1137  {
1138  //
1139  // failed
1140  //
1141  DPRINT1("[USBSTOR] Failed to build irp\n");
1142  return Status;
1143  }
1144 
1145  //
1146  // get device extension
1147  //
1148  PDODeviceExtension = (PPDO_DEVICE_EXTENSION)PDODeviceObject->DeviceExtension;
1149 
1150  //
1151  // send irp
1152  //
1153  ASSERT(Irp);
1154  ASSERT(PDODeviceExtension->LowerDeviceObject);
1155  Status = IoCallDriver(PDODeviceExtension->Self, Irp);
1156 
1157  if (Status == STATUS_PENDING)
1158  {
1159  //
1160  // wait for completion
1161  //
1163  Status = Irp->IoStatus.Status;
1164  }
1165 
1166  if (NT_SUCCESS(Status))
1167  {
1168  //
1169  // store result
1170  //
1171  *OutData = Request->DataBuffer;
1172  }
1173  else
1174  {
1175  //
1176  // free the data
1177  //
1178  ExFreePoolWithTag(Request->DataBuffer, USB_STOR_TAG);
1179  *OutData = NULL;
1180  }
1181 
1182  //
1183  // free resources
1184  //
1186  IoFreeMdl(Irp->MdlAddress);
1187  IoFreeIrp(Irp);
1188  return Status;
1189 }
1190 
1191 NTSTATUS
1193  IN PDEVICE_OBJECT PDODeviceObject)
1194 {
1195  NTSTATUS Status;
1196  PPDO_DEVICE_EXTENSION PDODeviceExtension;
1198 
1199  //
1200  // get device extension
1201  //
1202  PDODeviceExtension = (PPDO_DEVICE_EXTENSION)PDODeviceObject->DeviceExtension;
1203 
1204  //
1205  // send request
1206  //
1207  Status = USBSTOR_SendIrp(PDODeviceObject, sizeof(UFI_INQUIRY_RESPONSE), SCSIOP_INQUIRY, (PVOID*)&Response);
1208  if (!NT_SUCCESS(Status))
1209  {
1210  //
1211  // command failed
1212  //
1213  DPRINT1("USBSTOR_SendInquiryIrp Failed with %x\n", Status);
1214  return Status;
1215  }
1216 
1217  DPRINT1("Response %p\n", Response);
1218  DPRINT1("DeviceType %x\n", Response->DeviceType);
1219  DPRINT1("RMB %x\n", Response->RMB);
1220  DPRINT1("Version %x\n", Response->Version);
1221  DPRINT1("Format %x\n", Response->Format);
1222  DPRINT1("Length %x\n", Response->Length);
1223  DPRINT1("Reserved %p\n", Response->Reserved);
1224  DPRINT1("Vendor %c%c%c%c%c%c%c%c\n", Response->Vendor[0], Response->Vendor[1], Response->Vendor[2], Response->Vendor[3], Response->Vendor[4], Response->Vendor[5], Response->Vendor[6], Response->Vendor[7]);
1225  DPRINT1("Product %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n", Response->Product[0], Response->Product[1], Response->Product[2], Response->Product[3],
1226  Response->Product[4], Response->Product[5], Response->Product[6], Response->Product[7],
1227  Response->Product[8], Response->Product[9], Response->Product[10], Response->Product[11],
1228  Response->Product[12], Response->Product[13], Response->Product[14], Response->Product[15]);
1229 
1230  DPRINT1("Revision %c%c%c%c\n", Response->Revision[0], Response->Revision[1], Response->Revision[2], Response->Revision[3]);
1231 
1232  //
1233  // store result
1234  //
1235  PDODeviceExtension->InquiryData = (PVOID)Response;
1236  return Status;
1237 }
1238 
1239 NTSTATUS
1241  IN PDEVICE_OBJECT PDODeviceObject)
1242 {
1243  NTSTATUS Status;
1244  PPDO_DEVICE_EXTENSION PDODeviceExtension;
1245  PUCHAR Response;
1246 
1247  //
1248  // get device extension
1249  //
1250  PDODeviceExtension = (PPDO_DEVICE_EXTENSION)PDODeviceObject->DeviceExtension;
1251 
1252  //
1253  // send request
1254  //
1255  Status = USBSTOR_SendIrp(PDODeviceObject, 0xFC, SCSIOP_READ_FORMATTED_CAPACITY, (PVOID*)&Response);
1256  if (!NT_SUCCESS(Status))
1257  {
1258  //
1259  // command failed
1260  //
1261  return Status;
1262  }
1263 
1264  //
1265  // check if its a floppy
1266  //
1267  PDODeviceExtension->IsFloppy = USBSTOR_IsFloppy(Response, 0xFC /*FIXME*/, &PDODeviceExtension->MediumTypeCode);
1268 
1269  //
1270  // free response
1271  //
1273  return Status;
1274 }
1275 
1276 
1277 
1278 NTSTATUS
1281  IN UCHAR LUN)
1282 {
1283  PDEVICE_OBJECT PDO;
1284  NTSTATUS Status;
1285  PPDO_DEVICE_EXTENSION PDODeviceExtension;
1287  PFDO_DEVICE_EXTENSION FDODeviceExtension;
1288 
1289  //
1290  // get device extension
1291  //
1292  FDODeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
1293 
1294 
1295  //
1296  // create child device object
1297  //
1299  if (!NT_SUCCESS(Status))
1300  {
1301  //
1302  // failed to create device
1303  //
1304  return Status;
1305  }
1306 
1307  //
1308  // patch the stack size
1309  //
1311 
1312  //
1313  // get device extension
1314  //
1315  PDODeviceExtension = (PPDO_DEVICE_EXTENSION)PDO->DeviceExtension;
1316 
1317  //
1318  // initialize device extension
1319  //
1320  RtlZeroMemory(PDODeviceExtension, sizeof(PDO_DEVICE_EXTENSION));
1321  PDODeviceExtension->Common.IsFDO = FALSE;
1322  PDODeviceExtension->LowerDeviceObject = DeviceObject;
1323  PDODeviceExtension->PDODeviceObject = &FDODeviceExtension->ChildPDO[LUN];
1324  PDODeviceExtension->Self = PDO;
1325  PDODeviceExtension->LUN = LUN;
1326 
1327  //
1328  // set device flags
1329  //
1331 
1332  //
1333  // device is initialized
1334  //
1335  PDO->Flags &= ~DO_DEVICE_INITIALIZING;
1336 
1337  //
1338  // output device object
1339  //
1340  FDODeviceExtension->ChildPDO[LUN] = PDO;
1341 
1342  //
1343  // send inquiry command by irp
1344  //
1347 
1348  //
1349  // check response data
1350  //
1351  Response = (PUFI_INQUIRY_RESPONSE)PDODeviceExtension->InquiryData;
1352  ASSERT(Response);
1353 
1354  if (Response->DeviceType == 0)
1355  {
1356  //
1357  // check if it is a floppy
1358  //
1360 
1361  //
1362  // display result
1363  //
1364  DPRINT1("[USBSTOR] Status %x IsFloppy %x MediumTypeCode %x\n", Status, PDODeviceExtension->IsFloppy, PDODeviceExtension->MediumTypeCode);
1365 
1366  //
1367  // failing command is non critical
1368  //
1370  }
1371 
1372  //
1373  // done
1374  //
1375  return Status;
1376 }
NTSTATUS USBSTOR_SendInquiryIrp(IN PDEVICE_OBJECT PDODeviceObject)
Definition: pdo.c:1192
#define DO_DEVICE_INITIALIZING
Definition: env_spec_w32.h:399
signed char * PCHAR
Definition: retypes.h:7
CONST char * PCSZ
Definition: umtypes.h:125
#define IN
Definition: typedefs.h:38
#define TRUE
Definition: types.h:120
struct _KEVENT * PKEVENT
#define IRP_MN_REMOVE_DEVICE
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define IRP_MN_QUERY_ID
VOID USBSTOR_ConvertToUnicodeString(IN CHAR *Buffer, IN ULONG ResultBufferLength, IN ULONG ResultBufferOffset, OUT LPWSTR ResultBuffer, OUT PULONG NewResultBufferOffset)
Definition: pdo.c:288
NTSTATUS USBSTOR_PdoHandleDeviceRelations(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp)
Definition: pdo.c:515
struct UFI_INQUIRY_RESPONSE * PUFI_INQUIRY_RESPONSE
USHORT MaximumLength
Definition: env_spec_w32.h:370
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
_In_ PIRP Irp
Definition: csq.h:116
DeviceType
Definition: mmdrv.h:41
PDEVICE_OBJECT Objects[1]
Definition: iotypes.h:2055
unsigned char * PUCHAR
Definition: retypes.h:3
char CHAR
Definition: xmlstorage.h:175
VOID NTAPI MmBuildMdlForNonPagedPool(IN PMDL Mdl)
Definition: mdlsup.c:428
PVOID AllocateItem(IN POOL_TYPE PoolType, IN SIZE_T NumberOfBytes)
Definition: misc.c:30
Definition: cdrw_hw.h:28
LONG NTSTATUS
Definition: precomp.h:26
NTSTATUS USBSTOR_PdoHandleQueryDeviceText(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: pdo.c:179
struct _PDO_DEVICE_EXTENSION * PPDO_DEVICE_EXTENSION
BOOLEAN USBSTOR_IsFloppy(IN PUCHAR Buffer, IN ULONG BufferLength, OUT PUCHAR MediumTypeCode)
Definition: misc.c:427
#define FILE_DEVICE_MASS_STORAGE
Definition: imports.h:62
NTSTATUS USBSTOR_SendIrp(IN PDEVICE_OBJECT PDODeviceObject, IN ULONG DataTransferLength, IN UCHAR OpCode, OUT PVOID *OutData)
Definition: pdo.c:1120
_In_ ULONG TotalLength
Definition: usbdlib.h:145
#define SRB_FLAGS_DATA_IN
Definition: srb.h:392
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
struct _FDO_DEVICE_EXTENSION * PFDO_DEVICE_EXTENSION
LPCSTR USBSTOR_GetDeviceType(IN PINQUIRYDATA InquiryData, IN UCHAR IsFloppy)
Definition: pdo.c:19
#define DO_DIRECT_IO
Definition: env_spec_w32.h:396
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:515
NTSYSAPI VOID NTAPI RtlInitAnsiString(PANSI_STRING DestinationString, PCSZ SourceString)
UCHAR Revision[4]
Definition: usbstor.h:147
_In_ NDIS_HANDLE _In_ PNDIS_REQUEST Request
Definition: ndis.h:5173
#define sprintf(buf, format,...)
Definition: sprintf.c:55
NTSTATUS USBSTOR_PdoHandleQueryDeviceId(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: pdo.c:234
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
#define IRP_MN_QUERY_REMOVE_DEVICE
LPCSTR USBSTOR_GetGenericType(IN PINQUIRYDATA InquiryData, IN UCHAR IsFloppy)
Definition: pdo.c:71
_In_ PVOID _In_ ULONG Event
Definition: iotypes.h:435
_Must_inspect_result_ _In_opt_ PVOID _In_opt_ PVOID InstanceId
Definition: fsrtlfuncs.h:907
struct _DEVICE_RELATIONS * PDEVICE_RELATIONS
PVOID DeviceExtension
Definition: env_spec_w32.h:418
smooth NULL
Definition: ftsmooth.c:416
#define SCSIOP_READ_FORMATTED_CAPACITY
Definition: scsi.h:272
union _CDB * PCDB
#define IoCompleteRequest
Definition: irp.c:1240
NTSTATUS NTAPI USBSTOR_SyncForwardIrp(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: misc.c:34
NTSTATUS USBSTOR_PdoHandleQueryInstanceId(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp)
Definition: pdo.c:472
COMMON_DEVICE_EXTENSION Common
Definition: pci.h:55
void DPRINT(...)
Definition: polytest.cpp:61
Definition: bufpool.h:45
const char * LPCSTR
Definition: xmlstorage.h:183
void * PVOID
Definition: retypes.h:9
#define FILE_AUTOGENERATED_DEVICE_NAME
Definition: iotypes.h:138
#define IRP_MN_QUERY_STOP_DEVICE
NTSTATUS USBSTOR_SendFormatCapacityIrp(IN PDEVICE_OBJECT PDODeviceObject)
Definition: pdo.c:1240
#define SCSIOP_INQUIRY
Definition: cdrw_hw.h:888
#define IRP_MN_SURPRISE_REMOVAL
Definition: ntifs_ex.h:408
NTSTATUS USBSTOR_PdoHandlePnp(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp)
Definition: pdo.c:549
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
#define swprintf(buf, format,...)
Definition: sprintf.c:56
#define IRP_MN_START_DEVICE
NTSTATUS NTAPI USBSTOR_CompletionRoutine(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Ctx)
Definition: pdo.c:973
static const UCHAR Index[8]
Definition: usbohci.c:18
PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:2867
#define IRP_MN_QUERY_DEVICE_TEXT
#define IRP_MJ_INTERNAL_DEVICE_CONTROL
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
VOID NTAPI IoFreeMdl(PMDL Mdl)
Definition: iomdl.c:146
Definition: ncftp.h:89
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
NTSTATUS USBSTOR_PdoHandleQueryCompatibleId(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp)
Definition: pdo.c:435
unsigned char UCHAR
Definition: xmlstorage.h:181
_CRTIMP wchar_t *__cdecl wcscpy(_Out_writes_z_(_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
static const WCHAR L[]
Definition: oid.c:1250
NTSTATUS USBSTOR_AllocateIrp(IN PDEVICE_OBJECT DeviceObject, IN ULONG DataTransferLength, IN UCHAR OpCode, IN PKEVENT Event, OUT PSCSI_REQUEST_BLOCK *OutRequest, OUT PIRP *OutIrp)
Definition: pdo.c:988
#define USB_STOR_TAG
Definition: usbstor.h:10
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2647
NTSTATUS USBSTOR_PdoHandleQueryHardwareId(IN PDEVICE_OBJECT DeviceObject, IN OUT PIRP Irp)
Definition: pdo.c:323
* PDEVICE_CAPABILITIES
Definition: iotypes.h:928
Status
Definition: gdiplustypes.h:24
PMDL NTAPI IoAllocateMdl(IN PVOID VirtualAddress, IN ULONG Length, IN BOOLEAN SecondaryBuffer, IN BOOLEAN ChargeQuota, IN PIRP Irp)
Definition: iomdl.c:22
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
VOID NTAPI IoDeleteDevice(IN PDEVICE_OBJECT DeviceObject)
Definition: device.c:1251
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
NTSYSAPI NTSTATUS NTAPI RtlAnsiStringToUnicodeString(PUNICODE_STRING DestinationString, PANSI_STRING SourceString, BOOLEAN AllocateDestinationString)
unsigned int * PULONG
Definition: retypes.h:1
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
#define IRP_MN_QUERY_DEVICE_RELATIONS
ULONG CopyField(IN PUCHAR Name, IN PCHAR Buffer, IN ULONG MaxLength)
Definition: pdo.c:167
UCHAR Product[16]
Definition: usbstor.h:146
#define DPRINT1
Definition: precomp.h:8
NTSTATUS USBSTOR_CreatePDO(IN PDEVICE_OBJECT DeviceObject, IN UCHAR LUN)
Definition: pdo.c:896
#define OUT
Definition: typedefs.h:39
#define ObReferenceObject
Definition: obfuncs.h:204
VOID NTAPI IoFreeIrp(IN PIRP Irp)
Definition: irp.c:1666
#define SRB_FUNCTION_EXECUTE_SCSI
Definition: srb.h:307
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:409
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:566
NTSTATUS NTAPI IoCreateDevice(IN PDRIVER_OBJECT DriverObject, IN ULONG DeviceExtensionSize, IN PUNICODE_STRING DeviceName, IN DEVICE_TYPE DeviceType, IN ULONG DeviceCharacteristics, IN BOOLEAN Exclusive, OUT PDEVICE_OBJECT *DeviceObject)
Definition: device.c:1031
struct Response Response
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#define ULONG_PTR
Definition: config.h:101
OpCode
Definition: dlist.c:229
PIRP NTAPI IoAllocateIrp(IN CCHAR StackSize, IN BOOLEAN ChargeQuota)
Definition: irp.c:615
#define FILE_DEVICE_SECURE_OPEN
Definition: cdrw_usr.h:46
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
WCHAR * LPWSTR
Definition: xmlstorage.h:184
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2772
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
return STATUS_SUCCESS
Definition: btrfs.c:2938
PKMT_RESULTBUFFER ResultBuffer
#define DO_MAP_IO_BUFFER
Definition: env_spec_w32.h:397
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
UCHAR AsByte[16]
Definition: scsi.h:1658
#define IRP_MN_QUERY_CAPABILITIES