ReactOS  0.4.14-dev-52-g6116262
enum.c
Go to the documentation of this file.
1 /*++
2 
3 Copyright (C) Microsoft Corporation, 1991 - 1999
4 
5 Module Name:
6 
7  pnp.c
8 
9 Abstract:
10 
11  SCSI disk class driver
12 
13 Environment:
14 
15  kernel mode only
16 
17 Notes:
18 
19 Revision History:
20 
21 --*/
22 
23 #include "disk.h"
24 
25 #ifdef ALLOC_PRAGMA
26 
27 #pragma alloc_text(PAGE, DiskConvertExtendedToLayout)
28 #pragma alloc_text(PAGE, DiskConvertPartitionToExtended)
29 #pragma alloc_text(PAGE, DiskConvertLayoutToExtended)
30 #pragma alloc_text(PAGE, DiskCreatePdo)
31 #pragma alloc_text(PAGE, DiskEnumerateDevice)
32 #pragma alloc_text(PAGE, DiskUpdateRemovablePartitions)
33 #pragma alloc_text(PAGE, DiskUpdatePartitions)
34 #pragma alloc_text(PAGE, DiskCreatePdo)
35 
36 #endif
37 
39 NTAPI
42  )
43 {
44  ULONG i;
45  ULONG LayoutSize;
47  PPARTITION_INFORMATION Partition;
48  PPARTITION_INFORMATION_EX PartitionEx;
49 
50  PAGED_CODE ();
51 
52  ASSERT ( LayoutEx );
53 
54 
55  //
56  // The only valid conversion is from an MBR extended layout structure to
57  // the old structure.
58  //
59 
60  if (LayoutEx->PartitionStyle != PARTITION_STYLE_MBR) {
61  ASSERT ( FALSE );
62  return NULL;
63  }
64 
65  LayoutSize = FIELD_OFFSET (DRIVE_LAYOUT_INFORMATION, PartitionEntry[0]) +
66  LayoutEx->PartitionCount * sizeof (PARTITION_INFORMATION);
67 
68  Layout = ExAllocatePoolWithTag (
70  LayoutSize,
72  );
73 
74  if ( Layout == NULL ) {
75  return NULL;
76  }
77 
78  Layout->Signature = LayoutEx->Mbr.Signature;
79  Layout->PartitionCount = LayoutEx->PartitionCount;
80 
81  for (i = 0; i < LayoutEx->PartitionCount; i++) {
82 
83  Partition = &Layout->PartitionEntry[i];
84  PartitionEx = &LayoutEx->PartitionEntry[i];
85 
86  Partition->StartingOffset = PartitionEx->StartingOffset;
87  Partition->PartitionLength = PartitionEx->PartitionLength;
88  Partition->RewritePartition = PartitionEx->RewritePartition;
89  Partition->PartitionNumber = PartitionEx->PartitionNumber;
90 
91  Partition->PartitionType = PartitionEx->Mbr.PartitionType;
92  Partition->BootIndicator = PartitionEx->Mbr.BootIndicator;
93  Partition->RecognizedPartition = PartitionEx->Mbr.RecognizedPartition;
94  Partition->HiddenSectors = PartitionEx->Mbr.HiddenSectors;
95  }
96 
97  return Layout;
98 }
99 
100 VOID
101 NTAPI
103  IN PPARTITION_INFORMATION Partition,
104  OUT PPARTITION_INFORMATION_EX PartitionEx
105  )
106 
107 /*++
108 
109 Routine Description:
110 
111  Convert a PARTITION_INFORMATION structure to a PARTITION_INFORMATION_EX
112  structure.
113 
114 Arguments:
115 
116  Partition - A pointer to the PARTITION_INFORMATION structure to convert.
117 
118  PartitionEx - A pointer to a buffer where the converted
119  PARTITION_INFORMATION_EX structure is to be stored.
120 
121 Return Values:
122 
123  None.
124 
125 --*/
126 
127 {
128  PAGED_CODE ();
129 
130  ASSERT ( PartitionEx != NULL );
131  ASSERT ( Partition != NULL );
132 
133  PartitionEx->PartitionStyle = PARTITION_STYLE_MBR;
134  PartitionEx->StartingOffset = Partition->StartingOffset;
135  PartitionEx->PartitionLength = Partition->PartitionLength;
136  PartitionEx->RewritePartition = Partition->RewritePartition;
137  PartitionEx->PartitionNumber = Partition->PartitionNumber;
138 
139  PartitionEx->Mbr.PartitionType = Partition->PartitionType;
140  PartitionEx->Mbr.BootIndicator = Partition->BootIndicator;
141  PartitionEx->Mbr.RecognizedPartition = Partition->RecognizedPartition;
142  PartitionEx->Mbr.HiddenSectors = Partition->HiddenSectors;
143 }
144 
146 NTAPI
149  )
150 
151 /*++
152 
153 Routine Description:
154 
155  Convert a DRIVE_LAYOUT_INFORMATION structure into a
156  DRIVE_LAYOUT_INFORMATION_EX structure.
157 
158 Arguments:
159 
160  Layout - The source DRIVE_LAYOUT_INFORMATION structure.
161 
162 Return Values:
163 
164  The resultant DRIVE_LAYOUT_INFORMATION_EX structure. This buffer must
165  be freed by the callee using ExFreePool.
166 
167 --*/
168 
169 {
170  ULONG i;
171  ULONG size;
173 
174  PAGED_CODE ();
175 
176  ASSERT ( Layout != NULL );
177 
178 
179  //
180  // Allocate enough space for a DRIVE_LAYOUT_INFORMATION_EX structure
181  // plus as many PARTITION_INFORMATION_EX structures as are in the
182  // source array.
183  //
184 
185  size = FIELD_OFFSET (DRIVE_LAYOUT_INFORMATION_EX, PartitionEntry[0]) +
186  Layout->PartitionCount * sizeof ( PARTITION_INFORMATION_EX );
187 
188  layoutEx = ExAllocatePoolWithTag(
189  NonPagedPool,
190  size,
192  );
193 
194  if ( layoutEx == NULL ) {
195  return NULL;
196  }
197 
198  //
199  // Convert the disk information.
200  //
201 
203  layoutEx->PartitionCount = Layout->PartitionCount;
204  layoutEx->Mbr.Signature = Layout->Signature;
205 
206  for (i = 0; i < Layout->PartitionCount; i++) {
207 
208  //
209  // Convert each entry.
210  //
211 
213  &Layout->PartitionEntry[i],
214  &layoutEx->PartitionEntry[i]
215  );
216  }
217 
218  return layoutEx;
219 }
220 
221 NTSTATUS
222 NTAPI
224  IN PDEVICE_OBJECT Fdo
225  )
226 
227 /*++
228 
229 Routine Description:
230 
231  This routine is called by the class driver to update the PDO list off
232  of this FDO. The disk driver also calls it internally to re-create
233  device objects.
234 
235  This routine will read the partition table and create new PDO objects as
236  necessary. PDO's that no longer exist will be pulled out of the PDO list
237  so that pnp will destroy them.
238 
239 Arguments:
240 
241  Fdo - a pointer to the FDO being re-enumerated
242 
243 Return Value:
244 
245  status
246 
247 --*/
248 
249 {
250  PCOMMON_DEVICE_EXTENSION commonExtension = Fdo->DeviceExtension;
251  PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
252 
253  //PPHYSICAL_DEVICE_EXTENSION pdoExtension = NULL;
254 
255  PDISK_DATA diskData = (PDISK_DATA) commonExtension->DriverData;
256 
257  //PDEVICE_OBJECT pdo = NULL;
258 
259  //ULONG numberListElements = 0;
260 
261  PDRIVE_LAYOUT_INFORMATION_EX partitionList;
262 
264 
265  ASSERT(commonExtension->IsFdo);
266 
267  PAGED_CODE();
268 
269  //
270  // Update our image of the size of the drive. This may be necessary if
271  // the drive size is extended or we just released a reservation to
272  // ensure the kernel doesn't reject the partition table.
273  //
274 
276 
277  //
278  // Lock out anyone else trying to repartition the disk.
279  //
280 
281  DiskAcquirePartitioningLock(fdoExtension);
282 
283  //
284  // Create objects for all the partitions on the device.
285  //
286 
287  status = DiskReadPartitionTableEx(fdoExtension, FALSE, &partitionList);
288 
289  //
290  // If the I/O read partition table failed and this is a removable device,
291  // then fix up the partition list to make it look like there is one
292  // zero length partition.
293  //
294 
295  if ((!NT_SUCCESS(status) || partitionList->PartitionCount == 0) &&
296  Fdo->Characteristics & FILE_REMOVABLE_MEDIA) {
297 
298  SIZE_T partitionListSize;
299 
300  //
301  // Remember whether the drive is ready.
302  //
303 
304  diskData->ReadyStatus = status;
305 
306  //
307  // Allocate and zero a partition list.
308  //
309 
310  partitionListSize =
311  FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION_EX, PartitionEntry[1]);
312 
313  partitionList = ExAllocatePoolWithTag(NonPagedPool,
314  partitionListSize,
316 
317  if (partitionList != NULL) {
318 
319  RtlZeroMemory( partitionList, partitionListSize );
320 
321  //
322  // Set the partition count to one and the status to success
323  // so one device object will be created. Set the partition type
324  // to a bogus value.
325  //
326 
327  partitionList->PartitionStyle = PARTITION_STYLE_MBR;
328  partitionList->PartitionCount = 1;
329 
331  } else {
333  }
334  }
335 
336  if (NT_SUCCESS(status)) {
337 
338  diskData->UpdatePartitionRoutine(Fdo, partitionList);
339 
340  //
341  // Record disk signature.
342  //
343 
344  if (partitionList->PartitionStyle == PARTITION_STYLE_MBR) {
345 
347  diskData->Mbr.Signature = partitionList->Mbr.Signature;
348 
349  } else {
350 
352  diskData->Efi.DiskId = partitionList->Gpt.DiskId;
353  }
354  }
355 
356  DiskReleasePartitioningLock(fdoExtension);
357 
358  return(STATUS_SUCCESS);
359 
360 } // end DiskEnumerateDevice()
361 
362 VOID
363 NTAPI
365  IN PDEVICE_OBJECT Fdo,
367  )
368 
369 /*++
370 
371 Routine Description:
372 
373  This routine is called by the class DLL to update the PDO list off of this
374  FDO. The disk driver also calls it internally to re-create device objects.
375 
376  This routine will read the partition table and update the size of the
377  single partition device object which always exists for removable devices.
378 
379 Arguments:
380 
381  Fdo - a pointer to the FDO being reenumerated.
382 
383 Return Value:
384 
385  status
386 
387 --*/
388 
389 {
390 
391  PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
392 
393  PPHYSICAL_DEVICE_EXTENSION pdoExtension = NULL;
394 
395  ULONG partitionCount;
396 
397  ULONG partitionNumber;
398  ULONG partitionOrdinal = 0;
399  //ULONG newPartitionNumber;
400 
401  PDISK_DATA pdoData;
403 
404  PPARTITION_INFORMATION_EX partitionEntry;
405  PARTITION_STYLE partitionStyle;
406 
407  PAGED_CODE();
408 
409  ASSERT(Fdo->Characteristics & FILE_REMOVABLE_MEDIA);
410 
411  partitionStyle = PartitionList->PartitionStyle;
412  partitionCount = PartitionList->PartitionCount;
413 
414  for(partitionNumber = 0;
415  partitionNumber < partitionCount;
416  partitionNumber++) {
417 
418  partitionEntry = &(PartitionList->PartitionEntry[partitionNumber]);
419 
420  partitionEntry->PartitionNumber = 0;
421  }
422 
423  //
424  // Get exclusive access to the child list while repartitioning.
425  //
426 
427  ClassAcquireChildLock(fdoExtension);
428 
429  //
430  // Removable media should never have more than one PDO.
431  //
432 
433  pdoExtension = fdoExtension->CommonExtension.ChildList;
434 
435  if(pdoExtension == NULL) {
436 
437  PARTITION_INFORMATION_EX tmpPartitionEntry;
438  PDEVICE_OBJECT pdo;
439 
440  //
441  // There is no PDO currently. Create one and pre-initialize it with
442  // a zero length.
443  //
444 
445  RtlZeroMemory(&tmpPartitionEntry, sizeof(tmpPartitionEntry));
446 
447  tmpPartitionEntry.PartitionNumber = 1;
448 
449  DebugPrint((1, "DiskUpdateRemovablePartitions: Creating RM partition\n"));
450 
451  status = DiskCreatePdo(Fdo,
452  0,
453  &tmpPartitionEntry,
454  partitionStyle,
455  &pdo);
456 
457  if(!NT_SUCCESS(status)) {
458 
459  DebugPrint((1, "DiskUpdateRemovablePartitions: error %lx creating "
460  "new PDO for RM partition\n",
461  status));
462 
463  ClassReleaseChildLock(fdoExtension);
464  return;
465  }
466 
467  //
468  // mark the new device as enumerated
469  //
470 
471  pdoExtension = pdo->DeviceExtension;
472  pdoExtension->IsMissing = FALSE;
473 
474  }
475 
476  pdoData = pdoExtension->CommonExtension.DriverData;
477 
478  //
479  // Search the partition list for a valid entry. We're looking for a
480  // primary partition since we only support the one.
481  //
482 
483  for(partitionNumber = 0;
484  partitionNumber < partitionCount;
485  partitionNumber++) {
486 
487  partitionEntry = &(PartitionList->PartitionEntry[partitionNumber]);
488 
489 
490  //
491  // Is this partition interesting?
492  //
493 
494  if (partitionStyle == PARTITION_STYLE_MBR) {
495 
496  if(partitionEntry->Mbr.PartitionType == PARTITION_ENTRY_UNUSED ||
497  IsContainerPartition(partitionEntry->Mbr.PartitionType)) {
498 
499  continue;
500  }
501  }
502 
503  partitionOrdinal++;
504 
505  //
506  // We have found the first and thus only partition allowed on
507  // this disk. Update the information in the PDO to match the new
508  // partition.
509  //
510  DebugPrint((1, "DiskUpdateRemovablePartitions: Matched %wZ to #%d, "
511  "ordinal %d\n",
512  &pdoExtension->CommonExtension.DeviceName,
513  partitionEntry->PartitionNumber,
514  partitionOrdinal));
515 
516 
517  partitionEntry->PartitionNumber = 1;
518 
519  pdoData->PartitionStyle = partitionStyle;
520  pdoData->PartitionOrdinal = partitionOrdinal;
521  ASSERT(partitionEntry->PartitionLength.LowPart != 0x23456789);
522 
523  pdoExtension->CommonExtension.StartingOffset =
524  partitionEntry->StartingOffset;
525 
526  pdoExtension->CommonExtension.PartitionLength =
527  partitionEntry->PartitionLength;
528 
529 
530  if (partitionStyle == PARTITION_STYLE_MBR) {
531 
532  pdoData->Mbr.HiddenSectors = partitionEntry->Mbr.HiddenSectors;
533  pdoData->Mbr.BootIndicator = partitionEntry->Mbr.BootIndicator;
534 
535 
536  //
537  // If this partition is being re-written then update the type
538  // information as well
539  //
540 
541  if (partitionEntry->RewritePartition) {
542  pdoData->Mbr.PartitionType = partitionEntry->Mbr.PartitionType;
543  }
544 
545  } else {
546 
547  pdoData->Efi.PartitionType = partitionEntry->Gpt.PartitionType;
548  pdoData->Efi.PartitionId = partitionEntry->Gpt.PartitionId;
549  pdoData->Efi.Attributes = partitionEntry->Gpt.Attributes;
550 
552  pdoData->Efi.PartitionName,
553  partitionEntry->Gpt.Name,
554  sizeof (pdoData->Efi.PartitionName)
555  );
556  }
557 
558  //
559  // Mark this one as found
560  //
561 
562  pdoExtension->IsMissing = FALSE;
563  ClassReleaseChildLock(fdoExtension);
564  return;
565  }
566 
567  //
568  // No interesting partition was found.
569  //
570 
571  if (partitionStyle == PARTITION_STYLE_MBR) {
572 
573  pdoData->Mbr.HiddenSectors = 0;
574  pdoData->Mbr.PartitionType = PARTITION_ENTRY_UNUSED;
575 
576  } else {
577 
578  RtlZeroMemory (&pdoData->Efi,
579  sizeof (pdoData->Efi)
580  );
581  }
582 
583  pdoExtension->CommonExtension.StartingOffset.QuadPart = 0;
584  pdoExtension->CommonExtension.PartitionLength.QuadPart = 0;
585 
586  ClassReleaseChildLock(fdoExtension);
587  return;
588 }
589 
590 VOID
591 NTAPI
593  IN PDEVICE_OBJECT Fdo,
595  )
596 
597 /*++
598 
599 Routine Description:
600 
601  This routine will synchronize the information held in the partition list
602  with the device objects hanging off this Fdo. Any new partition objects
603  will be created, any non-existant ones will be marked as un-enumerated.
604 
605  This will be done in several stages:
606 
607  * Clear state (partition number) from every entry in the partition
608  list
609 
610  * Set IsMissing flag on every child of this FDO
611 
612  * For each child of the FDO:
613  if a matching partition exists in the partition list,
614  update the partition number in the table, update the
615  ordinal in the object and mark the object as enumerated
616 
617  * For each un-enumerated device object
618  zero out the partition information to invalidate the device
619  delete the symbolic link if any
620 
621  * For each un-matched entry in the partition list:
622  create a new partition object
623  update the partition number in the list entry
624  create a new symbolic link if necessary
625 
626 Arguments:
627 
628  Fdo - a pointer to the functional device object this partition list is for
629 
630  PartitionList - a pointer to the partition list being updated
631 
632 Return Value:
633 
634  none
635 
636 --*/
637 
638 {
639  PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
640 
641  PPHYSICAL_DEVICE_EXTENSION oldChildList = NULL;
642  PPHYSICAL_DEVICE_EXTENSION pdoExtension = NULL;
643 
644  ULONG partitionCount;
645 
646  ULONG partitionNumber;
647  ULONG partitionOrdinal;
648  ULONG newPartitionNumber;
649 
650  PPARTITION_INFORMATION_EX partitionEntry = NULL;
651  PDISK_DATA pdoData;
652  PARTITION_STYLE partitionStyle;
653 
655 
656  PAGED_CODE();
657 
658  //
659  // Get exclusive access to the child list.
660  //
661 
662  ClassAcquireChildLock(fdoExtension);
663 
664  partitionStyle = PartitionList->PartitionStyle;
665 
666  partitionCount = PartitionList->PartitionCount;
667 
668  //
669  // Pull all the child device objects off the children list. We'll
670  // add them back later.
671  //
672 
673  oldChildList = fdoExtension->CommonExtension.ChildList;
674  fdoExtension->CommonExtension.ChildList = NULL;
675 
676  //
677  // Clear the partition numbers from the list entries
678  //
679 
680  for(partitionNumber = 0;
681  partitionNumber < partitionCount;
682  partitionNumber++) {
683 
684  partitionEntry = &(PartitionList->PartitionEntry[partitionNumber]);
685  partitionEntry->PartitionNumber = 0;
686  }
687 
688  //
689  // Now match each child partition to it's entry (if any) in the partition
690  // list.
691  //
692 
693  while(oldChildList != NULL) {
694 
695  pdoExtension = oldChildList;
696  pdoData = pdoExtension->CommonExtension.DriverData;
697 
698  //
699  // Check all partition entries for a match on offset and length
700  //
701 
702  partitionOrdinal = 0;
703 
704  for(partitionNumber = 0;
705  partitionNumber < partitionCount;
706  partitionNumber++) {
707 
708  partitionEntry = &(PartitionList->PartitionEntry[partitionNumber]);
709 
710  //
711  // Is this an interesting partition entry?
712  //
713 
714  if (partitionStyle == PARTITION_STYLE_MBR) {
715 
716  if((partitionEntry->Mbr.PartitionType == PARTITION_ENTRY_UNUSED) ||
717  (IsContainerPartition(partitionEntry->Mbr.PartitionType))) {
718 
719  continue;
720  }
721  }
722 
723  partitionOrdinal++;
724 
725  if(partitionEntry->PartitionNumber) {
726 
727  //
728  // This partition has already been found - skip it
729  //
730 
731  continue;
732  }
733 
734  //
735  // Let's see if the partition information matches
736  //
737 
738  if(partitionEntry->StartingOffset.QuadPart !=
739  pdoExtension->CommonExtension.StartingOffset.QuadPart) {
740  continue;
741  }
742 
743  if(partitionEntry->PartitionLength.QuadPart !=
744  pdoExtension->CommonExtension.PartitionLength.QuadPart) {
745  continue;
746  }
747 
748  //
749  // Yep - it matches. Update the information in the entry
750  //
751 
752  partitionEntry->PartitionNumber = pdoExtension->CommonExtension.PartitionNumber;
753 
754  if (partitionStyle == PARTITION_STYLE_MBR) {
755 
756  pdoData->Mbr.HiddenSectors = partitionEntry->Mbr.HiddenSectors;
757 
758  }
759 
760  break;
761  }
762 
763  if(partitionNumber != partitionCount) {
764 
765  DebugPrint((1, "DiskUpdatePartitions: Matched %wZ to #%d, ordinal "
766  "%d\n",
767  &pdoExtension->CommonExtension.DeviceName,
768  partitionEntry->PartitionNumber,
769  partitionOrdinal));
770 
771  ASSERT(partitionEntry->PartitionLength.LowPart != 0x23456789);
772  // ASSERT(pdoExtension->CommonExtension.PartitionLength.QuadPart != 0);
773 
774  pdoData->PartitionStyle = partitionStyle;
775 
776  //
777  // we found a match - update the information in the device object
778  // extension and driverdata
779  //
780 
781  pdoData->PartitionOrdinal = partitionOrdinal;
782 
783  //
784  // If this partition is being re-written then update the type
785  // information as well
786  //
787 
788 
789  if (partitionStyle == PARTITION_STYLE_MBR) {
790 
791  if(partitionEntry->RewritePartition) {
792  pdoData->Mbr.PartitionType = partitionEntry->Mbr.PartitionType;
793  }
794 
795  } else {
796 
797  DebugPrint((1, "DiskUpdatePartitions: EFI Partition %ws\n",
798  pdoData->Efi.PartitionName
799  ));
800 
801  pdoData->Efi.PartitionType = partitionEntry->Gpt.PartitionType;
802  pdoData->Efi.PartitionId = partitionEntry->Gpt.PartitionId;
803  pdoData->Efi.Attributes = partitionEntry->Gpt.Attributes;
804 
806  pdoData->Efi.PartitionName,
807  partitionEntry->Gpt.Name,
808  sizeof (pdoData->Efi.PartitionName)
809  );
810  }
811 
812  //
813  // Mark this one as found.
814  //
815 
816  pdoExtension->IsMissing = FALSE;
817 
818  //
819  // Pull it out of the old child list and add it into the
820  // real one.
821  //
822 
823  oldChildList = pdoExtension->CommonExtension.ChildList;
824 
825  pdoExtension->CommonExtension.ChildList =
826  fdoExtension->CommonExtension.ChildList;
827 
828  fdoExtension->CommonExtension.ChildList = pdoExtension;
829 
830  } else {
831 
832  //PDEVICE_OBJECT nextPdo;
833 
834  DebugPrint ((1, "DiskUpdatePartitions: Deleting %wZ\n",
835  &pdoExtension->CommonExtension.DeviceName));
836 
837  if (partitionStyle == PARTITION_STYLE_GPT) {
838 
839  DebugPrint ((1, "DiskUpdatePartitions: EFI Partition %ws\n",
840  pdoData->Efi.PartitionName
841  ));
842  }
843  //
844  // no matching entry in the partition list - throw this partition
845  // object away
846  //
847 
848  pdoExtension->CommonExtension.PartitionLength.QuadPart = 0;
849 
850  //
851  // grab a pointer to the next child before we mark this one as
852  // missing since missing devices could vanish at any time.
853  //
854 
855  oldChildList = pdoExtension->CommonExtension.ChildList;
856  pdoExtension->CommonExtension.ChildList = (PVOID) -1;
857 
858  //
859  // Now tell the class driver that this child is "missing" - this
860  // will cause it to be deleted.
861  //
862 
863 
864  ClassMarkChildMissing(pdoExtension, FALSE);
865  }
866  }
867 
868  //
869  // At this point the old child list had best be empty.
870  //
871 
872  ASSERT(oldChildList == NULL);
873 
874  //
875  // Iterate through the partition entries and create any partition
876  // objects that don't already exist
877  //
878 
879  partitionOrdinal = 0;
880  newPartitionNumber = 0;
881 
882  for(partitionNumber = 0;
883  partitionNumber < partitionCount;
884  partitionNumber++) {
885 
886  PDEVICE_OBJECT pdo;
887 
888  partitionEntry = &(PartitionList->PartitionEntry[partitionNumber]);
889 
890  //
891  // Is this partition interesting
892  //
893 
894  if (partitionStyle == PARTITION_STYLE_MBR) {
895 
896  if((partitionEntry->Mbr.PartitionType == PARTITION_ENTRY_UNUSED) ||
897  (IsContainerPartition(partitionEntry->Mbr.PartitionType))) {
898 
899  continue;
900  }
901  }
902 
903  //
904  // Increment the count of interesting partitions
905  //
906 
907  partitionOrdinal++;
908  newPartitionNumber++;
909 
910  //
911  // Has this already been matched
912  //
913 
914  if(partitionEntry->PartitionNumber == 0) {
915 
916  LONG i;
917 
918  //
919  // find the first safe partition number for this device
920  //
921 
922  for(i = 0; i < (LONG) partitionCount; i++) {
923 
924 
925  PPARTITION_INFORMATION_EX tmp = &(PartitionList->PartitionEntry[i]);
926 
927  if (partitionStyle == PARTITION_STYLE_MBR) {
930  continue;
931  }
932  }
933 
934  if(tmp->PartitionNumber == newPartitionNumber) {
935 
936  //
937  // Found a matching partition number - increment the count
938  // and restart the scan.
939  //
940 
941  newPartitionNumber++;
942  i = -1;
943  continue;
944  }
945  }
946 
947  //
948  // Assign this partition a partition number
949  //
950 
951  partitionEntry->PartitionNumber = newPartitionNumber;
952 
953  DebugPrint((1, "DiskUpdatePartitions: Found new partition #%d, ord %d "
954  "starting at %#016I64x and running for %#016I64x\n",
955  partitionEntry->PartitionNumber,
956  partitionOrdinal,
957  partitionEntry->StartingOffset.QuadPart,
958  partitionEntry->PartitionLength.QuadPart));
959 
960  ClassReleaseChildLock(fdoExtension);
961 
962  status = DiskCreatePdo(Fdo,
963  partitionOrdinal,
964  partitionEntry,
965  partitionStyle,
966  &pdo);
967 
968  ClassAcquireChildLock(fdoExtension);
969 
970  if(!NT_SUCCESS(status)) {
971 
972  DebugPrint((1, "DiskUpdatePartitions: error %lx creating "
973  "new PDO for partition ordinal %d, number %d\n",
974  status,
975  partitionOrdinal,
976  partitionEntry->PartitionNumber));
977 
978  //
979  // don't increment the partition number - we'll try to reuse
980  // it for the next child.
981  //
982 
983  partitionEntry->PartitionNumber = 0;
984  newPartitionNumber--;
985 
986  continue;
987  }
988 
989  //
990  // mark the new device as enumerated
991  //
992 
993  pdoExtension = pdo->DeviceExtension;
994  pdoExtension->IsMissing = FALSE;
995 
996  //
997  // This number's taken already - try to scanning the partition
998  // table more than once for a new number.
999  //
1000 
1001  }
1002  }
1003 
1004  //
1005  // ISSUE - 2000/02/09 - math: Review.
1006  // Is PartitionStyle the only field that needs updating?
1007  //
1008 
1009  {
1010  PCOMMON_DEVICE_EXTENSION commonExtension;
1011  PDISK_DATA diskData;
1012 
1013  commonExtension = Fdo->DeviceExtension;
1014  diskData = (PDISK_DATA)(commonExtension->DriverData);
1015 
1016  diskData->PartitionStyle = partitionStyle;
1017  }
1018 
1019  ClassReleaseChildLock(fdoExtension);
1020  return;
1021 }
1022 
1023 NTSTATUS
1024 NTAPI
1026  IN PDEVICE_OBJECT Fdo,
1027  IN ULONG PartitionOrdinal,
1028  IN PPARTITION_INFORMATION_EX PartitionEntry,
1029  IN PARTITION_STYLE PartitionStyle,
1031  )
1032 
1033 /*++
1034 
1035 Routine Description:
1036 
1037  This routine will create and initialize a new partition device object
1038  (PDO) and insert it into the FDO partition list.
1039 
1040 Arguments:
1041 
1042  Fdo - a pointer to the functional device object this PDO will be a child
1043  of
1044 
1045  PartitionOrdinal - the partition ordinal for this PDO
1046 
1047  PartitionEntry - the partition information for this device object
1048 
1049  PartitionStyle - what style of partition table entry PartitionEntry is;
1050  currently either MBR or EFI
1051 
1052  Pdo - a location to store the pdo pointer upon successful completion
1053 
1054 Return Value:
1055 
1056  status
1057 
1058 --*/
1059 
1060 {
1061  PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
1062 
1063  PDEVICE_OBJECT pdo = NULL;
1064  PPHYSICAL_DEVICE_EXTENSION pdoExtension = NULL;
1065 
1066  PUCHAR deviceName = NULL;
1067 
1068  PDISK_DATA diskData = fdoExtension->CommonExtension.DriverData;
1069 
1070  ULONG numberListElements;
1071 
1073 
1074  PAGED_CODE();
1075 
1076  //
1077  // Create partition object and set up partition parameters.
1078  //
1079 
1081  fdoExtension->DeviceNumber,
1082  PartitionEntry->PartitionNumber,
1083  &PartitionEntry->StartingOffset,
1084  &PartitionEntry->PartitionLength,
1085  &deviceName);
1086 
1087  if(!NT_SUCCESS(status)) {
1088 
1089  DebugPrint((1, "DiskCreatePdo - Can't generate name %lx\n", status));
1090  return status;
1091  }
1092 
1093  DebugPrint((2, "DiskCreatePdo: Create device object %s\n", deviceName));
1094 
1095  status = ClassCreateDeviceObject(Fdo->DriverObject,
1096  deviceName,
1097  Fdo,
1098  FALSE,
1099  &pdo);
1100 
1101  if (!NT_SUCCESS(status)) {
1102 
1103  DebugPrint((1, "DiskEnumerateDevice: Can't create device object for %s\n", deviceName));
1104 
1105  return status;
1106  }
1107 
1108  //
1109  // Set up device extension fields.
1110  //
1111 
1112  pdoExtension = pdo->DeviceExtension;
1113 
1114  //
1115  // Set up device object fields.
1116  //
1117 
1118  SET_FLAG(pdo->Flags, DO_DIRECT_IO);
1119 
1120  pdo->StackSize = (CCHAR)
1121  pdoExtension->CommonExtension.LowerDeviceObject->StackSize + 1;
1122 
1123  //
1124  // Get pointer to new disk data.
1125  //
1126 
1127  diskData = (PDISK_DATA) pdoExtension->CommonExtension.DriverData;
1128 
1129  //
1130  // Set the alignment requirements for the device based on the
1131  // host adapter requirements
1132  //
1133 
1134  if (Fdo->AlignmentRequirement > pdo->AlignmentRequirement) {
1135  pdo->AlignmentRequirement = Fdo->AlignmentRequirement;
1136  }
1137 
1138  if (fdoExtension->SrbFlags & SRB_FLAGS_QUEUE_ACTION_ENABLE) {
1139  numberListElements = 30;
1140  } else {
1141  numberListElements = 8;
1142  }
1143 
1144  //
1145  // Build the lookaside list for srb's for this partition based on
1146  // whether the adapter and disk can do tagged queueing. Don't bother to
1147  // check the status - this can't fail when called for a PDO.
1148  //
1149 
1151  numberListElements);
1152 
1153  //
1154  // Set the sense-data pointer in the device extension.
1155  //
1156 
1157  diskData->PartitionOrdinal = PartitionOrdinal;
1158  pdoExtension->CommonExtension.PartitionNumber = PartitionEntry->PartitionNumber;
1159 
1160  //
1161  // Initialize relevant data.
1162  //
1163 
1164  if (PartitionStyle == PARTITION_STYLE_MBR) {
1165 
1166  diskData->Mbr.PartitionType = PartitionEntry->Mbr.PartitionType;
1167  diskData->Mbr.BootIndicator = PartitionEntry->Mbr.BootIndicator;
1168  diskData->Mbr.HiddenSectors = PartitionEntry->Mbr.HiddenSectors;
1169 
1170  } else {
1171 
1172  diskData->Efi.PartitionType = PartitionEntry->Gpt.PartitionType;
1173  diskData->Efi.PartitionId = PartitionEntry->Gpt.PartitionType;
1174  diskData->Efi.Attributes = PartitionEntry->Gpt.Attributes;
1175  RtlCopyMemory (diskData->Efi.PartitionName,
1176  PartitionEntry->Gpt.Name,
1177  sizeof (diskData->Efi.PartitionName)
1178  );
1179  }
1180 
1181  DebugPrint((2, "DiskEnumerateDevice: Partition type is %x\n",
1182  diskData->Mbr.PartitionType));
1183 
1184  pdoExtension->CommonExtension.StartingOffset =
1185  PartitionEntry->StartingOffset;
1186 
1187  pdoExtension->CommonExtension.PartitionLength =
1188  PartitionEntry->PartitionLength;
1189 
1190 
1191  DebugPrint((1, "DiskCreatePdo: hidden sectors value for pdo %#p set to %#x\n",
1192  pdo,
1193  diskData->Mbr.HiddenSectors));
1194 
1195  //
1196  // Check for removable media support.
1197  //
1198 
1199  if (fdoExtension->DeviceDescriptor->RemovableMedia) {
1200  SET_FLAG(pdo->Characteristics, FILE_REMOVABLE_MEDIA);
1201  }
1202 
1203  pdoExtension->CommonExtension.DeviceObject = pdo;
1204 
1206 
1207  *Pdo = pdo;
1208 
1209  return status;
1210 }
1211 
1212 VOID
1213 NTAPI
1216  )
1217 {
1218  PDISK_DATA diskData = FdoExtension->CommonExtension.DriverData;
1219 
1220  PAGED_CODE();
1221 
1222  ASSERT_FDO(FdoExtension->DeviceObject);
1223 
1225  UserRequest,
1226  UserMode,
1227  FALSE,
1228  NULL);
1229  return;
1230 }
1231 
1232 VOID
1233 NTAPI
1236  )
1237 {
1238  PDISK_DATA diskData = FdoExtension->CommonExtension.DriverData;
1239 
1240  PAGED_CODE();
1241 
1242  ASSERT_FDO(FdoExtension->DeviceObject);
1243 
1245  return;
1246 }
#define DO_DEVICE_INITIALIZING
Definition: env_spec_w32.h:399
COMMON_DEVICE_EXTENSION CommonExtension
Definition: classpnp.h:628
#define DISK_TAG_PART_LIST
Definition: disk.h:60
LARGE_INTEGER PartitionLength
Definition: classpnp.h:594
struct _DISK_DATA * PDISK_DATA
#define IN
Definition: typedefs.h:38
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
LARGE_INTEGER PartitionLength
Definition: ntdddisk.h:394
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_ PDEVICE_OBJECT Pdo
Definition: classpnp.h:301
VOID NTAPI ClassAcquireChildLock(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: class.c:8483
ActualNumberDriverObjects * sizeof(PDRIVER_OBJECT)) PDRIVER_OBJECT *DriverObjectList
PDRIVE_LAYOUT_INFORMATION_EX NTAPI DiskConvertLayoutToExtended(IN CONST PDRIVE_LAYOUT_INFORMATION Layout)
Definition: enum.c:147
VOID NTAPI DiskUpdateRemovablePartitions(IN PDEVICE_OBJECT Fdo, IN OUT PDRIVE_LAYOUT_INFORMATION_EX PartitionList)
Definition: enum.c:364
unsigned char * PUCHAR
Definition: retypes.h:3
NTSTATUS ReadyStatus
Definition: disk.h:222
LONG NTSTATUS
Definition: precomp.h:26
COMMON_DEVICE_EXTENSION CommonExtension
Definition: classpnp.h:695
VOID NTAPI DiskAcquirePartitioningLock(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: enum.c:1214
#define IsContainerPartition(PartitionType)
Definition: ntdddisk.h:245
struct _PARTITION_INFORMATION PARTITION_INFORMATION
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
PARTITION_INFORMATION_MBR Mbr
Definition: imports.h:226
#define PAGED_CODE()
Definition: video.h:57
#define DO_DIRECT_IO
Definition: env_spec_w32.h:396
ULONG PartitionOrdinal
Definition: disk.c:79
PDISK_UPDATE_PARTITIONS UpdatePartitionRoutine
Definition: disk.h:230
PARTITION_INFORMATION_GPT Gpt
Definition: imports.h:227
#define PARTITION_ENTRY_UNUSED
Definition: disk.h:86
#define ASSERT_FDO(x)
Definition: pci.h:35
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
struct _PARTITION_INFORMATION_EX PARTITION_INFORMATION_EX
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
long LONG
Definition: pedump.c:60
#define FILE_REMOVABLE_MEDIA
Definition: nt_native.h:807
#define CLEAR_FLAG(Flags, Bit)
Definition: classpnp.h:155
struct _DISK_DATA::@998::@1001 Mbr
PVOID DeviceExtension
Definition: env_spec_w32.h:418
VOID NTAPI DiskConvertPartitionToExtended(IN PPARTITION_INFORMATION Partition, OUT PPARTITION_INFORMATION_EX PartitionEx)
Definition: enum.c:102
smooth NULL
Definition: ftsmooth.c:416
PARTITION_INFORMATION PartitionEntry[1]
Definition: ntdddisk.h:471
NTSTATUS NTAPI ClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject, IN PCCHAR ObjectNameBuffer, IN PDEVICE_OBJECT LowerDevice, IN BOOLEAN IsFdo, IN OUT PDEVICE_OBJECT *DeviceObject)
Definition: class.c:5687
NTSTATUS NTAPI DiskGenerateDeviceName(IN BOOLEAN IsFdo, IN ULONG DeviceNumber, IN OPTIONAL ULONG PartitionNumber, IN OPTIONAL PLARGE_INTEGER StartingOffset, IN OPTIONAL PLARGE_INTEGER PartitionLength, OUT PUCHAR *RawName)
Definition: pnp.c:783
void * PVOID
Definition: retypes.h:9
KEVENT PartitioningEvent
Definition: disk.h:242
LARGE_INTEGER StartingOffset
Definition: classpnp.h:595
PARTITION_STYLE PartitionStyle
Definition: disk.h:103
PDEVICE_OBJECT DeviceObject
Definition: pci.h:42
GLsizeiptr size
Definition: glext.h:5919
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
char CCHAR
Definition: typedefs.h:50
LARGE_INTEGER StartingOffset
Definition: ntdddisk.h:393
#define DiskReadDriveCapacity(Fdo)
Definition: disk.h:860
DRIVE_LAYOUT_INFORMATION_MBR Mbr
Definition: ntdddisk.h:489
PSTORAGE_DEVICE_DESCRIPTOR DeviceDescriptor
Definition: classpnp.h:698
LARGE_INTEGER PartitionLength
Definition: imports.h:222
static PPARTLIST PartitionList
Definition: usetup.c:73
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
BOOLEAN RewritePartition
Definition: ntdddisk.h:400
LARGE_INTEGER StartingOffset
Definition: imports.h:221
enum _PARTITION_STYLE PARTITION_STYLE
ULONG LowPart
Definition: typedefs.h:104
ULONG AlignmentRequirement
Definition: env_spec_w32.h:420
#define SET_FLAG(Flags, Bit)
Definition: classpnp.h:154
ULONG NTAPI DebugPrint(IN PSTRING DebugString, IN ULONG ComponentId, IN ULONG Level)
Definition: debug.c:23
ULONG_PTR SIZE_T
Definition: typedefs.h:78
VOID NTAPI DiskUpdatePartitions(IN PDEVICE_OBJECT Fdo, IN OUT PDRIVE_LAYOUT_INFORMATION_EX PartitionList)
Definition: enum.c:592
VOID NTAPI ClassInitializeSrbLookasideList(IN PCOMMON_DEVICE_EXTENSION CommonExtension, IN ULONG NumberElements)
Definition: obsolete.c:941
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
PDRIVE_LAYOUT_INFORMATION NTAPI DiskConvertExtendedToLayout(IN CONST PDRIVE_LAYOUT_INFORMATION_EX LayoutEx)
Definition: enum.c:40
NTSTATUS NTAPI DiskReadPartitionTableEx(IN PFUNCTIONAL_DEVICE_EXTENSION Fdo, IN BOOLEAN BypassCache, OUT PDRIVE_LAYOUT_INFORMATION_EX *DriveLayout)
Definition: part.c:49
BOOLEAN NTAPI ClassMarkChildMissing(IN PPHYSICAL_DEVICE_EXTENSION Child, IN BOOLEAN AcquireChildLock)
Definition: class.c:6657
PARTITION_INFORMATION_EX PartitionEntry[1]
Definition: ntdddisk.h:492
#define OUT
Definition: typedefs.h:39
unsigned int ULONG
Definition: retypes.h:1
#define IO_NO_INCREMENT
Definition: iotypes.h:566
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
NTSTATUS NTAPI DiskEnumerateDevice(IN PDEVICE_OBJECT Fdo)
Definition: enum.c:223
BOOLEAN RecognizedPartition
Definition: ntdddisk.h:399
VOID NTAPI DiskReleasePartitioningLock(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: enum.c:1234
VOID NTAPI ClassReleaseChildLock(IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension)
Definition: class.c:8526
return STATUS_SUCCESS
Definition: btrfs.c:2966
static SERVICE_STATUS status
Definition: service.c:31
NTSTATUS NTAPI DiskCreatePdo(IN PDEVICE_OBJECT Fdo, IN ULONG PartitionOrdinal, IN PPARTITION_INFORMATION_EX PartitionEntry, IN PARTITION_STYLE PartitionStyle, OUT PDEVICE_OBJECT *Pdo)
Definition: enum.c:1025
#define CONST
Definition: pedump.c:81
struct _DISK_DATA::@998::@1002 Efi
#define SRB_FLAGS_QUEUE_ACTION_ENABLE
Definition: srb.h:387
LONGLONG QuadPart
Definition: typedefs.h:112
Definition: ps.c:97