ReactOS  0.4.15-dev-5461-g062a8f2
partlist.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS DiskPart
3  * LICENSE: GPL - See COPYING in the top level directory
4  * FILE: base/system/diskpart/partlist.c
5  * PURPOSE: Manages all the partitions of the OS in an interactive way.
6  * PROGRAMMERS: Eric Kohl
7  */
8 
9 /* INCLUDES *******************************************************************/
10 
11 #include "diskpart.h"
12 #include <ntddscsi.h>
13 
14 #define NDEBUG
15 #include <debug.h>
16 
17 #define InsertAscendingList(ListHead, NewEntry, Type, ListEntryField, SortField)\
18 {\
19  PLIST_ENTRY current;\
20 \
21  current = (ListHead)->Flink;\
22  while (current != (ListHead))\
23  {\
24  if (CONTAINING_RECORD(current, Type, ListEntryField)->SortField >=\
25  (NewEntry)->SortField)\
26  {\
27  break;\
28  }\
29  current = current->Flink;\
30  }\
31 \
32  InsertTailList(current, &((NewEntry)->ListEntryField));\
33 }
34 
35 /* We have to define it there, because it is not in the MS DDK */
36 #define PARTITION_LINUX 0x83
37 
38 #define PARTITION_TBL_SIZE 4
39 
40 #include <pshpack1.h>
41 
42 typedef struct _PARTITION
43 {
44  unsigned char BootFlags; /* bootable? 0=no, 128=yes */
45  unsigned char StartingHead; /* beginning head number */
46  unsigned char StartingSector; /* beginning sector number */
47  unsigned char StartingCylinder; /* 10 bit nmbr, with high 2 bits put in begsect */
48  unsigned char PartitionType; /* Operating System type indicator code */
49  unsigned char EndingHead; /* ending head number */
50  unsigned char EndingSector; /* ending sector number */
51  unsigned char EndingCylinder; /* also a 10 bit nmbr, with same high 2 bit trick */
52  unsigned int StartingBlock; /* first sector relative to start of disk */
53  unsigned int SectorCount; /* number of sectors in partition */
55 
56 typedef struct _PARTITION_SECTOR
57 {
58  UCHAR BootCode[440]; /* 0x000 */
59  ULONG Signature; /* 0x1B8 */
60  UCHAR Reserved[2]; /* 0x1BC */
62  USHORT Magic; /* 0x1FE */
64 
65 #include <poppack.h>
66 
67 
68 /* GLOBALS ********************************************************************/
69 
73 
77 
78 
79 /* FUNCTIONS ******************************************************************/
80 
85 {
86  ULONGLONG Temp;
87 
88  Temp = Value / Alignment;
89 
90  return Temp * Alignment;
91 }
92 
93 static
94 VOID
96  PDISKENTRY DiskEntry)
97 {
99  WCHAR KeyName[32];
101 
102  RtlInitUnicodeString(&DiskEntry->DriverName,
103  NULL);
104 
106  L"\\Scsi\\Scsi Port %lu",
107  DiskEntry->Port);
108 
110  sizeof(QueryTable));
111 
112  QueryTable[0].Name = L"Driver";
114  QueryTable[0].EntryContext = &DiskEntry->DriverName;
115 
117  KeyName,
118  QueryTable,
119  NULL,
120  NULL);
121  if (!NT_SUCCESS(Status))
122  {
123  DPRINT1("RtlQueryRegistryValues() failed (Status %lx)\n", Status);
124  }
125 }
126 
127 static
128 NTSTATUS
129 NTAPI
135  PVOID Context,
137 {
138  PBIOSDISKENTRY BiosDiskEntry = (PBIOSDISKENTRY)Context;
139  UNICODE_STRING NameU;
140 
141  if (ValueType == REG_SZ &&
142  ValueLength == 20 * sizeof(WCHAR))
143  {
144  NameU.Buffer = (PWCHAR)ValueData;
145  NameU.Length = NameU.MaximumLength = 8 * sizeof(WCHAR);
146  RtlUnicodeStringToInteger(&NameU, 16, &BiosDiskEntry->Checksum);
147 
148  NameU.Buffer = (PWCHAR)ValueData + 9;
149  RtlUnicodeStringToInteger(&NameU, 16, &BiosDiskEntry->Signature);
150 
151  return STATUS_SUCCESS;
152  }
153 
154  return STATUS_UNSUCCESSFUL;
155 }
156 
157 static
158 NTSTATUS
159 NTAPI
165  PVOID Context,
167 {
168  PBIOSDISKENTRY BiosDiskEntry = (PBIOSDISKENTRY)Context;
169  PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
170  PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry;
171  ULONG i;
172 
175  return STATUS_UNSUCCESSFUL;
176 
177  FullResourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)ValueData;
178 
179  /* Hm. Version and Revision are not set on Microsoft Windows XP... */
180 #if 0
181  if (FullResourceDescriptor->PartialResourceList.Version != 1 ||
182  FullResourceDescriptor->PartialResourceList.Revision != 1)
183  return STATUS_UNSUCCESSFUL;
184 #endif
185 
186  for (i = 0; i < FullResourceDescriptor->PartialResourceList.Count; i++)
187  {
189  FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].u.DeviceSpecificData.DataSize != sizeof(CM_DISK_GEOMETRY_DEVICE_DATA))
190  continue;
191 
192  DiskGeometry = (PCM_DISK_GEOMETRY_DEVICE_DATA)&FullResourceDescriptor->PartialResourceList.PartialDescriptors[i + 1];
193  BiosDiskEntry->DiskGeometry = *DiskGeometry;
194 
195  return STATUS_SUCCESS;
196  }
197 
198  return STATUS_UNSUCCESSFUL;
199 }
200 
201 static
202 NTSTATUS
203 NTAPI
209  PVOID Context,
211 {
212  PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
214  ULONG i;
215 
218  return STATUS_UNSUCCESSFUL;
219 
220  FullResourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)ValueData;
221 
222  /* Hm. Version and Revision are not set on Microsoft Windows XP... */
223 #if 0
224  if (FullResourceDescriptor->PartialResourceList.Version != 1 ||
225  FullResourceDescriptor->PartialResourceList.Revision != 1)
226  return STATUS_UNSUCCESSFUL;
227 #endif
228 
229  for (i = 0; i < FullResourceDescriptor->PartialResourceList.Count; i++)
230  {
232  FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].u.DeviceSpecificData.DataSize % sizeof(CM_INT13_DRIVE_PARAMETER) != 0)
233  continue;
234 
235  *Int13Drives = (CM_INT13_DRIVE_PARAMETER*)RtlAllocateHeap(RtlGetProcessHeap(), 0,
236  FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].u.DeviceSpecificData.DataSize);
237  if (*Int13Drives == NULL)
238  return STATUS_NO_MEMORY;
239 
240  memcpy(*Int13Drives,
241  &FullResourceDescriptor->PartialResourceList.PartialDescriptors[i + 1],
242  FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].u.DeviceSpecificData.DataSize);
243  return STATUS_SUCCESS;
244  }
245 
246  return STATUS_UNSUCCESSFUL;
247 }
248 
249 
250 #define ROOT_NAME L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter"
251 
252 static
253 VOID
255 {
257  WCHAR Name[120];
258  ULONG AdapterCount;
259  ULONG DiskCount;
261  PCM_INT13_DRIVE_PARAMETER Int13Drives;
262  PBIOSDISKENTRY BiosDiskEntry;
263 
264  memset(QueryTable, 0, sizeof(QueryTable));
265 
266  QueryTable[1].Name = L"Configuration Data";
268  Int13Drives = NULL;
270  L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System",
271  &QueryTable[1],
272  (PVOID)&Int13Drives,
273  NULL);
274  if (!NT_SUCCESS(Status))
275  {
276  DPRINT1("Unable to query the 'Configuration Data' key in '\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System', status=%lx\n", Status);
277  return;
278  }
279 
280  AdapterCount = 0;
281  while (1)
282  {
284  L"%s\\%lu", ROOT_NAME, AdapterCount);
286  Name,
287  &QueryTable[2],
288  NULL,
289  NULL);
290  if (!NT_SUCCESS(Status))
291  {
292  break;
293  }
294 
296  L"%s\\%lu\\DiskController", ROOT_NAME, AdapterCount);
298  Name,
299  &QueryTable[2],
300  NULL,
301  NULL);
302  if (NT_SUCCESS(Status))
303  {
304  while (1)
305  {
307  L"%s\\%lu\\DiskController\\0", ROOT_NAME, AdapterCount);
309  Name,
310  &QueryTable[2],
311  NULL,
312  NULL);
313  if (!NT_SUCCESS(Status))
314  {
315  RtlFreeHeap(RtlGetProcessHeap(), 0, Int13Drives);
316  return;
317  }
318 
320  L"%s\\%lu\\DiskController\\0\\DiskPeripheral", ROOT_NAME, AdapterCount);
322  Name,
323  &QueryTable[2],
324  NULL,
325  NULL);
326  if (NT_SUCCESS(Status))
327  {
328  QueryTable[0].Name = L"Identifier";
330  QueryTable[1].Name = L"Configuration Data";
332 
333  DiskCount = 0;
334  while (1)
335  {
336  BiosDiskEntry = (BIOSDISKENTRY*)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BIOSDISKENTRY));
337  if (BiosDiskEntry == NULL)
338  {
339  break;
340  }
341 
343  L"%s\\%lu\\DiskController\\0\\DiskPeripheral\\%lu", ROOT_NAME, AdapterCount, DiskCount);
345  Name,
346  QueryTable,
347  (PVOID)BiosDiskEntry,
348  NULL);
349  if (!NT_SUCCESS(Status))
350  {
351  RtlFreeHeap(RtlGetProcessHeap(), 0, BiosDiskEntry);
352  break;
353  }
354 
355  BiosDiskEntry->DiskNumber = DiskCount;
356  BiosDiskEntry->Recognized = FALSE;
357 
358  if (DiskCount < Int13Drives[0].NumberDrives)
359  {
360  BiosDiskEntry->Int13DiskData = Int13Drives[DiskCount];
361  }
362  else
363  {
364  DPRINT1("Didn't find int13 drive datas for disk %u\n", DiskCount);
365  }
366 
367  InsertTailList(&BiosDiskListHead, &BiosDiskEntry->ListEntry);
368 
369  DPRINT("DiskNumber: %lu\n", BiosDiskEntry->DiskNumber);
370  DPRINT("Signature: %08lx\n", BiosDiskEntry->Signature);
371  DPRINT("Checksum: %08lx\n", BiosDiskEntry->Checksum);
372  DPRINT("BytesPerSector: %lu\n", BiosDiskEntry->DiskGeometry.BytesPerSector);
373  DPRINT("NumberOfCylinders: %lu\n", BiosDiskEntry->DiskGeometry.NumberOfCylinders);
374  DPRINT("NumberOfHeads: %lu\n", BiosDiskEntry->DiskGeometry.NumberOfHeads);
375  DPRINT("DriveSelect: %02x\n", BiosDiskEntry->Int13DiskData.DriveSelect);
376  DPRINT("MaxCylinders: %lu\n", BiosDiskEntry->Int13DiskData.MaxCylinders);
377  DPRINT("SectorsPerTrack: %d\n", BiosDiskEntry->Int13DiskData.SectorsPerTrack);
378  DPRINT("MaxHeads: %d\n", BiosDiskEntry->Int13DiskData.MaxHeads);
379  DPRINT("NumberDrives: %d\n", BiosDiskEntry->Int13DiskData.NumberDrives);
380 
381  DiskCount++;
382  }
383  }
384 
385  RtlFreeHeap(RtlGetProcessHeap(), 0, Int13Drives);
386  return;
387  }
388  }
389 
390  AdapterCount++;
391  }
392 
393  RtlFreeHeap(RtlGetProcessHeap(), 0, Int13Drives);
394 }
395 
396 
397 static
398 VOID
400  ULONG DiskNumber,
401  PDISKENTRY DiskEntry,
402  ULONG PartitionIndex,
404 {
406  PPARTENTRY PartEntry;
407 
408  PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[PartitionIndex];
409  if (PartitionInfo->PartitionType == 0 ||
411  return;
412 
413  PartEntry = RtlAllocateHeap(RtlGetProcessHeap(),
415  sizeof(PARTENTRY));
416  if (PartEntry == NULL)
417  {
418  return;
419  }
420 
421  PartEntry->DiskEntry = DiskEntry;
422 
423  PartEntry->StartSector.QuadPart = (ULONGLONG)PartitionInfo->StartingOffset.QuadPart / DiskEntry->BytesPerSector;
424  PartEntry->SectorCount.QuadPart = (ULONGLONG)PartitionInfo->PartitionLength.QuadPart / DiskEntry->BytesPerSector;
425 
426  PartEntry->BootIndicator = PartitionInfo->BootIndicator;
427  PartEntry->PartitionType = PartitionInfo->PartitionType;
428 
429  PartEntry->LogicalPartition = LogicalPartition;
430  PartEntry->IsPartitioned = TRUE;
431  PartEntry->PartitionNumber = PartitionInfo->PartitionNumber;
432  PartEntry->PartitionIndex = PartitionIndex;
433 
434  if (IsContainerPartition(PartEntry->PartitionType))
435  {
436  PartEntry->FormatState = Unformatted;
437 
438  if (LogicalPartition == FALSE && DiskEntry->ExtendedPartition == NULL)
439  DiskEntry->ExtendedPartition = PartEntry;
440  }
441  else if ((PartEntry->PartitionType == PARTITION_FAT_12) ||
442  (PartEntry->PartitionType == PARTITION_FAT_16) ||
443  (PartEntry->PartitionType == PARTITION_HUGE) ||
444  (PartEntry->PartitionType == PARTITION_XINT13) ||
445  (PartEntry->PartitionType == PARTITION_FAT32) ||
446  (PartEntry->PartitionType == PARTITION_FAT32_XINT13))
447  {
448 #if 0
449  if (CheckFatFormat())
450  {
451  PartEntry->FormatState = Preformatted;
452  }
453  else
454  {
455  PartEntry->FormatState = Unformatted;
456  }
457 #endif
458  PartEntry->FormatState = Preformatted;
459  }
460  else if (PartEntry->PartitionType == PARTITION_LINUX)
461  {
462 #if 0
463  if (CheckExt2Format())
464  {
465  PartEntry->FormatState = Preformatted;
466  }
467  else
468  {
469  PartEntry->FormatState = Unformatted;
470  }
471 #endif
472  PartEntry->FormatState = Preformatted;
473  }
474  else if (PartEntry->PartitionType == PARTITION_IFS)
475  {
476 #if 0
477  if (CheckNtfsFormat())
478  {
479  PartEntry->FormatState = Preformatted;
480  }
481  else if (CheckHpfsFormat())
482  {
483  PartEntry->FormatState = Preformatted;
484  }
485  else
486  {
487  PartEntry->FormatState = Unformatted;
488  }
489 #endif
490  PartEntry->FormatState = Preformatted;
491  }
492  else
493  {
494  PartEntry->FormatState = UnknownFormat;
495  }
496 
497  if (LogicalPartition)
499  &PartEntry->ListEntry);
500  else
502  &PartEntry->ListEntry);
503 }
504 
505 
506 static
507 VOID
509  PDISKENTRY DiskEntry)
510 {
511  ULONGLONG LastStartSector;
512  ULONGLONG LastSectorCount;
513  ULONGLONG LastUnusedSectorCount;
514  PPARTENTRY PartEntry;
515  PPARTENTRY NewPartEntry;
517 
518  DPRINT("ScanForUnpartitionedDiskSpace()\n");
519 
520  if (IsListEmpty(&DiskEntry->PrimaryPartListHead))
521  {
522  DPRINT1("No primary partition!\n");
523 
524  /* Create a partition table that represents the empty disk */
525  NewPartEntry = RtlAllocateHeap(RtlGetProcessHeap(),
527  sizeof(PARTENTRY));
528  if (NewPartEntry == NULL)
529  return;
530 
531  NewPartEntry->DiskEntry = DiskEntry;
532 
533  NewPartEntry->IsPartitioned = FALSE;
534  NewPartEntry->StartSector.QuadPart = (ULONGLONG)DiskEntry->SectorAlignment;
535  NewPartEntry->SectorCount.QuadPart = AlignDown(DiskEntry->SectorCount.QuadPart, DiskEntry->SectorAlignment) -
536  NewPartEntry->StartSector.QuadPart;
537 
538  DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
539  DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
540  DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
541 
542  NewPartEntry->FormatState = Unformatted;
543 
545  &NewPartEntry->ListEntry);
546 
547  return;
548  }
549 
550  /* Start partition at head 1, cylinder 0 */
551  LastStartSector = DiskEntry->SectorAlignment;
552  LastSectorCount = 0ULL;
553  LastUnusedSectorCount = 0ULL;
554 
555  Entry = DiskEntry->PrimaryPartListHead.Flink;
556  while (Entry != &DiskEntry->PrimaryPartListHead)
557  {
558  PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
559 
560  if (PartEntry->PartitionType != PARTITION_ENTRY_UNUSED ||
561  PartEntry->SectorCount.QuadPart != 0ULL)
562  {
563  LastUnusedSectorCount =
564  PartEntry->StartSector.QuadPart - (LastStartSector + LastSectorCount);
565 
566  if (PartEntry->StartSector.QuadPart > (LastStartSector + LastSectorCount) &&
567  LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment)
568  {
569  DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount);
570 
571  NewPartEntry = RtlAllocateHeap(RtlGetProcessHeap(),
573  sizeof(PARTENTRY));
574  if (NewPartEntry == NULL)
575  return;
576 
577  NewPartEntry->DiskEntry = DiskEntry;
578 
579  NewPartEntry->IsPartitioned = FALSE;
580  NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount;
581  NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + LastUnusedSectorCount, DiskEntry->SectorAlignment) -
582  NewPartEntry->StartSector.QuadPart;
583 
584  DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
585  DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
586  DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
587 
588  NewPartEntry->FormatState = Unformatted;
589 
590  /* Insert the table into the list */
591  InsertTailList(&PartEntry->ListEntry,
592  &NewPartEntry->ListEntry);
593  }
594 
595  LastStartSector = PartEntry->StartSector.QuadPart;
596  LastSectorCount = PartEntry->SectorCount.QuadPart;
597  }
598 
599  Entry = Entry->Flink;
600  }
601 
602  /* Check for trailing unpartitioned disk space */
603  if ((LastStartSector + LastSectorCount) < DiskEntry->SectorCount.QuadPart)
604  {
605  LastUnusedSectorCount = AlignDown(DiskEntry->SectorCount.QuadPart - (LastStartSector + LastSectorCount), DiskEntry->SectorAlignment);
606 
607  if (LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment)
608  {
609  DPRINT1("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount);
610 
611  NewPartEntry = RtlAllocateHeap(RtlGetProcessHeap(),
613  sizeof(PARTENTRY));
614  if (NewPartEntry == NULL)
615  return;
616 
617  NewPartEntry->DiskEntry = DiskEntry;
618 
619  NewPartEntry->IsPartitioned = FALSE;
620  NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount;
621  NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + LastUnusedSectorCount, DiskEntry->SectorAlignment) -
622  NewPartEntry->StartSector.QuadPart;
623 
624  DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
625  DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
626  DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
627 
628  NewPartEntry->FormatState = Unformatted;
629 
630  /* Append the table to the list */
632  &NewPartEntry->ListEntry);
633  }
634  }
635 
636  if (DiskEntry->ExtendedPartition != NULL)
637  {
638  if (IsListEmpty(&DiskEntry->LogicalPartListHead))
639  {
640  DPRINT1("No logical partition!\n");
641 
642  /* Create a partition table entry that represents the empty extended partition */
643  NewPartEntry = RtlAllocateHeap(RtlGetProcessHeap(),
645  sizeof(PARTENTRY));
646  if (NewPartEntry == NULL)
647  return;
648 
649  NewPartEntry->DiskEntry = DiskEntry;
650  NewPartEntry->LogicalPartition = TRUE;
651 
652  NewPartEntry->IsPartitioned = FALSE;
653  NewPartEntry->StartSector.QuadPart = DiskEntry->ExtendedPartition->StartSector.QuadPart + (ULONGLONG)DiskEntry->SectorAlignment;
654  NewPartEntry->SectorCount.QuadPart = DiskEntry->ExtendedPartition->SectorCount.QuadPart - (ULONGLONG)DiskEntry->SectorAlignment;
655 
656  DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
657  DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
658  DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
659 
660  NewPartEntry->FormatState = Unformatted;
661 
663  &NewPartEntry->ListEntry);
664 
665  return;
666  }
667 
668  /* Start partition at head 1, cylinder 0 */
669  LastStartSector = DiskEntry->ExtendedPartition->StartSector.QuadPart + (ULONGLONG)DiskEntry->SectorAlignment;
670  LastSectorCount = 0ULL;
671  LastUnusedSectorCount = 0ULL;
672 
673  Entry = DiskEntry->LogicalPartListHead.Flink;
674  while (Entry != &DiskEntry->LogicalPartListHead)
675  {
676  PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
677 
678  if (PartEntry->PartitionType != PARTITION_ENTRY_UNUSED ||
679  PartEntry->SectorCount.QuadPart != 0ULL)
680  {
681  LastUnusedSectorCount =
682  PartEntry->StartSector.QuadPart - (ULONGLONG)DiskEntry->SectorAlignment - (LastStartSector + LastSectorCount);
683 
684  if ((PartEntry->StartSector.QuadPart - (ULONGLONG)DiskEntry->SectorAlignment) > (LastStartSector + LastSectorCount) &&
685  LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment)
686  {
687  DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount);
688 
689  NewPartEntry = RtlAllocateHeap(RtlGetProcessHeap(),
691  sizeof(PARTENTRY));
692  if (NewPartEntry == NULL)
693  return;
694 
695  NewPartEntry->DiskEntry = DiskEntry;
696  NewPartEntry->LogicalPartition = TRUE;
697 
698  NewPartEntry->IsPartitioned = FALSE;
699  NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount;
700  NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + LastUnusedSectorCount, DiskEntry->SectorAlignment) -
701  NewPartEntry->StartSector.QuadPart;
702 
703  DPRINT("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
704  DPRINT("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
705  DPRINT("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
706 
707  NewPartEntry->FormatState = Unformatted;
708 
709  /* Insert the table into the list */
710  InsertTailList(&PartEntry->ListEntry,
711  &NewPartEntry->ListEntry);
712  }
713 
714  LastStartSector = PartEntry->StartSector.QuadPart;
715  LastSectorCount = PartEntry->SectorCount.QuadPart;
716  }
717 
718  Entry = Entry->Flink;
719  }
720 
721  /* Check for trailing unpartitioned disk space */
722  if ((LastStartSector + LastSectorCount) < DiskEntry->ExtendedPartition->StartSector.QuadPart + DiskEntry->ExtendedPartition->SectorCount.QuadPart)
723  {
724  LastUnusedSectorCount = AlignDown(DiskEntry->ExtendedPartition->StartSector.QuadPart + DiskEntry->ExtendedPartition->SectorCount.QuadPart - (LastStartSector + LastSectorCount),
725  DiskEntry->SectorAlignment);
726 
727  if (LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment)
728  {
729  DPRINT("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount);
730 
731  NewPartEntry = RtlAllocateHeap(RtlGetProcessHeap(),
733  sizeof(PARTENTRY));
734  if (NewPartEntry == NULL)
735  return;
736 
737  NewPartEntry->DiskEntry = DiskEntry;
738  NewPartEntry->LogicalPartition = TRUE;
739 
740  NewPartEntry->IsPartitioned = FALSE;
741  NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount;
742  NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + LastUnusedSectorCount, DiskEntry->SectorAlignment) -
743  NewPartEntry->StartSector.QuadPart;
744 
745  DPRINT("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
746  DPRINT("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
747  DPRINT("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
748 
749  NewPartEntry->FormatState = Unformatted;
750 
751  /* Append the table to the list */
753  &NewPartEntry->ListEntry);
754  }
755  }
756  }
757 
758  DPRINT("ScanForUnpartitionedDiskSpace() done\n");
759 }
760 
761 
762 static
763 VOID
766  ULONG DiskNumber)
767 {
768  DISK_GEOMETRY DiskGeometry;
769  SCSI_ADDRESS ScsiAddress;
770  PDISKENTRY DiskEntry;
773  PPARTITION_SECTOR Mbr;
774  PULONG Buffer;
776  WCHAR Identifier[20];
777  ULONG Checksum;
779  ULONG i;
780  PLIST_ENTRY ListEntry;
781  PBIOSDISKENTRY BiosDiskEntry;
782  ULONG LayoutBufferSize;
783  PDRIVE_LAYOUT_INFORMATION NewLayoutBuffer;
784 
786  NULL,
787  NULL,
788  NULL,
789  &Iosb,
791  NULL,
792  0,
793  &DiskGeometry,
794  sizeof(DISK_GEOMETRY));
795  if (!NT_SUCCESS(Status))
796  {
797  return;
798  }
799 
800  if (DiskGeometry.MediaType != FixedMedia &&
801  DiskGeometry.MediaType != RemovableMedia)
802  {
803  return;
804  }
805 
807  NULL,
808  NULL,
809  NULL,
810  &Iosb,
812  NULL,
813  0,
814  &ScsiAddress,
815  sizeof(SCSI_ADDRESS));
816  if (!NT_SUCCESS(Status))
817  {
818  return;
819  }
820 
821  Mbr = (PARTITION_SECTOR*)RtlAllocateHeap(RtlGetProcessHeap(),
822  0,
823  DiskGeometry.BytesPerSector);
824  if (Mbr == NULL)
825  {
826  return;
827  }
828 
829  FileOffset.QuadPart = 0;
831  NULL,
832  NULL,
833  NULL,
834  &Iosb,
835  (PVOID)Mbr,
836  DiskGeometry.BytesPerSector,
837  &FileOffset,
838  NULL);
839  if (!NT_SUCCESS(Status))
840  {
841  RtlFreeHeap(RtlGetProcessHeap(), 0, Mbr);
842  DPRINT1("NtReadFile failed, status=%x\n", Status);
843  return;
844  }
845  Signature = Mbr->Signature;
846 
847  /* Calculate the MBR checksum */
848  Checksum = 0;
849  Buffer = (PULONG)Mbr;
850  for (i = 0; i < 128; i++)
851  {
852  Checksum += Buffer[i];
853  }
854  Checksum = ~Checksum + 1;
855 
856  StringCchPrintfW(Identifier, ARRAYSIZE(Identifier),
857  L"%08x-%08x-A", Checksum, Signature);
858  DPRINT("Identifier: %S\n", Identifier);
859 
860  DiskEntry = RtlAllocateHeap(RtlGetProcessHeap(),
862  sizeof(DISKENTRY));
863  if (DiskEntry == NULL)
864  {
865  return;
866  }
867 
868 // DiskEntry->Checksum = Checksum;
869 // DiskEntry->Signature = Signature;
870  DiskEntry->BiosFound = FALSE;
871 
872  /* Check if this disk has a valid MBR */
873  if (Mbr->BootCode[0] == 0 && Mbr->BootCode[1] == 0)
874  DiskEntry->NoMbr = TRUE;
875  else
876  DiskEntry->NoMbr = FALSE;
877 
878  /* Free Mbr sector buffer */
879  RtlFreeHeap(RtlGetProcessHeap(), 0, Mbr);
880 
881  ListEntry = BiosDiskListHead.Flink;
882  while (ListEntry != &BiosDiskListHead)
883  {
884  BiosDiskEntry = CONTAINING_RECORD(ListEntry, BIOSDISKENTRY, ListEntry);
885  /* FIXME:
886  * Compare the size from bios and the reported size from driver.
887  * If we have more than one disk with a zero or with the same signatur
888  * we must create new signatures and reboot. After the reboot,
889  * it is possible to identify the disks.
890  */
891  if (BiosDiskEntry->Signature == Signature &&
892  BiosDiskEntry->Checksum == Checksum &&
893  !BiosDiskEntry->Recognized)
894  {
895  if (!DiskEntry->BiosFound)
896  {
897  DiskEntry->BiosDiskNumber = BiosDiskEntry->DiskNumber;
898  DiskEntry->BiosFound = TRUE;
899  BiosDiskEntry->Recognized = TRUE;
900  }
901  else
902  {
903  }
904  }
905  ListEntry = ListEntry->Flink;
906  }
907 
908  if (!DiskEntry->BiosFound)
909  {
910 #if 0
911  RtlFreeHeap(ProcessHeap, 0, DiskEntry);
912  return;
913 #else
914  DPRINT1("WARNING: Setup could not find a matching BIOS disk entry. Disk %d is not be bootable by the BIOS!\n", DiskNumber);
915 #endif
916  }
917 
920 
921  DiskEntry->Cylinders = DiskGeometry.Cylinders.QuadPart;
922  DiskEntry->TracksPerCylinder = DiskGeometry.TracksPerCylinder;
923  DiskEntry->SectorsPerTrack = DiskGeometry.SectorsPerTrack;
924  DiskEntry->BytesPerSector = DiskGeometry.BytesPerSector;
925 
926  DPRINT("Cylinders %I64u\n", DiskEntry->Cylinders);
927  DPRINT("TracksPerCylinder %I64u\n", DiskEntry->TracksPerCylinder);
928  DPRINT("SectorsPerTrack %I64u\n", DiskEntry->SectorsPerTrack);
929  DPRINT("BytesPerSector %I64u\n", DiskEntry->BytesPerSector);
930 
931  DiskEntry->SectorCount.QuadPart = DiskGeometry.Cylinders.QuadPart *
932  (ULONGLONG)DiskGeometry.TracksPerCylinder *
933  (ULONGLONG)DiskGeometry.SectorsPerTrack;
934 
935 // DiskEntry->SectorAlignment = DiskGeometry.SectorsPerTrack;
936 // DiskEntry->CylinderAlignment = DiskGeometry.SectorsPerTrack * DiskGeometry.TracksPerCylinder;
937  DiskEntry->SectorAlignment = (1024 * 1024) / DiskGeometry.BytesPerSector;
938  DiskEntry->CylinderAlignment = (1024 * 1024) / DiskGeometry.BytesPerSector;
939 
940  DPRINT1("SectorCount: %I64u\n", DiskEntry->SectorCount);
941  DPRINT1("SectorAlignment: %lu\n", DiskEntry->SectorAlignment);
942  DPRINT1("CylinderAlignment: %lu\n", DiskEntry->CylinderAlignment);
943 
944  DiskEntry->DiskNumber = DiskNumber;
945  DiskEntry->Port = ScsiAddress.PortNumber;
946  DiskEntry->PathId = ScsiAddress.PathId;
947  DiskEntry->TargetId = ScsiAddress.TargetId;
948  DiskEntry->Lun = ScsiAddress.Lun;
949 
950  GetDriverName(DiskEntry);
951 
952  InsertAscendingList(&DiskListHead, DiskEntry, DISKENTRY, ListEntry, DiskNumber);
953 
954  /* Allocate a layout buffer with 4 partition entries first */
955  LayoutBufferSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
956  ((4 - ANYSIZE_ARRAY) * sizeof(PARTITION_INFORMATION));
957  DiskEntry->LayoutBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
959  LayoutBufferSize);
960  if (DiskEntry->LayoutBuffer == NULL)
961  {
962  DPRINT1("Failed to allocate the disk layout buffer!\n");
963  return;
964  }
965 
966  for (;;)
967  {
968  DPRINT1("Buffer size: %lu\n", LayoutBufferSize);
970  NULL,
971  NULL,
972  NULL,
973  &Iosb,
975  NULL,
976  0,
977  DiskEntry->LayoutBuffer,
978  LayoutBufferSize);
979  if (NT_SUCCESS(Status))
980  break;
981 
983  {
984  DPRINT1("NtDeviceIoControlFile() failed (Status: 0x%08lx)\n", Status);
985  return;
986  }
987 
988  LayoutBufferSize += 4 * sizeof(PARTITION_INFORMATION);
989  NewLayoutBuffer = RtlReAllocateHeap(RtlGetProcessHeap(),
991  DiskEntry->LayoutBuffer,
992  LayoutBufferSize);
993  if (NewLayoutBuffer == NULL)
994  {
995  DPRINT1("Failed to reallocate the disk layout buffer!\n");
996  return;
997  }
998 
999  DiskEntry->LayoutBuffer = NewLayoutBuffer;
1000  }
1001 
1002  DPRINT1("PartitionCount: %lu\n", DiskEntry->LayoutBuffer->PartitionCount);
1003 
1004 #ifdef DUMP_PARTITION_TABLE
1005  DumpPartitionTable(DiskEntry);
1006 #endif
1007 
1008  if (DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart != 0 &&
1009  DiskEntry->LayoutBuffer->PartitionEntry[0].PartitionLength.QuadPart != 0 &&
1010  DiskEntry->LayoutBuffer->PartitionEntry[0].PartitionType != 0)
1011  {
1012  if ((DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart / DiskEntry->BytesPerSector) % DiskEntry->SectorsPerTrack == 0)
1013  {
1014  DPRINT("Use %lu Sector alignment!\n", DiskEntry->SectorsPerTrack);
1015  }
1016  else if (DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart % (1024 * 1024) == 0)
1017  {
1018  DPRINT1("Use megabyte (%lu Sectors) alignment!\n", (1024 * 1024) / DiskEntry->BytesPerSector);
1019  }
1020  else
1021  {
1022  DPRINT1("No matching alignment found! Partition 1 starts at %I64u\n", DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart);
1023  }
1024  }
1025  else
1026  {
1027  DPRINT1("No valid partition table found! Use megabyte (%lu Sectors) alignment!\n", (1024 * 1024) / DiskEntry->BytesPerSector);
1028  }
1029 
1030 
1031  if (DiskEntry->LayoutBuffer->PartitionCount == 0)
1032  {
1033  DiskEntry->NewDisk = TRUE;
1034  DiskEntry->LayoutBuffer->PartitionCount = 4;
1035 
1036  for (i = 0; i < 4; i++)
1038  }
1039  else
1040  {
1041  for (i = 0; i < 4; i++)
1042  {
1043  AddPartitionToDisk(DiskNumber, DiskEntry, i, FALSE);
1044  }
1045 
1046  for (i = 4; i < DiskEntry->LayoutBuffer->PartitionCount; i += 4)
1047  {
1048  AddPartitionToDisk(DiskNumber, DiskEntry, i, TRUE);
1049  }
1050  }
1051 
1052  ScanForUnpartitionedDiskSpace(DiskEntry);
1053 }
1054 
1055 
1056 NTSTATUS
1058 {
1062  ULONG ReturnSize;
1063  NTSTATUS Status;
1064  ULONG DiskNumber;
1068 
1069  CurrentDisk = NULL;
1071 
1072 // BootDisk = NULL;
1073 // BootPartition = NULL;
1074 
1075 // TempDisk = NULL;
1076 // TempPartition = NULL;
1077 // FormatState = Start;
1078 
1081 
1083 
1085  &Sdi,
1086  sizeof(SYSTEM_DEVICE_INFORMATION),
1087  &ReturnSize);
1088  if (!NT_SUCCESS(Status))
1089  {
1090  return Status;
1091  }
1092 
1093  for (DiskNumber = 0; DiskNumber < Sdi.NumberOfDisks; DiskNumber++)
1094  {
1096  L"\\Device\\Harddisk%d\\Partition0",
1097  DiskNumber);
1098 
1100  Buffer);
1101 
1103  &Name,
1104  0,
1105  NULL,
1106  NULL);
1107 
1111  &Iosb,
1114  if (NT_SUCCESS(Status))
1115  {
1116  AddDiskToList(FileHandle, DiskNumber);
1117 
1119  }
1120  }
1121 
1122 // UpdateDiskSignatures(List);
1123 
1124 // AssignDriveLetters(List);
1125 
1126  return STATUS_SUCCESS;
1127 }
1128 
1129 
1130 VOID
1132 {
1133  PDISKENTRY DiskEntry;
1134  PBIOSDISKENTRY BiosDiskEntry;
1135  PPARTENTRY PartEntry;
1137 
1138  CurrentDisk = NULL;
1140 
1141  /* Release disk and partition info */
1142  while (!IsListEmpty(&DiskListHead))
1143  {
1145  DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
1146 
1147  /* Release driver name */
1148  RtlFreeUnicodeString(&DiskEntry->DriverName);
1149 
1150  /* Release primary partition list */
1151  while (!IsListEmpty(&DiskEntry->PrimaryPartListHead))
1152  {
1153  Entry = RemoveHeadList(&DiskEntry->PrimaryPartListHead);
1154  PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
1155 
1156  RtlFreeHeap(RtlGetProcessHeap(), 0, PartEntry);
1157  }
1158 
1159  /* Release logical partition list */
1160  while (!IsListEmpty(&DiskEntry->LogicalPartListHead))
1161  {
1162  Entry = RemoveHeadList(&DiskEntry->LogicalPartListHead);
1163  PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
1164 
1165  RtlFreeHeap(RtlGetProcessHeap(), 0, PartEntry);
1166  }
1167 
1168  /* Release layout buffer */
1169  if (DiskEntry->LayoutBuffer != NULL)
1170  RtlFreeHeap(RtlGetProcessHeap(), 0, DiskEntry->LayoutBuffer);
1171 
1172 
1173  /* Release disk entry */
1174  RtlFreeHeap(RtlGetProcessHeap(), 0, DiskEntry);
1175  }
1176 
1177  /* Release the bios disk info */
1178  while (!IsListEmpty(&BiosDiskListHead))
1179  {
1181  BiosDiskEntry = CONTAINING_RECORD(Entry, BIOSDISKENTRY, ListEntry);
1182 
1183  RtlFreeHeap(RtlGetProcessHeap(), 0, BiosDiskEntry);
1184  }
1185 }
1186 
1187 
1188 static
1189 VOID
1192  _In_ PVOLENTRY VolumeEntry)
1193 {
1194  DWORD dwBytesReturned = 0, dwLength, i;
1195  PVOLUME_DISK_EXTENTS pExtents;
1196  BOOL bResult;
1197  DWORD dwError;
1198 
1199  dwLength = sizeof(VOLUME_DISK_EXTENTS);
1200  pExtents = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, dwLength);
1201  if (pExtents == NULL)
1202  return;
1203 
1204  bResult = DeviceIoControl(VolumeHandle,
1206  NULL,
1207  0,
1208  pExtents,
1209  dwLength,
1210  &dwBytesReturned,
1211  NULL);
1212  if (!bResult)
1213  {
1214  dwError = GetLastError();
1215 
1216  if (dwError != ERROR_MORE_DATA)
1217  {
1218  RtlFreeHeap(RtlGetProcessHeap(), 0, pExtents);
1219  return;
1220  }
1221  else
1222  {
1223  dwLength = sizeof(VOLUME_DISK_EXTENTS) + ((pExtents->NumberOfDiskExtents - 1) * sizeof(DISK_EXTENT));
1224  RtlFreeHeap(RtlGetProcessHeap(), 0, pExtents);
1225  pExtents = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, dwLength);
1226  if (pExtents == NULL)
1227  {
1228  return;
1229  }
1230 
1231  bResult = DeviceIoControl(VolumeHandle,
1233  NULL,
1234  0,
1235  pExtents,
1236  dwLength,
1237  &dwBytesReturned,
1238  NULL);
1239  if (!bResult)
1240  {
1241  RtlFreeHeap(RtlGetProcessHeap(), 0, pExtents);
1242  return;
1243  }
1244  }
1245  }
1246 
1247  for (i = 0; i < pExtents->NumberOfDiskExtents; i++)
1248  VolumeEntry->Size.QuadPart += pExtents->Extents[i].ExtentLength.QuadPart;
1249 
1250  VolumeEntry->pExtents = pExtents;
1251 }
1252 
1253 
1254 static
1255 VOID
1258  _In_ PVOLENTRY VolumeEntry)
1259 {
1262  NTSTATUS Status;
1263 
1265  &IoStatusBlock,
1266  &DeviceInfo,
1269  if (!NT_SUCCESS(Status))
1270  return;
1271 
1272  switch (DeviceInfo.DeviceType)
1273  {
1274  case FILE_DEVICE_CD_ROM:
1276  VolumeEntry->VolumeType = VOLUME_TYPE_CDROM;
1277  break;
1278 
1279  case FILE_DEVICE_DISK:
1281  if (DeviceInfo.Characteristics & FILE_REMOVABLE_MEDIA)
1282  VolumeEntry->VolumeType = VOLUME_TYPE_REMOVABLE;
1283  else
1284  VolumeEntry->VolumeType = VOLUME_TYPE_PARTITION;
1285  break;
1286 
1287  default:
1288  VolumeEntry->VolumeType = VOLUME_TYPE_UNKNOWN;
1289  break;
1290  }
1291 }
1292 
1293 
1294 static
1295 VOID
1297  ULONG ulVolumeNumber,
1298  PWSTR pszVolumeName)
1299 {
1300  PVOLENTRY VolumeEntry;
1302 
1303  DWORD dwError, dwLength;
1304  WCHAR szPathNames[MAX_PATH + 1];
1305  WCHAR szVolumeName[MAX_PATH + 1];
1306  WCHAR szFilesystem[MAX_PATH + 1];
1307 
1308  DWORD CharCount = 0;
1309  size_t Index = 0;
1310 
1314  NTSTATUS Status;
1315 
1316  DPRINT("AddVolumeToList(%S)\n", pszVolumeName);
1317 
1318  VolumeEntry = RtlAllocateHeap(RtlGetProcessHeap(),
1320  sizeof(VOLENTRY));
1321  if (VolumeEntry == NULL)
1322  return;
1323 
1324  VolumeEntry->VolumeNumber = ulVolumeNumber;
1325  wcscpy(VolumeEntry->VolumeName, pszVolumeName);
1326 
1327  Index = wcslen(pszVolumeName) - 1;
1328 
1329  pszVolumeName[Index] = L'\0';
1330 
1331  CharCount = QueryDosDeviceW(&pszVolumeName[4], VolumeEntry->DeviceName, ARRAYSIZE(VolumeEntry->DeviceName));
1332 
1333  pszVolumeName[Index] = L'\\';
1334 
1335  if (CharCount == 0)
1336  {
1337  RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeEntry);
1338  return;
1339  }
1340 
1341  DPRINT("DeviceName: %S\n", VolumeEntry->DeviceName);
1342 
1343  RtlInitUnicodeString(&Name, VolumeEntry->DeviceName);
1344 
1346  &Name,
1347  0,
1348  NULL,
1349  NULL);
1350 
1352  SYNCHRONIZE,
1354  &Iosb,
1355  0,
1357  if (NT_SUCCESS(Status))
1358  {
1359  GetVolumeType(VolumeHandle, VolumeEntry);
1360  GetVolumeExtents(VolumeHandle, VolumeEntry);
1362  }
1363 
1364  if (GetVolumeInformationW(pszVolumeName,
1365  szVolumeName,
1366  MAX_PATH + 1,
1367  NULL, // [out, optional] LPDWORD lpVolumeSerialNumber,
1368  NULL, // [out, optional] LPDWORD lpMaximumComponentLength,
1369  NULL, // [out, optional] LPDWORD lpFileSystemFlags,
1370  szFilesystem,
1371  MAX_PATH + 1))
1372  {
1373  VolumeEntry->pszLabel = RtlAllocateHeap(RtlGetProcessHeap(),
1374  0,
1375  (wcslen(szVolumeName) + 1) * sizeof(WCHAR));
1376  if (VolumeEntry->pszLabel)
1377  wcscpy(VolumeEntry->pszLabel, szVolumeName);
1378 
1379  VolumeEntry->pszFilesystem = RtlAllocateHeap(RtlGetProcessHeap(),
1380  0,
1381  (wcslen(szFilesystem) + 1) * sizeof(WCHAR));
1382  if (VolumeEntry->pszFilesystem)
1383  wcscpy(VolumeEntry->pszFilesystem, szFilesystem);
1384  }
1385  else
1386  {
1387  dwError = GetLastError();
1388  if (dwError == ERROR_UNRECOGNIZED_VOLUME)
1389  {
1390  VolumeEntry->pszFilesystem = RtlAllocateHeap(RtlGetProcessHeap(),
1391  0,
1392  (3 + 1) * sizeof(WCHAR));
1393  if (VolumeEntry->pszFilesystem)
1394  wcscpy(VolumeEntry->pszFilesystem, L"RAW");
1395  }
1396  }
1397 
1398  if (GetVolumePathNamesForVolumeNameW(pszVolumeName,
1399  szPathNames,
1400  ARRAYSIZE(szPathNames),
1401  &dwLength))
1402  {
1403  VolumeEntry->DriveLetter = szPathNames[0];
1404  }
1405 
1407  &VolumeEntry->ListEntry);
1408 }
1409 
1410 
1411 NTSTATUS
1413 {
1414  HANDLE hVolume = INVALID_HANDLE_VALUE;
1415  WCHAR szVolumeName[MAX_PATH];
1416  ULONG ulVolumeNumber = 0;
1417  BOOL Success;
1418 
1419  CurrentVolume = NULL;
1420 
1422 
1423  hVolume = FindFirstVolumeW(szVolumeName, ARRAYSIZE(szVolumeName));
1424  if (hVolume == INVALID_HANDLE_VALUE)
1425  {
1426 
1427  return STATUS_UNSUCCESSFUL;
1428  }
1429 
1430  AddVolumeToList(ulVolumeNumber++, szVolumeName);
1431 
1432  for (;;)
1433  {
1434  Success = FindNextVolumeW(hVolume, szVolumeName, ARRAYSIZE(szVolumeName));
1435  if (!Success)
1436  {
1437  break;
1438  }
1439 
1440  AddVolumeToList(ulVolumeNumber++, szVolumeName);
1441  }
1442 
1443  FindVolumeClose(hVolume);
1444 
1445  return STATUS_SUCCESS;
1446 }
1447 
1448 
1449 VOID
1451 {
1453  PVOLENTRY VolumeEntry;
1454 
1455  CurrentVolume = NULL;
1456 
1457  /* Release disk and partition info */
1458  while (!IsListEmpty(&VolumeListHead))
1459  {
1461  VolumeEntry = CONTAINING_RECORD(Entry, VOLENTRY, ListEntry);
1462 
1463  if (VolumeEntry->pszLabel)
1464  RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeEntry->pszLabel);
1465 
1466  if (VolumeEntry->pszFilesystem)
1467  RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeEntry->pszFilesystem);
1468 
1469  if (VolumeEntry->pExtents)
1470  RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeEntry->pExtents);
1471 
1472  /* Release disk entry */
1473  RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeEntry);
1474  }
1475 }
1476 
1477 
1478 NTSTATUS
1480  _In_ PDISKENTRY DiskEntry)
1481 {
1482  NTSTATUS Status;
1487  ULONG BufferSize;
1489  ULONG PartitionCount;
1490  PLIST_ENTRY ListEntry;
1491  PPARTENTRY PartEntry;
1493 
1494  DPRINT("WritePartitions() Disk: %lu\n", DiskEntry->DiskNumber);
1495 
1496  /* If the disk is not dirty, there is nothing to do */
1497  if (!DiskEntry->Dirty)
1498  return STATUS_SUCCESS;
1499 
1501  L"\\Device\\Harddisk%lu\\Partition0",
1502  DiskEntry->DiskNumber);
1504 
1506  &Name,
1508  NULL,
1509  NULL);
1510 
1514  &Iosb,
1515  0,
1517  if (!NT_SUCCESS(Status))
1518  {
1519  DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
1520  return Status;
1521  }
1522 
1523  //
1524  // FIXME: We first *MUST* use IOCTL_DISK_CREATE_DISK to initialize
1525  // the disk in MBR or GPT format in case the disk was not initialized!!
1526  // For this we must ask the user which format to use.
1527  //
1528 
1529  /* Save the original partition count to be restored later (see comment below) */
1530  PartitionCount = DiskEntry->LayoutBuffer->PartitionCount;
1531 
1532  /* Set the new disk layout and retrieve its updated version with possibly modified partition numbers */
1534  ((PartitionCount - 1) * sizeof(PARTITION_INFORMATION));
1536  NULL,
1537  NULL,
1538  NULL,
1539  &Iosb,
1541  DiskEntry->LayoutBuffer,
1542  BufferSize,
1543  DiskEntry->LayoutBuffer,
1544  BufferSize);
1546 
1547  /*
1548  * IOCTL_DISK_SET_DRIVE_LAYOUT calls IoWritePartitionTable(), which converts
1549  * DiskEntry->LayoutBuffer->PartitionCount into a partition *table* count,
1550  * where such a table is expected to enumerate up to 4 partitions:
1551  * partition *table* count == ROUND_UP(PartitionCount, 4) / 4 .
1552  * Due to this we need to restore the original PartitionCount number.
1553  */
1554  DiskEntry->LayoutBuffer->PartitionCount = PartitionCount;
1555 
1556  /* Check whether the IOCTL_DISK_SET_DRIVE_LAYOUT call succeeded */
1557  if (!NT_SUCCESS(Status))
1558  {
1559  DPRINT1("IOCTL_DISK_SET_DRIVE_LAYOUT failed (Status 0x%08lx)\n", Status);
1560  return Status;
1561  }
1562 
1563  /* Update the partition numbers */
1564 
1565  /* Update the primary partition table */
1566  for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
1567  ListEntry != &DiskEntry->PrimaryPartListHead;
1568  ListEntry = ListEntry->Flink)
1569  {
1570  PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
1571 
1572  if (PartEntry->IsPartitioned)
1573  {
1575  PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex];
1576  PartEntry->PartitionNumber = PartitionInfo->PartitionNumber;
1577  }
1578  }
1579 
1580  /* Update the logical partition table */
1581  for (ListEntry = DiskEntry->LogicalPartListHead.Flink;
1582  ListEntry != &DiskEntry->LogicalPartListHead;
1583  ListEntry = ListEntry->Flink)
1584  {
1585  PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
1586 
1587  if (PartEntry->IsPartitioned)
1588  {
1590  PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex];
1591  PartEntry->PartitionNumber = PartitionInfo->PartitionNumber;
1592  }
1593  }
1594 
1595  /* The layout has been successfully updated, the disk is not dirty anymore */
1596  DiskEntry->Dirty = FALSE;
1597 
1598  return Status;
1599 }
1600 
1601 
1602 static
1603 BOOLEAN
1606 {
1607  if (PartitionInfo->StartingOffset.QuadPart == 0 &&
1608  PartitionInfo->PartitionLength.QuadPart == 0)
1609  {
1610  return TRUE;
1611  }
1612 
1613  return FALSE;
1614 }
1615 
1616 
1617 static
1618 BOOLEAN
1621  IN PDISKENTRY DiskEntry,
1622  IN PPARTENTRY PartEntry)
1623 {
1624  if ((PartitionInfo->StartingOffset.QuadPart == PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector) &&
1625  (PartitionInfo->PartitionLength.QuadPart == PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector))
1626  {
1627  return TRUE;
1628  }
1629 
1630  return FALSE;
1631 }
1632 
1633 
1634 ULONG
1636  _In_ PDISKENTRY DiskEntry)
1637 {
1639  PPARTENTRY PartEntry;
1640  ULONG Count = 0;
1641 
1642  for (Entry = DiskEntry->PrimaryPartListHead.Flink;
1643  Entry != &DiskEntry->PrimaryPartListHead;
1644  Entry = Entry->Flink)
1645  {
1646  PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
1647  if (PartEntry->IsPartitioned)
1648  Count++;
1649  }
1650 
1651  return Count;
1652 }
1653 
1654 
1655 static
1656 ULONG
1658  _In_ PDISKENTRY DiskEntry)
1659 {
1660  PLIST_ENTRY ListEntry;
1661  PPARTENTRY PartEntry;
1662  ULONG Count = 0;
1663 
1664  for (ListEntry = DiskEntry->LogicalPartListHead.Flink;
1665  ListEntry != &DiskEntry->LogicalPartListHead;
1666  ListEntry = ListEntry->Flink)
1667  {
1668  PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
1669  if (PartEntry->IsPartitioned)
1670  Count++;
1671  }
1672 
1673  return Count;
1674 }
1675 
1676 
1677 static
1678 BOOLEAN
1680  _In_ PDISKENTRY DiskEntry)
1681 {
1682  PDRIVE_LAYOUT_INFORMATION NewLayoutBuffer;
1683  ULONG NewPartitionCount;
1684  ULONG CurrentPartitionCount = 0;
1685  ULONG LayoutBufferSize;
1686  ULONG i;
1687 
1688  DPRINT1("ReAllocateLayoutBuffer()\n");
1689 
1690  NewPartitionCount = 4 + GetLogicalPartitionCount(DiskEntry) * 4;
1691 
1692  if (DiskEntry->LayoutBuffer)
1693  CurrentPartitionCount = DiskEntry->LayoutBuffer->PartitionCount;
1694 
1695  DPRINT1("CurrentPartitionCount: %lu ; NewPartitionCount: %lu\n",
1696  CurrentPartitionCount, NewPartitionCount);
1697 
1698  if (CurrentPartitionCount == NewPartitionCount)
1699  return TRUE;
1700 
1701  LayoutBufferSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
1702  ((NewPartitionCount - ANYSIZE_ARRAY) * sizeof(PARTITION_INFORMATION));
1703  NewLayoutBuffer = RtlReAllocateHeap(RtlGetProcessHeap(),
1705  DiskEntry->LayoutBuffer,
1706  LayoutBufferSize);
1707  if (NewLayoutBuffer == NULL)
1708  {
1709  DPRINT1("Failed to allocate the new layout buffer (size: %lu)\n", LayoutBufferSize);
1710  return FALSE;
1711  }
1712 
1713  NewLayoutBuffer->PartitionCount = NewPartitionCount;
1714 
1715  /* If the layout buffer grows, make sure the new (empty) entries are written to the disk */
1716  if (NewPartitionCount > CurrentPartitionCount)
1717  {
1718  for (i = CurrentPartitionCount; i < NewPartitionCount; i++)
1719  {
1720  NewLayoutBuffer->PartitionEntry[i].RewritePartition = TRUE;
1721  }
1722  }
1723 
1724  DiskEntry->LayoutBuffer = NewLayoutBuffer;
1725 
1726  return TRUE;
1727 }
1728 
1729 
1730 VOID
1732  _In_ PDISKENTRY DiskEntry)
1733 {
1735  PPARTITION_INFORMATION LinkInfo = NULL;
1736  PLIST_ENTRY ListEntry;
1737  PPARTENTRY PartEntry;
1738  LARGE_INTEGER HiddenSectors64;
1739  ULONG Index;
1740  ULONG PartitionNumber = 1;
1741 
1742  DPRINT1("UpdateDiskLayout()\n");
1743 
1744  /* Resize the layout buffer if necessary */
1745  if (ReAllocateLayoutBuffer(DiskEntry) == FALSE)
1746  {
1747  DPRINT("ReAllocateLayoutBuffer() failed.\n");
1748  return;
1749  }
1750 
1751  /* Update the primary partition table */
1752  Index = 0;
1753  for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
1754  ListEntry != &DiskEntry->PrimaryPartListHead;
1755  ListEntry = ListEntry->Flink)
1756  {
1757  PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
1758 
1759  if (PartEntry->IsPartitioned)
1760  {
1762 
1763  PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
1764  PartEntry->PartitionIndex = Index;
1765 
1766  /* Reset the current partition number only for newly-created (unmounted) partitions */
1767  if (PartEntry->New)
1768  PartEntry->PartitionNumber = 0;
1769 
1770  PartEntry->OnDiskPartitionNumber = (!IsContainerPartition(PartEntry->PartitionType) ? PartitionNumber : 0);
1771 
1772  if (!IsSamePrimaryLayoutEntry(PartitionInfo, DiskEntry, PartEntry))
1773  {
1774  DPRINT1("Updating primary partition entry %lu\n", Index);
1775 
1776  PartitionInfo->StartingOffset.QuadPart = PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector;
1777  PartitionInfo->PartitionLength.QuadPart = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
1778  PartitionInfo->HiddenSectors = PartEntry->StartSector.LowPart;
1779  PartitionInfo->PartitionNumber = PartEntry->PartitionNumber;
1780  PartitionInfo->PartitionType = PartEntry->PartitionType;
1781  PartitionInfo->BootIndicator = PartEntry->BootIndicator;
1782  PartitionInfo->RecognizedPartition = IsRecognizedPartition(PartEntry->PartitionType);
1783  PartitionInfo->RewritePartition = TRUE;
1784  }
1785 
1786  if (!IsContainerPartition(PartEntry->PartitionType))
1787  PartitionNumber++;
1788 
1789  Index++;
1790  }
1791  }
1792 
1793  ASSERT(Index <= 4);
1794 
1795  /* Update the logical partition table */
1796  Index = 4;
1797  for (ListEntry = DiskEntry->LogicalPartListHead.Flink;
1798  ListEntry != &DiskEntry->LogicalPartListHead;
1799  ListEntry = ListEntry->Flink)
1800  {
1801  PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
1802 
1803  if (PartEntry->IsPartitioned)
1804  {
1806 
1807  PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
1808  PartEntry->PartitionIndex = Index;
1809 
1810  /* Reset the current partition number only for newly-created (unmounted) partitions */
1811  if (PartEntry->New)
1812  PartEntry->PartitionNumber = 0;
1813 
1815 
1816  DPRINT1("Updating logical partition entry %lu\n", Index);
1817 
1818  PartitionInfo->StartingOffset.QuadPart = PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector;
1819  PartitionInfo->PartitionLength.QuadPart = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
1820  PartitionInfo->HiddenSectors = DiskEntry->SectorAlignment;
1821  PartitionInfo->PartitionNumber = PartEntry->PartitionNumber;
1822  PartitionInfo->PartitionType = PartEntry->PartitionType;
1823  PartitionInfo->BootIndicator = FALSE;
1824  PartitionInfo->RecognizedPartition = IsRecognizedPartition(PartEntry->PartitionType);
1825  PartitionInfo->RewritePartition = TRUE;
1826 
1827  /* Fill the link entry of the previous partition entry */
1828  if (LinkInfo != NULL)
1829  {
1830  LinkInfo->StartingOffset.QuadPart = (PartEntry->StartSector.QuadPart - DiskEntry->SectorAlignment) * DiskEntry->BytesPerSector;
1831  LinkInfo->PartitionLength.QuadPart = (PartEntry->StartSector.QuadPart + DiskEntry->SectorAlignment) * DiskEntry->BytesPerSector;
1832  HiddenSectors64.QuadPart = PartEntry->StartSector.QuadPart - DiskEntry->SectorAlignment - DiskEntry->ExtendedPartition->StartSector.QuadPart;
1833  LinkInfo->HiddenSectors = HiddenSectors64.LowPart;
1834  LinkInfo->PartitionNumber = 0;
1835  LinkInfo->PartitionType = PARTITION_EXTENDED;
1836  LinkInfo->BootIndicator = FALSE;
1837  LinkInfo->RecognizedPartition = FALSE;
1838  LinkInfo->RewritePartition = TRUE;
1839  }
1840 
1841  /* Save a pointer to the link entry of the current partition entry */
1842  LinkInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index + 1];
1843 
1844  PartitionNumber++;
1845  Index += 4;
1846  }
1847  }
1848 
1849  /* Wipe unused primary partition entries */
1850  for (Index = GetPrimaryPartitionCount(DiskEntry); Index < 4; Index++)
1851  {
1852  DPRINT1("Primary partition entry %lu\n", Index);
1853 
1854  PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
1855 
1857  {
1858  DPRINT1("Wiping primary partition entry %lu\n", Index);
1859 
1860  PartitionInfo->StartingOffset.QuadPart = 0;
1861  PartitionInfo->PartitionLength.QuadPart = 0;
1862  PartitionInfo->HiddenSectors = 0;
1863  PartitionInfo->PartitionNumber = 0;
1864  PartitionInfo->PartitionType = PARTITION_ENTRY_UNUSED;
1865  PartitionInfo->BootIndicator = FALSE;
1866  PartitionInfo->RecognizedPartition = FALSE;
1867  PartitionInfo->RewritePartition = TRUE;
1868  }
1869  }
1870 
1871  /* Wipe unused logical partition entries */
1872  for (Index = 4; Index < DiskEntry->LayoutBuffer->PartitionCount; Index++)
1873  {
1874  if (Index % 4 >= 2)
1875  {
1876  DPRINT1("Logical partition entry %lu\n", Index);
1877 
1878  PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
1879 
1881  {
1882  DPRINT1("Wiping partition entry %lu\n", Index);
1883 
1884  PartitionInfo->StartingOffset.QuadPart = 0;
1885  PartitionInfo->PartitionLength.QuadPart = 0;
1886  PartitionInfo->HiddenSectors = 0;
1887  PartitionInfo->PartitionNumber = 0;
1888  PartitionInfo->PartitionType = PARTITION_ENTRY_UNUSED;
1889  PartitionInfo->BootIndicator = FALSE;
1890  PartitionInfo->RecognizedPartition = FALSE;
1891  PartitionInfo->RewritePartition = TRUE;
1892  }
1893  }
1894  }
1895 
1896  DiskEntry->Dirty = TRUE;
1897 }
1898 
1899 
1900 PPARTENTRY
1902  _In_ PPARTENTRY PartEntry)
1903 {
1904  PDISKENTRY DiskEntry = PartEntry->DiskEntry;
1905  PPARTENTRY PrevPartEntry;
1906  PLIST_ENTRY ListHead;
1907 
1908  if (PartEntry->LogicalPartition)
1909  ListHead = &DiskEntry->LogicalPartListHead;
1910  else
1911  ListHead = &DiskEntry->PrimaryPartListHead;
1912 
1913  if (PartEntry->ListEntry.Blink != ListHead)
1914  {
1915  PrevPartEntry = CONTAINING_RECORD(PartEntry->ListEntry.Blink,
1916  PARTENTRY,
1917  ListEntry);
1918  if (!PrevPartEntry->IsPartitioned)
1919  {
1920  ASSERT(PrevPartEntry->PartitionType == PARTITION_ENTRY_UNUSED);
1921  return PrevPartEntry;
1922  }
1923  }
1924 
1925  return NULL;
1926 }
1927 
1928 
1929 PPARTENTRY
1931  _In_ PPARTENTRY PartEntry)
1932 {
1933  PDISKENTRY DiskEntry = PartEntry->DiskEntry;
1934  PPARTENTRY NextPartEntry;
1935  PLIST_ENTRY ListHead;
1936 
1937  if (PartEntry->LogicalPartition)
1938  ListHead = &DiskEntry->LogicalPartListHead;
1939  else
1940  ListHead = &DiskEntry->PrimaryPartListHead;
1941 
1942  if (PartEntry->ListEntry.Flink != ListHead)
1943  {
1944  NextPartEntry = CONTAINING_RECORD(PartEntry->ListEntry.Flink,
1945  PARTENTRY,
1946  ListEntry);
1947  if (!NextPartEntry->IsPartitioned)
1948  {
1949  ASSERT(NextPartEntry->PartitionType == PARTITION_ENTRY_UNUSED);
1950  return NextPartEntry;
1951  }
1952  }
1953 
1954  return NULL;
1955 }
1956 
1957 NTSTATUS
1959  _In_ PPARTENTRY PartEntry)
1960 {
1961  NTSTATUS Status;
1962  NTSTATUS LockStatus;
1966  HANDLE PartitionHandle;
1968 
1969  /* Check whether the partition is valid and was mounted by the system */
1970  if (!PartEntry->IsPartitioned ||
1971  IsContainerPartition(PartEntry->PartitionType) ||
1972  !IsRecognizedPartition(PartEntry->PartitionType) ||
1973  PartEntry->FormatState == UnknownFormat ||
1974  // NOTE: If FormatState == Unformatted but *FileSystem != 0 this means
1975  // it has been usually mounted with RawFS and thus needs to be dismounted.
1976 /* !*PartEntry->FileSystem || */
1977  PartEntry->PartitionNumber == 0)
1978  {
1979  /* The partition is not mounted, so just return success */
1980  return STATUS_SUCCESS;
1981  }
1982 
1983  ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
1984 
1985  /* Open the volume */
1987  L"\\Device\\Harddisk%lu\\Partition%lu",
1988  PartEntry->DiskEntry->DiskNumber,
1989  PartEntry->PartitionNumber);
1991 
1993  &Name,
1995  NULL,
1996  NULL);
1997 
1998  Status = NtOpenFile(&PartitionHandle,
2001  &IoStatusBlock,
2004  if (!NT_SUCCESS(Status))
2005  {
2006  DPRINT1("ERROR: Cannot open volume %wZ for dismounting! (Status 0x%lx)\n", &Name, Status);
2007  return Status;
2008  }
2009 
2010  /* Lock the volume */
2011  LockStatus = NtFsControlFile(PartitionHandle,
2012  NULL,
2013  NULL,
2014  NULL,
2015  &IoStatusBlock,
2017  NULL,
2018  0,
2019  NULL,
2020  0);
2021  if (!NT_SUCCESS(LockStatus))
2022  {
2023  DPRINT1("WARNING: Failed to lock volume! Operations may fail! (Status 0x%lx)\n", LockStatus);
2024  }
2025 
2026  /* Dismount the volume */
2027  Status = NtFsControlFile(PartitionHandle,
2028  NULL,
2029  NULL,
2030  NULL,
2031  &IoStatusBlock,
2033  NULL,
2034  0,
2035  NULL,
2036  0);
2037  if (!NT_SUCCESS(Status))
2038  {
2039  DPRINT1("Failed to unmount volume (Status 0x%lx)\n", Status);
2040  }
2041 
2042  /* Unlock the volume */
2043  LockStatus = NtFsControlFile(PartitionHandle,
2044  NULL,
2045  NULL,
2046  NULL,
2047  &IoStatusBlock,
2049  NULL,
2050  0,
2051  NULL,
2052  0);
2053  if (!NT_SUCCESS(LockStatus))
2054  {
2055  DPRINT1("Failed to unlock volume (Status 0x%lx)\n", LockStatus);
2056  }
2057 
2058  /* Close the volume */
2059  NtClose(PartitionHandle);
2060 
2061  return Status;
2062 }
2063 
2064 
2065 PVOLENTRY
2067  _In_ PPARTENTRY PartEntry)
2068 {
2070  PVOLENTRY VolumeEntry;
2071  ULONG i;
2072 
2073  if ((PartEntry == NULL) ||
2074  (PartEntry->DiskEntry == NULL))
2075  return NULL;
2076 
2078  while (Entry != &VolumeListHead)
2079  {
2080  VolumeEntry = CONTAINING_RECORD(Entry, VOLENTRY, ListEntry);
2081 
2082  if (VolumeEntry->pExtents == NULL)
2083  return NULL;
2084 
2085  for (i = 0; i < VolumeEntry->pExtents->NumberOfDiskExtents; i++)
2086  {
2087  if (VolumeEntry->pExtents->Extents[i].DiskNumber == PartEntry->DiskEntry->DiskNumber)
2088  {
2089  if ((VolumeEntry->pExtents->Extents[i].StartingOffset.QuadPart == PartEntry->StartSector.QuadPart * PartEntry->DiskEntry->BytesPerSector) &&
2090  (VolumeEntry->pExtents->Extents[i].ExtentLength.QuadPart == PartEntry->SectorCount.QuadPart * PartEntry->DiskEntry->BytesPerSector))
2091  return VolumeEntry;
2092  }
2093  }
2094 
2095  Entry = Entry->Flink;
2096  }
2097 
2098  return NULL;
2099 }
2100 
2101 
2102 VOID
2104  _In_ PVOLENTRY VolumeEntry)
2105 {
2106  if (VolumeEntry == NULL)
2107  return;
2108 
2109  if (VolumeEntry == CurrentVolume)
2110  CurrentVolume = NULL;
2111 
2112  RemoveEntryList(&VolumeEntry->ListEntry);
2113 
2114  if (VolumeEntry->pszLabel)
2115  RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeEntry->pszLabel);
2116 
2117  if (VolumeEntry->pszFilesystem)
2118  RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeEntry->pszFilesystem);
2119 
2120  if (VolumeEntry->pExtents)
2121  RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeEntry->pExtents);
2122 
2123  /* Release disk entry */
2124  RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeEntry);
2125 }
2126 
2127 /* EOF */
UCHAR PathId
Definition: scsi_port.h:149
LIST_ENTRY DiskListHead
Definition: partlist.c:70
LIST_ENTRY PrimaryPartListHead
Definition: partlist.h:131
USHORT TargetId
Definition: diskpart.h:167
#define PARTITION_FAT32
Definition: disk.h:95
LARGE_INTEGER ExtentLength
Definition: ntddvol.h:115
while(CdLookupNextInitialFileDirent(IrpContext, Fcb, FileContext))
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
PPARTLIST CreatePartitionList(VOID)
Definition: partlist.c:1847
UCHAR PortNumber
Definition: scsi_port.h:148
#define CmResourceTypeDeviceSpecific
Definition: hwresource.cpp:127
_In_ PCWSTR _Inout_ _At_ QueryTable _Pre_unknown_ PRTL_QUERY_REGISTRY_TABLE QueryTable
Definition: rtlfuncs.h:4196
#define IN
Definition: typedefs.h:39
#define FILE_DEVICE_DISK
Definition: winioctl.h:113
ULONG PartitionNumber
Definition: partlist.h:55
ULARGE_INTEGER StartSector
Definition: partlist.h:49
#define FSCTL_UNLOCK_VOLUME
Definition: nt_native.h:833
NTSYSAPI NTSTATUS NTAPI NtQuerySystemInformation(IN SYSTEM_INFORMATION_CLASS SystemInfoClass, OUT PVOID SystemInfoBuffer, IN ULONG SystemInfoBufferSize, OUT PULONG BytesReturned OPTIONAL)
LARGE_INTEGER PartitionLength
Definition: ntdddisk.h:414
#define IOCTL_SCSI_GET_ADDRESS
Definition: scsi_port.h:52
PDISKENTRY CurrentDisk
Definition: partlist.c:74
NTSYSAPI NTSTATUS WINAPI RtlQueryRegistryValues(ULONG, PCWSTR, PRTL_QUERY_REGISTRY_TABLE, PVOID, PVOID)
struct _Entry Entry
Definition: kefuncs.h:629
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
ULONG CylinderAlignment
Definition: partlist.h:99
USHORT MaximumLength
Definition: env_spec_w32.h:370
static NTSTATUS NTAPI DiskConfigurationDataQueryRoutine(PWSTR ValueName, ULONG ValueType, PVOID ValueData, ULONG ValueLength, PVOID Context, PVOID EntryContext)
Definition: partlist.c:160
LIST_ENTRY BiosDiskListHead
Definition: partlist.c:71
#define ERROR_UNRECOGNIZED_VOLUME
Definition: winerror.h:584
#define ANYSIZE_ARRAY
Definition: typedefs.h:46
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
PPARTENTRY GetNextUnpartitionedEntry(_In_ PPARTENTRY PartEntry)
Definition: partlist.c:1930
unsigned char EndingSector
Definition: partlist.h:187
#define TRUE
Definition: types.h:120
uint16_t * PWSTR
Definition: typedefs.h:56
#define FILE_DIRECTORY_FILE
Definition: constants.h:491
BOOL WINAPI GetVolumePathNamesForVolumeNameW(IN LPCWSTR lpszVolumeName, IN LPWSTR lpszVolumePathNames, IN DWORD cchBufferLength, OUT PDWORD lpcchReturnLength)
Definition: volume.c:1227
ULARGE_INTEGER SectorCount
Definition: partlist.h:50
ULONG Checksum
Definition: partlist.h:146
FORCEINLINE BOOLEAN IsEmptyLayoutEntry(IN PPARTITION_INFORMATION PartitionInfo)
Definition: partlist.c:2396
ULONG Signature
Definition: partlist.h:145
struct _PARTITION_SECTOR * PPARTITION_SECTOR
LONG NTSTATUS
Definition: precomp.h:26
VOID UpdateDiskLayout(_In_ PDISKENTRY DiskEntry)
Definition: partlist.c:1731
struct _VOLUME_DISK_EXTENTS VOLUME_DISK_EXTENTS
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:606
#define PARTITION_TBL_SIZE
Definition: partlist.c:38
PVOLUME_DISK_EXTENTS pExtents
Definition: diskpart.h:202
VOID RemoveVolume(_In_ PVOLENTRY VolumeEntry)
Definition: partlist.c:2103
PVOLENTRY GetVolumeFromPartition(_In_ PPARTENTRY PartEntry)
Definition: partlist.c:2066
ULONG DiskNumber
Definition: partlist.h:111
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
DWORD WINAPI GetLastError(VOID)
Definition: except.c:1040
$ULONG LowPart
Definition: ntbasedef.h:569
#define IsContainerPartition(PartitionType)
Definition: ntdddisk.h:316
ULONG BytesPerSector
Definition: ntdddisk.h:409
HANDLE WINAPI FindFirstVolumeW(IN LPWSTR volume, IN DWORD len)
Definition: volume.c:660
ULONG TracksPerCylinder
Definition: ntdddisk.h:407
NTSYSAPI NTSTATUS NTAPI NtDeviceIoControlFile(IN HANDLE hFile, IN HANDLE hEvent OPTIONAL, IN PIO_APC_ROUTINE IoApcRoutine OPTIONAL, IN PVOID IoApcContext OPTIONAL, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN ULONG DeviceIoControlCode, IN PVOID InBuffer OPTIONAL, IN ULONG InBufferLength, OUT PVOID OutBuffer OPTIONAL, IN ULONG OutBufferLength)
struct _CM_DISK_GEOMETRY_DEVICE_DATA * PCM_DISK_GEOMETRY_DEVICE_DATA
uint16_t * PWCHAR
Definition: typedefs.h:56
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define InsertTailList(ListHead, Entry)
DISK_EXTENT Extents[1]
Definition: ntddvol.h:120
static ULONG GetLogicalPartitionCount(_In_ PDISKENTRY DiskEntry)
Definition: partlist.c:1657
_In_ ULONG _In_ ULONG PartitionNumber
Definition: iofuncs.h:2060
struct _PARTITION_INFORMATION PARTITION_INFORMATION
struct _BIOSDISKENTRY * PBIOSDISKENTRY
ULONG DiskNumber
Definition: ntddvol.h:113
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _In_ ULONG _Out_opt_ PULONG _Out_opt_ PULONG ValueType
Definition: wdfregistry.h:279
UCHAR TargetId
Definition: scsi_port.h:150
_Must_inspect_result_ FORCEINLINE BOOLEAN IsListEmpty(_In_ const LIST_ENTRY *ListHead)
Definition: rtlfuncs.h:57
struct _CM_PARTIAL_RESOURCE_DESCRIPTOR::@381::@390 DeviceSpecificData
unsigned char EndingCylinder
Definition: partlist.h:188
#define FILE_SHARE_READ
Definition: compat.h:136
LIST_ENTRY ListEntry
Definition: diskpart.h:189
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define PARTITION_XINT13
Definition: disk.h:97
PPARTENTRY ExtendedPartition
Definition: partlist.h:135
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
#define FILE_DEVICE_CD_ROM
Definition: winioctl.h:108
#define PARTITION_ENTRY_UNUSED
Definition: disk.h:86
struct _PARTITION * PPARTITION
CM_PARTIAL_RESOURCE_LIST PartialResourceList
Definition: hwresource.cpp:160
static VOID AddDiskToList(HANDLE FileHandle, ULONG DiskNumber)
Definition: partlist.c:764
LIST_ENTRY ListEntry
Definition: partlist.h:43
BOOLEAN LogicalPartition
Definition: partlist.h:63
unsigned char BootFlags
Definition: partlist.h:181
NTSTATUS DismountVolume(IN PPARTENTRY PartEntry)
Definition: partlist.c:2940
BOOL WINAPI FindNextVolumeW(IN HANDLE handle, IN LPWSTR volume, IN DWORD len)
Definition: volume.c:1082
#define L(x)
Definition: ntvdm.h:50
PRTL_QUERY_REGISTRY_ROUTINE QueryRoutine
Definition: nt_native.h:109
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
static VOID EnumerateBiosDiskEntries(VOID)
Definition: partlist.c:254
struct _BIOSDISKENTRY BIOSDISKENTRY
ULONGLONG QuadPart
Definition: ms-dtyp.idl:185
#define FALSE
Definition: types.h:117
IN HANDLE DstPath
Definition: fsutil.h:76
unsigned int BOOL
Definition: ntddk_ex.h:94
WCHAR DriveLetter
Definition: diskpart.h:195
FORMATSTATE FormatState
Definition: partlist.h:61
#define PARTITION_HUGE
Definition: disk.h:92
#define FILE_READ_DATA
Definition: nt_native.h:628
#define GENERIC_WRITE
Definition: nt_native.h:90
#define FILE_REMOVABLE_MEDIA
Definition: nt_native.h:807
struct _DRIVE_LAYOUT_INFORMATION DRIVE_LAYOUT_INFORMATION
NTSTATUS CreateVolumeList(VOID)
Definition: partlist.c:1412
WCHAR VolumeName[MAX_PATH]
Definition: diskpart.h:192
#define ROOT_NAME
Definition: partlist.c:250
struct _CM_FULL_RESOURCE_DESCRIPTOR * PCM_FULL_RESOURCE_DESCRIPTOR
struct NameRec_ * Name
Definition: cdprocs.h:459
union Alignment_ Alignment
unsigned int SectorCount
Definition: partlist.h:190
unsigned char BOOLEAN
_In_ PCWSTR _Inout_ _At_ QueryTable EntryContext
Definition: rtlfuncs.h:4196
PARTITION_INFORMATION PartitionEntry[1]
Definition: ntdddisk.h:426
DWORD WINAPI QueryDosDeviceW(LPCWSTR lpDeviceName, LPWSTR lpTargetPath, DWORD ucchMax)
Definition: dosdev.c:542
unsigned int StartingBlock
Definition: partlist.h:189
#define _In_
Definition: ms_sal.h:308
FORCEINLINE PLIST_ENTRY RemoveHeadList(_Inout_ PLIST_ENTRY ListHead)
Definition: rtlfuncs.h:128
_Reserved_ PVOID Reserved
Definition: winddi.h:3974
Definition: bufpool.h:45
#define PARTITION_IFS
Definition: disk.h:93
PWSTR pszLabel
Definition: diskpart.h:197
#define REG_FULL_RESOURCE_DESCRIPTOR
Definition: nt_native.h:1503
_Must_inspect_result_ _In_ WDFDEVICE _In_ PCUNICODE_STRING KeyName
Definition: wdfdevice.h:2697
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
#define ULL(a, b)
Definition: format_msg.c:27
WCHAR DeviceName[MAX_PATH]
Definition: diskpart.h:193
ULARGE_INTEGER SectorCount
Definition: partlist.h:97
#define PARTITION_EXTENDED
Definition: disk.h:91
ULONG SectorAlignment
Definition: partlist.h:98
#define FILE_DEVICE_DISK_FILE_SYSTEM
Definition: winioctl.h:114
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:588
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:406
#define FSCTL_DISMOUNT_VOLUME
Definition: nt_native.h:834
Status
Definition: gdiplustypes.h:24
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
NTSYSAPI NTSTATUS NTAPI NtOpenFile(OUT PHANDLE phFile, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN ULONG ShareMode, IN ULONG OpenMode)
Definition: file.c:3951
USHORT Lun
Definition: diskpart.h:168
int Count
Definition: noreturn.cpp:7
UCHAR PartitionType
Definition: partlist.h:53
BOOLEAN BiosFound
Definition: partlist.h:102
struct _DISKENTRY * DiskEntry
Definition: partlist.h:46
ULONG BytesPerSector
Definition: partlist.h:95
NTSYSAPI NTSTATUS NTAPI NtFsControlFile(IN HANDLE hFile, IN HANDLE hEvent OPTIONAL, IN PIO_APC_ROUTINE IoApcRoutine OPTIONAL, IN PVOID IoApcContext OPTIONAL, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN ULONG DeviceIoControlCode, IN PVOID InBuffer OPTIONAL, IN ULONG InBufferLength, OUT PVOID OutBuffer OPTIONAL, IN ULONG OutBufferLength)
#define ASSERT(a)
Definition: mode.c:44
__wchar_t WCHAR
Definition: xmlstorage.h:180
static DWORD DWORD * dwLength
Definition: fusion.c:85
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
LARGE_INTEGER StartingOffset
Definition: ntdddisk.h:413
UNICODE_STRING DriverName
Definition: partlist.h:123
_In_ WDFCOLLECTION _In_ ULONG Index
uint64_t ULONGLONG
Definition: typedefs.h:67
LARGE_INTEGER Cylinders
Definition: ntdddisk.h:405
ULONG OnDiskPartitionNumber
Definition: partlist.h:54
unsigned char StartingCylinder
Definition: partlist.h:184
ULONG SectorsPerTrack
Definition: ntdddisk.h:408
#define IsRecognizedPartition(PartitionType)
Definition: ntdddisk.h:342
#define MAX_PATH
Definition: compat.h:34
CM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry
Definition: partlist.h:148
_In_ GUID _In_ PVOID ValueData
Definition: hubbusif.h:311
struct _DeviceInfo DeviceInfo
_In_ ULONG _In_ struct _SET_PARTITION_INFORMATION_EX * PartitionInfo
Definition: iofuncs.h:2105
static VOID GetVolumeType(_In_ HANDLE VolumeHandle, _In_ PVOLENTRY VolumeEntry)
Definition: partlist.c:1256
unsigned long DWORD
Definition: ntddk_ex.h:95
MEDIA_TYPE MediaType
Definition: ntdddisk.h:406
_Must_inspect_result_ _Out_ PHANDLE VolumeHandle
Definition: fltkernel.h:2283
USHORT PathId
Definition: diskpart.h:166
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define PARTITION_FAT_16
Definition: disk.h:90
unsigned char PartitionType
Definition: partlist.h:185
struct _PARTITION PARTITION
ULONGLONG AlignDown(IN ULONGLONG Value, IN ULONG Alignment)
Definition: partlist.c:67
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
BOOLEAN RewritePartition
Definition: ntdddisk.h:420
VOID DestroyVolumeList(VOID)
Definition: partlist.c:1450
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING ValueName
Definition: wdfregistry.h:240
unsigned char UCHAR
Definition: xmlstorage.h:181
CM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptors[1]
Definition: hwresource.cpp:119
_CRTIMP wchar_t *__cdecl wcscpy(_Out_writes_z_(_String_length_(_Source)+1) wchar_t *_Dest, _In_z_ const wchar_t *_Source)
ULONG SectorsPerTrack
Definition: partlist.h:94
LIST_ENTRY VolumeListHead
Definition: partlist.c:72
ULONG LowPart
Definition: typedefs.h:106
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
ULONG BiosDiskNumber
Definition: diskpart.h:160
VOID DestroyPartitionList(IN PPARTLIST List)
Definition: partlist.c:1931
PVOLENTRY CurrentVolume
Definition: partlist.c:76
#define IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
Definition: ntddvol.h:41
#define GENERIC_READ
Definition: compat.h:135
Definition: typedefs.h:119
#define SYNCHRONIZE
Definition: nt_native.h:61
#define RTL_REGISTRY_ABSOLUTE
Definition: nt_native.h:161
#define InsertAscendingList(ListHead, NewEntry, Type, ListEntryField, SortField)
Definition: partlist.c:17
#define ERROR_MORE_DATA
Definition: dderror.h:13
ULONGLONG Cylinders
Definition: partlist.h:92
HANDLE ProcessHeap
Definition: servman.c:15
BOOLEAN New
Definition: partlist.h:71
#define IOCTL_DISK_GET_DRIVE_LAYOUT
Definition: ntdddisk.h:91
BOOLEAN Recognized
Definition: diskpart.h:140
BOOL WINAPI GetVolumeInformationW(IN LPCWSTR lpRootPathName, IN LPWSTR lpVolumeNameBuffer, IN DWORD nVolumeNameSize, OUT LPDWORD lpVolumeSerialNumber OPTIONAL, OUT LPDWORD lpMaximumComponentLength OPTIONAL, OUT LPDWORD lpFileSystemFlags OPTIONAL, OUT LPWSTR lpFileSystemNameBuffer OPTIONAL, IN DWORD nFileSystemNameSize)
Definition: volume.c:226
ULONG NumberOfDiskExtents
Definition: ntddvol.h:119
unsigned char EndingHead
Definition: partlist.h:186
_Must_inspect_result_ _In_opt_ PFLT_INSTANCE _Out_ PHANDLE FileHandle
Definition: fltkernel.h:1230
LARGE_INTEGER StartingOffset
Definition: ntddvol.h:114
NTSTATUS NTAPI NtQueryVolumeInformationFile(HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock, PVOID FsInformation, ULONG Length, FS_INFORMATION_CLASS FsInformationClass)
BOOL WINAPI DeviceIoControl(IN HANDLE hDevice, IN DWORD dwIoControlCode, IN LPVOID lpInBuffer OPTIONAL, IN DWORD nInBufferSize OPTIONAL, OUT LPVOID lpOutBuffer OPTIONAL, IN DWORD nOutBufferSize OPTIONAL, OUT LPDWORD lpBytesReturned OPTIONAL, IN LPOVERLAPPED lpOverlapped OPTIONAL)
Definition: deviceio.c:136
ULONG VolumeNumber
Definition: diskpart.h:191
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
unsigned char StartingHead
Definition: partlist.h:182
unsigned short USHORT
Definition: pedump.c:61
ULONG DiskNumber
Definition: partlist.h:144
_In_ PFCB _In_ LONGLONG FileOffset
Definition: cdprocs.h:159
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
PARTITION Partition[PARTITION_TBL_SIZE]
Definition: partlist.h:198
UCHAR BootCode[440]
Definition: partlist.h:195
STRSAFEAPI StringCchPrintfW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszFormat,...)
Definition: strsafe.h:530
static VOID GetDriverName(PDISKENTRY DiskEntry)
Definition: partlist.c:95
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
#define FILE_OPEN_FOR_BACKUP_INTENT
Definition: from_kernel.h:42
USHORT Port
Definition: partlist.h:113
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
unsigned int * PULONG
Definition: retypes.h:1
#define NULL
Definition: types.h:112
PWSTR pszFilesystem
Definition: diskpart.h:198
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
ULONG GetPrimaryPartitionCount(_In_ PDISKENTRY DiskEntry)
Definition: partlist.c:1635
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
ULONG TracksPerCylinder
Definition: partlist.h:93
#define PARTITION_LINUX
Definition: partlist.c:36
#define DPRINT1
Definition: precomp.h:8
LIST_ENTRY LogicalPartListHead
Definition: partlist.h:132
BOOLEAN BootIndicator
Definition: partlist.h:52
#define FILE_SYNCHRONOUS_IO_NONALERT
Definition: from_kernel.h:31
NTSTATUS WritePartitions(IN PDISKENTRY DiskEntry)
Definition: partlist.c:3619
#define FILE_DEVICE_CD_ROM_FILE_SYSTEM
Definition: winioctl.h:109
#define FSCTL_LOCK_VOLUME
Definition: nt_native.h:832
static VOID AddPartitionToDisk(ULONG DiskNumber, PDISKENTRY DiskEntry, ULONG PartitionIndex, BOOLEAN LogicalPartition)
Definition: partlist.c:399
return Iosb
Definition: create.c:4402
#define PARTITION_FAT_12
Definition: disk.h:87
NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToInteger(PUNICODE_STRING String, ULONG Base, PULONG Value)
unsigned int ULONG
Definition: retypes.h:1
PPARTENTRY GetPrevUnpartitionedEntry(_In_ PPARTENTRY PartEntry)
Definition: partlist.c:1901
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
NTSYSAPI PVOID WINAPI RtlReAllocateHeap(HANDLE, ULONG, PVOID, SIZE_T)
Definition: heap.c:2667
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
struct _PARTITION_SECTOR PARTITION_SECTOR
#define IOCTL_DISK_SET_DRIVE_LAYOUT
Definition: ntdddisk.h:205
BOOLEAN RecognizedPartition
Definition: ntdddisk.h:419
#define PARTITION_FAT32_XINT13
Definition: disk.h:96
#define STATUS_SUCCESS
Definition: shellext.h:65
union _CM_PARTIAL_RESOURCE_DESCRIPTOR::@381 u
unsigned char StartingSector
Definition: partlist.h:183
#define DPRINT
Definition: sndvol32.h:71
static NTSTATUS NTAPI DiskIdentifierQueryRoutine(PWSTR ValueName, ULONG ValueType, PVOID ValueData, ULONG ValueLength, PVOID Context, PVOID EntryContext)
Definition: partlist.c:130
#define RTL_REGISTRY_DEVICEMAP
Definition: nt_native.h:165
static BOOLEAN ReAllocateLayoutBuffer(_In_ PDISKENTRY DiskEntry)
Definition: partlist.c:1679
static VOID ScanForUnpartitionedDiskSpace(PDISKENTRY DiskEntry)
Definition: partlist.c:508
static VOID GetVolumeExtents(_In_ HANDLE VolumeHandle, _In_ PVOLENTRY VolumeEntry)
Definition: partlist.c:1190
static const WCHAR Signature[]
Definition: parser.c:141
static VOID AddVolumeToList(ULONG ulVolumeNumber, PWSTR pszVolumeName)
Definition: partlist.c:1296
BOOL WINAPI FindVolumeClose(IN HANDLE hFindVolume)
Definition: volume.c:741
PDRIVE_LAYOUT_INFORMATION LayoutBuffer
Definition: partlist.h:125
static NTSTATUS NTAPI SystemConfigurationDataQueryRoutine(PWSTR ValueName, ULONG ValueType, PVOID ValueData, ULONG ValueLength, PVOID Context, PVOID EntryContext)
Definition: partlist.c:204
#define memset(x, y, z)
Definition: compat.h:39
FORCEINLINE BOOLEAN IsSamePrimaryLayoutEntry(IN PPARTITION_INFORMATION PartitionInfo, IN PDISKENTRY DiskEntry, IN PPARTENTRY PartEntry)
Definition: partlist.c:2411
BOOLEAN NewDisk
Definition: partlist.h:120
base of all file and directory entries
Definition: entries.h:82
#define IOCTL_DISK_GET_DRIVE_GEOMETRY
Definition: cdrw_usr.h:169
BOOLEAN NoMbr
Definition: diskpart.h:174
#define RTL_QUERY_REGISTRY_DIRECT
Definition: nt_native.h:144
NTSTATUS NTAPI NtReadFile(HANDLE FileHandle, HANDLE Event, PIO_APC_ROUTINE ApcRoutine, PVOID ApcContext, PIO_STATUS_BLOCK IoStatusBlock, PVOID Buffer, ULONG Length, PLARGE_INTEGER ByteOffset, PULONG Key)
#define BufferSize
Definition: mmc.h:75
_In_ WDFMEMORY _Out_opt_ size_t * BufferSize
Definition: wdfmemory.h:251
LONGLONG QuadPart
Definition: typedefs.h:114
struct _DISK_EXTENT DISK_EXTENT
PPARTENTRY CurrentPartition
Definition: partlist.c:75
BOOLEAN IsPartitioned
Definition: partlist.h:66
ULONG PartitionIndex
Definition: partlist.h:56
#define REG_SZ
Definition: layer.c:22
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _In_ ULONG ValueLength
Definition: wdfregistry.h:271