[USB]
[reactos.git] / reactos / drivers / usb / usbstor / pdo.c
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 LPCSTR
15 USBSTOR_GetDeviceType(
16 IN PUFI_INQUIRY_RESPONSE InquiryData)
17 {
18 //
19 // check if device type is zero
20 //
21 if (InquiryData->DeviceType == 0)
22 {
23 //
24 // direct access device
25 //
26
27 //
28 // FIXME: check if floppy
29 //
30 return "Disk";
31 }
32
33 //
34 // FIXME: use constant - derrived from http://en.wikipedia.org/wiki/SCSI_Peripheral_Device_Type
35 //
36 switch (InquiryData->DeviceType)
37 {
38 case 1:
39 {
40 //
41 // sequential device, i.e magnetic tape
42 //
43 return "Sequential";
44 }
45 case 4:
46 {
47 //
48 // write once device
49 //
50 return "Worm";
51 }
52 case 5:
53 {
54 //
55 // CDROM device
56 //
57 return "CdRom";
58 }
59 case 7:
60 {
61 //
62 // optical memory device
63 //
64 return "Optical";
65 }
66 case 8:
67 {
68 //
69 // medium change device
70 //
71 return "Changer";
72 }
73 default:
74 {
75 //
76 // other device
77 //
78 return "Other";
79 }
80 }
81 }
82
83 LPCSTR
84 USBSTOR_GetGenericType(
85 IN PUFI_INQUIRY_RESPONSE InquiryData)
86 {
87 //
88 // check if device type is zero
89 //
90 if (InquiryData->DeviceType == 0)
91 {
92 //
93 // direct access device
94 //
95
96 //
97 // FIXME: check if floppy
98 //
99 return "GenDisk";
100 }
101
102 //
103 // FIXME: use constant - derrived from http://en.wikipedia.org/wiki/SCSI_Peripheral_Device_Type
104 //
105 switch (InquiryData->DeviceType)
106 {
107 case 1:
108 {
109 //
110 // sequential device, i.e magnetic tape
111 //
112 return "GenSequential";
113 }
114 case 4:
115 {
116 //
117 // write once device
118 //
119 return "GenWorm";
120 }
121 case 5:
122 {
123 //
124 // CDROM device
125 //
126 return "GenCdRom";
127 }
128 case 7:
129 {
130 //
131 // optical memory device
132 //
133 return "GenOptical";
134 }
135 case 8:
136 {
137 //
138 // medium change device
139 //
140 return "GenChanger";
141 }
142 default:
143 {
144 //
145 // other device
146 //
147 return "UsbstorOther";
148 }
149 }
150 }
151
152
153 ULONG
154 CopyField(
155 IN PUCHAR Name,
156 IN PCHAR Buffer,
157 IN ULONG MaxLength)
158 {
159 ULONG Index;
160
161 for(Index = 0; Index < MaxLength; Index++)
162 {
163 if (Name[Index] <= ' ' || Name[Index] >= 0x7F /* last printable ascii character */ || Name[Index] == ',')
164 {
165 //
166 // convert to underscore
167 //
168 Buffer[Index] = '_';
169 }
170 else
171 {
172 //
173 // just copy character
174 //
175 Buffer[Index] = Name[Index];
176 }
177 }
178
179 return MaxLength;
180 }
181
182 NTSTATUS
183 USBSTOR_PdoHandleQueryDeviceText(
184 IN PDEVICE_OBJECT DeviceObject,
185 IN PIRP Irp)
186 {
187 //PPDO_DEVICE_EXTENSION DeviceExtension;
188 PIO_STACK_LOCATION IoStack;
189 LPWSTR Buffer;
190 static WCHAR DeviceText[] = L"USB Mass Storage Device";
191
192 //
193 // get current stack location
194 //
195 IoStack = IoGetCurrentIrpStackLocation(Irp);
196
197 if (IoStack->Parameters.QueryDeviceText.DeviceTextType == DeviceTextDescription)
198 {
199 DPRINT("USBSTOR_PdoHandleQueryDeviceText DeviceTextDescription\n");
200
201 //
202 // allocate item
203 //
204 Buffer = (LPWSTR)AllocateItem(PagedPool, sizeof(DeviceText));
205 if (!Buffer)
206 {
207 //
208 // no memory
209 //
210 Irp->IoStatus.Information = 0;
211 return STATUS_INSUFFICIENT_RESOURCES;
212 }
213
214 //
215 // copy buffer
216 //
217 wcscpy(Buffer, DeviceText);
218
219 //
220 // save result
221 //
222 Irp->IoStatus.Information = (ULONG_PTR)Buffer;
223 return STATUS_SUCCESS;
224 }
225 else
226 {
227 DPRINT("USBSTOR_PdoHandleQueryDeviceText DeviceTextLocationInformation\n");
228
229 //
230 // allocate item
231 //
232 Buffer = (LPWSTR)AllocateItem(PagedPool, sizeof(DeviceText));
233 if (!Buffer)
234 {
235 //
236 // no memory
237 //
238 Irp->IoStatus.Information = 0;
239 return STATUS_INSUFFICIENT_RESOURCES;
240 }
241
242 //
243 // copy buffer
244 //
245 wcscpy(Buffer, DeviceText);
246
247 //
248 // save result
249 //
250 Irp->IoStatus.Information = (ULONG_PTR)Buffer;
251 return STATUS_SUCCESS;
252 }
253
254 }
255
256
257 NTSTATUS
258 USBSTOR_PdoHandleQueryDeviceId(
259 IN PDEVICE_OBJECT DeviceObject,
260 IN PIRP Irp)
261 {
262 PPDO_DEVICE_EXTENSION DeviceExtension;
263 NTSTATUS Status;
264 CHAR Buffer[100];
265 LPCSTR DeviceType;
266 ULONG Offset = 0;
267 PUFI_INQUIRY_RESPONSE InquiryData;
268 ANSI_STRING AnsiString;
269 UNICODE_STRING DeviceId;
270
271 //
272 // get device extension
273 //
274 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
275
276 //
277 // sanity check
278 //
279 ASSERT(DeviceExtension->InquiryData);
280
281 //
282 // get inquiry data
283 //
284 InquiryData = (PUFI_INQUIRY_RESPONSE)DeviceExtension->InquiryData;
285
286 //
287 // get device type
288 //
289 DeviceType = USBSTOR_GetDeviceType(InquiryData);
290
291 //
292 // zero buffer
293 //
294 RtlZeroMemory(Buffer, sizeof(Buffer));
295
296 //
297 // lets create device string
298 //
299 Offset = sprintf(&Buffer[Offset], "USBSTOR\\");
300 Offset += sprintf(&Buffer[Offset], DeviceType);
301 Offset += sprintf(&Buffer[Offset], "&Ven_");
302 Offset += CopyField(InquiryData->Vendor, &Buffer[Offset], 8);
303 Offset += sprintf(&Buffer[Offset], "&Prod_");
304 Offset += CopyField(InquiryData->Product, &Buffer[Offset], 16);
305 Offset += sprintf(&Buffer[Offset], "&Rev_");
306 Offset += CopyField(InquiryData->Revision, &Buffer[Offset], 4);
307
308 //
309 // now initialize ansi string
310 //
311 RtlInitAnsiString(&AnsiString, (PCSZ)Buffer);
312
313 //
314 // allocate DeviceId string
315 //
316 DeviceId.Length = 0;
317 DeviceId.MaximumLength = (strlen((PCHAR)Buffer) + 1) * sizeof(WCHAR);
318 DeviceId.Buffer = (LPWSTR)AllocateItem(PagedPool, DeviceId.MaximumLength);
319 if (!DeviceId.Buffer)
320 {
321 //
322 // no memory
323 //
324 Irp->IoStatus.Information = 0;
325 return STATUS_INSUFFICIENT_RESOURCES;
326 }
327
328
329 //
330 // convert to unicode
331 //
332 Status = RtlAnsiStringToUnicodeString(&DeviceId, &AnsiString, FALSE);
333
334 if (NT_SUCCESS(Status))
335 {
336 //
337 // store result
338 //
339 Irp->IoStatus.Information = (ULONG_PTR)DeviceId.Buffer;
340 }
341
342 DPRINT("DeviceId %wZ Status %x\n", &DeviceId, Status);
343
344 //
345 // done
346 //
347 return Status;
348 }
349
350 VOID
351 USBSTOR_ConvertToUnicodeString(
352 IN CHAR * Buffer,
353 IN ULONG ResultBufferLength,
354 IN ULONG ResultBufferOffset,
355 OUT LPWSTR ResultBuffer,
356 OUT PULONG NewResultBufferOffset)
357 {
358 UNICODE_STRING DeviceString;
359 ANSI_STRING AnsiString;
360 NTSTATUS Status;
361
362 ASSERT(ResultBufferLength);
363 ASSERT(ResultBufferLength > ResultBufferOffset);
364
365 DPRINT("ResultBufferOffset %lu ResultBufferLength %lu Buffer %s Length %lu\n", ResultBufferOffset, ResultBufferLength, Buffer, strlen(Buffer));
366
367 //
368 // construct destination string
369 //
370 DeviceString.Buffer = &ResultBuffer[ResultBufferOffset];
371 DeviceString.Length = 0;
372 DeviceString.MaximumLength = (ResultBufferLength - ResultBufferOffset) * sizeof(WCHAR);
373
374 //
375 // initialize source string
376 //
377 RtlInitAnsiString(&AnsiString, Buffer);
378
379 //
380 // convert to unicode
381 //
382 Status = RtlAnsiStringToUnicodeString(&DeviceString, &AnsiString, FALSE);
383 ASSERT(Status == STATUS_SUCCESS);
384
385 //
386 // subtract consumed bytes
387 //
388 ResultBufferLength -= (DeviceString.Length + sizeof(WCHAR)) / sizeof(WCHAR);
389 ResultBufferOffset += (DeviceString.Length + sizeof(WCHAR)) / sizeof(WCHAR);
390
391 //
392 // store new offset
393 //
394 *NewResultBufferOffset = ResultBufferOffset;
395 }
396
397
398
399 NTSTATUS
400 USBSTOR_PdoHandleQueryHardwareId(
401 IN PDEVICE_OBJECT DeviceObject,
402 IN OUT PIRP Irp)
403 {
404 PPDO_DEVICE_EXTENSION PDODeviceExtension;
405 PFDO_DEVICE_EXTENSION FDODeviceExtension;
406 LPCSTR GenericType, DeviceType;
407 LPWSTR Buffer;
408 CHAR Id1[50], Id2[50], Id3[50], Id4[50], Id5[50], Id6[50];
409 ULONG Id1Length, Id2Length, Id3Length, Id4Length, Id5Length,Id6Length;
410 ULONG Offset, TotalLength, Length;
411 PUFI_INQUIRY_RESPONSE InquiryData;
412
413 //
414 // get PDO device extension
415 //
416 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
417
418 //
419 // get FDO device extension
420 //
421 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)PDODeviceExtension->LowerDeviceObject->DeviceExtension;
422
423 //
424 // sanity check
425 //
426 ASSERT(FDODeviceExtension->DeviceDescriptor);
427
428 //
429 // get inquiry data
430 //
431 InquiryData = (PUFI_INQUIRY_RESPONSE)PDODeviceExtension->InquiryData;
432
433
434 //
435 // get device type and generic type
436 //
437 DeviceType = USBSTOR_GetDeviceType(InquiryData);
438 GenericType = USBSTOR_GetGenericType(InquiryData);
439
440 ASSERT(GenericType);
441
442 //
443 // generate id 1
444 // USBSTOR\SCSIType_Vendor(8)_Product(16)_Revision(4)
445 //
446 RtlZeroMemory(Id1, sizeof(Id1));
447 Offset = 0;
448 Offset = sprintf(&Id1[Offset], "USBSTOR\\");
449 Offset += sprintf(&Id1[Offset], DeviceType);
450 Offset += CopyField(InquiryData->Vendor, &Id1[Offset], 8);
451 Offset += CopyField(InquiryData->Product, &Id1[Offset], 16);
452 Offset += CopyField(InquiryData->Revision, &Id1[Offset], 4);
453 Id1Length = strlen(Id1) + 1;
454 DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId1 %s\n", Id1);
455
456 //
457 // generate id 2
458 // USBSTOR\SCSIType_VENDOR(8)_Product(16)
459 //
460 RtlZeroMemory(Id2, sizeof(Id2));
461 Offset = 0;
462 Offset = sprintf(&Id2[Offset], "USBSTOR\\");
463 Offset += sprintf(&Id2[Offset], DeviceType);
464 Offset += CopyField(InquiryData->Vendor, &Id2[Offset], 8);
465 Offset += CopyField(InquiryData->Product, &Id2[Offset], 16);
466 Id2Length = strlen(Id2) + 1;
467 DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId2 %s\n", Id2);
468
469 //
470 // generate id 3
471 // USBSTOR\SCSIType_VENDOR(8)
472 //
473 RtlZeroMemory(Id3, sizeof(Id3));
474 Offset = 0;
475 Offset = sprintf(&Id3[Offset], "USBSTOR\\");
476 Offset += sprintf(&Id3[Offset], DeviceType);
477 Offset += CopyField(InquiryData->Vendor, &Id3[Offset], 8);
478 Id3Length = strlen(Id3) + 1;
479 DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId3 %s\n", Id3);
480
481 //
482 // generate id 4
483 // USBSTOR\SCSIType_VENDOR(8)_Product(16)_Revision(1)
484 //
485 RtlZeroMemory(Id4, sizeof(Id4));
486 Offset = 0;
487 Offset = sprintf(&Id4[Offset], "USBSTOR\\");
488 Offset += sprintf(&Id4[Offset], DeviceType);
489 Offset += CopyField(InquiryData->Vendor, &Id4[Offset], 8);
490 Offset += CopyField(InquiryData->Product, &Id4[Offset], 16);
491 Offset += CopyField(InquiryData->Revision, &Id4[Offset], 1);
492 Id4Length = strlen(Id4) + 1;
493 DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId4 %s\n", Id4);
494
495 //
496 // generate id 5
497 // USBSTOR\SCSIType
498 //
499 RtlZeroMemory(Id5, sizeof(Id5));
500 Offset = 0;
501 Offset = sprintf(&Id5[Offset], "USBSTOR\\");
502 Offset += sprintf(&Id5[Offset], GenericType);
503 Id5Length = strlen(Id5) + 1;
504 DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId5 %s\n", Id5);
505
506 //
507 // generate id 6
508 // SCSIType
509 //
510 RtlZeroMemory(Id6, sizeof(Id6));
511 Offset = 0;
512 Offset = sprintf(&Id6[Offset], GenericType);
513 Id6Length = strlen(Id6) + 1;
514 DPRINT("USBSTOR_PdoHandleQueryHardwareId HardwareId6 %s\n", Id6);
515
516 //
517 // compute total length
518 //
519 TotalLength = Id1Length + Id2Length + Id3Length + Id4Length + Id5Length + Id6Length + 1;
520
521 //
522 // allocate buffer
523 //
524 Buffer = (LPWSTR)AllocateItem(PagedPool, TotalLength * sizeof(WCHAR));
525 if (!Buffer)
526 {
527 //
528 // no memory
529 //
530 Irp->IoStatus.Information = 0;
531 return STATUS_INSUFFICIENT_RESOURCES;
532 }
533
534 //
535 // reset offset
536 //
537 Offset = 0;
538 Length = TotalLength;
539
540 USBSTOR_ConvertToUnicodeString(Id1, Length, Offset, Buffer, &Offset);
541 USBSTOR_ConvertToUnicodeString(Id2, Length, Offset, Buffer, &Offset);
542 USBSTOR_ConvertToUnicodeString(Id3, Length, Offset, Buffer, &Offset);
543 USBSTOR_ConvertToUnicodeString(Id4, Length, Offset, Buffer, &Offset);
544 USBSTOR_ConvertToUnicodeString(Id5, Length, Offset, Buffer, &Offset);
545 USBSTOR_ConvertToUnicodeString(Id6, Length, Offset, Buffer, &Offset);
546
547 //
548 // sanity check
549 //
550 ASSERT(Offset + 1 == Length);
551
552 //
553 // store result
554 //
555 Irp->IoStatus.Information = (ULONG_PTR)Buffer;
556
557 //
558 // done
559 //
560 return STATUS_SUCCESS;
561 }
562
563 NTSTATUS
564 USBSTOR_PdoHandleQueryCompatibleId(
565 IN PDEVICE_OBJECT DeviceObject,
566 IN OUT PIRP Irp)
567 {
568 PPDO_DEVICE_EXTENSION PDODeviceExtension;
569 PFDO_DEVICE_EXTENSION FDODeviceExtension;
570 CHAR Buffer[100];
571 ULONG Length, Offset;
572 LPWSTR InstanceId;
573 LPCSTR DeviceType;
574
575 //
576 // get PDO device extension
577 //
578 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
579
580 //
581 // get FDO device extension
582 //
583 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)PDODeviceExtension->LowerDeviceObject->DeviceExtension;
584
585 //
586 // sanity check
587 //
588 ASSERT(FDODeviceExtension->DeviceDescriptor);
589
590 //
591 // get target device type
592 //
593 DeviceType = USBSTOR_GetDeviceType((PUFI_INQUIRY_RESPONSE)PDODeviceExtension->InquiryData);
594
595 //
596 // zero memory
597 //
598 RtlZeroMemory(Buffer, sizeof(Buffer));
599
600 //
601 // format instance id
602 //
603 Length = sprintf(Buffer, "USBSTOR\\%s", DeviceType) + 1;
604 Length += sprintf(&Buffer[Length], "USBSTOR\\%s", "RAW") + 2;
605
606 //
607 // allocate instance id
608 //
609 InstanceId = (LPWSTR)AllocateItem(PagedPool, Length * sizeof(WCHAR));
610 if (!InstanceId)
611 {
612 //
613 // no memory
614 //
615 Irp->IoStatus.Information = 0;
616 return STATUS_INSUFFICIENT_RESOURCES;
617 }
618
619 USBSTOR_ConvertToUnicodeString(Buffer, Length, 0, InstanceId, &Offset);
620 USBSTOR_ConvertToUnicodeString(&Buffer[Offset], Length, Offset, InstanceId, &Offset);
621
622 DPRINT("USBSTOR_PdoHandleQueryCompatibleId %S\n", InstanceId);
623
624 //
625 // store result
626 //
627 Irp->IoStatus.Information = (ULONG_PTR)InstanceId;
628
629 //
630 // completed successfully
631 //
632 return STATUS_SUCCESS;
633 }
634
635 NTSTATUS
636 USBSTOR_PdoHandleQueryInstanceId(
637 IN PDEVICE_OBJECT DeviceObject,
638 IN OUT PIRP Irp)
639 {
640 PPDO_DEVICE_EXTENSION PDODeviceExtension;
641 PFDO_DEVICE_EXTENSION FDODeviceExtension;
642 WCHAR Buffer[100];
643 ULONG Length;
644 LPWSTR InstanceId;
645
646 //
647 // get PDO device extension
648 //
649 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
650
651 //
652 // get FDO device extension
653 //
654 FDODeviceExtension = (PFDO_DEVICE_EXTENSION)PDODeviceExtension->LowerDeviceObject->DeviceExtension;
655
656 //
657 // format instance id
658 //
659 if (FDODeviceExtension->SerialNumber)
660 {
661 //
662 // using serial number from device
663 //
664 swprintf(Buffer, L"%s&%d", FDODeviceExtension->SerialNumber->bString, PDODeviceExtension->LUN);
665 }
666 else
667 {
668 //
669 // FIXME: should use some random value
670 //
671 swprintf(Buffer, L"%s&%d", L"00000000", PDODeviceExtension->LUN);
672 }
673
674 //
675 // calculate length
676 //
677 Length = wcslen(Buffer) + 1;
678
679 //
680 // allocate instance id
681 //
682 InstanceId = (LPWSTR)AllocateItem(PagedPool, Length * sizeof(WCHAR));
683 if (!InstanceId)
684 {
685 //
686 // no memory
687 //
688 Irp->IoStatus.Information = 0;
689 return STATUS_INSUFFICIENT_RESOURCES;
690 }
691
692 //
693 // copy instance id
694 //
695 wcscpy(InstanceId, Buffer);
696
697 DPRINT("USBSTOR_PdoHandleQueryInstanceId %S\n", InstanceId);
698
699 //
700 // store result
701 //
702 Irp->IoStatus.Information = (ULONG_PTR)InstanceId;
703
704 //
705 // completed successfully
706 //
707 return STATUS_SUCCESS;
708 }
709
710 NTSTATUS
711 USBSTOR_PdoHandleDeviceRelations(
712 IN PDEVICE_OBJECT DeviceObject,
713 IN OUT PIRP Irp)
714 {
715 PDEVICE_RELATIONS DeviceRelations;
716 PIO_STACK_LOCATION IoStack;
717
718 DPRINT("USBSTOR_PdoHandleDeviceRelations\n");
719
720 //
721 // get current irp stack location
722 //
723 IoStack = IoGetCurrentIrpStackLocation(Irp);
724
725 //
726 // check if relation type is BusRelations
727 //
728 if (IoStack->Parameters.QueryDeviceRelations.Type != TargetDeviceRelation)
729 {
730 //
731 // PDO handles only target device relation
732 //
733 return Irp->IoStatus.Status;
734 }
735
736 //
737 // allocate device relations
738 //
739 DeviceRelations = (PDEVICE_RELATIONS)AllocateItem(PagedPool, sizeof(DEVICE_RELATIONS));
740 if (!DeviceRelations)
741 {
742 //
743 // no memory
744 //
745 return STATUS_INSUFFICIENT_RESOURCES;
746 }
747
748 //
749 // initialize device relations
750 //
751 DeviceRelations->Count = 1;
752 DeviceRelations->Objects[0] = DeviceObject;
753 ObReferenceObject(DeviceObject);
754
755 //
756 // store result
757 //
758 Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
759
760 //
761 // completed successfully
762 //
763 return STATUS_SUCCESS;
764 }
765
766
767 NTSTATUS
768 USBSTOR_PdoHandlePnp(
769 IN PDEVICE_OBJECT DeviceObject,
770 IN OUT PIRP Irp)
771 {
772 PIO_STACK_LOCATION IoStack;
773 PPDO_DEVICE_EXTENSION DeviceExtension;
774 NTSTATUS Status;
775 PDEVICE_CAPABILITIES Caps;
776 ULONG bDelete;
777
778 //
779 // get current stack location
780 //
781 IoStack = IoGetCurrentIrpStackLocation(Irp);
782
783 //
784 // get device extension
785 //
786 DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
787
788 //
789 // sanity check
790 //
791 ASSERT(DeviceExtension->Common.IsFDO == FALSE);
792
793 switch(IoStack->MinorFunction)
794 {
795 case IRP_MN_QUERY_DEVICE_RELATIONS:
796 {
797 Status = USBSTOR_PdoHandleDeviceRelations(DeviceObject, Irp);
798 break;
799 }
800 case IRP_MN_QUERY_DEVICE_TEXT:
801 {
802 Status = USBSTOR_PdoHandleQueryDeviceText(DeviceObject, Irp);
803 break;
804 }
805 case IRP_MN_QUERY_ID:
806 {
807 if (IoStack->Parameters.QueryId.IdType == BusQueryDeviceID)
808 {
809 //
810 // handle query device id
811 //
812 Status = USBSTOR_PdoHandleQueryDeviceId(DeviceObject, Irp);
813 break;
814 }
815 else if (IoStack->Parameters.QueryId.IdType == BusQueryHardwareIDs)
816 {
817 //
818 // handle instance id
819 //
820 Status = USBSTOR_PdoHandleQueryHardwareId(DeviceObject, Irp);
821 break;
822 }
823 else if (IoStack->Parameters.QueryId.IdType == BusQueryInstanceID)
824 {
825 //
826 // handle instance id
827 //
828 Status = USBSTOR_PdoHandleQueryInstanceId(DeviceObject, Irp);
829 break;
830 }
831 else if (IoStack->Parameters.QueryId.IdType == BusQueryCompatibleIDs)
832 {
833 //
834 // handle instance id
835 //
836 Status = USBSTOR_PdoHandleQueryCompatibleId(DeviceObject, Irp);
837 break;
838 }
839
840 DPRINT1("USBSTOR_PdoHandlePnp: IRP_MN_QUERY_ID IdType %x unimplemented\n", IoStack->Parameters.QueryId.IdType);
841 Status = STATUS_NOT_SUPPORTED;
842 Irp->IoStatus.Information = 0;
843 break;
844 }
845 case IRP_MN_REMOVE_DEVICE:
846 {
847 DPRINT("IRP_MN_REMOVE_DEVICE\n");
848
849 if(*DeviceExtension->PDODeviceObject != NULL)
850 {
851 //
852 // clear entry in FDO pdo list
853 //
854 *DeviceExtension->PDODeviceObject = NULL;
855 bDelete = TRUE;
856 }
857 else
858 {
859 //
860 // device object already marked for deletion
861 //
862 bDelete = FALSE;
863 }
864
865 /* Complete the IRP */
866 Irp->IoStatus.Status = STATUS_SUCCESS;
867 IoCompleteRequest(Irp, IO_NO_INCREMENT);
868
869 if (bDelete)
870 {
871 /* Delete the device object */
872 IoDeleteDevice(DeviceObject);
873 }
874 return STATUS_SUCCESS;
875 }
876 case IRP_MN_QUERY_CAPABILITIES:
877 {
878 //
879 // just forward irp to lower device
880 //
881 Status = USBSTOR_SyncForwardIrp(DeviceExtension->LowerDeviceObject, Irp);
882 ASSERT(Status == STATUS_SUCCESS);
883
884 if (NT_SUCCESS(Status))
885 {
886 //
887 // check if no unique id
888 //
889 Caps = (PDEVICE_CAPABILITIES)IoStack->Parameters.DeviceCapabilities.Capabilities;
890 Caps->UniqueID = TRUE; //FIXME
891 Caps->Removable = TRUE; //FIXME
892 }
893 break;
894 }
895 case IRP_MN_QUERY_REMOVE_DEVICE:
896 case IRP_MN_QUERY_STOP_DEVICE:
897 {
898 //
899 // if we're not claimed it's ok
900 //
901 if (DeviceExtension->Claimed)
902 {
903 Status = STATUS_UNSUCCESSFUL;
904 DPRINT1("[USBSTOR] Request %x fails because device is still claimed\n", IoStack->MinorFunction);
905 }
906 else
907 Status = STATUS_SUCCESS;
908 break;
909 }
910 case IRP_MN_START_DEVICE:
911 {
912 //
913 // no-op for PDO
914 //
915 Status = STATUS_SUCCESS;
916 break;
917 }
918 default:
919 {
920 //
921 // do nothing
922 //
923 Status = Irp->IoStatus.Status;
924 }
925 }
926
927 //
928 // complete request
929 //
930 if (Status != STATUS_PENDING)
931 {
932 //
933 // store result
934 //
935 Irp->IoStatus.Status = Status;
936
937 //
938 // complete request
939 //
940 IoCompleteRequest(Irp, IO_NO_INCREMENT);
941 }
942
943 //
944 // done processing
945 //
946 return Status;
947 }
948
949 NTSTATUS
950 USBSTOR_CreatePDO(
951 IN PDEVICE_OBJECT DeviceObject,
952 OUT PDEVICE_OBJECT *ChildDeviceObject)
953 {
954 PDEVICE_OBJECT PDO;
955 NTSTATUS Status;
956 PPDO_DEVICE_EXTENSION PDODeviceExtension;
957
958 //
959 // create child device object
960 //
961 Status = IoCreateDevice(DeviceObject->DriverObject, sizeof(PDO_DEVICE_EXTENSION), NULL, FILE_DEVICE_MASS_STORAGE, FILE_AUTOGENERATED_DEVICE_NAME | FILE_DEVICE_SECURE_OPEN, FALSE, &PDO);
962 if (!NT_SUCCESS(Status))
963 {
964 //
965 // failed to create device
966 //
967 return Status;
968 }
969
970 //
971 // patch the stack size
972 //
973 PDO->StackSize = DeviceObject->StackSize;
974
975 //
976 // get device extension
977 //
978 PDODeviceExtension = (PPDO_DEVICE_EXTENSION)PDO->DeviceExtension;
979
980 //
981 // initialize device extension
982 //
983 RtlZeroMemory(PDODeviceExtension, sizeof(PDO_DEVICE_EXTENSION));
984 PDODeviceExtension->Common.IsFDO = FALSE;
985 PDODeviceExtension->LowerDeviceObject = DeviceObject;
986 PDODeviceExtension->PDODeviceObject = ChildDeviceObject;
987
988 //
989 // set device flags
990 //
991 PDO->Flags |= DO_DIRECT_IO | DO_MAP_IO_BUFFER;
992
993 //
994 // device is initialized
995 //
996 PDO->Flags &= ~DO_DEVICE_INITIALIZING;
997
998 //
999 // output device object
1000 //
1001 *ChildDeviceObject = PDO;
1002
1003 USBSTOR_SendInquiryCmd(PDO);
1004
1005 //
1006 // done
1007 //
1008 return Status;
1009 }