ReactOS 0.4.16-dev-2204-g370eb8c
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
13#define NDEBUG
14#include <debug.h>
15
16#define InsertAscendingList(ListHead, NewEntry, Type, ListEntryField, SortField)\
17{\
18 PLIST_ENTRY current;\
19\
20 current = (ListHead)->Flink;\
21 while (current != (ListHead))\
22 {\
23 if (CONTAINING_RECORD(current, Type, ListEntryField)->SortField >=\
24 (NewEntry)->SortField)\
25 {\
26 break;\
27 }\
28 current = current->Flink;\
29 }\
30\
31 InsertTailList(current, &((NewEntry)->ListEntryField));\
32}
33
34/* We have to define it there, because it is not in the MS DDK */
35#define PARTITION_LINUX 0x83
36
37#define PARTITION_TBL_SIZE 4
38
39#define MBR_MAGIC 0xAA55
40
41#include <pshpack1.h>
42
43typedef struct _PARTITION
44{
45 unsigned char BootFlags; /* bootable? 0=no, 128=yes */
46 unsigned char StartingHead; /* beginning head number */
47 unsigned char StartingSector; /* beginning sector number */
48 unsigned char StartingCylinder; /* 10 bit nmbr, with high 2 bits put in begsect */
49 unsigned char PartitionType; /* Operating System type indicator code */
50 unsigned char EndingHead; /* ending head number */
51 unsigned char EndingSector; /* ending sector number */
52 unsigned char EndingCylinder; /* also a 10 bit nmbr, with same high 2 bit trick */
53 unsigned int StartingBlock; /* first sector relative to start of disk */
54 unsigned int SectorCount; /* number of sectors in partition */
56
57typedef struct _PARTITION_SECTOR
58{
59 UCHAR BootCode[440]; /* 0x000 */
60 ULONG Signature; /* 0x1B8 */
61 UCHAR Reserved[2]; /* 0x1BC */
63 USHORT Magic; /* 0x1FE */
65
66#include <poppack.h>
67
68
69/* GLOBALS ********************************************************************/
70
74
78
79
80/* FUNCTIONS ******************************************************************/
81
82#ifdef DUMP_PARTITION_TABLE
83VOID
84DumpPartitionTable(
85 _In_ PDISKENTRY DiskEntry)
86{
88 ULONG i;
89
90 DbgPrint("\n");
91
92 if (DiskEntry->LayoutBuffer->PartitionStyle == PARTITION_STYLE_MBR)
93 {
94 DbgPrint("Index Start Length Hidden Nr Type Boot RW\n");
95 DbgPrint("----- ------------ ------------ ---------- -- ---- ---- --\n");
96
97 for (i = 0; i < DiskEntry->LayoutBuffer->PartitionCount; i++)
98 {
99 PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[i];
100 DbgPrint(" %3lu %12I64u %12I64u %10lu %2lu %2x %c %c\n",
101 i,
102 PartitionInfo->StartingOffset.QuadPart / DiskEntry->BytesPerSector,
103 PartitionInfo->PartitionLength.QuadPart / DiskEntry->BytesPerSector,
104 PartitionInfo->Mbr.HiddenSectors,
105 PartitionInfo->PartitionNumber,
106 PartitionInfo->Mbr.PartitionType,
107 PartitionInfo->Mbr.BootIndicator ? '*': ' ',
108 PartitionInfo->RewritePartition ? 'Y': 'N');
109 }
110 }
111 else if (DiskEntry->LayoutBuffer->PartitionStyle == PARTITION_STYLE_GPT)
112 {
113 DbgPrint("Index Start Length Nr RW Type \n");
114 DbgPrint("----- ------------ ------------ -- -- --------\n");
115 for (i = 0; i < DiskEntry->LayoutBuffer->PartitionCount; i++)
116 {
117 PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[i];
118
119 DbgPrint(" %3lu %12I64u %12I64u %2lu %c %08lx\n",
120 i,
121 PartitionInfo->StartingOffset.QuadPart / DiskEntry->BytesPerSector,
122 PartitionInfo->PartitionLength.QuadPart / DiskEntry->BytesPerSector,
123 PartitionInfo->PartitionNumber,
124 PartitionInfo->RewritePartition ? 'Y': 'N',
125 PartitionInfo->Gpt.PartitionType.Data1);
126 }
127 }
128
129 DbgPrint("\n");
130}
131#endif
132
133#ifdef DUMP_PARTITION_LIST
134VOID
135DumpPartitionList(
136 _In_ PDISKENTRY DiskEntry)
137{
138 PLIST_ENTRY ListEntry;
139 PPARTENTRY PartEntry;
140
141 DbgPrint("\n");
142
143 if (DiskEntry->PartitionStyle == PARTITION_STYLE_GPT)
144 {
145 DbgPrint("Disk Start Disk End Disk Length \n");
146 DbgPrint("------------ ------------ ------------\n");
147 DbgPrint("%12I64u %12I64u %12I64u\n",
148 DiskEntry->StartSector.QuadPart,
149 DiskEntry->EndSector.QuadPart,
150 DiskEntry->EndSector.QuadPart - DiskEntry->StartSector.QuadPart + 1);
151
152 DbgPrint("\n");
153
154 DbgPrint("Start End Length Nr Type P\n");
155 DbgPrint("------------ ------------ ------------ --- -------- --\n");
156
157 for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
158 ListEntry != &DiskEntry->PrimaryPartListHead;
159 ListEntry = ListEntry->Flink)
160 {
161 PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
162
163 DbgPrint("%12I64u %12I64u %12I64u %3lu %08lx %c\n",
164 PartEntry->StartSector.QuadPart,
165 PartEntry->StartSector.QuadPart + PartEntry->SectorCount.QuadPart - 1,
166 PartEntry->SectorCount.QuadPart,
167 PartEntry->PartitionNumber,
168 PartEntry->Gpt.PartitionType.Data1,
169 PartEntry->IsPartitioned ? 'Y': 'N');
170 }
171 }
172 else if (DiskEntry->PartitionStyle == PARTITION_STYLE_MBR)
173 {
174 DbgPrint("Disk Start Disk End Disk Length \n");
175 DbgPrint("------------ ------------ ------------\n");
176 DbgPrint("%12I64u %12I64u %12I64u\n",
177 DiskEntry->StartSector.QuadPart,
178 DiskEntry->EndSector.QuadPart,
179 DiskEntry->EndSector.QuadPart - DiskEntry->StartSector.QuadPart + 1);
180
181 }
182
183 DbgPrint("\n");
184}
185#endif
186
187
192{
193 ULONGLONG Temp;
194
195 Temp = Value / Alignment;
196
197 return Temp * Alignment;
198}
199
200static
201VOID
203 PDISKENTRY DiskEntry)
204{
206 WCHAR KeyName[32];
208
210 NULL);
211
213 L"\\Scsi\\Scsi Port %lu",
214 DiskEntry->Port);
215
217 sizeof(QueryTable));
218
219 QueryTable[0].Name = L"Driver";
221 QueryTable[0].EntryContext = &DiskEntry->DriverName;
222
224 KeyName,
226 NULL,
227 NULL);
228 if (!NT_SUCCESS(Status))
229 {
230 DPRINT1("RtlQueryRegistryValues() failed (Status %lx)\n", Status);
231 }
232}
233
234static
236NTAPI
244{
245 PBIOSDISKENTRY BiosDiskEntry = (PBIOSDISKENTRY)Context;
246 UNICODE_STRING NameU;
247
248 if (ValueType == REG_SZ &&
249 ValueLength == 20 * sizeof(WCHAR))
250 {
251 NameU.Buffer = (PWCHAR)ValueData;
252 NameU.Length = NameU.MaximumLength = 8 * sizeof(WCHAR);
253 RtlUnicodeStringToInteger(&NameU, 16, &BiosDiskEntry->Checksum);
254
255 NameU.Buffer = (PWCHAR)ValueData + 9;
256 RtlUnicodeStringToInteger(&NameU, 16, &BiosDiskEntry->Signature);
257
258 return STATUS_SUCCESS;
259 }
260
261 return STATUS_UNSUCCESSFUL;
262}
263
264static
266NTAPI
274{
275 PBIOSDISKENTRY BiosDiskEntry = (PBIOSDISKENTRY)Context;
276 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
278 ULONG i;
279
282 return STATUS_UNSUCCESSFUL;
283
284 FullResourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)ValueData;
285
286 /* Hm. Version and Revision are not set on Microsoft Windows XP... */
287#if 0
288 if (FullResourceDescriptor->PartialResourceList.Version != 1 ||
289 FullResourceDescriptor->PartialResourceList.Revision != 1)
290 return STATUS_UNSUCCESSFUL;
291#endif
292
293 for (i = 0; i < FullResourceDescriptor->PartialResourceList.Count; i++)
294 {
297 continue;
298
299 DiskGeometry = (PCM_DISK_GEOMETRY_DEVICE_DATA)&FullResourceDescriptor->PartialResourceList.PartialDescriptors[i + 1];
300 BiosDiskEntry->DiskGeometry = *DiskGeometry;
301
302 return STATUS_SUCCESS;
303 }
304
305 return STATUS_UNSUCCESSFUL;
306}
307
308static
310NTAPI
318{
319 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
321 ULONG i;
322
325 return STATUS_UNSUCCESSFUL;
326
327 FullResourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)ValueData;
328
329 /* Hm. Version and Revision are not set on Microsoft Windows XP... */
330#if 0
331 if (FullResourceDescriptor->PartialResourceList.Version != 1 ||
332 FullResourceDescriptor->PartialResourceList.Revision != 1)
333 return STATUS_UNSUCCESSFUL;
334#endif
335
336 for (i = 0; i < FullResourceDescriptor->PartialResourceList.Count; i++)
337 {
339 FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].u.DeviceSpecificData.DataSize % sizeof(CM_INT13_DRIVE_PARAMETER) != 0)
340 continue;
341
342 *Int13Drives = (CM_INT13_DRIVE_PARAMETER*)RtlAllocateHeap(RtlGetProcessHeap(), 0,
343 FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].u.DeviceSpecificData.DataSize);
344 if (*Int13Drives == NULL)
345 return STATUS_NO_MEMORY;
346
347 memcpy(*Int13Drives,
348 &FullResourceDescriptor->PartialResourceList.PartialDescriptors[i + 1],
349 FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].u.DeviceSpecificData.DataSize);
350 return STATUS_SUCCESS;
351 }
352
353 return STATUS_UNSUCCESSFUL;
354}
355
356
357#define ROOT_NAME L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter"
358
359static
360VOID
362{
364 WCHAR Name[120];
365 ULONG AdapterCount;
366 ULONG DiskCount;
368 PCM_INT13_DRIVE_PARAMETER Int13Drives;
369 PBIOSDISKENTRY BiosDiskEntry;
370
371 memset(QueryTable, 0, sizeof(QueryTable));
372
373 QueryTable[1].Name = L"Configuration Data";
375 Int13Drives = NULL;
377 L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System",
378 &QueryTable[1],
379 (PVOID)&Int13Drives,
380 NULL);
381 if (!NT_SUCCESS(Status))
382 {
383 DPRINT1("Unable to query the 'Configuration Data' key in '\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System', status=%lx\n", Status);
384 return;
385 }
386
387 AdapterCount = 0;
388 while (1)
389 {
391 L"%s\\%lu", ROOT_NAME, AdapterCount);
393 Name,
394 &QueryTable[2],
395 NULL,
396 NULL);
397 if (!NT_SUCCESS(Status))
398 {
399 break;
400 }
401
403 L"%s\\%lu\\DiskController", ROOT_NAME, AdapterCount);
405 Name,
406 &QueryTable[2],
407 NULL,
408 NULL);
409 if (NT_SUCCESS(Status))
410 {
411 while (1)
412 {
414 L"%s\\%lu\\DiskController\\0", ROOT_NAME, AdapterCount);
416 Name,
417 &QueryTable[2],
418 NULL,
419 NULL);
420 if (!NT_SUCCESS(Status))
421 {
422 RtlFreeHeap(RtlGetProcessHeap(), 0, Int13Drives);
423 return;
424 }
425
427 L"%s\\%lu\\DiskController\\0\\DiskPeripheral", ROOT_NAME, AdapterCount);
429 Name,
430 &QueryTable[2],
431 NULL,
432 NULL);
433 if (NT_SUCCESS(Status))
434 {
435 QueryTable[0].Name = L"Identifier";
437 QueryTable[1].Name = L"Configuration Data";
439
440 DiskCount = 0;
441 while (1)
442 {
443 BiosDiskEntry = (BIOSDISKENTRY*)RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BIOSDISKENTRY));
444 if (BiosDiskEntry == NULL)
445 {
446 break;
447 }
448
450 L"%s\\%lu\\DiskController\\0\\DiskPeripheral\\%lu", ROOT_NAME, AdapterCount, DiskCount);
452 Name,
454 (PVOID)BiosDiskEntry,
455 NULL);
456 if (!NT_SUCCESS(Status))
457 {
458 RtlFreeHeap(RtlGetProcessHeap(), 0, BiosDiskEntry);
459 break;
460 }
461
462 BiosDiskEntry->DiskNumber = DiskCount;
463 BiosDiskEntry->Recognized = FALSE;
464
465 if (DiskCount < Int13Drives[0].NumberDrives)
466 {
467 BiosDiskEntry->Int13DiskData = Int13Drives[DiskCount];
468 }
469 else
470 {
471 DPRINT1("Didn't find int13 drive datas for disk %u\n", DiskCount);
472 }
473
474 InsertTailList(&BiosDiskListHead, &BiosDiskEntry->ListEntry);
475
476 DPRINT("DiskNumber: %lu\n", BiosDiskEntry->DiskNumber);
477 DPRINT("Signature: %08lx\n", BiosDiskEntry->Signature);
478 DPRINT("Checksum: %08lx\n", BiosDiskEntry->Checksum);
479 DPRINT("BytesPerSector: %lu\n", BiosDiskEntry->DiskGeometry.BytesPerSector);
480 DPRINT("NumberOfCylinders: %lu\n", BiosDiskEntry->DiskGeometry.NumberOfCylinders);
481 DPRINT("NumberOfHeads: %lu\n", BiosDiskEntry->DiskGeometry.NumberOfHeads);
482 DPRINT("DriveSelect: %02x\n", BiosDiskEntry->Int13DiskData.DriveSelect);
483 DPRINT("MaxCylinders: %lu\n", BiosDiskEntry->Int13DiskData.MaxCylinders);
484 DPRINT("SectorsPerTrack: %d\n", BiosDiskEntry->Int13DiskData.SectorsPerTrack);
485 DPRINT("MaxHeads: %d\n", BiosDiskEntry->Int13DiskData.MaxHeads);
486 DPRINT("NumberDrives: %d\n", BiosDiskEntry->Int13DiskData.NumberDrives);
487
488 DiskCount++;
489 }
490 }
491
492 RtlFreeHeap(RtlGetProcessHeap(), 0, Int13Drives);
493 return;
494 }
495 }
496
497 AdapterCount++;
498 }
499
500 RtlFreeHeap(RtlGetProcessHeap(), 0, Int13Drives);
501}
502
503
504static
505VOID
507 ULONG DiskNumber,
508 PDISKENTRY DiskEntry,
509 ULONG PartitionIndex,
511{
513 PPARTENTRY PartEntry;
514
515 PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[PartitionIndex];
516 if (PartitionInfo->Mbr.PartitionType == 0 ||
517 (LogicalPartition == TRUE && IsContainerPartition(PartitionInfo->Mbr.PartitionType)))
518 return;
519
520 PartEntry = RtlAllocateHeap(RtlGetProcessHeap(),
522 sizeof(PARTENTRY));
523 if (PartEntry == NULL)
524 {
525 /* TODO: Error message */
526 return;
527 }
528
529 PartEntry->DiskEntry = DiskEntry;
530
531 PartEntry->StartSector.QuadPart = (ULONGLONG)PartitionInfo->StartingOffset.QuadPart / DiskEntry->BytesPerSector;
532 PartEntry->SectorCount.QuadPart = (ULONGLONG)PartitionInfo->PartitionLength.QuadPart / DiskEntry->BytesPerSector;
533
534 PartEntry->Mbr.BootIndicator = PartitionInfo->Mbr.BootIndicator;
535 PartEntry->Mbr.PartitionType = PartitionInfo->Mbr.PartitionType;
536
538 PartEntry->IsPartitioned = TRUE;
539 PartEntry->PartitionNumber = PartitionInfo->PartitionNumber;
540 PartEntry->PartitionIndex = PartitionIndex;
541
542 if (IsContainerPartition(PartEntry->Mbr.PartitionType))
543 {
544 PartEntry->FormatState = Unformatted;
545
546 if (LogicalPartition == FALSE && DiskEntry->ExtendedPartition == NULL)
547 DiskEntry->ExtendedPartition = PartEntry;
548 }
549 else if ((PartEntry->Mbr.PartitionType == PARTITION_FAT_12) ||
550 (PartEntry->Mbr.PartitionType == PARTITION_FAT_16) ||
551 (PartEntry->Mbr.PartitionType == PARTITION_HUGE) ||
552 (PartEntry->Mbr.PartitionType == PARTITION_XINT13) ||
553 (PartEntry->Mbr.PartitionType == PARTITION_FAT32) ||
555 {
556#if 0
557 if (CheckFatFormat())
558 {
559 PartEntry->FormatState = Preformatted;
560 }
561 else
562 {
563 PartEntry->FormatState = Unformatted;
564 }
565#endif
566 PartEntry->FormatState = Preformatted;
567 }
568 else if (PartEntry->Mbr.PartitionType == PARTITION_LINUX)
569 {
570#if 0
571 if (CheckExt2Format())
572 {
573 PartEntry->FormatState = Preformatted;
574 }
575 else
576 {
577 PartEntry->FormatState = Unformatted;
578 }
579#endif
580 PartEntry->FormatState = Preformatted;
581 }
582 else if (PartEntry->Mbr.PartitionType == PARTITION_IFS)
583 {
584#if 0
585 if (CheckNtfsFormat())
586 {
587 PartEntry->FormatState = Preformatted;
588 }
589 else if (CheckHpfsFormat())
590 {
591 PartEntry->FormatState = Preformatted;
592 }
593 else
594 {
595 PartEntry->FormatState = Unformatted;
596 }
597#endif
598 PartEntry->FormatState = Preformatted;
599 }
600 else
601 {
602 PartEntry->FormatState = UnknownFormat;
603 }
604
607 &PartEntry->ListEntry);
608 else
610 &PartEntry->ListEntry);
611}
612
613
614static
615VOID
617 ULONG DiskNumber,
618 PDISKENTRY DiskEntry,
619 ULONG PartitionIndex)
620{
622 PPARTENTRY PartEntry;
623
624 PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[PartitionIndex];
625 if (IsEqualGUID(&PartitionInfo->Gpt.PartitionType, &PARTITION_ENTRY_UNUSED_GUID))
626 return;
627
628 PartEntry = RtlAllocateHeap(RtlGetProcessHeap(),
630 sizeof(PARTENTRY));
631 if (PartEntry == NULL)
632 {
633 /* TODO: Error message */
634 return;
635 }
636
637 PartEntry->DiskEntry = DiskEntry;
638
639 PartEntry->StartSector.QuadPart = (ULONGLONG)PartitionInfo->StartingOffset.QuadPart / DiskEntry->BytesPerSector;
640 PartEntry->SectorCount.QuadPart = (ULONGLONG)PartitionInfo->PartitionLength.QuadPart / DiskEntry->BytesPerSector;
641
642 CopyMemory(&PartEntry->Gpt.PartitionType, &PartitionInfo->Gpt.PartitionType, sizeof(GUID));
643 CopyMemory(&PartEntry->Gpt.PartitionId, &PartitionInfo->Gpt.PartitionId, sizeof(GUID));
644 PartEntry->Gpt.Attributes = PartitionInfo->Gpt.Attributes;
645
646 PartEntry->LogicalPartition = FALSE;
647 PartEntry->IsPartitioned = TRUE;
648 PartEntry->PartitionNumber = PartitionInfo->PartitionNumber;
649 PartEntry->PartitionIndex = PartitionIndex;
650
651 /* TODO: Determine the format state */
652 PartEntry->FormatState = Unformatted;
653
655 &PartEntry->ListEntry);
656}
657
658
659VOID
661 PDISKENTRY DiskEntry)
662{
663 ULONGLONG StartSector, EndSector;
664 ULONGLONG LastStartSector;
665 ULONGLONG LastSectorCount;
666 ULONGLONG LastUnusedSectorCount;
667 PPARTENTRY PartEntry;
668 PPARTENTRY NewPartEntry;
670
671 DPRINT("ScanForUnpartitionedMbrDiskSpace()\n");
672
673 /* Calculate the disk sector limits */
674 /* Limit the SectorCount to 2^32 sectors for MBR disks */
675 StartSector = (ULONGLONG)DiskEntry->SectorAlignment;
676 EndSector = min(DiskEntry->SectorCount.QuadPart, 0x100000000) - 1;
677
678 if (IsListEmpty(&DiskEntry->PrimaryPartListHead))
679 {
680 DPRINT1("No primary partition!\n");
681
682 /* Create a partition table that represents the empty disk */
683 NewPartEntry = RtlAllocateHeap(RtlGetProcessHeap(),
685 sizeof(PARTENTRY));
686 if (NewPartEntry == NULL)
687 return;
688
689 NewPartEntry->DiskEntry = DiskEntry;
690
691 NewPartEntry->IsPartitioned = FALSE;
692 NewPartEntry->StartSector.QuadPart = StartSector;
693 NewPartEntry->SectorCount.QuadPart = AlignDown(EndSector + 1, DiskEntry->SectorAlignment) -
694 NewPartEntry->StartSector.QuadPart;
695
696 DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
697 DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
698 DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
699
700 NewPartEntry->FormatState = Unformatted;
701
703 &NewPartEntry->ListEntry);
704
705 return;
706 }
707
708 /* Start at the first usable sector */
709 LastStartSector = StartSector;
710 LastSectorCount = 0ULL;
711 LastUnusedSectorCount = 0ULL;
712
713 Entry = DiskEntry->PrimaryPartListHead.Flink;
714 while (Entry != &DiskEntry->PrimaryPartListHead)
715 {
716 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
717
718 if (PartEntry->Mbr.PartitionType != PARTITION_ENTRY_UNUSED ||
719 PartEntry->SectorCount.QuadPart != 0ULL)
720 {
721 LastUnusedSectorCount =
722 PartEntry->StartSector.QuadPart - (LastStartSector + LastSectorCount);
723
724 if (PartEntry->StartSector.QuadPart > (LastStartSector + LastSectorCount) &&
725 LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment)
726 {
727 DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount);
728
729 NewPartEntry = RtlAllocateHeap(RtlGetProcessHeap(),
731 sizeof(PARTENTRY));
732 if (NewPartEntry == NULL)
733 return;
734
735 NewPartEntry->DiskEntry = DiskEntry;
736
737 NewPartEntry->IsPartitioned = FALSE;
738 NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount;
739 NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + LastUnusedSectorCount, DiskEntry->SectorAlignment) -
740 NewPartEntry->StartSector.QuadPart;
741
742 DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
743 DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
744 DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
745
746 NewPartEntry->FormatState = Unformatted;
747
748 /* Insert the table into the list */
749 InsertTailList(&PartEntry->ListEntry,
750 &NewPartEntry->ListEntry);
751 }
752
753 LastStartSector = PartEntry->StartSector.QuadPart;
754 LastSectorCount = PartEntry->SectorCount.QuadPart;
755 }
756
757 Entry = Entry->Flink;
758 }
759
760 /* Check for trailing unpartitioned disk space */
761 if ((LastStartSector + LastSectorCount) < (EndSector + 1))
762 {
763 LastUnusedSectorCount = AlignDown((EndSector + 1) - (LastStartSector + LastSectorCount), DiskEntry->SectorAlignment);
764
765 if (LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment)
766 {
767 DPRINT1("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount);
768
769 NewPartEntry = RtlAllocateHeap(RtlGetProcessHeap(),
771 sizeof(PARTENTRY));
772 if (NewPartEntry == NULL)
773 return;
774
775 NewPartEntry->DiskEntry = DiskEntry;
776
777 NewPartEntry->IsPartitioned = FALSE;
778 NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount;
779 NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + LastUnusedSectorCount, DiskEntry->SectorAlignment) -
780 NewPartEntry->StartSector.QuadPart;
781
782 DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
783 DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
784 DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
785
786 NewPartEntry->FormatState = Unformatted;
787
788 /* Append the table to the list */
790 &NewPartEntry->ListEntry);
791 }
792 }
793
794 if (DiskEntry->ExtendedPartition != NULL)
795 {
796 if (IsListEmpty(&DiskEntry->LogicalPartListHead))
797 {
798 DPRINT1("No logical partition!\n");
799
800 /* Create a partition table entry that represents the empty extended partition */
801 NewPartEntry = RtlAllocateHeap(RtlGetProcessHeap(),
803 sizeof(PARTENTRY));
804 if (NewPartEntry == NULL)
805 return;
806
807 NewPartEntry->DiskEntry = DiskEntry;
808 NewPartEntry->LogicalPartition = TRUE;
809
810 NewPartEntry->IsPartitioned = FALSE;
811 NewPartEntry->StartSector.QuadPart = DiskEntry->ExtendedPartition->StartSector.QuadPart + (ULONGLONG)DiskEntry->SectorAlignment;
812 NewPartEntry->SectorCount.QuadPart = DiskEntry->ExtendedPartition->SectorCount.QuadPart - (ULONGLONG)DiskEntry->SectorAlignment;
813
814 DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
815 DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
816 DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
817
818 NewPartEntry->FormatState = Unformatted;
819
821 &NewPartEntry->ListEntry);
822
823 return;
824 }
825
826 /* Start partition at head 1, cylinder 0 */
827 LastStartSector = DiskEntry->ExtendedPartition->StartSector.QuadPart + (ULONGLONG)DiskEntry->SectorAlignment;
828 LastSectorCount = 0ULL;
829 LastUnusedSectorCount = 0ULL;
830
831 Entry = DiskEntry->LogicalPartListHead.Flink;
832 while (Entry != &DiskEntry->LogicalPartListHead)
833 {
834 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
835
836 if (PartEntry->Mbr.PartitionType != PARTITION_ENTRY_UNUSED ||
837 PartEntry->SectorCount.QuadPart != 0ULL)
838 {
839 LastUnusedSectorCount =
840 PartEntry->StartSector.QuadPart - (ULONGLONG)DiskEntry->SectorAlignment - (LastStartSector + LastSectorCount);
841
842 if ((PartEntry->StartSector.QuadPart - (ULONGLONG)DiskEntry->SectorAlignment) > (LastStartSector + LastSectorCount) &&
843 LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment)
844 {
845 DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount);
846
847 NewPartEntry = RtlAllocateHeap(RtlGetProcessHeap(),
849 sizeof(PARTENTRY));
850 if (NewPartEntry == NULL)
851 return;
852
853 NewPartEntry->DiskEntry = DiskEntry;
854 NewPartEntry->LogicalPartition = TRUE;
855
856 NewPartEntry->IsPartitioned = FALSE;
857 NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount;
858 NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + LastUnusedSectorCount, DiskEntry->SectorAlignment) -
859 NewPartEntry->StartSector.QuadPart;
860
861 DPRINT("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
862 DPRINT("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
863 DPRINT("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
864
865 NewPartEntry->FormatState = Unformatted;
866
867 /* Insert the table into the list */
868 InsertTailList(&PartEntry->ListEntry,
869 &NewPartEntry->ListEntry);
870 }
871
872 LastStartSector = PartEntry->StartSector.QuadPart;
873 LastSectorCount = PartEntry->SectorCount.QuadPart;
874 }
875
876 Entry = Entry->Flink;
877 }
878
879 /* Check for trailing unpartitioned disk space */
880 if ((LastStartSector + LastSectorCount) < DiskEntry->ExtendedPartition->StartSector.QuadPart + DiskEntry->ExtendedPartition->SectorCount.QuadPart)
881 {
882 LastUnusedSectorCount = AlignDown(DiskEntry->ExtendedPartition->StartSector.QuadPart + DiskEntry->ExtendedPartition->SectorCount.QuadPart - (LastStartSector + LastSectorCount),
883 DiskEntry->SectorAlignment);
884
885 if (LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment)
886 {
887 DPRINT("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount);
888
889 NewPartEntry = RtlAllocateHeap(RtlGetProcessHeap(),
891 sizeof(PARTENTRY));
892 if (NewPartEntry == NULL)
893 return;
894
895 NewPartEntry->DiskEntry = DiskEntry;
896 NewPartEntry->LogicalPartition = TRUE;
897
898 NewPartEntry->IsPartitioned = FALSE;
899 NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount;
900 NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + LastUnusedSectorCount, DiskEntry->SectorAlignment) -
901 NewPartEntry->StartSector.QuadPart;
902
903 DPRINT("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
904 DPRINT("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
905 DPRINT("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
906
907 NewPartEntry->FormatState = Unformatted;
908
909 /* Append the table to the list */
911 &NewPartEntry->ListEntry);
912 }
913 }
914 }
915
916 DPRINT("ScanForUnpartitionedMbrDiskSpace() done\n");
917}
918
919
920VOID
922 PDISKENTRY DiskEntry)
923{
924 ULONGLONG LastStartSector;
925 ULONGLONG LastSectorCount;
926 ULONGLONG LastUnusedSectorCount;
927 PPARTENTRY PartEntry;
928 PPARTENTRY NewPartEntry;
930
931 DPRINT("ScanForUnpartitionedGptDiskSpace()\n");
932
933#ifdef DUMP_PARTITION_LIST
934 DumpPartitionList(DiskEntry);
935#endif
936
937 if (IsListEmpty(&DiskEntry->PrimaryPartListHead))
938 {
939 DPRINT("No partitions!\n");
940
941 /* Create a partition table that represents the empty disk */
942 NewPartEntry = RtlAllocateHeap(RtlGetProcessHeap(),
944 sizeof(PARTENTRY));
945 if (NewPartEntry == NULL)
946 return;
947
948 NewPartEntry->DiskEntry = DiskEntry;
949
950 NewPartEntry->IsPartitioned = FALSE;
951 NewPartEntry->StartSector.QuadPart = DiskEntry->StartSector.QuadPart;
952 NewPartEntry->SectorCount.QuadPart = DiskEntry->EndSector.QuadPart - DiskEntry->StartSector.QuadPart + 1;
953
954 DPRINT("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
955 DPRINT("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
956 DPRINT("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
957
958 NewPartEntry->FormatState = Unformatted;
959
961 &NewPartEntry->ListEntry);
962
963#ifdef DUMP_PARTITION_LIST
964 DumpPartitionList(DiskEntry);
965#endif
966
967 return;
968 }
969
970 /* Start at the first usable sector */
971 LastStartSector = DiskEntry->StartSector.QuadPart;
972 LastSectorCount = 0ULL;
973 LastUnusedSectorCount = 0ULL;
974
975 Entry = DiskEntry->PrimaryPartListHead.Flink;
976 while (Entry != &DiskEntry->PrimaryPartListHead)
977 {
978 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
979
980 if (!IsEqualGUID(&PartEntry->Gpt.PartitionType, &PARTITION_ENTRY_UNUSED_GUID) ||
981 PartEntry->SectorCount.QuadPart != 0ULL)
982 {
983 LastUnusedSectorCount =
984 PartEntry->StartSector.QuadPart - (LastStartSector + LastSectorCount);
985
986 if (PartEntry->StartSector.QuadPart > (LastStartSector + LastSectorCount) &&
987 LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment)
988 {
989 DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount);
990
991 NewPartEntry = RtlAllocateHeap(RtlGetProcessHeap(),
993 sizeof(PARTENTRY));
994 if (NewPartEntry == NULL)
995 return;
996
997 NewPartEntry->DiskEntry = DiskEntry;
998
999 NewPartEntry->IsPartitioned = FALSE;
1000 NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount;
1001 NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + LastUnusedSectorCount, DiskEntry->SectorAlignment) -
1002 NewPartEntry->StartSector.QuadPart;
1003
1004 DPRINT("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
1005 DPRINT("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
1006 DPRINT("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
1007
1008 NewPartEntry->FormatState = Unformatted;
1009
1010 /* Insert the table into the list */
1011 InsertTailList(&PartEntry->ListEntry,
1012 &NewPartEntry->ListEntry);
1013 }
1014
1015 LastStartSector = PartEntry->StartSector.QuadPart;
1016 LastSectorCount = PartEntry->SectorCount.QuadPart;
1017 }
1018
1019 Entry = Entry->Flink;
1020 }
1021
1022 /* Check for trailing unpartitioned disk space */
1023 if ((LastStartSector + LastSectorCount) < DiskEntry->EndSector.QuadPart + 1)
1024 {
1025 LastUnusedSectorCount = AlignDown(DiskEntry->EndSector.QuadPart + 1 - (LastStartSector + LastSectorCount), DiskEntry->SectorAlignment);
1026
1027 if (LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment)
1028 {
1029 DPRINT("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount);
1030
1031 NewPartEntry = RtlAllocateHeap(RtlGetProcessHeap(),
1033 sizeof(PARTENTRY));
1034 if (NewPartEntry == NULL)
1035 return;
1036
1037 NewPartEntry->DiskEntry = DiskEntry;
1038
1039 NewPartEntry->IsPartitioned = FALSE;
1040 NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount;
1041 NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + LastUnusedSectorCount, DiskEntry->SectorAlignment) -
1042 NewPartEntry->StartSector.QuadPart;
1043
1044 DPRINT("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
1045 DPRINT("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
1046 DPRINT("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
1047
1048 NewPartEntry->FormatState = Unformatted;
1049
1050 /* Append the table to the list */
1052 &NewPartEntry->ListEntry);
1053 }
1054 }
1055
1056#ifdef DUMP_PARTITION_LIST
1057 DumpPartitionList(DiskEntry);
1058#endif
1059
1060 DPRINT("ScanForUnpartitionedGptDiskSpace() done\n");
1061}
1062
1063
1064VOID
1067 _In_ PDISKENTRY DiskEntry)
1068{
1069 ULONG LayoutBufferSize;
1070 PDRIVE_LAYOUT_INFORMATION_EX NewLayoutBuffer;
1073
1074 /* Allocate a layout buffer with 4 partition entries first */
1075 LayoutBufferSize = sizeof(DRIVE_LAYOUT_INFORMATION_EX) +
1076 ((4 - ANYSIZE_ARRAY) * sizeof(PARTITION_INFORMATION_EX));
1077 DiskEntry->LayoutBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
1079 LayoutBufferSize);
1080 if (DiskEntry->LayoutBuffer == NULL)
1081 {
1082 DPRINT1("Failed to allocate the disk layout buffer!\n");
1083 return;
1084 }
1085
1086 for (;;)
1087 {
1088 DPRINT("Buffer size: %lu\n", LayoutBufferSize);
1090 NULL,
1091 NULL,
1092 NULL,
1093 &Iosb,
1095 NULL,
1096 0,
1097 DiskEntry->LayoutBuffer,
1098 LayoutBufferSize);
1099 if (NT_SUCCESS(Status))
1100 break;
1101
1103 {
1104 DPRINT1("NtDeviceIoControlFile() failed (Status: 0x%08lx)\n", Status);
1105 return;
1106 }
1107
1108 LayoutBufferSize += 4 * sizeof(PARTITION_INFORMATION_EX);
1109 NewLayoutBuffer = RtlReAllocateHeap(RtlGetProcessHeap(),
1111 DiskEntry->LayoutBuffer,
1112 LayoutBufferSize);
1113 if (NewLayoutBuffer == NULL)
1114 {
1115 DPRINT1("Failed to reallocate the disk layout buffer!\n");
1116 return;
1117 }
1118
1119 DiskEntry->LayoutBuffer = NewLayoutBuffer;
1120 }
1121}
1122
1123
1124static
1125VOID
1128 ULONG DiskNumber)
1129{
1130 DISK_GEOMETRY DiskGeometry;
1131 SCSI_ADDRESS ScsiAddress;
1132 PDISKENTRY DiskEntry;
1136 PULONG Buffer;
1138 WCHAR Identifier[20];
1139 ULONG Checksum;
1141 ULONG i;
1142 PLIST_ENTRY ListEntry;
1143 PBIOSDISKENTRY BiosDiskEntry;
1144
1146 NULL,
1147 NULL,
1148 NULL,
1149 &Iosb,
1151 NULL,
1152 0,
1153 &DiskGeometry,
1154 sizeof(DISK_GEOMETRY));
1155 if (!NT_SUCCESS(Status))
1156 {
1157 return;
1158 }
1159
1160 if (DiskGeometry.MediaType != FixedMedia &&
1161 DiskGeometry.MediaType != RemovableMedia)
1162 {
1163 return;
1164 }
1165
1167 NULL,
1168 NULL,
1169 NULL,
1170 &Iosb,
1172 NULL,
1173 0,
1174 &ScsiAddress,
1175 sizeof(SCSI_ADDRESS));
1176 if (!NT_SUCCESS(Status))
1177 {
1178 return;
1179 }
1180
1181 PBYTE pBuffer = NULL;
1182
1183 pBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
1185 1024);
1186
1187 STORAGE_PROPERTY_QUERY StoragePropertyQuery;
1188 StoragePropertyQuery.PropertyId = StorageDeviceProperty;
1189 StoragePropertyQuery.QueryType = PropertyStandardQuery;
1191 NULL,
1192 NULL,
1193 NULL,
1194 &Iosb,
1196 &StoragePropertyQuery,
1197 sizeof(STORAGE_PROPERTY_QUERY),
1198 pBuffer,
1199 1024);
1200 if (!NT_SUCCESS(Status))
1201 {
1202 RtlFreeHeap(RtlGetProcessHeap(), 0, pBuffer);
1203 pBuffer = NULL;
1204 }
1205
1206
1207 Mbr = (PARTITION_SECTOR*)RtlAllocateHeap(RtlGetProcessHeap(),
1208 0,
1209 DiskGeometry.BytesPerSector);
1210 if (Mbr == NULL)
1211 {
1212 return;
1213 }
1214
1215 FileOffset.QuadPart = 0;
1217 NULL,
1218 NULL,
1219 NULL,
1220 &Iosb,
1221 (PVOID)Mbr,
1222 DiskGeometry.BytesPerSector,
1223 &FileOffset,
1224 NULL);
1225 if (!NT_SUCCESS(Status))
1226 {
1227 RtlFreeHeap(RtlGetProcessHeap(), 0, Mbr);
1228 DPRINT1("NtReadFile failed, status=%x\n", Status);
1229 return;
1230 }
1231 Signature = Mbr->Signature;
1232
1233 /* Calculate the MBR checksum */
1234 Checksum = 0;
1235 Buffer = (PULONG)Mbr;
1236 for (i = 0; i < 128; i++)
1237 {
1238 Checksum += Buffer[i];
1239 }
1240 Checksum = ~Checksum + 1;
1241
1243 L"%08x-%08x-A", Checksum, Signature);
1244 DPRINT("Identifier: %S\n", Identifier);
1245
1246 DiskEntry = RtlAllocateHeap(RtlGetProcessHeap(),
1248 sizeof(DISKENTRY));
1249 if (DiskEntry == NULL)
1250 {
1251 if (pBuffer)
1252 RtlFreeHeap(RtlGetProcessHeap(), 0, pBuffer);
1253 RtlFreeHeap(RtlGetProcessHeap(), 0, Mbr);
1254 return;
1255 }
1256
1257 if (pBuffer)
1258 {
1259 PSTORAGE_DESCRIPTOR_HEADER pDescriptorHeader;
1260
1261 pDescriptorHeader = (PSTORAGE_DESCRIPTOR_HEADER)pBuffer;
1262 DPRINT("DescriptorHeader.Size %lu\n", pDescriptorHeader->Size);
1263
1264 if (pDescriptorHeader->Size <= 1024)
1265 {
1266 PSTORAGE_DEVICE_DESCRIPTOR pDeviceDescriptor;
1267 pDeviceDescriptor = (PSTORAGE_DEVICE_DESCRIPTOR)pBuffer;
1268 DPRINT("VendorIdOffset %lu\n", pDeviceDescriptor->VendorIdOffset);
1269 DPRINT("ProductIdOffset %lu\n", pDeviceDescriptor->ProductIdOffset);
1270 DPRINT("ProductRevisionOffset %lu\n", pDeviceDescriptor->ProductRevisionOffset);
1271 DPRINT("SerialNumberOffset %lu\n", pDeviceDescriptor->SerialNumberOffset);
1272 DPRINT("BusType: %u\n", pDeviceDescriptor->BusType);
1273 if (pDeviceDescriptor->VendorIdOffset)
1274 {
1275 DPRINT("Vendor: %s\n", (PSTR)((ULONG_PTR)pBuffer + pDeviceDescriptor->VendorIdOffset));
1276 }
1277
1278 if (pDeviceDescriptor->ProductIdOffset)
1279 {
1280 DPRINT("Product: %s\n", (PSTR)((ULONG_PTR)pBuffer + pDeviceDescriptor->ProductIdOffset));
1281 }
1282
1283 INT VendorLength = 0, ProductLength = 0;
1284 PWSTR VendorBuffer = NULL, ProductBuffer = NULL;
1285
1286 if (pDeviceDescriptor->VendorIdOffset)
1287 {
1288 VendorLength = MultiByteToWideChar(437,
1289 0,
1290 (PSTR)((ULONG_PTR)pBuffer + pDeviceDescriptor->VendorIdOffset),
1291 -1,
1292 NULL,
1293 0);
1294 VendorBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
1296 VendorLength * sizeof(WCHAR));
1297 if (VendorBuffer)
1299 0,
1300 (PSTR)((ULONG_PTR)pBuffer + pDeviceDescriptor->VendorIdOffset),
1301 -1,
1302 VendorBuffer,
1303 VendorLength);
1304 }
1305
1306 if (pDeviceDescriptor->ProductIdOffset)
1307 {
1308 ProductLength = MultiByteToWideChar(437,
1309 0,
1310 (PSTR)((ULONG_PTR)pBuffer + pDeviceDescriptor->ProductIdOffset),
1311 -1,
1312 NULL,
1313 0);
1314
1315 ProductBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
1317 ProductLength * sizeof(WCHAR));
1318 if (ProductBuffer)
1320 0,
1321 (PSTR)((ULONG_PTR)pBuffer + pDeviceDescriptor->ProductIdOffset),
1322 -1,
1323 ProductBuffer,
1324 ProductLength);
1325 }
1326
1327 DiskEntry->Description = RtlAllocateHeap(RtlGetProcessHeap(),
1329 (VendorLength + ProductLength + 2) * sizeof(WCHAR));
1330 if (VendorBuffer)
1331 wcscat(DiskEntry->Description, VendorBuffer);
1332
1333 if ((VendorLength > 0) && (ProductLength > 0))
1334 wcscat(DiskEntry->Description, L" ");
1335
1336 if (ProductBuffer)
1337 wcscat(DiskEntry->Description, ProductBuffer);
1338
1339 DiskEntry->BusType = pDeviceDescriptor->BusType;
1340
1341 if (VendorBuffer)
1342 RtlFreeHeap(RtlGetProcessHeap(), 0, VendorBuffer);
1343
1344 if (ProductBuffer)
1345 RtlFreeHeap(RtlGetProcessHeap(), 0, ProductBuffer);
1346 }
1347
1348 RtlFreeHeap(RtlGetProcessHeap(), 0, pBuffer);
1349 }
1350
1351// DiskEntry->Checksum = Checksum;
1352// DiskEntry->Signature = Signature;
1353 DiskEntry->BiosFound = FALSE;
1354
1355 /* Check the disk partition style */
1356 if (Mbr->Magic != MBR_MAGIC)
1357 {
1358 DPRINT("Partition style: RAW\n");
1359 DiskEntry->PartitionStyle = PARTITION_STYLE_RAW;
1360 }
1361 else
1362 {
1363 if (Mbr->Partition[0].PartitionType == PARTITION_GPT)
1364 {
1365 DPRINT("Partition style: GPT\n");
1367 }
1368 else
1369 {
1370 DPRINT("Partition style: MBR\n");
1372 }
1373 }
1374
1375 /* Free Mbr sector buffer */
1376 RtlFreeHeap(RtlGetProcessHeap(), 0, Mbr);
1377
1378 ListEntry = BiosDiskListHead.Flink;
1379 while (ListEntry != &BiosDiskListHead)
1380 {
1381 BiosDiskEntry = CONTAINING_RECORD(ListEntry, BIOSDISKENTRY, ListEntry);
1382 /* FIXME:
1383 * Compare the size from bios and the reported size from driver.
1384 * If we have more than one disk with a zero or with the same signatur
1385 * we must create new signatures and reboot. After the reboot,
1386 * it is possible to identify the disks.
1387 */
1388 if (BiosDiskEntry->Signature == Signature &&
1389 BiosDiskEntry->Checksum == Checksum &&
1390 !BiosDiskEntry->Recognized)
1391 {
1392 if (!DiskEntry->BiosFound)
1393 {
1394 DiskEntry->BiosDiskNumber = BiosDiskEntry->DiskNumber;
1395 DiskEntry->BiosFound = TRUE;
1396 BiosDiskEntry->Recognized = TRUE;
1397 }
1398 else
1399 {
1400 }
1401 }
1402 ListEntry = ListEntry->Flink;
1403 }
1404
1405 if (!DiskEntry->BiosFound)
1406 {
1407#if 0
1408 RtlFreeHeap(ProcessHeap, 0, DiskEntry);
1409 return;
1410#else
1411 DPRINT1("WARNING: Setup could not find a matching BIOS disk entry. Disk %d is not be bootable by the BIOS!\n", DiskNumber);
1412#endif
1413 }
1414
1417
1418 DiskEntry->Cylinders = DiskGeometry.Cylinders.QuadPart;
1419 DiskEntry->TracksPerCylinder = DiskGeometry.TracksPerCylinder;
1420 DiskEntry->SectorsPerTrack = DiskGeometry.SectorsPerTrack;
1421 DiskEntry->BytesPerSector = DiskGeometry.BytesPerSector;
1422
1423 DPRINT("Cylinders %I64u\n", DiskEntry->Cylinders);
1424 DPRINT("TracksPerCylinder %I64u\n", DiskEntry->TracksPerCylinder);
1425 DPRINT("SectorsPerTrack %I64u\n", DiskEntry->SectorsPerTrack);
1426 DPRINT("BytesPerSector %I64u\n", DiskEntry->BytesPerSector);
1427
1428 DiskEntry->SectorCount.QuadPart = DiskGeometry.Cylinders.QuadPart *
1429 (ULONGLONG)DiskGeometry.TracksPerCylinder *
1430 (ULONGLONG)DiskGeometry.SectorsPerTrack;
1431
1432// DiskEntry->SectorAlignment = DiskGeometry.SectorsPerTrack;
1433// DiskEntry->CylinderAlignment = DiskGeometry.SectorsPerTrack * DiskGeometry.TracksPerCylinder;
1434 DiskEntry->SectorAlignment = (1024 * 1024) / DiskGeometry.BytesPerSector;
1435 DiskEntry->CylinderAlignment = (1024 * 1024) / DiskGeometry.BytesPerSector;
1436
1437 DPRINT("SectorCount: %I64u\n", DiskEntry->SectorCount);
1438 DPRINT("SectorAlignment: %lu\n", DiskEntry->SectorAlignment);
1439 DPRINT("CylinderAlignment: %lu\n", DiskEntry->CylinderAlignment);
1440
1441 DiskEntry->DiskNumber = DiskNumber;
1442 DiskEntry->Port = ScsiAddress.PortNumber;
1443 DiskEntry->PathId = ScsiAddress.PathId;
1444 DiskEntry->TargetId = ScsiAddress.TargetId;
1445 DiskEntry->Lun = ScsiAddress.Lun;
1446
1447 GetDriverName(DiskEntry);
1448
1449 InsertAscendingList(&DiskListHead, DiskEntry, DISKENTRY, ListEntry, DiskNumber);
1450
1451 ReadLayoutBuffer(FileHandle, DiskEntry);
1452
1453 DPRINT("PartitionCount: %lu\n", DiskEntry->LayoutBuffer->PartitionCount);
1454
1455#ifdef DUMP_PARTITION_TABLE
1456 DumpPartitionTable(DiskEntry);
1457#endif
1458
1459 if (DiskEntry->PartitionStyle == PARTITION_STYLE_MBR)
1460 {
1461 if (DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart != 0 &&
1463 DiskEntry->LayoutBuffer->PartitionEntry[0].Mbr.PartitionType != 0)
1464 {
1465 if ((DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart / DiskEntry->BytesPerSector) % DiskEntry->SectorsPerTrack == 0)
1466 {
1467 DPRINT("Use %lu Sector alignment!\n", DiskEntry->SectorsPerTrack);
1468 }
1469 else if (DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart % (1024 * 1024) == 0)
1470 {
1471 DPRINT1("Use megabyte (%lu Sectors) alignment!\n", (1024 * 1024) / DiskEntry->BytesPerSector);
1472 }
1473 else
1474 {
1475 DPRINT1("No matching alignment found! Partition 1 starts at %I64u\n", DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart);
1476 }
1477 }
1478 else
1479 {
1480 DPRINT1("No valid partition table found! Use megabyte (%lu Sectors) alignment!\n", (1024 * 1024) / DiskEntry->BytesPerSector);
1481 }
1482
1483 /* Calculate the number of usable sectors */
1484 /* Limit the number of usable sectors to 2^32 */
1485 DiskEntry->StartSector.QuadPart = (ULONGLONG)DiskEntry->SectorAlignment;
1486 DiskEntry->EndSector.QuadPart = min(DiskEntry->SectorCount.QuadPart, 0x100000000) - 1;
1487
1488 if (DiskEntry->LayoutBuffer->PartitionCount == 0)
1489 {
1490 DiskEntry->NewDisk = TRUE;
1491 DiskEntry->LayoutBuffer->PartitionCount = 4;
1492
1493 for (i = 0; i < 4; i++)
1495 }
1496 else
1497 {
1498 for (i = 0; i < 4; i++)
1499 {
1500 AddMbrPartitionToDisk(DiskNumber, DiskEntry, i, FALSE);
1501 }
1502
1503 for (i = 4; i < DiskEntry->LayoutBuffer->PartitionCount; i += 4)
1504 {
1505 AddMbrPartitionToDisk(DiskNumber, DiskEntry, i, TRUE);
1506 }
1507 }
1508
1510 }
1511 else if (DiskEntry->PartitionStyle == PARTITION_STYLE_GPT)
1512 {
1513 /* Calculate the number of usable sectors */
1514 DiskEntry->StartSector.QuadPart = AlignDown(DiskEntry->LayoutBuffer->Gpt.StartingUsableOffset.QuadPart / DiskEntry->BytesPerSector,
1515 DiskEntry->SectorAlignment) + (ULONGLONG)DiskEntry->SectorAlignment;
1516 DiskEntry->EndSector.QuadPart = AlignDown(DiskEntry->StartSector.QuadPart + (DiskEntry->LayoutBuffer->Gpt.UsableLength.QuadPart / DiskEntry->BytesPerSector) - 1,
1517 DiskEntry->SectorAlignment);
1518
1519 if (DiskEntry->LayoutBuffer->PartitionCount == 0)
1520 {
1521 DiskEntry->NewDisk = TRUE;
1522 }
1523 else
1524 {
1525 for (i = 0; i < DiskEntry->LayoutBuffer->PartitionCount; i++)
1526 {
1527 AddGptPartitionToDisk(DiskNumber, DiskEntry, i);
1528 }
1529 }
1530
1532 }
1533}
1534
1535
1538{
1542 ULONG ReturnSize;
1544 ULONG DiskNumber;
1548
1549 CurrentDisk = NULL;
1551
1552// BootDisk = NULL;
1553// BootPartition = NULL;
1554
1555// TempDisk = NULL;
1556// TempPartition = NULL;
1557// FormatState = Start;
1558
1561
1563
1565 &Sdi,
1567 &ReturnSize);
1568 if (!NT_SUCCESS(Status))
1569 {
1570 return Status;
1571 }
1572
1573 for (DiskNumber = 0; DiskNumber < Sdi.NumberOfDisks; DiskNumber++)
1574 {
1576 L"\\Device\\Harddisk%d\\Partition0",
1577 DiskNumber);
1578
1580 Buffer);
1581
1583 &Name,
1584 0,
1585 NULL,
1586 NULL);
1587
1591 &Iosb,
1594 if (NT_SUCCESS(Status))
1595 {
1596 AddDiskToList(FileHandle, DiskNumber);
1597
1599 }
1600 }
1601
1602// UpdateDiskSignatures(List);
1603
1604// AssignDriveLetters(List);
1605
1606 return STATUS_SUCCESS;
1607}
1608
1609
1610VOID
1612{
1613 PDISKENTRY DiskEntry;
1614 PBIOSDISKENTRY BiosDiskEntry;
1615 PPARTENTRY PartEntry;
1617
1618 CurrentDisk = NULL;
1620
1621 /* Release disk and partition info */
1622 while (!IsListEmpty(&DiskListHead))
1623 {
1625 DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
1626
1627 /* Release driver name */
1628 RtlFreeUnicodeString(&DiskEntry->DriverName);
1629
1630 /* Release primary partition list */
1631 while (!IsListEmpty(&DiskEntry->PrimaryPartListHead))
1632 {
1634 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
1635
1636 RtlFreeHeap(RtlGetProcessHeap(), 0, PartEntry);
1637 }
1638
1639 /* Release logical partition list */
1640 while (!IsListEmpty(&DiskEntry->LogicalPartListHead))
1641 {
1643 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
1644
1645 RtlFreeHeap(RtlGetProcessHeap(), 0, PartEntry);
1646 }
1647
1648 /* Release layout buffer */
1649 if (DiskEntry->LayoutBuffer != NULL)
1650 RtlFreeHeap(RtlGetProcessHeap(), 0, DiskEntry->LayoutBuffer);
1651
1652 if (DiskEntry->Description != NULL)
1653 RtlFreeHeap(RtlGetProcessHeap(), 0, DiskEntry->Description);
1654
1655 if (DiskEntry->Location != NULL)
1656 RtlFreeHeap(RtlGetProcessHeap(), 0, DiskEntry->Location);
1657
1658 /* Release disk entry */
1659 RtlFreeHeap(RtlGetProcessHeap(), 0, DiskEntry);
1660 }
1661
1662 /* Release the bios disk info */
1663 while (!IsListEmpty(&BiosDiskListHead))
1664 {
1666 BiosDiskEntry = CONTAINING_RECORD(Entry, BIOSDISKENTRY, ListEntry);
1667
1668 RtlFreeHeap(RtlGetProcessHeap(), 0, BiosDiskEntry);
1669 }
1670}
1671
1672
1673static
1674VOID
1677 _In_ PVOLENTRY VolumeEntry)
1678{
1679 DWORD dwBytesReturned = 0, dwLength, i;
1680 PVOLUME_DISK_EXTENTS pExtents;
1681 BOOL bResult;
1682 DWORD dwError;
1683
1684 dwLength = sizeof(VOLUME_DISK_EXTENTS);
1685 pExtents = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, dwLength);
1686 if (pExtents == NULL)
1687 return;
1688
1689 bResult = DeviceIoControl(VolumeHandle,
1691 NULL,
1692 0,
1693 pExtents,
1694 dwLength,
1695 &dwBytesReturned,
1696 NULL);
1697 if (!bResult)
1698 {
1699 dwError = GetLastError();
1700
1701 if (dwError != ERROR_MORE_DATA)
1702 {
1703 RtlFreeHeap(RtlGetProcessHeap(), 0, pExtents);
1704 return;
1705 }
1706 else
1707 {
1708 dwLength = sizeof(VOLUME_DISK_EXTENTS) + ((pExtents->NumberOfDiskExtents - 1) * sizeof(DISK_EXTENT));
1709 RtlFreeHeap(RtlGetProcessHeap(), 0, pExtents);
1710 pExtents = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, dwLength);
1711 if (pExtents == NULL)
1712 {
1713 return;
1714 }
1715
1716 bResult = DeviceIoControl(VolumeHandle,
1718 NULL,
1719 0,
1720 pExtents,
1721 dwLength,
1722 &dwBytesReturned,
1723 NULL);
1724 if (!bResult)
1725 {
1726 RtlFreeHeap(RtlGetProcessHeap(), 0, pExtents);
1727 return;
1728 }
1729 }
1730 }
1731
1732 for (i = 0; i < pExtents->NumberOfDiskExtents; i++)
1733 VolumeEntry->Size.QuadPart += pExtents->Extents[i].ExtentLength.QuadPart;
1734
1735 VolumeEntry->pExtents = pExtents;
1736}
1737
1738
1739static
1740VOID
1743 _In_ PVOLENTRY VolumeEntry)
1744{
1748
1751 &DeviceInfo,
1754 if (!NT_SUCCESS(Status))
1755 return;
1756
1757 switch (DeviceInfo.DeviceType)
1758 {
1759 case FILE_DEVICE_CD_ROM:
1761 VolumeEntry->VolumeType = VOLUME_TYPE_CDROM;
1762 break;
1763
1764 case FILE_DEVICE_DISK:
1766 if (DeviceInfo.Characteristics & FILE_REMOVABLE_MEDIA)
1767 VolumeEntry->VolumeType = VOLUME_TYPE_REMOVABLE;
1768 else
1769 VolumeEntry->VolumeType = VOLUME_TYPE_PARTITION;
1770 break;
1771
1772 default:
1773 VolumeEntry->VolumeType = VOLUME_TYPE_UNKNOWN;
1774 break;
1775 }
1776}
1777
1778
1779static
1780VOID
1783 _In_ PVOLENTRY VolumeEntry)
1784{
1786 FILE_FS_FULL_SIZE_INFORMATION FullSizeInfo;
1789
1790 ZeroMemory(&FullSizeInfo, sizeof(FullSizeInfo));
1793 &FullSizeInfo,
1796 if (NT_SUCCESS(Status))
1797 {
1798 DPRINT("FullSizeInfo.TotalAllocationUnits %I64u\n", FullSizeInfo.TotalAllocationUnits.QuadPart);
1799 DPRINT("FullSizeInfo.SectorsPerAllocationUnit %lu\n", FullSizeInfo.SectorsPerAllocationUnit);
1800 DPRINT("FullSizeInfo.BytesPerSector %lu\n", FullSizeInfo.BytesPerSector);
1801
1802 VolumeEntry->TotalAllocationUnits.QuadPart = FullSizeInfo.TotalAllocationUnits.QuadPart;
1803 VolumeEntry->SectorsPerAllocationUnit = FullSizeInfo.SectorsPerAllocationUnit;
1804 VolumeEntry->BytesPerSector = FullSizeInfo.BytesPerSector;
1805 }
1806 else
1807 {
1808 ZeroMemory(&SizeInfo, sizeof(SizeInfo));
1811 &SizeInfo,
1814 if (NT_SUCCESS(Status))
1815 {
1816 DPRINT("SizeInfo.TotalAllocationUnits %I64u\n", SizeInfo.TotalAllocationUnits.QuadPart);
1817 DPRINT("SizeInfo.SectorsPerAllocationUnit %lu\n", SizeInfo.SectorsPerAllocationUnit);
1818 DPRINT("SizeInfo.BytesPerSector %lu\n", SizeInfo.BytesPerSector);
1819
1820 VolumeEntry->TotalAllocationUnits.QuadPart = SizeInfo.TotalAllocationUnits.QuadPart;
1821 VolumeEntry->SectorsPerAllocationUnit = SizeInfo.SectorsPerAllocationUnit;
1822 VolumeEntry->BytesPerSector = SizeInfo.BytesPerSector;
1823 }
1824 else
1825 {
1826 DPRINT("GetVolumeSize() failed!\n");
1827 }
1828 }
1829}
1830
1831
1832static
1835 _In_ PVOLENTRY VolumeEntry)
1836{
1838 PDISKENTRY DiskEntry;
1839 INT i;
1840
1841 DPRINT("GetDiskFromVolume(%p)\n", VolumeEntry);
1842
1843 DPRINT("Extents: %p\n", VolumeEntry->pExtents);
1844 if (VolumeEntry->pExtents == NULL)
1845 return NULL;
1846
1847 DPRINT("Extents: %lu\n", VolumeEntry->pExtents->NumberOfDiskExtents);
1848
1850 while (Entry != &DiskListHead)
1851 {
1852 DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
1853
1854 for (i = 0; i < VolumeEntry->pExtents->NumberOfDiskExtents; i++)
1855 {
1856 DPRINT("DiskNumber: %lu -- %lu\n", VolumeEntry->pExtents->Extents[i].DiskNumber, DiskEntry->DiskNumber);
1857 if (VolumeEntry->pExtents->Extents[i].DiskNumber == DiskEntry->DiskNumber)
1858 return DiskEntry;
1859 }
1860
1861 Entry = Entry->Flink;
1862 }
1863
1864 return NULL;
1865}
1866
1867
1868static
1871 _In_ PVOLENTRY VolumeEntry)
1872{
1873 PLIST_ENTRY Entry1, Entry2;
1874 PDISKENTRY DiskEntry;
1875 PPARTENTRY PartEntry;
1876 INT i;
1877
1878 DPRINT("GetPartitionFromVolume(%p)\n", VolumeEntry);
1879
1880 DPRINT("Extents: %p\n", VolumeEntry->pExtents);
1881 if (VolumeEntry->pExtents == NULL)
1882 return NULL;
1883
1884 DPRINT("Extents: %lu\n", VolumeEntry->pExtents->NumberOfDiskExtents);
1885
1886 Entry1 = DiskListHead.Flink;
1887 while (Entry1 != &DiskListHead)
1888 {
1889 DiskEntry = CONTAINING_RECORD(Entry1, DISKENTRY, ListEntry);
1890
1891 for (i = 0; i < VolumeEntry->pExtents->NumberOfDiskExtents; i++)
1892 {
1893 DPRINT("DiskNumber: %lu -- %lu\n", VolumeEntry->pExtents->Extents[i].DiskNumber, DiskEntry->DiskNumber);
1894 if (VolumeEntry->pExtents->Extents[i].DiskNumber == DiskEntry->DiskNumber)
1895 {
1896
1897 Entry2 = DiskEntry->PrimaryPartListHead.Flink;
1898 while (Entry2 != &DiskEntry->PrimaryPartListHead)
1899 {
1900 PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
1901
1902 if ((VolumeEntry->pExtents->Extents[i].StartingOffset.QuadPart == PartEntry->StartSector.QuadPart * PartEntry->DiskEntry->BytesPerSector) &&
1903 (VolumeEntry->pExtents->Extents[i].ExtentLength.QuadPart == PartEntry->SectorCount.QuadPart * PartEntry->DiskEntry->BytesPerSector))
1904 return PartEntry;
1905
1906 Entry2 = Entry2->Flink;
1907 }
1908
1909 Entry2 = DiskEntry->LogicalPartListHead.Flink;
1910 while (Entry2 != &DiskEntry->LogicalPartListHead)
1911 {
1912 PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
1913
1914 if ((VolumeEntry->pExtents->Extents[i].StartingOffset.QuadPart == PartEntry->StartSector.QuadPart * PartEntry->DiskEntry->BytesPerSector) &&
1915 (VolumeEntry->pExtents->Extents[i].ExtentLength.QuadPart == PartEntry->SectorCount.QuadPart * PartEntry->DiskEntry->BytesPerSector))
1916 return PartEntry;
1917
1918 Entry2 = Entry2->Flink;
1919 }
1920 }
1921 }
1922
1923 Entry1 = Entry1->Flink;
1924 }
1925
1926 return NULL;
1927}
1928
1929
1930static
1931VOID
1933 _In_ PVOLENTRY VolumeEntry)
1934{
1935 WCHAR szSystemPartition[MAX_PATH];
1936 PPARTENTRY PartEntry;
1937 HKEY hKey;
1938 DWORD dwError, dwLength;
1939
1940 DPRINT("IsVolumeSystem()\n");
1941
1942 VolumeEntry->IsSystem = FALSE;
1943
1945 L"SYSTEM\\Setup",
1946 0,
1947 KEY_READ,
1948 &hKey);
1949 if (dwError != ERROR_SUCCESS)
1950 {
1951 DPRINT1("\n");
1952 return;
1953 }
1954
1955 dwLength = sizeof(szSystemPartition);
1956 dwError = RegQueryValueExW(hKey,
1957 L"SystemPartition",
1958 NULL,
1959 NULL,
1960 (PBYTE)szSystemPartition,
1961 &dwLength);
1963
1964 if (dwError != ERROR_SUCCESS)
1965 {
1966 DPRINT1("\n");
1967 return;
1968 }
1969
1970 DPRINT("SystemPartition: %S\n", szSystemPartition);
1971 DPRINT("DeviceName: %S\n", VolumeEntry->DeviceName);
1972
1973 if (_wcsnicmp(szSystemPartition, VolumeEntry->DeviceName, wcslen(szSystemPartition)) == 0)
1974 {
1975 VolumeEntry->IsSystem = TRUE;
1976
1977 PartEntry = GetPartitionForVolume(VolumeEntry);
1978 if (PartEntry)
1979 PartEntry->IsSystem = TRUE;
1980 }
1981}
1982
1983
1984static
1985VOID
1987 _In_ PVOLENTRY VolumeEntry)
1988{
1989 WCHAR szSystemDir[MAX_PATH];
1990 PDISKENTRY DiskEntry;
1991 PPARTENTRY PartEntry;
1992
1993 DPRINT("IsVolumeBoot()\n");
1994
1995 VolumeEntry->IsBoot = FALSE;
1996
1997 if (VolumeEntry->DriveLetter == UNICODE_NULL)
1998 return;
1999
2000 GetSystemDirectoryW(szSystemDir,
2001 ARRAYSIZE(szSystemDir));
2002
2003 DPRINT("SystemDirectory: %S\n", szSystemDir);
2004 DPRINT("DriveLetter: %C\n", VolumeEntry->DriveLetter);
2005
2006 if (szSystemDir[0] == VolumeEntry->DriveLetter)
2007 {
2008 VolumeEntry->IsBoot = TRUE;
2009
2010 PartEntry = GetPartitionForVolume(VolumeEntry);
2011 if (PartEntry)
2012 PartEntry->IsBoot = TRUE;
2013
2014 DiskEntry = GetDiskForVolume(VolumeEntry);
2015 if (DiskEntry)
2016 DiskEntry->IsBoot = TRUE;
2017 }
2018}
2019
2020
2021static
2022VOID
2024 ULONG ulVolumeNumber,
2025 PWSTR pszVolumeName)
2026{
2027 PVOLENTRY VolumeEntry;
2029
2030 DWORD dwError, dwLength;
2031 WCHAR szPathNames[MAX_PATH + 1];
2032 WCHAR szVolumeName[MAX_PATH + 1];
2033 WCHAR szFilesystem[MAX_PATH + 1];
2034
2035 DWORD CharCount = 0;
2036 size_t Index = 0;
2037
2042
2043 DPRINT("AddVolumeToList(%S)\n", pszVolumeName);
2044
2045 VolumeEntry = RtlAllocateHeap(RtlGetProcessHeap(),
2047 sizeof(VOLENTRY));
2048 if (VolumeEntry == NULL)
2049 return;
2050
2051 VolumeEntry->VolumeNumber = ulVolumeNumber;
2052 wcscpy(VolumeEntry->VolumeName, pszVolumeName);
2053
2054 Index = wcslen(pszVolumeName) - 1;
2055
2056 pszVolumeName[Index] = L'\0';
2057
2058 CharCount = QueryDosDeviceW(&pszVolumeName[4], VolumeEntry->DeviceName, ARRAYSIZE(VolumeEntry->DeviceName));
2059
2060 pszVolumeName[Index] = L'\\';
2061
2062 if (CharCount == 0)
2063 {
2064 RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeEntry);
2065 return;
2066 }
2067
2068 DPRINT("DeviceName: %S\n", VolumeEntry->DeviceName);
2069
2070 RtlInitUnicodeString(&Name, VolumeEntry->DeviceName);
2071
2073 &Name,
2074 0,
2075 NULL,
2076 NULL);
2077
2081 &Iosb,
2082 0,
2084 if (NT_SUCCESS(Status))
2085 {
2086 GetVolumeType(VolumeHandle, VolumeEntry);
2087 GetVolumeExtents(VolumeHandle, VolumeEntry);
2088 GetVolumeSize(VolumeHandle, VolumeEntry);
2090 }
2091
2092 if (GetVolumeInformationW(pszVolumeName,
2093 szVolumeName,
2094 MAX_PATH + 1,
2095 &VolumeEntry->SerialNumber,
2096 NULL,
2097 NULL,
2098 szFilesystem,
2099 MAX_PATH + 1))
2100 {
2101 VolumeEntry->pszLabel = RtlAllocateHeap(RtlGetProcessHeap(),
2102 0,
2103 (wcslen(szVolumeName) + 1) * sizeof(WCHAR));
2104 if (VolumeEntry->pszLabel)
2105 wcscpy(VolumeEntry->pszLabel, szVolumeName);
2106
2107 VolumeEntry->pszFilesystem = RtlAllocateHeap(RtlGetProcessHeap(),
2108 0,
2109 (wcslen(szFilesystem) + 1) * sizeof(WCHAR));
2110 if (VolumeEntry->pszFilesystem)
2111 wcscpy(VolumeEntry->pszFilesystem, szFilesystem);
2112 }
2113 else
2114 {
2115 dwError = GetLastError();
2116 if (dwError == ERROR_UNRECOGNIZED_VOLUME)
2117 {
2118 VolumeEntry->pszFilesystem = RtlAllocateHeap(RtlGetProcessHeap(),
2119 0,
2120 (3 + 1) * sizeof(WCHAR));
2121 if (VolumeEntry->pszFilesystem)
2122 wcscpy(VolumeEntry->pszFilesystem, L"RAW");
2123 VolumeEntry->SerialNumber = 0;
2124 VolumeEntry->SectorsPerAllocationUnit = 1;
2125 VolumeEntry->BytesPerSector = 512;
2126 VolumeEntry->VolumeType = VOLUME_TYPE_PARTITION;
2127 }
2128 }
2129
2130 if (GetVolumePathNamesForVolumeNameW(pszVolumeName,
2131 szPathNames,
2132 ARRAYSIZE(szPathNames),
2133 &dwLength))
2134 {
2135 INT nPathLength;
2136 PWSTR pszPath = szPathNames;
2137 while (*pszPath != UNICODE_NULL)
2138 {
2139 DPRINT("PathName: %S\n", pszPath);
2140 nPathLength = wcslen(pszPath);
2141 if ((nPathLength == 3) && (iswalpha(pszPath[0])) &&
2142 (pszPath[1] == L':') && (pszPath[2] == L'\\'))
2143 VolumeEntry->DriveLetter = pszPath[0];
2144
2145 pszPath += (nPathLength + 1);
2146 }
2147 }
2148
2149 IsVolumeSystem(VolumeEntry);
2150 IsVolumeBoot(VolumeEntry);
2151
2153 &VolumeEntry->ListEntry);
2154}
2155
2156
2159{
2160 HANDLE hVolume = INVALID_HANDLE_VALUE;
2161 WCHAR szVolumeName[MAX_PATH];
2162 ULONG ulVolumeNumber = 0;
2163 BOOL Success;
2164
2166
2168
2169 hVolume = FindFirstVolumeW(szVolumeName, ARRAYSIZE(szVolumeName));
2170 if (hVolume == INVALID_HANDLE_VALUE)
2171 {
2172
2173 return STATUS_UNSUCCESSFUL;
2174 }
2175
2176 AddVolumeToList(ulVolumeNumber++, szVolumeName);
2177
2178 for (;;)
2179 {
2180 Success = FindNextVolumeW(hVolume, szVolumeName, ARRAYSIZE(szVolumeName));
2181 if (!Success)
2182 {
2183 break;
2184 }
2185
2186 AddVolumeToList(ulVolumeNumber++, szVolumeName);
2187 }
2188
2189 FindVolumeClose(hVolume);
2190
2191 return STATUS_SUCCESS;
2192}
2193
2194
2195VOID
2197{
2199 PVOLENTRY VolumeEntry;
2200
2202
2203 /* Release disk and partition info */
2204 while (!IsListEmpty(&VolumeListHead))
2205 {
2207 VolumeEntry = CONTAINING_RECORD(Entry, VOLENTRY, ListEntry);
2208
2209 if (VolumeEntry->pszLabel)
2210 RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeEntry->pszLabel);
2211
2212 if (VolumeEntry->pszFilesystem)
2213 RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeEntry->pszFilesystem);
2214
2215 if (VolumeEntry->pExtents)
2216 RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeEntry->pExtents);
2217
2218 /* Release disk entry */
2219 RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeEntry);
2220 }
2221}
2222
2223
2226 _In_ PDISKENTRY DiskEntry)
2227{
2235 ULONG PartitionCount;
2236 PLIST_ENTRY ListEntry;
2237 PPARTENTRY PartEntry;
2239
2240 DPRINT("WriteMbrPartitions() Disk: %lu\n", DiskEntry->DiskNumber);
2241
2242 /* If the disk is not dirty, there is nothing to do */
2243 if (!DiskEntry->Dirty)
2244 return STATUS_SUCCESS;
2245
2247 L"\\Device\\Harddisk%lu\\Partition0",
2248 DiskEntry->DiskNumber);
2250
2252 &Name,
2254 NULL,
2255 NULL);
2256
2260 &Iosb,
2261 0,
2263 if (!NT_SUCCESS(Status))
2264 {
2265 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
2266 return Status;
2267 }
2268
2269 //
2270 // FIXME: We first *MUST* use IOCTL_DISK_CREATE_DISK to initialize
2271 // the disk in MBR or GPT format in case the disk was not initialized!!
2272 // For this we must ask the user which format to use.
2273 //
2274
2275 /* Save the original partition count to be restored later (see comment below) */
2276 PartitionCount = DiskEntry->LayoutBuffer->PartitionCount;
2277
2278 /* Set the new disk layout and retrieve its updated version with possibly modified partition numbers */
2279 BufferSize = sizeof(DRIVE_LAYOUT_INFORMATION_EX) +
2280 ((PartitionCount - 1) * sizeof(PARTITION_INFORMATION_EX));
2282 NULL,
2283 NULL,
2284 NULL,
2285 &Iosb,
2287 DiskEntry->LayoutBuffer,
2288 BufferSize,
2289 DiskEntry->LayoutBuffer,
2290 BufferSize);
2292
2293 /*
2294 * IOCTL_DISK_SET_DRIVE_LAYOUT calls IoWritePartitionTable(), which converts
2295 * DiskEntry->LayoutBuffer->PartitionCount into a partition *table* count,
2296 * where such a table is expected to enumerate up to 4 partitions:
2297 * partition *table* count == ROUND_UP(PartitionCount, 4) / 4 .
2298 * Due to this we need to restore the original PartitionCount number.
2299 */
2300 DiskEntry->LayoutBuffer->PartitionCount = PartitionCount;
2301
2302 /* Check whether the IOCTL_DISK_SET_DRIVE_LAYOUT call succeeded */
2303 if (!NT_SUCCESS(Status))
2304 {
2305 DPRINT1("IOCTL_DISK_SET_DRIVE_LAYOUT failed (Status 0x%08lx)\n", Status);
2306 return Status;
2307 }
2308
2309 /* Update the partition numbers */
2310
2311 /* Update the primary partition table */
2312 for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
2313 ListEntry != &DiskEntry->PrimaryPartListHead;
2314 ListEntry = ListEntry->Flink)
2315 {
2316 PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
2317
2318 if (PartEntry->IsPartitioned)
2319 {
2321 PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex];
2322 PartEntry->PartitionNumber = PartitionInfo->PartitionNumber;
2323 }
2324 }
2325
2326 /* Update the logical partition table */
2327 for (ListEntry = DiskEntry->LogicalPartListHead.Flink;
2328 ListEntry != &DiskEntry->LogicalPartListHead;
2329 ListEntry = ListEntry->Flink)
2330 {
2331 PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
2332
2333 if (PartEntry->IsPartitioned)
2334 {
2336 PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex];
2337 PartEntry->PartitionNumber = PartitionInfo->PartitionNumber;
2338 }
2339 }
2340
2341 /* The layout has been successfully updated, the disk is not dirty anymore */
2342 DiskEntry->Dirty = FALSE;
2343
2344 return Status;
2345}
2346
2347
2350 _In_ PDISKENTRY DiskEntry)
2351{
2359
2360 DPRINT("WriteGptPartitions() Disk: %lu\n", DiskEntry->DiskNumber);
2361
2362 /* If the disk is not dirty, there is nothing to do */
2363 if (!DiskEntry->Dirty)
2364 return STATUS_SUCCESS;
2365
2367 L"\\Device\\Harddisk%lu\\Partition0",
2368 DiskEntry->DiskNumber);
2370
2372 &Name,
2374 NULL,
2375 NULL);
2376
2380 &Iosb,
2381 0,
2383 if (!NT_SUCCESS(Status))
2384 {
2385 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
2386 return Status;
2387 }
2388
2389 //
2390 // FIXME: We first *MUST* use IOCTL_DISK_CREATE_DISK to initialize
2391 // the disk in MBR or GPT format in case the disk was not initialized!!
2392 // For this we must ask the user which format to use.
2393 //
2394
2395 /* Set the new disk layout and retrieve its updated version with possibly modified partition numbers */
2396 BufferSize = sizeof(DRIVE_LAYOUT_INFORMATION_EX) +
2397 ((DiskEntry->LayoutBuffer->PartitionCount - 1) * sizeof(PARTITION_INFORMATION_EX));
2399 NULL,
2400 NULL,
2401 NULL,
2402 &Iosb,
2404 DiskEntry->LayoutBuffer,
2405 BufferSize,
2406 DiskEntry->LayoutBuffer,
2407 BufferSize);
2409
2410 /* Check whether the IOCTL_DISK_SET_DRIVE_LAYOUT_EX call succeeded */
2411 if (!NT_SUCCESS(Status))
2412 {
2413 DPRINT1("IOCTL_DISK_SET_DRIVE_LAYOUT_EX failed (Status 0x%08lx)\n", Status);
2414 return Status;
2415 }
2416
2417 /* The layout has been successfully updated, the disk is not dirty anymore */
2418 DiskEntry->Dirty = FALSE;
2419
2420 return Status;
2421}
2422
2423
2424static
2425BOOLEAN
2428{
2429 if (PartitionInfo->StartingOffset.QuadPart == 0 &&
2430 PartitionInfo->PartitionLength.QuadPart == 0)
2431 {
2432 return TRUE;
2433 }
2434
2435 return FALSE;
2436}
2437
2438
2439static
2440BOOLEAN
2443 IN PDISKENTRY DiskEntry,
2444 IN PPARTENTRY PartEntry)
2445{
2446 if ((PartitionInfo->StartingOffset.QuadPart == PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector) &&
2447 (PartitionInfo->PartitionLength.QuadPart == PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector))
2448 {
2449 return TRUE;
2450 }
2451
2452 return FALSE;
2453}
2454
2455
2456ULONG
2458 _In_ PDISKENTRY DiskEntry)
2459{
2461 PPARTENTRY PartEntry;
2462 ULONG Count = 0;
2463
2464 for (Entry = DiskEntry->PrimaryPartListHead.Flink;
2465 Entry != &DiskEntry->PrimaryPartListHead;
2466 Entry = Entry->Flink)
2467 {
2468 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
2469 if (PartEntry->IsPartitioned)
2470 Count++;
2471 }
2472
2473 return Count;
2474}
2475
2476
2477static
2478ULONG
2480 _In_ PDISKENTRY DiskEntry)
2481{
2482 PLIST_ENTRY ListEntry;
2483 PPARTENTRY PartEntry;
2484 ULONG Count = 0;
2485
2486 for (ListEntry = DiskEntry->LogicalPartListHead.Flink;
2487 ListEntry != &DiskEntry->LogicalPartListHead;
2488 ListEntry = ListEntry->Flink)
2489 {
2490 PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
2491 if (PartEntry->IsPartitioned)
2492 Count++;
2493 }
2494
2495 return Count;
2496}
2497
2498
2499static
2500BOOLEAN
2502 _In_ PDISKENTRY DiskEntry)
2503{
2504 PDRIVE_LAYOUT_INFORMATION_EX NewLayoutBuffer;
2505 ULONG NewPartitionCount;
2506 ULONG CurrentPartitionCount = 0;
2507 ULONG LayoutBufferSize;
2508 ULONG i;
2509
2510 DPRINT1("ReAllocateLayoutBuffer()\n");
2511
2512 NewPartitionCount = 4 + GetLogicalPartitionCount(DiskEntry) * 4;
2513
2514 if (DiskEntry->LayoutBuffer)
2515 CurrentPartitionCount = DiskEntry->LayoutBuffer->PartitionCount;
2516
2517 DPRINT1("CurrentPartitionCount: %lu ; NewPartitionCount: %lu\n",
2518 CurrentPartitionCount, NewPartitionCount);
2519
2520 if (CurrentPartitionCount == NewPartitionCount)
2521 return TRUE;
2522
2523 LayoutBufferSize = sizeof(DRIVE_LAYOUT_INFORMATION_EX) +
2524 ((NewPartitionCount - ANYSIZE_ARRAY) * sizeof(PARTITION_INFORMATION_EX));
2525 NewLayoutBuffer = RtlReAllocateHeap(RtlGetProcessHeap(),
2527 DiskEntry->LayoutBuffer,
2528 LayoutBufferSize);
2529 if (NewLayoutBuffer == NULL)
2530 {
2531 DPRINT1("Failed to allocate the new layout buffer (size: %lu)\n", LayoutBufferSize);
2532 return FALSE;
2533 }
2534
2535 NewLayoutBuffer->PartitionCount = NewPartitionCount;
2536
2537 /* If the layout buffer grows, make sure the new (empty) entries are written to the disk */
2538 if (NewPartitionCount > CurrentPartitionCount)
2539 {
2540 for (i = CurrentPartitionCount; i < NewPartitionCount; i++)
2541 {
2542 NewLayoutBuffer->PartitionEntry[i].RewritePartition = TRUE;
2543 }
2544 }
2545
2546 DiskEntry->LayoutBuffer = NewLayoutBuffer;
2547
2548 return TRUE;
2549}
2550
2551
2552VOID
2554 _In_ PDISKENTRY DiskEntry)
2555{
2558 PLIST_ENTRY ListEntry;
2559 PPARTENTRY PartEntry;
2560 LARGE_INTEGER HiddenSectors64;
2561 ULONG Index;
2563
2564 DPRINT("UpdateMbrDiskLayout()\n");
2565
2566 /* Resize the layout buffer if necessary */
2567 if (ReAllocateLayoutBuffer(DiskEntry) == FALSE)
2568 {
2569 DPRINT("ReAllocateLayoutBuffer() failed.\n");
2570 return;
2571 }
2572
2573 DiskEntry->LayoutBuffer->PartitionStyle = PARTITION_STYLE_MBR;
2574
2575 /* Update the primary partition table */
2576 Index = 0;
2577 for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
2578 ListEntry != &DiskEntry->PrimaryPartListHead;
2579 ListEntry = ListEntry->Flink)
2580 {
2581 PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
2582
2583 if (PartEntry->IsPartitioned)
2584 {
2586
2587 PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
2588 PartEntry->PartitionIndex = Index;
2589
2590 /* Reset the current partition number only for newly-created (unmounted) partitions */
2591 if (PartEntry->New)
2592 PartEntry->PartitionNumber = 0;
2593
2595
2596 if (!IsSamePrimaryLayoutEntry(PartitionInfo, DiskEntry, PartEntry))
2597 {
2598 DPRINT1("Updating primary partition entry %lu\n", Index);
2599
2600 PartitionInfo->PartitionStyle = PARTITION_STYLE_MBR;
2601 PartitionInfo->StartingOffset.QuadPart = PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector;
2602 PartitionInfo->PartitionLength.QuadPart = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
2603 PartitionInfo->Mbr.HiddenSectors = PartEntry->StartSector.LowPart;
2604 PartitionInfo->PartitionNumber = PartEntry->PartitionNumber;
2605 PartitionInfo->Mbr.PartitionType = PartEntry->Mbr.PartitionType;
2606 PartitionInfo->Mbr.BootIndicator = PartEntry->Mbr.BootIndicator;
2607 PartitionInfo->Mbr.RecognizedPartition = IsRecognizedPartition(PartEntry->Mbr.PartitionType);
2608 PartitionInfo->RewritePartition = TRUE;
2609 }
2610
2611 if (!IsContainerPartition(PartEntry->Mbr.PartitionType))
2613
2614 Index++;
2615 }
2616 }
2617
2618 ASSERT(Index <= 4);
2619
2620 /* Update the logical partition table */
2621 Index = 4;
2622 for (ListEntry = DiskEntry->LogicalPartListHead.Flink;
2623 ListEntry != &DiskEntry->LogicalPartListHead;
2624 ListEntry = ListEntry->Flink)
2625 {
2626 PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
2627
2628 if (PartEntry->IsPartitioned)
2629 {
2631
2632 PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
2633 PartEntry->PartitionIndex = Index;
2634
2635 /* Reset the current partition number only for newly-created (unmounted) partitions */
2636 if (PartEntry->New)
2637 PartEntry->PartitionNumber = 0;
2638
2640
2641 DPRINT1("Updating logical partition entry %lu\n", Index);
2642
2643 PartitionInfo->PartitionStyle = PARTITION_STYLE_MBR;
2644 PartitionInfo->StartingOffset.QuadPart = PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector;
2645 PartitionInfo->PartitionLength.QuadPart = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
2646 PartitionInfo->Mbr.HiddenSectors = DiskEntry->SectorAlignment;
2647 PartitionInfo->PartitionNumber = PartEntry->PartitionNumber;
2648 PartitionInfo->Mbr.PartitionType = PartEntry->Mbr.PartitionType;
2649 PartitionInfo->Mbr.BootIndicator = FALSE;
2650 PartitionInfo->Mbr.RecognizedPartition = IsRecognizedPartition(PartEntry->Mbr.PartitionType);
2651 PartitionInfo->RewritePartition = TRUE;
2652
2653 /* Fill the link entry of the previous partition entry */
2654 if (LinkInfo != NULL)
2655 {
2657 LinkInfo->StartingOffset.QuadPart = (PartEntry->StartSector.QuadPart - DiskEntry->SectorAlignment) * DiskEntry->BytesPerSector;
2658 LinkInfo->PartitionLength.QuadPart = (PartEntry->StartSector.QuadPart + DiskEntry->SectorAlignment) * DiskEntry->BytesPerSector;
2659 HiddenSectors64.QuadPart = PartEntry->StartSector.QuadPart - DiskEntry->SectorAlignment - DiskEntry->ExtendedPartition->StartSector.QuadPart;
2660 LinkInfo->Mbr.HiddenSectors = HiddenSectors64.LowPart;
2661 LinkInfo->PartitionNumber = 0;
2663 LinkInfo->Mbr.BootIndicator = FALSE;
2664 LinkInfo->Mbr.RecognizedPartition = FALSE;
2665 LinkInfo->RewritePartition = TRUE;
2666 }
2667
2668 /* Save a pointer to the link entry of the current partition entry */
2669 LinkInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index + 1];
2670
2672 Index += 4;
2673 }
2674 }
2675
2676 /* Wipe unused primary partition entries */
2677 for (Index = GetPrimaryPartitionCount(DiskEntry); Index < 4; Index++)
2678 {
2679 DPRINT1("Primary partition entry %lu\n", Index);
2680
2681 PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
2682
2684 {
2685 DPRINT1("Wiping primary partition entry %lu\n", Index);
2686
2687 PartitionInfo->PartitionStyle = PARTITION_STYLE_MBR;
2688 PartitionInfo->StartingOffset.QuadPart = 0;
2689 PartitionInfo->PartitionLength.QuadPart = 0;
2690 PartitionInfo->Mbr.HiddenSectors = 0;
2691 PartitionInfo->PartitionNumber = 0;
2692 PartitionInfo->Mbr.PartitionType = PARTITION_ENTRY_UNUSED;
2693 PartitionInfo->Mbr.BootIndicator = FALSE;
2694 PartitionInfo->Mbr.RecognizedPartition = FALSE;
2695 PartitionInfo->RewritePartition = TRUE;
2696 }
2697 }
2698
2699 /* Wipe unused logical partition entries */
2700 for (Index = 4; Index < DiskEntry->LayoutBuffer->PartitionCount; Index++)
2701 {
2702 if (Index % 4 >= 2)
2703 {
2704 DPRINT1("Logical partition entry %lu\n", Index);
2705
2706 PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
2707
2709 {
2710 DPRINT1("Wiping partition entry %lu\n", Index);
2711
2712 PartitionInfo->PartitionStyle = PARTITION_STYLE_MBR;
2713 PartitionInfo->StartingOffset.QuadPart = 0;
2714 PartitionInfo->PartitionLength.QuadPart = 0;
2715 PartitionInfo->Mbr.HiddenSectors = 0;
2716 PartitionInfo->PartitionNumber = 0;
2717 PartitionInfo->Mbr.PartitionType = PARTITION_ENTRY_UNUSED;
2718 PartitionInfo->Mbr.BootIndicator = FALSE;
2719 PartitionInfo->Mbr.RecognizedPartition = FALSE;
2720 PartitionInfo->RewritePartition = TRUE;
2721 }
2722 }
2723 }
2724
2725 DiskEntry->Dirty = TRUE;
2726}
2727
2728
2729VOID
2731 _In_ PDISKENTRY DiskEntry,
2732 _In_ BOOL DeleteEntry)
2733{
2734 PLIST_ENTRY ListEntry;
2735 PPARTENTRY PartEntry;
2737 ULONG Count, Index;
2738
2739 DPRINT("UpdateGptDiskLayout()\n");
2740
2741 /* Count used partition entries */
2742 Count = 0;
2743 for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
2744 ListEntry != &DiskEntry->PrimaryPartListHead;
2745 ListEntry = ListEntry->Flink)
2746 {
2747 PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
2748
2749 if (!IsEqualGUID(&PartEntry->Gpt.PartitionType, &PARTITION_ENTRY_UNUSED_GUID))
2750 Count++;
2751 }
2752
2753 DPRINT("Used partition entries: %lu\n", Count);
2754
2755 if (DeleteEntry)
2756 Count++;
2757
2758 /* Reallocate the layout buffer */
2759 if (Count != DiskEntry->LayoutBuffer->PartitionCount)
2760 {
2761 PDRIVE_LAYOUT_INFORMATION_EX NewLayoutBuffer;
2762 ULONG NewLayoutBufferSize;
2763
2764 NewLayoutBufferSize = sizeof(DRIVE_LAYOUT_INFORMATION_EX) +
2766 NewLayoutBuffer = RtlReAllocateHeap(RtlGetProcessHeap(),
2768 DiskEntry->LayoutBuffer,
2769 NewLayoutBufferSize);
2770 if (NewLayoutBuffer == NULL)
2771 {
2772 DPRINT1("Failed to allocate the new layout buffer (size: %lu)\n", NewLayoutBufferSize);
2773 return;
2774 }
2775
2776 NewLayoutBuffer->PartitionCount = Count;
2777 DiskEntry->LayoutBuffer = NewLayoutBuffer;
2778 }
2779
2780 /* Fill the new layout buffer */
2781 Index = 0;
2782 for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
2783 ListEntry != &DiskEntry->PrimaryPartListHead;
2784 ListEntry = ListEntry->Flink)
2785 {
2786 PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
2787
2788 if (!IsEqualGUID(&PartEntry->Gpt.PartitionType, &PARTITION_ENTRY_UNUSED_GUID))
2789 {
2790 PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
2791 PartEntry->PartitionIndex = Index;
2792
2793 DPRINT("Updating primary partition entry %lu\n", Index);
2794 PartitionInfo->PartitionStyle = PARTITION_STYLE_GPT;
2795 PartitionInfo->StartingOffset.QuadPart = PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector;
2796 PartitionInfo->PartitionLength.QuadPart = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
2797 PartitionInfo->PartitionNumber = Index + 1;
2798 PartitionInfo->RewritePartition = TRUE;
2799 CopyMemory(&PartitionInfo->Gpt.PartitionType, &PartEntry->Gpt.PartitionType, sizeof(GUID));
2800 CopyMemory(&PartitionInfo->Gpt.PartitionId, &PartEntry->Gpt.PartitionId, sizeof(GUID));
2801 PartitionInfo->Gpt.Attributes = PartEntry->Gpt.Attributes;
2802 ZeroMemory(&PartitionInfo->Gpt.Name, 36 * sizeof(WCHAR)); /* ??? */
2803
2804 PartEntry->PartitionNumber = PartitionInfo->PartitionNumber;
2805
2806 Index++;
2807 }
2808 }
2809
2810 if (DeleteEntry)
2811 {
2812 PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
2814 PartitionInfo->RewritePartition = TRUE;
2815 }
2816}
2817
2818
2821 _In_ PPARTENTRY PartEntry)
2822{
2823 PDISKENTRY DiskEntry = PartEntry->DiskEntry;
2824 PPARTENTRY PrevPartEntry;
2825 PLIST_ENTRY ListHead;
2826
2827 if (PartEntry->LogicalPartition)
2828 ListHead = &DiskEntry->LogicalPartListHead;
2829 else
2830 ListHead = &DiskEntry->PrimaryPartListHead;
2831
2832 if (PartEntry->ListEntry.Blink != ListHead)
2833 {
2834 PrevPartEntry = CONTAINING_RECORD(PartEntry->ListEntry.Blink,
2835 PARTENTRY,
2836 ListEntry);
2837 if (!PrevPartEntry->IsPartitioned)
2838 {
2840 return PrevPartEntry;
2841 }
2842 }
2843
2844 return NULL;
2845}
2846
2847
2850 _In_ PPARTENTRY PartEntry)
2851{
2852 PDISKENTRY DiskEntry = PartEntry->DiskEntry;
2853 PPARTENTRY NextPartEntry;
2854 PLIST_ENTRY ListHead;
2855
2856 if (PartEntry->LogicalPartition)
2857 ListHead = &DiskEntry->LogicalPartListHead;
2858 else
2859 ListHead = &DiskEntry->PrimaryPartListHead;
2860
2861 if (PartEntry->ListEntry.Flink != ListHead)
2862 {
2863 NextPartEntry = CONTAINING_RECORD(PartEntry->ListEntry.Flink,
2864 PARTENTRY,
2865 ListEntry);
2866 if (!NextPartEntry->IsPartitioned)
2867 {
2869 return NextPartEntry;
2870 }
2871 }
2872
2873 return NULL;
2874}
2875
2876
2879 _In_ PPARTENTRY PartEntry)
2880{
2882 NTSTATUS LockStatus;
2886 HANDLE PartitionHandle;
2888
2889 /* Check whether the partition is valid and was mounted by the system */
2890 if (!PartEntry->IsPartitioned ||
2891 IsContainerPartition(PartEntry->Mbr.PartitionType) ||
2892 !IsRecognizedPartition(PartEntry->Mbr.PartitionType) ||
2893 PartEntry->FormatState == UnknownFormat ||
2894 // NOTE: If FormatState == Unformatted but *FileSystem != 0 this means
2895 // it has been usually mounted with RawFS and thus needs to be dismounted.
2896/* !*PartEntry->FileSystem || */
2897 PartEntry->PartitionNumber == 0)
2898 {
2899 /* The partition is not mounted, so just return success */
2900 return STATUS_SUCCESS;
2901 }
2902
2903 ASSERT(PartEntry->Mbr.PartitionType != PARTITION_ENTRY_UNUSED);
2904
2905 /* Open the volume */
2907 L"\\Device\\Harddisk%lu\\Partition%lu",
2908 PartEntry->DiskEntry->DiskNumber,
2909 PartEntry->PartitionNumber);
2911
2913 &Name,
2915 NULL,
2916 NULL);
2917
2918 Status = NtOpenFile(&PartitionHandle,
2924 if (!NT_SUCCESS(Status))
2925 {
2926 DPRINT1("ERROR: Cannot open volume %wZ for dismounting! (Status 0x%lx)\n", &Name, Status);
2927 return Status;
2928 }
2929
2930 /* Lock the volume */
2931 LockStatus = NtFsControlFile(PartitionHandle,
2932 NULL,
2933 NULL,
2934 NULL,
2937 NULL,
2938 0,
2939 NULL,
2940 0);
2941 if (!NT_SUCCESS(LockStatus))
2942 {
2943 DPRINT1("WARNING: Failed to lock volume! Operations may fail! (Status 0x%lx)\n", LockStatus);
2944 }
2945
2946 /* Dismount the volume */
2947 Status = NtFsControlFile(PartitionHandle,
2948 NULL,
2949 NULL,
2950 NULL,
2953 NULL,
2954 0,
2955 NULL,
2956 0);
2957 if (!NT_SUCCESS(Status))
2958 {
2959 DPRINT1("Failed to unmount volume (Status 0x%lx)\n", Status);
2960 }
2961
2962 /* Unlock the volume */
2963 LockStatus = NtFsControlFile(PartitionHandle,
2964 NULL,
2965 NULL,
2966 NULL,
2969 NULL,
2970 0,
2971 NULL,
2972 0);
2973 if (!NT_SUCCESS(LockStatus))
2974 {
2975 DPRINT1("Failed to unlock volume (Status 0x%lx)\n", LockStatus);
2976 }
2977
2978 /* Close the volume */
2979 NtClose(PartitionHandle);
2980
2981 return Status;
2982}
2983
2984
2987 _In_ PPARTENTRY PartEntry)
2988{
2990 PVOLENTRY VolumeEntry;
2991 ULONG i;
2992
2993 if ((PartEntry == NULL) ||
2994 (PartEntry->DiskEntry == NULL))
2995 return NULL;
2996
2998 while (Entry != &VolumeListHead)
2999 {
3000 VolumeEntry = CONTAINING_RECORD(Entry, VOLENTRY, ListEntry);
3001
3002 if (VolumeEntry->pExtents == NULL)
3003 return NULL;
3004
3005 for (i = 0; i < VolumeEntry->pExtents->NumberOfDiskExtents; i++)
3006 {
3007 if (VolumeEntry->pExtents->Extents[i].DiskNumber == PartEntry->DiskEntry->DiskNumber)
3008 {
3009 if ((VolumeEntry->pExtents->Extents[i].StartingOffset.QuadPart == PartEntry->StartSector.QuadPart * PartEntry->DiskEntry->BytesPerSector) &&
3010 (VolumeEntry->pExtents->Extents[i].ExtentLength.QuadPart == PartEntry->SectorCount.QuadPart * PartEntry->DiskEntry->BytesPerSector))
3011 return VolumeEntry;
3012 }
3013 }
3014
3015 Entry = Entry->Flink;
3016 }
3017
3018 return NULL;
3019}
3020
3021
3022VOID
3024 _In_ PVOLENTRY VolumeEntry)
3025{
3026 if (VolumeEntry == NULL)
3027 return;
3028
3029 if (VolumeEntry == CurrentVolume)
3031
3032 RemoveEntryList(&VolumeEntry->ListEntry);
3033
3034 if (VolumeEntry->pszLabel)
3035 RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeEntry->pszLabel);
3036
3037 if (VolumeEntry->pszFilesystem)
3038 RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeEntry->pszFilesystem);
3039
3040 if (VolumeEntry->pExtents)
3041 RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeEntry->pExtents);
3042
3043 /* Release disk entry */
3044 RtlFreeHeap(RtlGetProcessHeap(), 0, VolumeEntry);
3045}
3046
3047/* EOF */
unsigned char BOOLEAN
@ Identifier
Definition: asmpp.cpp:95
LONG NTSTATUS
Definition: precomp.h:26
HANDLE ProcessHeap
Definition: servman.c:15
#define FILE_DIRECTORY_FILE
Definition: constants.h:491
#define DPRINT1
Definition: precomp.h:8
#define PARTITION_IFS
Definition: disk.h:78
#define PARTITION_ENTRY_UNUSED
Definition: disk.h:71
#define PARTITION_XINT13
Definition: disk.h:82
#define PARTITION_FAT32
Definition: disk.h:80
#define PARTITION_FAT_12
Definition: disk.h:72
#define PARTITION_EXTENDED
Definition: disk.h:76
#define PARTITION_HUGE
Definition: disk.h:77
#define PARTITION_FAT_16
Definition: disk.h:75
#define PARTITION_GPT
Definition: disk.h:90
#define PARTITION_FAT32_XINT13
Definition: disk.h:81
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:616
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:634
#define RegCloseKey(hKey)
Definition: registry.h:49
while(CdLookupNextInitialFileDirent(IrpContext, Fcb, FileContext))
_In_ PFCB _In_ LONGLONG FileOffset
Definition: cdprocs.h:160
#define IOCTL_DISK_GET_DRIVE_GEOMETRY
Definition: cdrw_usr.h:169
Definition: bufpool.h:45
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
#define STATUS_NO_MEMORY
Definition: d3dkmdt.h:51
#define ERROR_MORE_DATA
Definition: dderror.h:13
#define BufferSize
Definition: mmc.h:75
#define ERROR_SUCCESS
Definition: deptool.c:10
LPWSTR Name
Definition: desk.c:124
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
@ VOLUME_TYPE_UNKNOWN
Definition: diskpart.h:114
@ VOLUME_TYPE_REMOVABLE
Definition: diskpart.h:113
@ VOLUME_TYPE_CDROM
Definition: diskpart.h:111
@ VOLUME_TYPE_PARTITION
Definition: diskpart.h:112
PDISKENTRY CurrentDisk
Definition: partlist.c:75
@ Preformatted
Definition: diskpart.h:105
@ LogicalPartition
Definition: disksup.c:48
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
LONG WINAPI RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
Definition: reg.c:3333
LONG WINAPI RegQueryValueExW(_In_ HKEY hkeyorg, _In_ LPCWSTR name, _In_ LPDWORD reserved, _In_ LPDWORD type, _In_ LPBYTE data, _In_ LPDWORD count)
Definition: reg.c:4103
#define INVALID_HANDLE_VALUE
Definition: compat.h:731
#define GENERIC_READ
Definition: compat.h:135
#define MAX_PATH
Definition: compat.h:34
#define MultiByteToWideChar
Definition: compat.h:110
#define FILE_SHARE_READ
Definition: compat.h:136
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
static DWORD DWORD * dwLength
Definition: fusion.c:86
DWORD WINAPI QueryDosDeviceW(LPCWSTR lpDeviceName, LPWSTR lpTargetPath, DWORD ucchMax)
Definition: dosdev.c:542
BOOL WINAPI FindNextVolumeW(IN HANDLE handle, IN LPWSTR volume, IN DWORD len)
Definition: volume.c:1082
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
HANDLE WINAPI FindFirstVolumeW(IN LPWSTR volume, IN DWORD len)
Definition: volume.c:660
BOOL WINAPI FindVolumeClose(IN HANDLE hFindVolume)
Definition: volume.c:741
BOOL WINAPI GetVolumePathNamesForVolumeNameW(IN LPCWSTR lpszVolumeName, IN LPWSTR lpszVolumePathNames, IN DWORD cchBufferLength, OUT PDWORD lpcchReturnLength)
Definition: volume.c:1227
UINT WINAPI GetSystemDirectoryW(OUT LPWSTR lpBuffer, IN UINT uSize)
Definition: path.c:2313
_ACRTIMP size_t __cdecl wcslen(const wchar_t *)
Definition: wcs.c:2983
_ACRTIMP int __cdecl _wcsnicmp(const wchar_t *, const wchar_t *, size_t)
Definition: wcs.c:195
static const WCHAR Signature[]
Definition: parser.c:141
#define L(x)
Definition: resources.c:13
return Iosb
Definition: create.c:4403
#define RemoveEntryList(Entry)
Definition: env_spec_w32.h:986
#define InsertTailList(ListHead, Entry)
#define IsListEmpty(ListHead)
Definition: env_spec_w32.h:954
#define RemoveHeadList(ListHead)
Definition: env_spec_w32.h:964
#define InitializeListHead(ListHead)
Definition: env_spec_w32.h:944
@ Success
Definition: eventcreate.c:712
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
#define IOCTL_DISK_GET_DRIVE_LAYOUT_EX
Definition: ntddk_ex.h:207
@ SystemDeviceInformation
Definition: ntddk_ex.h:18
_Must_inspect_result_ _In_opt_ PFLT_INSTANCE _Out_ PHANDLE FileHandle
Definition: fltkernel.h:1231
_Must_inspect_result_ _Out_ PHANDLE VolumeHandle
Definition: fltkernel.h:2283
#define FILE_SYNCHRONOUS_IO_NONALERT
Definition: from_kernel.h:31
@ FileFsDeviceInformation
Definition: from_kernel.h:222
@ FileFsSizeInformation
Definition: from_kernel.h:221
#define FILE_OPEN_FOR_BACKUP_INTENT
Definition: from_kernel.h:42
union Alignment_ Alignment
FxAutoRegKey hKey
Status
Definition: gdiplustypes.h:25
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
#define DbgPrint
Definition: hal.h:12
_In_ GUID _In_ PVOID ValueData
Definition: hubbusif.h:312
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
NTSYSAPI PVOID WINAPI RtlReAllocateHeap(HANDLE, ULONG, PVOID, SIZE_T) __WINE_ALLOC_SIZE(4) __WINE_DEALLOC(RtlFreeHeap
NTSYSAPI NTSTATUS WINAPI RtlQueryRegistryValues(ULONG, PCWSTR, PRTL_QUERY_REGISTRY_TABLE, PVOID, PVOID)
#define REG_SZ
Definition: layer.c:22
struct _BIOSDISKENTRY * PBIOSDISKENTRY
@ UnknownFormat
Definition: partlist.h:36
@ Unformatted
Definition: partlist.h:34
struct _BIOSDISKENTRY BIOSDISKENTRY
#define ZeroMemory
Definition: minwinbase.h:31
#define CopyMemory
Definition: minwinbase.h:29
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define ASSERT(a)
Definition: mode.c:44
struct _PARTITION_INFORMATION_EX PARTITION_INFORMATION_EX
@ PARTITION_STYLE_GPT
Definition: imports.h:202
@ PARTITION_STYLE_MBR
Definition: imports.h:201
#define ULL(a, b)
Definition: format_msg.c:27
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
#define min(a, b)
Definition: monoChain.cc:55
_In_ PCWSTR _Inout_ _At_ QueryTable EntryContext
Definition: rtlfuncs.h:4210
_In_ PCWSTR _Inout_ _At_ QueryTable _Pre_unknown_ PRTL_QUERY_REGISTRY_TABLE QueryTable
Definition: rtlfuncs.h:4211
#define _In_
Definition: no_sal2.h:158
int Count
Definition: noreturn.cpp:7
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:3953
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define SYNCHRONIZE
Definition: nt_native.h:61
#define FILE_READ_DATA
Definition: nt_native.h:628
#define FSCTL_LOCK_VOLUME
Definition: nt_native.h:832
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
#define KEY_READ
Definition: nt_native.h:1026
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define RTL_REGISTRY_ABSOLUTE
Definition: nt_native.h:161
NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToInteger(PUNICODE_STRING String, ULONG Base, PULONG Value)
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)
#define RTL_REGISTRY_DEVICEMAP
Definition: nt_native.h:165
#define RTL_QUERY_REGISTRY_DIRECT
Definition: nt_native.h:144
#define FSCTL_UNLOCK_VOLUME
Definition: nt_native.h:833
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
NTSYSAPI VOID NTAPI RtlFreeUnicodeString(PUNICODE_STRING UnicodeString)
#define FSCTL_DISMOUNT_VOLUME
Definition: nt_native.h:834
#define GENERIC_WRITE
Definition: nt_native.h:90
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 FILE_REMOVABLE_MEDIA
Definition: nt_native.h:807
#define REG_FULL_RESOURCE_DESCRIPTOR
Definition: nt_native.h:1506
#define UNICODE_NULL
#define IsContainerPartition(PartitionType)
Definition: ntdddisk.h:321
#define IsRecognizedPartition(PartitionType)
Definition: ntdddisk.h:342
@ RemovableMedia
Definition: ntdddisk.h:382
@ FixedMedia
Definition: ntdddisk.h:383
#define IOCTL_DISK_SET_DRIVE_LAYOUT_EX
Definition: ntdddisk.h:208
struct _VOLUME_DISK_EXTENTS VOLUME_DISK_EXTENTS
struct _DISK_EXTENT DISK_EXTENT
#define IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
Definition: ntddvol.h:44
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define FileFsFullSizeInformation
Definition: ntifs_ex.h:389
BYTE * PBYTE
Definition: pedump.c:66
unsigned short USHORT
Definition: pedump.c:61
#define IsEqualGUID(rguid1, rguid2)
Definition: guiddef.h:147
#define IOCTL_STORAGE_QUERY_PROPERTY
Definition: ntddstor.h:178
@ StorageDeviceProperty
Definition: ntddstor.h:512
@ PropertyStandardQuery
Definition: ntddstor.h:505
#define FILE_DEVICE_DISK_FILE_SYSTEM
Definition: winioctl.h:53
#define FILE_DEVICE_CD_ROM
Definition: winioctl.h:47
#define FILE_DEVICE_CD_ROM_FILE_SYSTEM
Definition: winioctl.h:48
#define FILE_DEVICE_DISK
Definition: winioctl.h:52
PVOID pBuffer
struct _CM_FULL_RESOURCE_DESCRIPTOR * PCM_FULL_RESOURCE_DESCRIPTOR
#define CmResourceTypeDeviceSpecific
Definition: restypes.h:108
#define IOCTL_SCSI_GET_ADDRESS
Definition: scsi_port.h:52
#define iswalpha(_c)
Definition: ctype.h:664
wcscat
wcscpy
#define memset(x, y, z)
Definition: compat.h:39
IN HANDLE DstPath
Definition: fsutil.h:81
static VOID GetDriverName(IN PDISKENTRY DiskEntry)
Definition: partlist.c:105
VOID NTAPI DestroyPartitionList(IN PPARTLIST List)
Definition: partlist.c:2074
static BOOLEAN IsSamePrimaryLayoutEntry(_In_ PPARTITION_INFORMATION PartitionInfo, _In_ PPARTENTRY PartEntry)
Definition: partlist.c:2492
ULONGLONG AlignDown(IN ULONGLONG Value, IN ULONG Alignment)
Definition: partlist.c:67
static NTSTATUS NTAPI DiskConfigurationDataQueryRoutine(PWSTR ValueName, ULONG ValueType, PVOID ValueData, ULONG ValueLength, PVOID Context, PVOID EntryContext)
Definition: partlist.c:237
#define ROOT_NAME
static VOID AddDiskToList(IN HANDLE FileHandle, IN ULONG DiskNumber, IN PPARTLIST List)
Definition: partlist.c:1445
static NTSTATUS NTAPI SystemConfigurationDataQueryRoutine(PWSTR ValueName, ULONG ValueType, PVOID ValueData, ULONG ValueLength, PVOID Context, PVOID EntryContext)
Definition: partlist.c:280
PPARTLIST NTAPI CreatePartitionList(VOID)
Definition: partlist.c:1988
static VOID EnumerateBiosDiskEntries(IN PPARTLIST PartList)
Definition: partlist.c:327
static BOOLEAN IsEmptyLayoutEntry(_In_ PPARTITION_INFORMATION PartitionInfo)
Definition: partlist.c:2483
static BOOLEAN ReAllocateLayoutBuffer(IN PDISKENTRY DiskEntry)
Definition: partlist.c:2537
#define GetLogicalPartitionCount(DiskEntry)
Definition: partlist.c:2530
#define GetPrimaryPartitionCount(DiskEntry)
Definition: partlist.c:2527
static NTSTATUS NTAPI DiskIdentifierQueryRoutine(PWSTR ValueName, ULONG ValueType, PVOID ValueData, ULONG ValueLength, PVOID Context, PVOID EntryContext)
Definition: partlist.c:207
NTSTATUS NTAPI NtQueryVolumeInformationFile(HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock, PVOID FsInformation, ULONG Length, FS_INFORMATION_CLASS FsInformationClass)
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
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 DPRINT
Definition: sndvol32.h:73
NTSYSAPI NTSTATUS NTAPI NtQuerySystemInformation(IN SYSTEM_INFORMATION_CLASS SystemInfoClass, OUT PVOID SystemInfoBuffer, IN ULONG SystemInfoBufferSize, OUT PULONG BytesReturned OPTIONAL)
STRSAFEAPI StringCchPrintfW(STRSAFE_LPWSTR pszDest, size_t cchDest, STRSAFE_LPCWSTR pszFormat,...)
Definition: strsafe.h:530
base of all file and directory entries
Definition: entries.h:83
BOOLEAN Recognized
Definition: diskpart.h:182
ULONG DiskNumber
Definition: partlist.h:162
ULONG Checksum
Definition: partlist.h:164
ULONG Signature
Definition: partlist.h:163
CM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry
Definition: partlist.h:166
CM_PARTIAL_RESOURCE_LIST PartialResourceList
Definition: restypes.h:144
union _CM_PARTIAL_RESOURCE_DESCRIPTOR::@432 u
struct _CM_PARTIAL_RESOURCE_DESCRIPTOR::@432::@441 DeviceSpecificData
CM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptors[1]
Definition: restypes.h:100
ULARGE_INTEGER EndSector
Definition: diskpart.h:206
ULONG SectorAlignment
Definition: partlist.h:116
ULONG BiosDiskNumber
Definition: diskpart.h:209
BOOL IsBoot
Definition: diskpart.h:234
ULARGE_INTEGER SectorCount
Definition: partlist.h:115
UNICODE_STRING DriverName
Definition: partlist.h:141
STORAGE_BUS_TYPE BusType
Definition: diskpart.h:194
ULONG SectorsPerTrack
Definition: partlist.h:112
USHORT TargetId
Definition: diskpart.h:216
PPARTENTRY ExtendedPartition
Definition: partlist.h:153
LIST_ENTRY LogicalPartListHead
Definition: partlist.h:150
BOOLEAN NewDisk
Definition: partlist.h:138
ULONG DiskNumber
Definition: partlist.h:129
ULONG BytesPerSector
Definition: partlist.h:113
USHORT PathId
Definition: diskpart.h:215
BOOLEAN BiosFound
Definition: partlist.h:120
PWSTR Location
Definition: diskpart.h:193
ULONGLONG Cylinders
Definition: partlist.h:110
USHORT Lun
Definition: diskpart.h:217
ULARGE_INTEGER StartSector
Definition: diskpart.h:205
USHORT Port
Definition: partlist.h:131
DWORD PartitionStyle
Definition: diskpart.h:223
ULONG TracksPerCylinder
Definition: partlist.h:111
LIST_ENTRY PrimaryPartListHead
Definition: partlist.h:149
PWSTR Description
Definition: diskpart.h:192
ULONG CylinderAlignment
Definition: partlist.h:117
PDRIVE_LAYOUT_INFORMATION LayoutBuffer
Definition: partlist.h:143
ULONG DiskNumber
Definition: ntddvol.h:48
LARGE_INTEGER StartingOffset
Definition: ntddvol.h:49
LARGE_INTEGER ExtentLength
Definition: ntddvol.h:50
MEDIA_TYPE MediaType
Definition: ntdddisk.h:401
LARGE_INTEGER Cylinders
Definition: ntdddisk.h:400
ULONG TracksPerCylinder
Definition: ntdddisk.h:402
ULONG SectorsPerTrack
Definition: ntdddisk.h:403
ULONG BytesPerSector
Definition: ntdddisk.h:404
PARTITION_INFORMATION PartitionEntry[1]
Definition: ntdddisk.h:421
LARGE_INTEGER TotalAllocationUnits
Definition: from_kernel.h:270
DWORD64 Attributes
Definition: diskpart.h:127
Definition: typedefs.h:120
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
BOOLEAN BootIndicator
Definition: diskpart.h:119
BOOLEAN IsPartitioned
Definition: partlist.h:82
BOOLEAN New
Definition: partlist.h:85
BOOL IsBoot
Definition: diskpart.h:171
ULARGE_INTEGER SectorCount
Definition: partlist.h:70
struct _DISKENTRY * DiskEntry
Definition: partlist.h:66
BOOLEAN LogicalPartition
Definition: partlist.h:79
MBR_PARTITION_DATA Mbr
Definition: diskpart.h:141
FORMATSTATE FormatState
Definition: diskpart.h:152
GPT_PARTITION_DATA Gpt
Definition: diskpart.h:142
BOOL IsSystem
Definition: diskpart.h:170
ULONG OnDiskPartitionNumber
Definition: partlist.h:74
LIST_ENTRY ListEntry
Definition: partlist.h:63
ULONG PartitionNumber
Definition: partlist.h:75
ULARGE_INTEGER StartSector
Definition: partlist.h:69
ULONG PartitionIndex
Definition: partlist.h:76
LARGE_INTEGER StartingOffset
Definition: imports.h:221
PARTITION_STYLE PartitionStyle
Definition: imports.h:220
PARTITION_INFORMATION_MBR Mbr
Definition: imports.h:226
LARGE_INTEGER PartitionLength
Definition: imports.h:222
LARGE_INTEGER StartingOffset
Definition: ntdddisk.h:408
LARGE_INTEGER PartitionLength
Definition: ntdddisk.h:409
BOOLEAN RewritePartition
Definition: ntdddisk.h:415
UCHAR BootCode[440]
Definition: partlist.h:216
PARTITION Partition[PARTITION_TBL_SIZE]
Definition: partlist.h:219
unsigned char PartitionType
Definition: partlist.h:206
unsigned char EndingSector
Definition: partlist.h:208
unsigned char BootFlags
Definition: partlist.h:202
unsigned char StartingHead
Definition: partlist.h:203
unsigned int StartingBlock
Definition: partlist.h:210
unsigned char EndingHead
Definition: partlist.h:207
unsigned char EndingCylinder
Definition: partlist.h:209
unsigned int SectorCount
Definition: partlist.h:211
unsigned char StartingSector
Definition: partlist.h:204
unsigned char StartingCylinder
Definition: partlist.h:205
PRTL_QUERY_REGISTRY_ROUTINE QueryRoutine
Definition: nt_native.h:109
UCHAR PathId
Definition: scsi_port.h:149
UCHAR TargetId
Definition: scsi_port.h:150
UCHAR PortNumber
Definition: scsi_port.h:148
STORAGE_BUS_TYPE BusType
Definition: ntddstor.h:298
STORAGE_QUERY_TYPE QueryType
Definition: ntddstor.h:553
STORAGE_PROPERTY_ID PropertyId
Definition: ntddstor.h:552
$ULONG LowPart
Definition: ntbasedef.h:581
ULONGLONG QuadPart
Definition: ms-dtyp.idl:185
USHORT MaximumLength
Definition: env_spec_w32.h:370
VOLUME_TYPE VolumeType
Definition: diskpart.h:251
PVOLUME_DISK_EXTENTS pExtents
Definition: diskpart.h:262
ULONG VolumeNumber
Definition: diskpart.h:242
ULONG SectorsPerAllocationUnit
Definition: diskpart.h:256
PWSTR pszFilesystem
Definition: diskpart.h:250
ULONG BytesPerSector
Definition: diskpart.h:257
DWORD SerialNumber
Definition: diskpart.h:245
WCHAR VolumeName[MAX_PATH]
Definition: diskpart.h:243
LIST_ENTRY ListEntry
Entry in VolumesList.
Definition: partlist.h:45
PWSTR pszLabel
Definition: diskpart.h:249
WCHAR DeviceName[MAX_PATH]
Definition: diskpart.h:244
WCHAR DriveLetter
Definition: diskpart.h:247
DISK_EXTENT Extents[1]
Definition: ntddvol.h:55
ULONG NumberOfDiskExtents
Definition: ntddvol.h:54
VOID UpdateMbrDiskLayout(_In_ PDISKENTRY DiskEntry)
Definition: partlist.c:2553
static PDISKENTRY GetDiskForVolume(_In_ PVOLENTRY VolumeEntry)
Definition: partlist.c:1834
VOID RemoveVolume(_In_ PVOLENTRY VolumeEntry)
Definition: partlist.c:3023
LIST_ENTRY VolumeListHead
Definition: partlist.c:73
static VOID GetVolumeType(_In_ HANDLE VolumeHandle, _In_ PVOLENTRY VolumeEntry)
Definition: partlist.c:1741
struct _PARTITION * PPARTITION
static VOID AddGptPartitionToDisk(ULONG DiskNumber, PDISKENTRY DiskEntry, ULONG PartitionIndex)
Definition: partlist.c:616
#define PARTITION_LINUX
Definition: partlist.c:35
LIST_ENTRY BiosDiskListHead
Definition: partlist.c:72
PPARTENTRY GetPrevUnpartitionedEntry(_In_ PPARTENTRY PartEntry)
Definition: partlist.c:2820
VOID UpdateGptDiskLayout(_In_ PDISKENTRY DiskEntry, _In_ BOOL DeleteEntry)
Definition: partlist.c:2730
VOID DestroyVolumeList(VOID)
Definition: partlist.c:2196
struct _PARTITION_SECTOR * PPARTITION_SECTOR
static VOID AddMbrPartitionToDisk(ULONG DiskNumber, PDISKENTRY DiskEntry, ULONG PartitionIndex, BOOLEAN LogicalPartition)
Definition: partlist.c:506
static VOID IsVolumeBoot(_In_ PVOLENTRY VolumeEntry)
Definition: partlist.c:1986
#define PARTITION_TBL_SIZE
Definition: partlist.c:37
static VOID AddVolumeToList(ULONG ulVolumeNumber, PWSTR pszVolumeName)
Definition: partlist.c:2023
NTSTATUS CreateVolumeList(VOID)
Definition: partlist.c:2158
NTSTATUS WriteMbrPartitions(_In_ PDISKENTRY DiskEntry)
Definition: partlist.c:2225
VOID ReadLayoutBuffer(_In_ HANDLE FileHandle, _In_ PDISKENTRY DiskEntry)
Definition: partlist.c:1065
LIST_ENTRY DiskListHead
Definition: partlist.c:71
struct _PARTITION_SECTOR PARTITION_SECTOR
VOID ScanForUnpartitionedMbrDiskSpace(PDISKENTRY DiskEntry)
Definition: partlist.c:660
PVOLENTRY CurrentVolume
Definition: partlist.c:77
PPARTENTRY CurrentPartition
Definition: partlist.c:76
NTSTATUS WriteGptPartitions(_In_ PDISKENTRY DiskEntry)
Definition: partlist.c:2349
PVOLENTRY GetVolumeFromPartition(_In_ PPARTENTRY PartEntry)
Definition: partlist.c:2986
static VOID GetVolumeSize(_In_ HANDLE VolumeHandle, _In_ PVOLENTRY VolumeEntry)
Definition: partlist.c:1781
PPARTENTRY GetNextUnpartitionedEntry(_In_ PPARTENTRY PartEntry)
Definition: partlist.c:2849
static PPARTENTRY GetPartitionForVolume(_In_ PVOLENTRY VolumeEntry)
Definition: partlist.c:1870
static VOID IsVolumeSystem(_In_ PVOLENTRY VolumeEntry)
Definition: partlist.c:1932
VOID ScanForUnpartitionedGptDiskSpace(PDISKENTRY DiskEntry)
Definition: partlist.c:921
#define MBR_MAGIC
Definition: partlist.c:39
static VOID GetVolumeExtents(_In_ HANDLE VolumeHandle, _In_ PVOLENTRY VolumeEntry)
Definition: partlist.c:1675
struct _PARTITION PARTITION
uint16_t * PWSTR
Definition: typedefs.h:56
uint32_t * PULONG
Definition: typedefs.h:59
char * PSTR
Definition: typedefs.h:51
#define ANYSIZE_ARRAY
Definition: typedefs.h:46
#define NTAPI
Definition: typedefs.h:36
int32_t INT
Definition: typedefs.h:58
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
uint16_t * PWCHAR
Definition: typedefs.h:56
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
LONGLONG QuadPart
Definition: typedefs.h:114
ULONG LowPart
Definition: typedefs.h:106
NTSTATUS DismountVolume(_Inout_ PVOLINFO Volume, _In_ BOOLEAN Force)
Attempts to dismount the designated volume.
Definition: volutil.c:152
_In_ WDFCOLLECTION _In_ ULONG Index
_Must_inspect_result_ _In_ WDFDEVICE _In_ PCUNICODE_STRING KeyName
Definition: wdfdevice.h:2705
_In_ WDFMEMORY _Out_opt_ size_t * BufferSize
Definition: wdfmemory.h:254
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _In_ ULONG _Out_opt_ PULONG _Out_opt_ PULONG ValueType
Definition: wdfregistry.h:282
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING ValueName
Definition: wdfregistry.h:243
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _In_ ULONG ValueLength
Definition: wdfregistry.h:275
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
_Reserved_ PVOID Reserved
Definition: winddi.h:3974
struct _STORAGE_DESCRIPTOR_HEADER * PSTORAGE_DESCRIPTOR_HEADER
struct _STORAGE_DEVICE_DESCRIPTOR * PSTORAGE_DEVICE_DESCRIPTOR
#define ERROR_UNRECOGNIZED_VOLUME
Definition: winerror.h:908
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
struct _CM_DISK_GEOMETRY_DEVICE_DATA * PCM_DISK_GEOMETRY_DEVICE_DATA
_In_ ULONG _In_ struct _SET_PARTITION_INFORMATION_EX * PartitionInfo
Definition: iofuncs.h:2105
_In_ ULONG _In_ ULONG PartitionNumber
Definition: iofuncs.h:2061
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180