ReactOS 0.4.15-dev-7907-g95bf896
partlist.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Setup Library
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Partition list functions
5 * COPYRIGHT: Copyright 2003-2019 Casper S. Hornstrup (chorns@users.sourceforge.net)
6 * Copyright 2018-2019 Hermes Belusca-Maito
7 */
8
9#include "precomp.h"
10#include <ntddscsi.h>
11
12#include "partlist.h"
13#include "fsrec.h"
14#include "registry.h"
15
16#define NDEBUG
17#include <debug.h>
18
19//#define DUMP_PARTITION_TABLE
20
21#include <pshpack1.h>
22
24{
28
29#include <poppack.h>
30
31
32/* FUNCTIONS ****************************************************************/
33
34#ifdef DUMP_PARTITION_TABLE
35static
36VOID
37DumpPartitionTable(
38 PDISKENTRY DiskEntry)
39{
41 ULONG i;
42
43 DbgPrint("\n");
44 DbgPrint("Index Start Length Hidden Nr Type Boot RW\n");
45 DbgPrint("----- ------------ ------------ ---------- -- ---- ---- --\n");
46
47 for (i = 0; i < DiskEntry->LayoutBuffer->PartitionCount; i++)
48 {
50 DbgPrint(" %3lu %12I64u %12I64u %10lu %2lu %2x %c %c\n",
51 i,
52 PartitionInfo->StartingOffset.QuadPart / DiskEntry->BytesPerSector,
53 PartitionInfo->PartitionLength.QuadPart / DiskEntry->BytesPerSector,
54 PartitionInfo->HiddenSectors,
55 PartitionInfo->PartitionNumber,
56 PartitionInfo->PartitionType,
57 PartitionInfo->BootIndicator ? '*': ' ',
58 PartitionInfo->RewritePartition ? 'Y': 'N');
59 }
60
61 DbgPrint("\n");
62}
63#endif
64
65
70{
71 ULONGLONG Temp;
72
73 Temp = Value / Alignment;
74
75 return Temp * Alignment;
76}
77
82{
83 ULONGLONG Temp, Result;
84
85 Temp = Value / Alignment;
86
87 Result = Temp * Alignment;
88 if (Value % Alignment)
90
91 return Result;
92}
93
96 IN ULONGLONG Dividend,
98{
99 return (Dividend + Divisor / 2) / Divisor;
100}
101
102
103static
104VOID
106 IN PDISKENTRY DiskEntry)
107{
109 WCHAR KeyName[32];
111
112 RtlInitUnicodeString(&DiskEntry->DriverName, NULL);
113
115 L"\\Scsi\\Scsi Port %hu",
116 DiskEntry->Port);
117
119
120 QueryTable[0].Name = L"Driver";
122 QueryTable[0].EntryContext = &DiskEntry->DriverName;
123
124 /* This will allocate DiskEntry->DriverName if needed */
126 KeyName,
128 NULL,
129 NULL);
130 if (!NT_SUCCESS(Status))
131 {
132 DPRINT1("RtlQueryRegistryValues() failed (Status %lx)\n", Status);
133 }
134}
135
136static
137VOID
140{
141 PDISKENTRY DiskEntry;
142 PPARTENTRY PartEntry;
143 PLIST_ENTRY Entry1;
144 PLIST_ENTRY Entry2;
146
147 Letter = L'C';
148
149 /* Assign drive letters to primary partitions */
150 for (Entry1 = List->DiskListHead.Flink;
151 Entry1 != &List->DiskListHead;
152 Entry1 = Entry1->Flink)
153 {
154 DiskEntry = CONTAINING_RECORD(Entry1, DISKENTRY, ListEntry);
155
156 for (Entry2 = DiskEntry->PrimaryPartListHead.Flink;
157 Entry2 != &DiskEntry->PrimaryPartListHead;
158 Entry2 = Entry2->Flink)
159 {
160 PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
161
162 PartEntry->DriveLetter = 0;
163
164 if (PartEntry->IsPartitioned &&
166 {
168
169 if (IsRecognizedPartition(PartEntry->PartitionType) ||
170 PartEntry->SectorCount.QuadPart != 0LL)
171 {
172 if (Letter <= L'Z')
173 {
174 PartEntry->DriveLetter = Letter;
175 Letter++;
176 }
177 }
178 }
179 }
180 }
181
182 /* Assign drive letters to logical drives */
183 for (Entry1 = List->DiskListHead.Flink;
184 Entry1 != &List->DiskListHead;
185 Entry1 = Entry1->Flink)
186 {
187 DiskEntry = CONTAINING_RECORD(Entry1, DISKENTRY, ListEntry);
188
189 for (Entry2 = DiskEntry->LogicalPartListHead.Flink;
190 Entry2 != &DiskEntry->LogicalPartListHead;
191 Entry2 = Entry2->Flink)
192 {
193 PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
194
195 PartEntry->DriveLetter = 0;
196
197 if (PartEntry->IsPartitioned)
198 {
200
201 if (IsRecognizedPartition(PartEntry->PartitionType) ||
202 PartEntry->SectorCount.QuadPart != 0LL)
203 {
204 if (Letter <= L'Z')
205 {
206 PartEntry->DriveLetter = Letter;
207 Letter++;
208 }
209 }
210 }
211 }
212 }
213}
214
215static NTSTATUS
216NTAPI
224{
225 PBIOSDISKENTRY BiosDiskEntry = (PBIOSDISKENTRY)Context;
226 UNICODE_STRING NameU;
227
228 if (ValueType == REG_SZ &&
229 ValueLength == 20 * sizeof(WCHAR) &&
230 ((PWCHAR)ValueData)[8] == L'-')
231 {
232 NameU.Buffer = (PWCHAR)ValueData;
233 NameU.Length = NameU.MaximumLength = 8 * sizeof(WCHAR);
234 RtlUnicodeStringToInteger(&NameU, 16, &BiosDiskEntry->Checksum);
235
236 NameU.Buffer = (PWCHAR)ValueData + 9;
237 RtlUnicodeStringToInteger(&NameU, 16, &BiosDiskEntry->Signature);
238
239 return STATUS_SUCCESS;
240 }
241
242 return STATUS_UNSUCCESSFUL;
243}
244
245static NTSTATUS
246NTAPI
254{
255 PBIOSDISKENTRY BiosDiskEntry = (PBIOSDISKENTRY)Context;
256 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
258 ULONG i;
259
262 return STATUS_UNSUCCESSFUL;
263
264 FullResourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)ValueData;
265
266 /* Hm. Version and Revision are not set on Microsoft Windows XP... */
267#if 0
268 if (FullResourceDescriptor->PartialResourceList.Version != 1 ||
269 FullResourceDescriptor->PartialResourceList.Revision != 1)
270 return STATUS_UNSUCCESSFUL;
271#endif
272
273 for (i = 0; i < FullResourceDescriptor->PartialResourceList.Count; i++)
274 {
277 continue;
278
279 DiskGeometry = (PCM_DISK_GEOMETRY_DEVICE_DATA)&FullResourceDescriptor->PartialResourceList.PartialDescriptors[i + 1];
280 BiosDiskEntry->DiskGeometry = *DiskGeometry;
281
282 return STATUS_SUCCESS;
283 }
284
285 return STATUS_UNSUCCESSFUL;
286}
287
288static NTSTATUS
289NTAPI
297{
298 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
300 ULONG i;
301
304 return STATUS_UNSUCCESSFUL;
305
306 FullResourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)ValueData;
307
308 /* Hm. Version and Revision are not set on Microsoft Windows XP... */
309#if 0
310 if (FullResourceDescriptor->PartialResourceList.Version != 1 ||
311 FullResourceDescriptor->PartialResourceList.Revision != 1)
312 return STATUS_UNSUCCESSFUL;
313#endif
314
315 for (i = 0; i < FullResourceDescriptor->PartialResourceList.Count; i++)
316 {
318 FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].u.DeviceSpecificData.DataSize % sizeof(CM_INT13_DRIVE_PARAMETER) != 0)
319 continue;
320
322 FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].u.DeviceSpecificData.DataSize);
323 if (*Int13Drives == NULL)
324 return STATUS_NO_MEMORY;
325
326 memcpy(*Int13Drives,
327 &FullResourceDescriptor->PartialResourceList.PartialDescriptors[i + 1],
328 FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].u.DeviceSpecificData.DataSize);
329 return STATUS_SUCCESS;
330 }
331
332 return STATUS_UNSUCCESSFUL;
333}
334
335
336static VOID
338 IN PPARTLIST PartList)
339{
341 WCHAR Name[120];
342 ULONG AdapterCount;
344 ULONG DiskCount;
346 PCM_INT13_DRIVE_PARAMETER Int13Drives;
347 PBIOSDISKENTRY BiosDiskEntry;
348
349#define ROOT_NAME L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter"
350
351 memset(QueryTable, 0, sizeof(QueryTable));
352
353 QueryTable[1].Name = L"Configuration Data";
355 Int13Drives = NULL;
357 L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System",
358 &QueryTable[1],
359 (PVOID)&Int13Drives,
360 NULL);
361 if (!NT_SUCCESS(Status))
362 {
363 DPRINT1("Unable to query the 'Configuration Data' key in '\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System', status=%lx\n", Status);
364 return;
365 }
366
367 for (AdapterCount = 0; ; ++AdapterCount)
368 {
370 L"%s\\%lu",
371 ROOT_NAME, AdapterCount);
373 Name,
374 &QueryTable[2],
375 NULL,
376 NULL);
377 if (!NT_SUCCESS(Status))
378 {
379 break;
380 }
381
383 L"%s\\%lu\\DiskController",
384 ROOT_NAME, AdapterCount);
386 Name,
387 &QueryTable[2],
388 NULL,
389 NULL);
390 if (NT_SUCCESS(Status))
391 {
392 for (ControllerCount = 0; ; ++ControllerCount)
393 {
395 L"%s\\%lu\\DiskController\\%lu",
396 ROOT_NAME, AdapterCount, ControllerCount);
398 Name,
399 &QueryTable[2],
400 NULL,
401 NULL);
402 if (!NT_SUCCESS(Status))
403 {
404 RtlFreeHeap(ProcessHeap, 0, Int13Drives);
405 return;
406 }
407
409 L"%s\\%lu\\DiskController\\%lu\\DiskPeripheral",
410 ROOT_NAME, AdapterCount, ControllerCount);
412 Name,
413 &QueryTable[2],
414 NULL,
415 NULL);
416 if (NT_SUCCESS(Status))
417 {
418 QueryTable[0].Name = L"Identifier";
420 QueryTable[1].Name = L"Configuration Data";
422
423 for (DiskCount = 0; ; ++DiskCount)
424 {
426 if (BiosDiskEntry == NULL)
427 {
428 RtlFreeHeap(ProcessHeap, 0, Int13Drives);
429 return;
430 }
431
433 L"%s\\%lu\\DiskController\\%lu\\DiskPeripheral\\%lu",
434 ROOT_NAME, AdapterCount, ControllerCount, DiskCount);
436 Name,
438 (PVOID)BiosDiskEntry,
439 NULL);
440 if (!NT_SUCCESS(Status))
441 {
442 RtlFreeHeap(ProcessHeap, 0, BiosDiskEntry);
443 RtlFreeHeap(ProcessHeap, 0, Int13Drives);
444 return;
445 }
446
447 BiosDiskEntry->AdapterNumber = 0; // And NOT "AdapterCount" as it needs to be hardcoded for BIOS!
448 BiosDiskEntry->ControllerNumber = ControllerCount;
449 BiosDiskEntry->DiskNumber = DiskCount;
450 BiosDiskEntry->DiskEntry = NULL;
451
452 if (DiskCount < Int13Drives[0].NumberDrives)
453 {
454 BiosDiskEntry->Int13DiskData = Int13Drives[DiskCount];
455 }
456 else
457 {
458 DPRINT1("Didn't find Int13 drive data for disk %u\n", DiskCount);
459 }
460
461 InsertTailList(&PartList->BiosDiskListHead, &BiosDiskEntry->ListEntry);
462
463 DPRINT("--->\n");
464 DPRINT("AdapterNumber: %lu\n", BiosDiskEntry->AdapterNumber);
465 DPRINT("ControllerNumber: %lu\n", BiosDiskEntry->ControllerNumber);
466 DPRINT("DiskNumber: %lu\n", BiosDiskEntry->DiskNumber);
467 DPRINT("Signature: %08lx\n", BiosDiskEntry->Signature);
468 DPRINT("Checksum: %08lx\n", BiosDiskEntry->Checksum);
469 DPRINT("BytesPerSector: %lu\n", BiosDiskEntry->DiskGeometry.BytesPerSector);
470 DPRINT("NumberOfCylinders: %lu\n", BiosDiskEntry->DiskGeometry.NumberOfCylinders);
471 DPRINT("NumberOfHeads: %lu\n", BiosDiskEntry->DiskGeometry.NumberOfHeads);
472 DPRINT("DriveSelect: %02x\n", BiosDiskEntry->Int13DiskData.DriveSelect);
473 DPRINT("MaxCylinders: %lu\n", BiosDiskEntry->Int13DiskData.MaxCylinders);
474 DPRINT("SectorsPerTrack: %d\n", BiosDiskEntry->Int13DiskData.SectorsPerTrack);
475 DPRINT("MaxHeads: %d\n", BiosDiskEntry->Int13DiskData.MaxHeads);
476 DPRINT("NumberDrives: %d\n", BiosDiskEntry->Int13DiskData.NumberDrives);
477 DPRINT("<---\n");
478 }
479 }
480 }
481 }
482 }
483
484 RtlFreeHeap(ProcessHeap, 0, Int13Drives);
485
486#undef ROOT_NAME
487}
488
489
490/*
491 * Detects whether a disk reports as a "super-floppy", i.e. an unpartitioned
492 * disk with a valid VBR, following the criteria used by IoReadPartitionTable()
493 * and IoWritePartitionTable():
494 * only one single partition starting at the beginning of the disk; the reported
495 * defaults are: partition number being zero and its type being FAT16 non-bootable.
496 * Note also that accessing \Device\HarddiskN\Partition0 or Partition1 returns
497 * the same data.
498 */
499// static
502 IN PDISKENTRY DiskEntry)
503{
505 ULONGLONG PartitionLengthEstimate;
506
507 /* No layout buffer: we cannot say anything yet */
508 if (DiskEntry->LayoutBuffer == NULL)
509 return FALSE;
510
511 /* We must have only one partition */
512 if (DiskEntry->LayoutBuffer->PartitionCount != 1)
513 return FALSE;
514
515 /* Get the single partition entry */
516 PartitionInfo = DiskEntry->LayoutBuffer->PartitionEntry;
517
518 /* The single partition must start at the beginning of the disk */
519 if (!(PartitionInfo->StartingOffset.QuadPart == 0 &&
520 PartitionInfo->HiddenSectors == 0))
521 {
522 return FALSE;
523 }
524
525 /* The disk signature is usually set to one; warn in case it's not */
526 if (DiskEntry->LayoutBuffer->Signature != 1)
527 {
528 DPRINT1("Super-Floppy disk %lu signature %08x != 1!\n",
529 DiskEntry->DiskNumber, DiskEntry->LayoutBuffer->Signature);
530 }
531
532 /*
533 * The partition number must be zero or one, be recognized,
534 * have FAT16 type and report as non-bootable.
535 */
536 if ((PartitionInfo->PartitionNumber != 0 &&
537 PartitionInfo->PartitionNumber != 1) ||
538 PartitionInfo->RecognizedPartition != TRUE ||
539 PartitionInfo->PartitionType != PARTITION_FAT_16 ||
540 PartitionInfo->BootIndicator != FALSE)
541 {
542 DPRINT1("Super-Floppy disk %lu does not return default settings!\n"
543 " PartitionNumber = %lu, expected 0\n"
544 " RecognizedPartition = %s, expected TRUE\n"
545 " PartitionType = 0x%02x, expected 0x04 (PARTITION_FAT_16)\n"
546 " BootIndicator = %s, expected FALSE\n",
547 DiskEntry->DiskNumber,
548 PartitionInfo->PartitionNumber,
549 PartitionInfo->RecognizedPartition ? "TRUE" : "FALSE",
550 PartitionInfo->PartitionType,
551 PartitionInfo->BootIndicator ? "TRUE" : "FALSE");
552 }
553
554 /* The partition lengths should agree */
555 PartitionLengthEstimate = GetDiskSizeInBytes(DiskEntry);
556 if (PartitionInfo->PartitionLength.QuadPart != PartitionLengthEstimate)
557 {
558 DPRINT1("PartitionLength = %I64u is different from PartitionLengthEstimate = %I64u\n",
559 PartitionInfo->PartitionLength.QuadPart, PartitionLengthEstimate);
560 }
561
562 return TRUE;
563}
564
565
566/*
567 * Inserts the disk region represented by PartEntry into either the primary
568 * or the logical partition list of the given disk.
569 * The lists are kept sorted by increasing order of start sectors.
570 * Of course no disk region should overlap at all with one another.
571 */
572static
575 IN PDISKENTRY DiskEntry,
576 IN PPARTENTRY PartEntry,
578{
581 PPARTENTRY PartEntry2;
582
583 /* Use the correct partition list */
585 List = &DiskEntry->LogicalPartListHead;
586 else
587 List = &DiskEntry->PrimaryPartListHead;
588
589 /* Find the first disk region before which we need to insert the new one */
590 for (Entry = List->Flink; Entry != List; Entry = Entry->Flink)
591 {
592 PartEntry2 = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
593
594 /* Ignore any unused empty region */
595 if ((PartEntry2->PartitionType == PARTITION_ENTRY_UNUSED &&
596 PartEntry2->StartSector.QuadPart == 0) || PartEntry2->SectorCount.QuadPart == 0)
597 {
598 continue;
599 }
600
601 /* If the current region ends before the one to be inserted, try again */
602 if (PartEntry2->StartSector.QuadPart + PartEntry2->SectorCount.QuadPart - 1 < PartEntry->StartSector.QuadPart)
603 continue;
604
605 /*
606 * One of the disk region boundaries crosses the desired region
607 * (it starts after the desired region, or ends before the end
608 * of the desired region): this is an impossible situation because
609 * disk regions (partitions) cannot overlap!
610 * Throw an error and bail out.
611 */
612 if (max(PartEntry->StartSector.QuadPart, PartEntry2->StartSector.QuadPart)
613 <=
614 min( PartEntry->StartSector.QuadPart + PartEntry->SectorCount.QuadPart - 1,
615 PartEntry2->StartSector.QuadPart + PartEntry2->SectorCount.QuadPart - 1))
616 {
617 DPRINT1("Disk region overlap problem, stopping there!\n"
618 "Partition to be inserted:\n"
619 " StartSector = %I64u ; EndSector = %I64u\n"
620 "Existing disk region:\n"
621 " StartSector = %I64u ; EndSector = %I64u\n",
622 PartEntry->StartSector.QuadPart,
623 PartEntry->StartSector.QuadPart + PartEntry->SectorCount.QuadPart - 1,
624 PartEntry2->StartSector.QuadPart,
625 PartEntry2->StartSector.QuadPart + PartEntry2->SectorCount.QuadPart - 1);
626 return FALSE;
627 }
628
629 /* We have found the first region before which the new one has to be inserted */
630 break;
631 }
632
633 /* Insert the disk region */
634 InsertTailList(Entry, &PartEntry->ListEntry);
635 return TRUE;
636}
637
638static
641 IN PDISKENTRY DiskEntry,
642 IN OUT PLIST_ENTRY ListHead,
643 IN ULONGLONG StartSector,
645 IN BOOLEAN LogicalSpace)
646{
647 PPARTENTRY NewPartEntry;
648
649 NewPartEntry = RtlAllocateHeap(ProcessHeap,
651 sizeof(PARTENTRY));
652 if (NewPartEntry == NULL)
653 return NULL;
654
655 NewPartEntry->DiskEntry = DiskEntry;
656
657 NewPartEntry->StartSector.QuadPart = StartSector;
658 NewPartEntry->SectorCount.QuadPart = SectorCount;
659
660 NewPartEntry->LogicalPartition = LogicalSpace;
661 NewPartEntry->IsPartitioned = FALSE;
663 NewPartEntry->FormatState = Unformatted;
664 NewPartEntry->FileSystem[0] = L'\0';
665
666 DPRINT1("First Sector : %I64u\n", NewPartEntry->StartSector.QuadPart);
667 DPRINT1("Last Sector : %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
668 DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
669
670 /* Insert the new entry into the list */
671 InsertTailList(ListHead, &NewPartEntry->ListEntry);
672
673 return NewPartEntry;
674}
675
676static
679 _Inout_ PPARTENTRY PartEntry,
680 _In_opt_ ULONGLONG SizeBytes)
681{
682 PDISKENTRY DiskEntry = PartEntry->DiskEntry;
684
685 DPRINT1("Current entry sector count: %I64u\n", PartEntry->SectorCount.QuadPart);
686
687 /* The entry must not be already partitioned and not be void */
688 ASSERT(!PartEntry->IsPartitioned);
689 ASSERT(PartEntry->SectorCount.QuadPart);
690
691 /* Convert the size in bytes to sector count. SizeBytes being
692 * zero means the caller wants to use all the empty space. */
693 if ((SizeBytes == 0) || (SizeBytes == GetPartEntrySizeInBytes(PartEntry)))
694 {
695 /* Use all of the unpartitioned disk space */
696 SectorCount = PartEntry->SectorCount.QuadPart;
697 }
698 else
699 {
700 SectorCount = SizeBytes / DiskEntry->BytesPerSector;
701 if (SectorCount == 0)
702 {
703 /* SizeBytes was certainly less than the minimal size, so fail */
704 DPRINT1("Partition size %I64u too small\n", SizeBytes);
705 return FALSE;
706 }
707 }
708 DPRINT1(" New sector count: %I64u\n", SectorCount);
709
710 /* Fail if we request more sectors than what the entry actually contains */
711 if (SectorCount > PartEntry->SectorCount.QuadPart)
712 return FALSE;
713
714 if ((SectorCount == 0) ||
715 (AlignDown(PartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) -
716 PartEntry->StartSector.QuadPart == PartEntry->SectorCount.QuadPart))
717 {
718 /* Reuse the whole current entry */
719 }
720 else
721 {
722 ULONGLONG StartSector;
723 ULONGLONG SectorCount2;
724 PPARTENTRY NewPartEntry;
725
726 /* Create a partition entry that represents the remaining space
727 * after the partition to be initialized */
728
729 StartSector = AlignDown(PartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment);
730 SectorCount2 = PartEntry->StartSector.QuadPart + PartEntry->SectorCount.QuadPart - StartSector;
731
732 NewPartEntry = CreateInsertBlankRegion(DiskEntry,
733 PartEntry->ListEntry.Flink,
734 StartSector,
735 SectorCount2,
736 PartEntry->LogicalPartition);
737 if (NewPartEntry == NULL)
738 {
739 DPRINT1("Failed to create a new empty region for disk space!\n");
740 return FALSE;
741 }
742
743 /* Resize down the partition entry; its StartSector remains the same */
744 PartEntry->SectorCount.QuadPart = StartSector - PartEntry->StartSector.QuadPart;
745 }
746
747 /* Convert the partition entry to 'New (Unformatted)' */
748 PartEntry->New = TRUE;
749 PartEntry->IsPartitioned = TRUE;
750
751// FIXME: Use FileSystemToMBRPartitionType() only for MBR, otherwise use PARTITION_BASIC_DATA_GUID.
752 PartEntry->PartitionType = FileSystemToMBRPartitionType(L"RAW",
753 PartEntry->StartSector.QuadPart,
754 PartEntry->SectorCount.QuadPart);
755 ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
756
757 PartEntry->FormatState = Unformatted;
758 PartEntry->FileSystem[0] = L'\0';
759 PartEntry->BootIndicator = FALSE;
760
761 DPRINT1("First Sector : %I64u\n", PartEntry->StartSector.QuadPart);
762 DPRINT1("Last Sector : %I64u\n", PartEntry->StartSector.QuadPart + PartEntry->SectorCount.QuadPart - 1);
763 DPRINT1("Total Sectors: %I64u\n", PartEntry->SectorCount.QuadPart);
764
765 return TRUE;
766}
767
768
769static
770VOID
772 IN ULONG DiskNumber,
773 IN PDISKENTRY DiskEntry,
774 IN ULONG PartitionIndex,
776{
779 PPARTENTRY PartEntry;
780 HANDLE PartitionHandle;
783 WCHAR PathBuffer[MAX_PATH];
785 UCHAR LabelBuffer[sizeof(FILE_FS_VOLUME_INFORMATION) + 256 * sizeof(WCHAR)];
787
788 PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[PartitionIndex];
789
790 if (PartitionInfo->PartitionType == PARTITION_ENTRY_UNUSED ||
792 {
793 return;
794 }
795
796 PartEntry = RtlAllocateHeap(ProcessHeap,
798 sizeof(PARTENTRY));
799 if (PartEntry == NULL)
800 return;
801
802 PartEntry->DiskEntry = DiskEntry;
803
804 PartEntry->StartSector.QuadPart = (ULONGLONG)PartitionInfo->StartingOffset.QuadPart / DiskEntry->BytesPerSector;
805 PartEntry->SectorCount.QuadPart = (ULONGLONG)PartitionInfo->PartitionLength.QuadPart / DiskEntry->BytesPerSector;
806
807 PartEntry->BootIndicator = PartitionInfo->BootIndicator;
808 PartEntry->PartitionType = PartitionInfo->PartitionType;
809
811 PartEntry->IsPartitioned = TRUE;
812 PartEntry->OnDiskPartitionNumber = PartitionInfo->PartitionNumber;
813 PartEntry->PartitionNumber = PartitionInfo->PartitionNumber;
814 PartEntry->PartitionIndex = PartitionIndex;
815
816 /* Specify the partition as initially unformatted */
817 PartEntry->FormatState = Unformatted;
818 PartEntry->FileSystem[0] = L'\0';
819
820 /* Initialize the partition volume label */
821 RtlZeroMemory(PartEntry->VolumeLabel, sizeof(PartEntry->VolumeLabel));
822
823 if (IsContainerPartition(PartEntry->PartitionType))
824 {
825 PartEntry->FormatState = Unformatted;
826
827 if (LogicalPartition == FALSE && DiskEntry->ExtendedPartition == NULL)
828 DiskEntry->ExtendedPartition = PartEntry;
829 }
830 else if (IsRecognizedPartition(PartEntry->PartitionType))
831 {
832 ASSERT(PartitionInfo->RecognizedPartition);
833 ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0);
834
835 /* Try to open the volume so as to mount it */
836 RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
837 L"\\Device\\Harddisk%lu\\Partition%lu",
838 DiskEntry->DiskNumber,
839 PartEntry->PartitionNumber);
840 RtlInitUnicodeString(&Name, PathBuffer);
841
843 &Name,
845 NULL,
846 NULL);
847
848 PartitionHandle = NULL;
849 Status = NtOpenFile(&PartitionHandle,
855 if (!NT_SUCCESS(Status))
856 {
857 DPRINT1("NtOpenFile() failed, Status 0x%08lx\n", Status);
858 }
859
860 if (PartitionHandle)
861 {
863
864 /* We don't have a FS, try to guess one */
865 Status = InferFileSystem(NULL, PartitionHandle,
866 PartEntry->FileSystem,
867 sizeof(PartEntry->FileSystem));
868 if (!NT_SUCCESS(Status))
869 DPRINT1("InferFileSystem() failed, Status 0x%08lx\n", Status);
870 }
871 if (*PartEntry->FileSystem)
872 {
873 ASSERT(PartitionHandle);
874
875 /*
876 * Handle partition mounted with RawFS: it is
877 * either unformatted or has an unknown format.
878 */
879 if (wcsicmp(PartEntry->FileSystem, L"RAW") == 0)
880 {
881 /*
882 * True unformatted partitions on NT are created with their
883 * partition type set to either one of the following values,
884 * and are mounted with RawFS. This is done this way since we
885 * are assured to have FAT support, which is the only FS that
886 * uses these partition types. Therefore, having a partition
887 * mounted with RawFS and with these partition types means that
888 * the FAT FS was unable to mount it beforehand and thus the
889 * partition is unformatted.
890 * However, any partition mounted by RawFS that does NOT have
891 * any of these partition types must be considered as having
892 * an unknown format.
893 */
894 if (PartEntry->PartitionType == PARTITION_FAT_12 ||
895 PartEntry->PartitionType == PARTITION_FAT_16 ||
896 PartEntry->PartitionType == PARTITION_HUGE ||
897 PartEntry->PartitionType == PARTITION_XINT13 ||
898 PartEntry->PartitionType == PARTITION_FAT32 ||
900 {
901 PartEntry->FormatState = Unformatted;
902 }
903 else
904 {
905 /* Close the partition before dismounting */
906 NtClose(PartitionHandle);
907 PartitionHandle = NULL;
908 /*
909 * Dismount the partition since RawFS owns it, and set its
910 * format to unknown (may or may not be actually formatted).
911 */
912 DismountVolume(PartEntry);
913 PartEntry->FormatState = UnknownFormat;
914 PartEntry->FileSystem[0] = L'\0';
915 }
916 }
917 else
918 {
919 PartEntry->FormatState = Preformatted;
920 }
921 }
922 else
923 {
924 PartEntry->FormatState = UnknownFormat;
925 }
926
927 /* Retrieve the partition volume label */
928 if (PartitionHandle)
929 {
930 Status = NtQueryVolumeInformationFile(PartitionHandle,
932 &LabelBuffer,
933 sizeof(LabelBuffer),
935 if (NT_SUCCESS(Status))
936 {
937 /* Copy the (possibly truncated) volume label and NULL-terminate it */
938 RtlStringCbCopyNW(PartEntry->VolumeLabel, sizeof(PartEntry->VolumeLabel),
939 LabelInfo->VolumeLabel, LabelInfo->VolumeLabelLength);
940 }
941 else
942 {
943 DPRINT1("NtQueryVolumeInformationFile() failed, Status 0x%08lx\n", Status);
944 }
945 }
946
947 /* Close the partition */
948 if (PartitionHandle)
949 NtClose(PartitionHandle);
950 }
951 else
952 {
953 /* Unknown partition, hence unknown format (may or may not be actually formatted) */
954 PartEntry->FormatState = UnknownFormat;
955 }
956
957 InsertDiskRegion(DiskEntry, PartEntry, LogicalPartition);
958}
959
960static
961VOID
963 IN PDISKENTRY DiskEntry)
964{
965 ULONGLONG StartSector;
967 ULONGLONG LastStartSector;
968 ULONGLONG LastSectorCount;
969 ULONGLONG LastUnusedSectorCount;
970 PPARTENTRY PartEntry;
971 PPARTENTRY NewPartEntry;
973
974 DPRINT("ScanForUnpartitionedDiskSpace()\n");
975
976 if (IsListEmpty(&DiskEntry->PrimaryPartListHead))
977 {
978 DPRINT1("No primary partition!\n");
979
980 /* Create a partition entry that represents the empty disk */
981
982 if (DiskEntry->SectorAlignment < 2048)
983 StartSector = 2048ULL;
984 else
985 StartSector = (ULONGLONG)DiskEntry->SectorAlignment;
986 SectorCount = AlignDown(DiskEntry->SectorCount.QuadPart, DiskEntry->SectorAlignment) - StartSector;
987
988 NewPartEntry = CreateInsertBlankRegion(DiskEntry,
989 &DiskEntry->PrimaryPartListHead,
990 StartSector,
992 FALSE);
993 if (NewPartEntry == NULL)
994 DPRINT1("Failed to create a new empty region for full disk space!\n");
995
996 return;
997 }
998
999 /* Start partition at head 1, cylinder 0 */
1000 if (DiskEntry->SectorAlignment < 2048)
1001 LastStartSector = 2048ULL;
1002 else
1003 LastStartSector = (ULONGLONG)DiskEntry->SectorAlignment;
1004 LastSectorCount = 0ULL;
1005 LastUnusedSectorCount = 0ULL;
1006
1007 for (Entry = DiskEntry->PrimaryPartListHead.Flink;
1008 Entry != &DiskEntry->PrimaryPartListHead;
1009 Entry = Entry->Flink)
1010 {
1011 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
1012
1013 if (PartEntry->PartitionType != PARTITION_ENTRY_UNUSED ||
1014 PartEntry->SectorCount.QuadPart != 0ULL)
1015 {
1016 LastUnusedSectorCount =
1017 PartEntry->StartSector.QuadPart - (LastStartSector + LastSectorCount);
1018
1019 if (PartEntry->StartSector.QuadPart > (LastStartSector + LastSectorCount) &&
1020 LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment)
1021 {
1022 DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount);
1023
1024 StartSector = LastStartSector + LastSectorCount;
1025 SectorCount = AlignDown(StartSector + LastUnusedSectorCount, DiskEntry->SectorAlignment) - StartSector;
1026
1027 /* Insert the table into the list */
1028 NewPartEntry = CreateInsertBlankRegion(DiskEntry,
1029 &PartEntry->ListEntry,
1030 StartSector,
1032 FALSE);
1033 if (NewPartEntry == NULL)
1034 {
1035 DPRINT1("Failed to create a new empty region for disk space!\n");
1036 return;
1037 }
1038 }
1039
1040 LastStartSector = PartEntry->StartSector.QuadPart;
1041 LastSectorCount = PartEntry->SectorCount.QuadPart;
1042 }
1043 }
1044
1045 /* Check for trailing unpartitioned disk space */
1046 if ((LastStartSector + LastSectorCount) < DiskEntry->SectorCount.QuadPart)
1047 {
1048 LastUnusedSectorCount = AlignDown(DiskEntry->SectorCount.QuadPart - (LastStartSector + LastSectorCount), DiskEntry->SectorAlignment);
1049
1050 if (LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment)
1051 {
1052 DPRINT("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount);
1053
1054 StartSector = LastStartSector + LastSectorCount;
1055 SectorCount = AlignDown(StartSector + LastUnusedSectorCount, DiskEntry->SectorAlignment) - StartSector;
1056
1057 /* Append the table to the list */
1058 NewPartEntry = CreateInsertBlankRegion(DiskEntry,
1059 &DiskEntry->PrimaryPartListHead,
1060 StartSector,
1062 FALSE);
1063 if (NewPartEntry == NULL)
1064 {
1065 DPRINT1("Failed to create a new empty region for trailing disk space!\n");
1066 return;
1067 }
1068 }
1069 }
1070
1071 if (DiskEntry->ExtendedPartition != NULL)
1072 {
1073 if (IsListEmpty(&DiskEntry->LogicalPartListHead))
1074 {
1075 DPRINT1("No logical partition!\n");
1076
1077 /* Create a partition entry that represents the empty extended partition */
1078
1079 StartSector = DiskEntry->ExtendedPartition->StartSector.QuadPart + (ULONGLONG)DiskEntry->SectorAlignment;
1080 SectorCount = DiskEntry->ExtendedPartition->SectorCount.QuadPart - (ULONGLONG)DiskEntry->SectorAlignment;
1081
1082 NewPartEntry = CreateInsertBlankRegion(DiskEntry,
1083 &DiskEntry->LogicalPartListHead,
1084 StartSector,
1086 TRUE);
1087 if (NewPartEntry == NULL)
1088 {
1089 DPRINT1("Failed to create a new empty region for full extended partition space!\n");
1090 return;
1091 }
1092
1093 return;
1094 }
1095
1096 /* Start partition at head 1, cylinder 0 */
1097 LastStartSector = DiskEntry->ExtendedPartition->StartSector.QuadPart + (ULONGLONG)DiskEntry->SectorAlignment;
1098 LastSectorCount = 0ULL;
1099 LastUnusedSectorCount = 0ULL;
1100
1101 for (Entry = DiskEntry->LogicalPartListHead.Flink;
1102 Entry != &DiskEntry->LogicalPartListHead;
1103 Entry = Entry->Flink)
1104 {
1105 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
1106
1107 if (PartEntry->PartitionType != PARTITION_ENTRY_UNUSED ||
1108 PartEntry->SectorCount.QuadPart != 0ULL)
1109 {
1110 LastUnusedSectorCount =
1111 PartEntry->StartSector.QuadPart - (ULONGLONG)DiskEntry->SectorAlignment - (LastStartSector + LastSectorCount);
1112
1113 if ((PartEntry->StartSector.QuadPart - (ULONGLONG)DiskEntry->SectorAlignment) > (LastStartSector + LastSectorCount) &&
1114 LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment)
1115 {
1116 DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount);
1117
1118 StartSector = LastStartSector + LastSectorCount;
1119 SectorCount = AlignDown(StartSector + LastUnusedSectorCount, DiskEntry->SectorAlignment) - StartSector;
1120
1121 /* Insert the table into the list */
1122 NewPartEntry = CreateInsertBlankRegion(DiskEntry,
1123 &PartEntry->ListEntry,
1124 StartSector,
1126 TRUE);
1127 if (NewPartEntry == NULL)
1128 {
1129 DPRINT1("Failed to create a new empty region for extended partition space!\n");
1130 return;
1131 }
1132 }
1133
1134 LastStartSector = PartEntry->StartSector.QuadPart;
1135 LastSectorCount = PartEntry->SectorCount.QuadPart;
1136 }
1137 }
1138
1139 /* Check for trailing unpartitioned disk space */
1140 if ((LastStartSector + LastSectorCount) < DiskEntry->ExtendedPartition->StartSector.QuadPart + DiskEntry->ExtendedPartition->SectorCount.QuadPart)
1141 {
1142 LastUnusedSectorCount = AlignDown(DiskEntry->ExtendedPartition->StartSector.QuadPart +
1143 DiskEntry->ExtendedPartition->SectorCount.QuadPart - (LastStartSector + LastSectorCount),
1144 DiskEntry->SectorAlignment);
1145
1146 if (LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment)
1147 {
1148 DPRINT("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount);
1149
1150 StartSector = LastStartSector + LastSectorCount;
1151 SectorCount = AlignDown(StartSector + LastUnusedSectorCount, DiskEntry->SectorAlignment) - StartSector;
1152
1153 /* Append the table to the list */
1154 NewPartEntry = CreateInsertBlankRegion(DiskEntry,
1155 &DiskEntry->LogicalPartListHead,
1156 StartSector,
1158 TRUE);
1159 if (NewPartEntry == NULL)
1160 {
1161 DPRINT1("Failed to create a new empty region for extended partition space!\n");
1162 return;
1163 }
1164 }
1165 }
1166 }
1167
1168 DPRINT("ScanForUnpartitionedDiskSpace() done\n");
1169}
1170
1171static
1172VOID
1175 IN PDISKENTRY DiskEntry)
1176{
1177 LARGE_INTEGER SystemTime;
1179 PLIST_ENTRY Entry2;
1180 PDISKENTRY DiskEntry2;
1181 PUCHAR Buffer;
1182
1183 if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
1184 {
1185 DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
1186 return;
1187 }
1188
1189 Buffer = (PUCHAR)&DiskEntry->LayoutBuffer->Signature;
1190
1191 while (TRUE)
1192 {
1193 NtQuerySystemTime(&SystemTime);
1194 RtlTimeToTimeFields(&SystemTime, &TimeFields);
1195
1196 Buffer[0] = (UCHAR)(TimeFields.Year & 0xFF) + (UCHAR)(TimeFields.Hour & 0xFF);
1197 Buffer[1] = (UCHAR)(TimeFields.Year >> 8) + (UCHAR)(TimeFields.Minute & 0xFF);
1198 Buffer[2] = (UCHAR)(TimeFields.Month & 0xFF) + (UCHAR)(TimeFields.Second & 0xFF);
1199 Buffer[3] = (UCHAR)(TimeFields.Day & 0xFF) + (UCHAR)(TimeFields.Milliseconds & 0xFF);
1200
1201 if (DiskEntry->LayoutBuffer->Signature == 0)
1202 {
1203 continue;
1204 }
1205
1206 /* Check if the signature already exist */
1207 /* FIXME:
1208 * Check also signatures from disks, which are
1209 * not visible (bootable) by the bios.
1210 */
1211 for (Entry2 = List->DiskListHead.Flink;
1212 Entry2 != &List->DiskListHead;
1213 Entry2 = Entry2->Flink)
1214 {
1215 DiskEntry2 = CONTAINING_RECORD(Entry2, DISKENTRY, ListEntry);
1216
1217 if (DiskEntry2->DiskStyle == PARTITION_STYLE_GPT)
1218 {
1219 DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
1220 continue;
1221 }
1222
1223 if (DiskEntry != DiskEntry2 &&
1224 DiskEntry->LayoutBuffer->Signature == DiskEntry2->LayoutBuffer->Signature)
1225 break;
1226 }
1227
1228 if (Entry2 == &List->DiskListHead)
1229 break;
1230 }
1231}
1232
1233static
1234VOID
1237{
1239 PDISKENTRY DiskEntry;
1240
1241 /* Update each disk */
1242 for (Entry = List->DiskListHead.Flink;
1243 Entry != &List->DiskListHead;
1244 Entry = Entry->Flink)
1245 {
1246 DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
1247
1248 if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
1249 {
1250 DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
1251 continue;
1252 }
1253
1254 if (DiskEntry->LayoutBuffer &&
1255 DiskEntry->LayoutBuffer->Signature == 0)
1256 {
1257 SetDiskSignature(List, DiskEntry);
1259 }
1260 }
1261}
1262
1263static
1264VOID
1267{
1268 PLIST_ENTRY ListEntry;
1269 PBIOSDISKENTRY BiosDiskEntry;
1270 PDISKENTRY DiskEntry;
1271 ULONG HwAdapterNumber = 0;
1272 ULONG HwControllerNumber = 0;
1273 ULONG RemovableDiskCount = 0;
1274
1275 /*
1276 * Enumerate the disks recognized by the BIOS and recompute the disk
1277 * numbers on the system when *ALL* removable disks are not connected.
1278 * The entries are inserted in increasing order of AdapterNumber,
1279 * ControllerNumber and DiskNumber.
1280 */
1281 for (ListEntry = List->BiosDiskListHead.Flink;
1282 ListEntry != &List->BiosDiskListHead;
1283 ListEntry = ListEntry->Flink)
1284 {
1285 BiosDiskEntry = CONTAINING_RECORD(ListEntry, BIOSDISKENTRY, ListEntry);
1286 DiskEntry = BiosDiskEntry->DiskEntry;
1287
1288 /*
1289 * If the adapter or controller numbers change, update them and reset
1290 * the number of removable disks on this adapter/controller.
1291 */
1292 if (HwAdapterNumber != BiosDiskEntry->AdapterNumber ||
1293 HwControllerNumber != BiosDiskEntry->ControllerNumber)
1294 {
1295 HwAdapterNumber = BiosDiskEntry->AdapterNumber;
1296 HwControllerNumber = BiosDiskEntry->ControllerNumber;
1297 RemovableDiskCount = 0;
1298 }
1299
1300 /* Adjust the actual hardware disk number */
1301 if (DiskEntry)
1302 {
1303 ASSERT(DiskEntry->HwDiskNumber == BiosDiskEntry->DiskNumber);
1304
1305 if (DiskEntry->MediaType == RemovableMedia)
1306 {
1307 /* Increase the number of removable disks and set the disk number to zero */
1308 ++RemovableDiskCount;
1309 DiskEntry->HwFixedDiskNumber = 0;
1310 }
1311 else // if (DiskEntry->MediaType == FixedMedia)
1312 {
1313 /* Adjust the fixed disk number, offset by the number of removable disks found before this one */
1314 DiskEntry->HwFixedDiskNumber = BiosDiskEntry->DiskNumber - RemovableDiskCount;
1315 }
1316 }
1317 else
1318 {
1319 DPRINT1("BIOS disk %lu is not recognized by NTOS!\n", BiosDiskEntry->DiskNumber);
1320 }
1321 }
1322}
1323
1324static
1325VOID
1328 IN ULONG DiskNumber,
1330{
1331 DISK_GEOMETRY DiskGeometry;
1332 SCSI_ADDRESS ScsiAddress;
1333 PDISKENTRY DiskEntry;
1337 PULONG Buffer;
1339 WCHAR Identifier[20];
1340 ULONG Checksum;
1342 ULONG i;
1343 PLIST_ENTRY ListEntry;
1344 PBIOSDISKENTRY BiosDiskEntry;
1345 ULONG LayoutBufferSize;
1346 PDRIVE_LAYOUT_INFORMATION NewLayoutBuffer;
1347
1348 /* Retrieve the drive geometry */
1350 NULL,
1351 NULL,
1352 NULL,
1353 &Iosb,
1355 NULL,
1356 0,
1357 &DiskGeometry,
1358 sizeof(DiskGeometry));
1359 if (!NT_SUCCESS(Status))
1360 return;
1361
1362 if (DiskGeometry.MediaType != FixedMedia &&
1363 DiskGeometry.MediaType != RemovableMedia)
1364 {
1365 return;
1366 }
1367
1368 /*
1369 * FIXME: Here we suppose the disk is always SCSI. What if it is
1370 * of another type? To check this we need to retrieve the name of
1371 * the driver the disk device belongs to.
1372 */
1374 NULL,
1375 NULL,
1376 NULL,
1377 &Iosb,
1379 NULL,
1380 0,
1381 &ScsiAddress,
1382 sizeof(ScsiAddress));
1383 if (!NT_SUCCESS(Status))
1384 return;
1385
1386 /*
1387 * Check whether the disk is initialized, by looking at its MBR.
1388 * NOTE that this must be generalized to GPT disks as well!
1389 */
1390
1392 0,
1393 DiskGeometry.BytesPerSector);
1394 if (Mbr == NULL)
1395 return;
1396
1397 FileOffset.QuadPart = 0;
1399 NULL,
1400 NULL,
1401 NULL,
1402 &Iosb,
1403 (PVOID)Mbr,
1404 DiskGeometry.BytesPerSector,
1405 &FileOffset,
1406 NULL);
1407 if (!NT_SUCCESS(Status))
1408 {
1409 RtlFreeHeap(ProcessHeap, 0, Mbr);
1410 DPRINT1("NtReadFile failed, status=%x\n", Status);
1411 return;
1412 }
1413 Signature = Mbr->Signature;
1414
1415 /* Calculate the MBR checksum */
1416 Checksum = 0;
1417 Buffer = (PULONG)Mbr;
1418 for (i = 0; i < 128; i++)
1419 {
1420 Checksum += Buffer[i];
1421 }
1422 Checksum = ~Checksum + 1;
1423
1425 L"%08x-%08x-%c",
1426 Checksum, Signature,
1427 (Mbr->Magic == PARTITION_MAGIC) ? L'A' : L'X');
1428 DPRINT("Identifier: %S\n", Identifier);
1429
1430 DiskEntry = RtlAllocateHeap(ProcessHeap,
1432 sizeof(DISKENTRY));
1433 if (DiskEntry == NULL)
1434 {
1435 RtlFreeHeap(ProcessHeap, 0, Mbr);
1436 DPRINT1("Failed to allocate a new disk entry.\n");
1437 return;
1438 }
1439
1440 DiskEntry->PartList = List;
1441
1442#if 0
1443 {
1444 FILE_FS_DEVICE_INFORMATION FileFsDevice;
1445
1446 /* Query the device for its type */
1448 &Iosb,
1449 &FileFsDevice,
1450 sizeof(FileFsDevice),
1452 if (!NT_SUCCESS(Status))
1453 {
1454 DPRINT1("Couldn't detect device type for disk %lu of identifier '%S'...\n", DiskNumber, Identifier);
1455 }
1456 else
1457 {
1458 DPRINT1("Disk %lu : DeviceType: 0x%08x ; Characteristics: 0x%08x\n", DiskNumber, FileFsDevice.DeviceType, FileFsDevice.Characteristics);
1459 }
1460 }
1461 // NOTE: We may also use NtQueryVolumeInformationFile(FileFsDeviceInformation).
1462#endif
1463 DiskEntry->MediaType = DiskGeometry.MediaType;
1464 if (DiskEntry->MediaType == RemovableMedia)
1465 {
1466 DPRINT1("Disk %lu of identifier '%S' is removable\n", DiskNumber, Identifier);
1467 }
1468 else // if (DiskEntry->MediaType == FixedMedia)
1469 {
1470 DPRINT1("Disk %lu of identifier '%S' is fixed\n", DiskNumber, Identifier);
1471 }
1472
1473// DiskEntry->Checksum = Checksum;
1474// DiskEntry->Signature = Signature;
1475 DiskEntry->BiosFound = FALSE;
1476
1477 /*
1478 * Check if this disk has a valid MBR: verify its signature,
1479 * and whether its two first bytes are a valid instruction
1480 * (related to this, see IsThereAValidBootSector() in partlist.c).
1481 *
1482 * See also ntoskrnl/fstub/fstubex.c!FstubDetectPartitionStyle().
1483 */
1484
1485 // DiskEntry->NoMbr = (Mbr->Magic != PARTITION_MAGIC || (*(PUSHORT)Mbr->BootCode) == 0x0000);
1486
1487 /* If we have not the 0xAA55 then it's raw partition */
1488 if (Mbr->Magic != PARTITION_MAGIC)
1489 {
1490 DiskEntry->DiskStyle = PARTITION_STYLE_RAW;
1491 }
1492 /* Check partitions types: if first is 0xEE and all the others 0, we have GPT */
1493 else if (Mbr->Partition[0].PartitionType == EFI_PMBR_OSTYPE_EFI &&
1494 Mbr->Partition[1].PartitionType == 0 &&
1495 Mbr->Partition[2].PartitionType == 0 &&
1496 Mbr->Partition[3].PartitionType == 0)
1497 {
1498 DiskEntry->DiskStyle = PARTITION_STYLE_GPT;
1499 }
1500 /* Otherwise, partition table is in MBR */
1501 else
1502 {
1503 DiskEntry->DiskStyle = PARTITION_STYLE_MBR;
1504 }
1505
1506 /* Free the MBR sector buffer */
1507 RtlFreeHeap(ProcessHeap, 0, Mbr);
1508
1509
1510 for (ListEntry = List->BiosDiskListHead.Flink;
1511 ListEntry != &List->BiosDiskListHead;
1512 ListEntry = ListEntry->Flink)
1513 {
1514 BiosDiskEntry = CONTAINING_RECORD(ListEntry, BIOSDISKENTRY, ListEntry);
1515 /* FIXME:
1516 * Compare the size from bios and the reported size from driver.
1517 * If we have more than one disk with a zero or with the same signature
1518 * we must create new signatures and reboot. After the reboot,
1519 * it is possible to identify the disks.
1520 */
1521 if (BiosDiskEntry->Signature == Signature &&
1522 BiosDiskEntry->Checksum == Checksum &&
1523 BiosDiskEntry->DiskEntry == NULL)
1524 {
1525 if (!DiskEntry->BiosFound)
1526 {
1527 DiskEntry->HwAdapterNumber = BiosDiskEntry->AdapterNumber;
1528 DiskEntry->HwControllerNumber = BiosDiskEntry->ControllerNumber;
1529 DiskEntry->HwDiskNumber = BiosDiskEntry->DiskNumber;
1530
1531 if (DiskEntry->MediaType == RemovableMedia)
1532 {
1533 /* Set the removable disk number to zero */
1534 DiskEntry->HwFixedDiskNumber = 0;
1535 }
1536 else // if (DiskEntry->MediaType == FixedMedia)
1537 {
1538 /* The fixed disk number will later be adjusted using the number of removable disks */
1539 DiskEntry->HwFixedDiskNumber = BiosDiskEntry->DiskNumber;
1540 }
1541
1542 DiskEntry->BiosFound = TRUE;
1543 BiosDiskEntry->DiskEntry = DiskEntry;
1544 break;
1545 }
1546 else
1547 {
1548 // FIXME: What to do?
1549 DPRINT1("Disk %lu of identifier '%S' has already been found?!\n", DiskNumber, Identifier);
1550 }
1551 }
1552 }
1553
1554 if (!DiskEntry->BiosFound)
1555 {
1556 DPRINT1("WARNING: Setup could not find a matching BIOS disk entry. Disk %lu may not be bootable by the BIOS!\n", DiskNumber);
1557 }
1558
1559 DiskEntry->Cylinders = DiskGeometry.Cylinders.QuadPart;
1560 DiskEntry->TracksPerCylinder = DiskGeometry.TracksPerCylinder;
1561 DiskEntry->SectorsPerTrack = DiskGeometry.SectorsPerTrack;
1562 DiskEntry->BytesPerSector = DiskGeometry.BytesPerSector;
1563
1564 DPRINT("Cylinders %I64u\n", DiskEntry->Cylinders);
1565 DPRINT("TracksPerCylinder %lu\n", DiskEntry->TracksPerCylinder);
1566 DPRINT("SectorsPerTrack %lu\n", DiskEntry->SectorsPerTrack);
1567 DPRINT("BytesPerSector %lu\n", DiskEntry->BytesPerSector);
1568
1569 DiskEntry->SectorCount.QuadPart = DiskGeometry.Cylinders.QuadPart *
1570 (ULONGLONG)DiskGeometry.TracksPerCylinder *
1571 (ULONGLONG)DiskGeometry.SectorsPerTrack;
1572
1573 DiskEntry->SectorAlignment = DiskGeometry.SectorsPerTrack;
1574 DiskEntry->CylinderAlignment = DiskGeometry.TracksPerCylinder *
1575 DiskGeometry.SectorsPerTrack;
1576
1577 DPRINT("SectorCount %I64u\n", DiskEntry->SectorCount.QuadPart);
1578 DPRINT("SectorAlignment %lu\n", DiskEntry->SectorAlignment);
1579
1580 DiskEntry->DiskNumber = DiskNumber;
1581 DiskEntry->Port = ScsiAddress.PortNumber;
1582 DiskEntry->Bus = ScsiAddress.PathId;
1583 DiskEntry->Id = ScsiAddress.TargetId;
1584
1585 GetDriverName(DiskEntry);
1586 /*
1587 * Actually it would be more correct somehow to use:
1588 *
1589 * OBJECT_NAME_INFORMATION NameInfo; // ObjectNameInfo;
1590 * ULONG ReturnedLength;
1591 *
1592 * Status = NtQueryObject(SomeHandleToTheDisk,
1593 * ObjectNameInformation,
1594 * &NameInfo,
1595 * sizeof(NameInfo),
1596 * &ReturnedLength);
1597 * etc...
1598 *
1599 * See examples in https://git.reactos.org/?p=reactos.git;a=blob;f=reactos/ntoskrnl/io/iomgr/error.c;hb=2f3a93ee9cec8322a86bf74b356f1ad83fc912dc#l267
1600 */
1601
1604
1605 InsertAscendingList(&List->DiskListHead, DiskEntry, DISKENTRY, ListEntry, DiskNumber);
1606
1607
1608 /*
1609 * We now retrieve the disk partition layout
1610 */
1611
1612 /*
1613 * Stop there now if the disk is GPT-partitioned,
1614 * since we currently do not support such disks.
1615 */
1616 if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
1617 {
1618 DPRINT1("GPT-partitioned disk detected, not currently supported by SETUP!\n");
1619 return;
1620 }
1621
1622 /* Allocate a layout buffer with 4 partition entries first */
1623 LayoutBufferSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
1624 ((4 - ANYSIZE_ARRAY) * sizeof(PARTITION_INFORMATION));
1627 LayoutBufferSize);
1628 if (DiskEntry->LayoutBuffer == NULL)
1629 {
1630 DPRINT1("Failed to allocate the disk layout buffer!\n");
1631 return;
1632 }
1633
1634 /* Keep looping while the drive layout buffer is too small */
1635 for (;;)
1636 {
1637 DPRINT1("Buffer size: %lu\n", LayoutBufferSize);
1639 NULL,
1640 NULL,
1641 NULL,
1642 &Iosb,
1644 NULL,
1645 0,
1646 DiskEntry->LayoutBuffer,
1647 LayoutBufferSize);
1648 if (NT_SUCCESS(Status))
1649 break;
1650
1652 {
1653 DPRINT1("NtDeviceIoControlFile() failed (Status: 0x%08lx)\n", Status);
1654 return;
1655 }
1656
1657 LayoutBufferSize += 4 * sizeof(PARTITION_INFORMATION);
1658 NewLayoutBuffer = RtlReAllocateHeap(ProcessHeap,
1660 DiskEntry->LayoutBuffer,
1661 LayoutBufferSize);
1662 if (NewLayoutBuffer == NULL)
1663 {
1664 DPRINT1("Failed to reallocate the disk layout buffer!\n");
1665 return;
1666 }
1667
1668 DiskEntry->LayoutBuffer = NewLayoutBuffer;
1669 }
1670
1671 DPRINT1("PartitionCount: %lu\n", DiskEntry->LayoutBuffer->PartitionCount);
1672
1673#ifdef DUMP_PARTITION_TABLE
1674 DumpPartitionTable(DiskEntry);
1675#endif
1676
1677 if (IsSuperFloppy(DiskEntry))
1678 DPRINT1("Disk %lu is a super-floppy\n", DiskNumber);
1679
1680 if (DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart != 0 &&
1683 {
1684 if ((DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart / DiskEntry->BytesPerSector) % DiskEntry->SectorsPerTrack == 0)
1685 {
1686 DPRINT("Use %lu Sector alignment!\n", DiskEntry->SectorsPerTrack);
1687 }
1688 else if (DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart % (1024 * 1024) == 0)
1689 {
1690 DPRINT1("Use megabyte (%lu Sectors) alignment!\n", (1024 * 1024) / DiskEntry->BytesPerSector);
1691 }
1692 else
1693 {
1694 DPRINT1("No matching alignment found! Partition 1 starts at %I64u\n", DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart);
1695 }
1696 }
1697 else
1698 {
1699 DPRINT1("No valid partition table found! Use megabyte (%lu Sectors) alignment!\n", (1024 * 1024) / DiskEntry->BytesPerSector);
1700 }
1701
1702 if (DiskEntry->LayoutBuffer->PartitionCount == 0)
1703 {
1704 DiskEntry->NewDisk = TRUE;
1705 DiskEntry->LayoutBuffer->PartitionCount = 4;
1706
1707 for (i = 0; i < 4; i++)
1708 {
1710 }
1711 }
1712 else
1713 {
1714 /* Enumerate and add the first four primary partitions */
1715 for (i = 0; i < 4; i++)
1716 {
1717 AddPartitionToDisk(DiskNumber, DiskEntry, i, FALSE);
1718 }
1719
1720 /* Enumerate and add the remaining partitions as logical ones */
1721 for (i = 4; i < DiskEntry->LayoutBuffer->PartitionCount; i += 4)
1722 {
1723 AddPartitionToDisk(DiskNumber, DiskEntry, i, TRUE);
1724 }
1725 }
1726
1728}
1729
1730/*
1731 * Retrieve the system disk, i.e. the fixed disk that is accessible by the
1732 * firmware during boot time and where the system partition resides.
1733 * If no system partition has been determined, we retrieve the first disk
1734 * that verifies the mentioned criteria above.
1735 */
1736static
1740{
1742 PDISKENTRY DiskEntry;
1743
1744 /* Check for empty disk list */
1745 if (IsListEmpty(&List->DiskListHead))
1746 return NULL;
1747
1748 /*
1749 * If we already have a system partition, the system disk
1750 * is the one on which the system partition resides.
1751 */
1752 if (List->SystemPartition)
1753 return List->SystemPartition->DiskEntry;
1754
1755 /* Loop over the disks and find the correct one */
1756 for (Entry = List->DiskListHead.Flink;
1757 Entry != &List->DiskListHead;
1758 Entry = Entry->Flink)
1759 {
1760 DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
1761
1762 /* The disk must be a fixed disk and be found by the firmware */
1763 if (DiskEntry->MediaType == FixedMedia && DiskEntry->BiosFound)
1764 {
1765 break;
1766 }
1767 }
1768 if (Entry == &List->DiskListHead)
1769 {
1770 /* We haven't encountered any suitable disk */
1771 return NULL;
1772 }
1773
1774 if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
1775 {
1776 DPRINT1("System disk -- GPT-partitioned disk detected, not currently supported by SETUP!\n");
1777 }
1778
1779 return DiskEntry;
1780}
1781
1782/*
1783 * Retrieve the actual "active" partition of the given disk.
1784 * On MBR disks, partition with the Active/Boot flag set;
1785 * on GPT disks, partition with the correct GUID.
1786 */
1787BOOLEAN
1789 IN PPARTENTRY PartEntry)
1790{
1791 // TODO: Support for GPT disks!
1792
1793 if (IsContainerPartition(PartEntry->PartitionType))
1794 return FALSE;
1795
1796 /* Check if the partition is partitioned, used and active */
1797 if (PartEntry->IsPartitioned &&
1798 // !IsContainerPartition(PartEntry->PartitionType) &&
1799 PartEntry->BootIndicator)
1800 {
1801 /* Yes it is */
1802 ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
1803 return TRUE;
1804 }
1805
1806 return FALSE;
1807}
1808
1809static
1812 IN PDISKENTRY DiskEntry)
1813{
1814 PLIST_ENTRY ListEntry;
1815 PPARTENTRY PartEntry;
1816 PPARTENTRY ActivePartition = NULL;
1817
1818 /* Check for empty disk list */
1819 // ASSERT(DiskEntry);
1820 if (!DiskEntry)
1821 return NULL;
1822
1823 /* Check for empty partition list */
1824 if (IsListEmpty(&DiskEntry->PrimaryPartListHead))
1825 return NULL;
1826
1827 if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
1828 {
1829 DPRINT1("GPT-partitioned disk detected, not currently supported by SETUP!\n");
1830 return NULL;
1831 }
1832
1833 /* Scan all (primary) partitions to find the active disk partition */
1834 for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
1835 ListEntry != &DiskEntry->PrimaryPartListHead;
1836 ListEntry = ListEntry->Flink)
1837 {
1838 /* Retrieve the partition */
1839 PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
1840 if (IsPartitionActive(PartEntry))
1841 {
1842 /* Yes, we've found it */
1843 ASSERT(DiskEntry == PartEntry->DiskEntry);
1844 ASSERT(PartEntry->IsPartitioned);
1845
1846 ActivePartition = PartEntry;
1847
1848 DPRINT1("Found active system partition %lu in disk %lu, drive letter %C\n",
1849 PartEntry->PartitionNumber, DiskEntry->DiskNumber,
1850 (PartEntry->DriveLetter == 0) ? L'-' : PartEntry->DriveLetter);
1851 break;
1852 }
1853 }
1854
1855 /* Check if the disk is new and if so, use its first partition as the active system partition */
1856 if (DiskEntry->NewDisk && ActivePartition != NULL)
1857 {
1858 // FIXME: What to do??
1859 DPRINT1("NewDisk TRUE but already existing active partition?\n");
1860 }
1861
1862 /* Return the active partition found (or none) */
1863 return ActivePartition;
1864}
1865
1868{
1870 PDISKENTRY SystemDisk;
1874 ULONG ReturnSize;
1876 ULONG DiskNumber;
1880
1882 0,
1883 sizeof(PARTLIST));
1884 if (List == NULL)
1885 return NULL;
1886
1887 List->SystemPartition = NULL;
1888
1889 InitializeListHead(&List->DiskListHead);
1890 InitializeListHead(&List->BiosDiskListHead);
1891
1892 /*
1893 * Enumerate the disks seen by the BIOS; this will be used later
1894 * to map drives seen by NTOS with their corresponding BIOS names.
1895 */
1897
1898 /* Enumerate disks seen by NTOS */
1900 &Sdi,
1901 sizeof(Sdi),
1902 &ReturnSize);
1903 if (!NT_SUCCESS(Status))
1904 {
1905 DPRINT1("NtQuerySystemInformation() failed, Status 0x%08lx\n", Status);
1907 return NULL;
1908 }
1909
1910 for (DiskNumber = 0; DiskNumber < Sdi.NumberOfDisks; DiskNumber++)
1911 {
1913 L"\\Device\\Harddisk%lu\\Partition0",
1914 DiskNumber);
1916
1918 &Name,
1920 NULL,
1921 NULL);
1922
1926 &Iosb,
1929 if (NT_SUCCESS(Status))
1930 {
1931 AddDiskToList(FileHandle, DiskNumber, List);
1933 }
1934 }
1935
1939
1940 /*
1941 * Retrieve the system partition: the active partition on the system
1942 * disk (the one that will be booted by default by the hardware).
1943 */
1944 SystemDisk = GetSystemDisk(List);
1945 List->SystemPartition = (SystemDisk ? GetActiveDiskPartition(SystemDisk) : NULL);
1946
1947 return List;
1948}
1949
1950VOID
1953{
1954 PDISKENTRY DiskEntry;
1955 PBIOSDISKENTRY BiosDiskEntry;
1956 PPARTENTRY PartEntry;
1958
1959 /* Release disk and partition info */
1960 while (!IsListEmpty(&List->DiskListHead))
1961 {
1962 Entry = RemoveHeadList(&List->DiskListHead);
1963 DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
1964
1965 /* Release driver name */
1966 RtlFreeUnicodeString(&DiskEntry->DriverName);
1967
1968 /* Release primary partition list */
1969 while (!IsListEmpty(&DiskEntry->PrimaryPartListHead))
1970 {
1972 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
1973
1974 RtlFreeHeap(ProcessHeap, 0, PartEntry);
1975 }
1976
1977 /* Release logical partition list */
1978 while (!IsListEmpty(&DiskEntry->LogicalPartListHead))
1979 {
1981 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
1982
1983 RtlFreeHeap(ProcessHeap, 0, PartEntry);
1984 }
1985
1986 /* Release layout buffer */
1987 if (DiskEntry->LayoutBuffer != NULL)
1988 RtlFreeHeap(ProcessHeap, 0, DiskEntry->LayoutBuffer);
1989
1990 /* Release disk entry */
1991 RtlFreeHeap(ProcessHeap, 0, DiskEntry);
1992 }
1993
1994 /* Release the bios disk info */
1995 while (!IsListEmpty(&List->BiosDiskListHead))
1996 {
1997 Entry = RemoveHeadList(&List->BiosDiskListHead);
1998 BiosDiskEntry = CONTAINING_RECORD(Entry, BIOSDISKENTRY, ListEntry);
1999
2000 RtlFreeHeap(ProcessHeap, 0, BiosDiskEntry);
2001 }
2002
2003 /* Release list head */
2005}
2006
2010 IN ULONG HwDiskNumber)
2011{
2012 PDISKENTRY DiskEntry;
2014
2015 /* Loop over the disks and find the correct one */
2016 for (Entry = List->DiskListHead.Flink;
2017 Entry != &List->DiskListHead;
2018 Entry = Entry->Flink)
2019 {
2020 DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
2021
2022 if (DiskEntry->HwDiskNumber == HwDiskNumber)
2023 {
2024 /* Disk found */
2025 return DiskEntry;
2026 }
2027 }
2028
2029 /* Disk not found, stop there */
2030 return NULL;
2031}
2032
2036 IN ULONG DiskNumber)
2037{
2038 PDISKENTRY DiskEntry;
2040
2041 /* Loop over the disks and find the correct one */
2042 for (Entry = List->DiskListHead.Flink;
2043 Entry != &List->DiskListHead;
2044 Entry = Entry->Flink)
2045 {
2046 DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
2047
2048 if (DiskEntry->DiskNumber == DiskNumber)
2049 {
2050 /* Disk found */
2051 return DiskEntry;
2052 }
2053 }
2054
2055 /* Disk not found, stop there */
2056 return NULL;
2057}
2058
2062 IN USHORT Port,
2063 IN USHORT Bus,
2064 IN USHORT Id)
2065{
2066 PDISKENTRY DiskEntry;
2068
2069 /* Loop over the disks and find the correct one */
2070 for (Entry = List->DiskListHead.Flink;
2071 Entry != &List->DiskListHead;
2072 Entry = Entry->Flink)
2073 {
2074 DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
2075
2076 if (DiskEntry->Port == Port &&
2077 DiskEntry->Bus == Bus &&
2078 DiskEntry->Id == Id)
2079 {
2080 /* Disk found */
2081 return DiskEntry;
2082 }
2083 }
2084
2085 /* Disk not found, stop there */
2086 return NULL;
2087}
2088
2093{
2094 PDISKENTRY DiskEntry;
2096
2097 /* Loop over the disks and find the correct one */
2098 for (Entry = List->DiskListHead.Flink;
2099 Entry != &List->DiskListHead;
2100 Entry = Entry->Flink)
2101 {
2102 DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
2103
2104 if (DiskEntry->LayoutBuffer->Signature == Signature)
2105 {
2106 /* Disk found */
2107 return DiskEntry;
2108 }
2109 }
2110
2111 /* Disk not found, stop there */
2112 return NULL;
2113}
2114
2117 // IN PPARTLIST List,
2118 IN PDISKENTRY DiskEntry,
2120{
2121 PPARTENTRY PartEntry;
2123
2124 if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
2125 {
2126 DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
2127 return NULL;
2128 }
2129
2130 /* Disk found, loop over the primary partitions first... */
2131 for (Entry = DiskEntry->PrimaryPartListHead.Flink;
2132 Entry != &DiskEntry->PrimaryPartListHead;
2133 Entry = Entry->Flink)
2134 {
2135 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
2136
2137 if (PartEntry->PartitionNumber == PartitionNumber)
2138 {
2139 /* Partition found */
2140 return PartEntry;
2141 }
2142 }
2143
2144 /* ... then over the logical partitions if needed */
2145 for (Entry = DiskEntry->LogicalPartListHead.Flink;
2146 Entry != &DiskEntry->LogicalPartListHead;
2147 Entry = Entry->Flink)
2148 {
2149 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
2150
2151 if (PartEntry->PartitionNumber == PartitionNumber)
2152 {
2153 /* Partition found */
2154 return PartEntry;
2155 }
2156 }
2157
2158 /* The partition was not found on the disk, stop there */
2159 return NULL;
2160}
2161
2162BOOLEAN
2165 IN ULONG DiskNumber,
2167 OUT PDISKENTRY* pDiskEntry,
2168 OUT PPARTENTRY* pPartEntry OPTIONAL)
2169{
2170 PDISKENTRY DiskEntry;
2171 PPARTENTRY PartEntry = NULL;
2172
2173 /* Find the disk */
2174 DiskEntry = GetDiskByNumber(List, DiskNumber);
2175 if (!DiskEntry)
2176 return FALSE;
2177
2178 /* If we have a partition (PartitionNumber != 0), find it */
2179 if (PartitionNumber != 0)
2180 {
2181 if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
2182 {
2183 DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
2184 return FALSE;
2185 }
2186
2187 PartEntry = GetPartition(/*List,*/ DiskEntry, PartitionNumber);
2188 if (!PartEntry)
2189 return FALSE;
2190 ASSERT(PartEntry->DiskEntry == DiskEntry);
2191 }
2192
2193 /* Return the disk (and optionally the partition) */
2194 *pDiskEntry = DiskEntry;
2195 if (pPartEntry) *pPartEntry = PartEntry;
2196 return TRUE;
2197}
2198
2199//
2200// NOTE: Was introduced broken in r6258 by Casper
2201//
2205 IN ULONG DiskNumber,
2207{
2208 PDISKENTRY DiskEntry;
2209 PPARTENTRY PartEntry;
2210
2211 DiskEntry = GetDiskByNumber(List, DiskNumber);
2212 if (!DiskEntry)
2213 return NULL;
2214
2215 PartEntry = GetPartition(/*List,*/ DiskEntry, PartitionNumber);
2216 if (!PartEntry)
2217 return NULL;
2218
2219 ASSERT(PartEntry->DiskEntry == DiskEntry);
2220 ASSERT(DiskEntry->DiskNumber == DiskNumber);
2221 ASSERT(PartEntry->PartitionNumber == PartitionNumber);
2222
2223 return PartEntry;
2224}
2225
2229 IN PPARTENTRY CurrentPart OPTIONAL)
2230{
2231 PLIST_ENTRY DiskListEntry;
2232 PLIST_ENTRY PartListEntry;
2234
2235 /* Fail if no disks are available */
2236 if (IsListEmpty(&List->DiskListHead))
2237 return NULL;
2238
2239 /* Check for the next usable entry on the current partition's disk */
2240 if (CurrentPart != NULL)
2241 {
2242 CurrentDisk = CurrentPart->DiskEntry;
2243
2244 if (CurrentPart->LogicalPartition)
2245 {
2246 /* Logical partition */
2247
2248 PartListEntry = CurrentPart->ListEntry.Flink;
2249 if (PartListEntry != &CurrentDisk->LogicalPartListHead)
2250 {
2251 /* Next logical partition */
2252 CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
2253 return CurrentPart;
2254 }
2255 else
2256 {
2257 PartListEntry = CurrentDisk->ExtendedPartition->ListEntry.Flink;
2258 if (PartListEntry != &CurrentDisk->PrimaryPartListHead)
2259 {
2260 CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
2261 return CurrentPart;
2262 }
2263 }
2264 }
2265 else
2266 {
2267 /* Primary or extended partition */
2268
2269 if (CurrentPart->IsPartitioned &&
2270 IsContainerPartition(CurrentPart->PartitionType))
2271 {
2272 /* First logical partition */
2273 PartListEntry = CurrentDisk->LogicalPartListHead.Flink;
2274 if (PartListEntry != &CurrentDisk->LogicalPartListHead)
2275 {
2276 CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
2277 return CurrentPart;
2278 }
2279 }
2280 else
2281 {
2282 /* Next primary partition */
2283 PartListEntry = CurrentPart->ListEntry.Flink;
2284 if (PartListEntry != &CurrentDisk->PrimaryPartListHead)
2285 {
2286 CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
2287 return CurrentPart;
2288 }
2289 }
2290 }
2291 }
2292
2293 /* Search for the first partition entry on the next disk */
2294 for (DiskListEntry = (CurrentPart ? CurrentDisk->ListEntry.Flink
2295 : List->DiskListHead.Flink);
2296 DiskListEntry != &List->DiskListHead;
2297 DiskListEntry = DiskListEntry->Flink)
2298 {
2299 CurrentDisk = CONTAINING_RECORD(DiskListEntry, DISKENTRY, ListEntry);
2300
2302 {
2303 DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
2304 continue;
2305 }
2306
2307 PartListEntry = CurrentDisk->PrimaryPartListHead.Flink;
2308 if (PartListEntry != &CurrentDisk->PrimaryPartListHead)
2309 {
2310 CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
2311 return CurrentPart;
2312 }
2313 }
2314
2315 return NULL;
2316}
2317
2321 IN PPARTENTRY CurrentPart OPTIONAL)
2322{
2323 PLIST_ENTRY DiskListEntry;
2324 PLIST_ENTRY PartListEntry;
2326
2327 /* Fail if no disks are available */
2328 if (IsListEmpty(&List->DiskListHead))
2329 return NULL;
2330
2331 /* Check for the previous usable entry on the current partition's disk */
2332 if (CurrentPart != NULL)
2333 {
2334 CurrentDisk = CurrentPart->DiskEntry;
2335
2336 if (CurrentPart->LogicalPartition)
2337 {
2338 /* Logical partition */
2339
2340 PartListEntry = CurrentPart->ListEntry.Blink;
2341 if (PartListEntry != &CurrentDisk->LogicalPartListHead)
2342 {
2343 /* Previous logical partition */
2344 CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
2345 }
2346 else
2347 {
2348 /* Extended partition */
2349 CurrentPart = CurrentDisk->ExtendedPartition;
2350 }
2351 return CurrentPart;
2352 }
2353 else
2354 {
2355 /* Primary or extended partition */
2356
2357 PartListEntry = CurrentPart->ListEntry.Blink;
2358 if (PartListEntry != &CurrentDisk->PrimaryPartListHead)
2359 {
2360 CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
2361
2362 if (CurrentPart->IsPartitioned &&
2363 IsContainerPartition(CurrentPart->PartitionType))
2364 {
2365 PartListEntry = CurrentDisk->LogicalPartListHead.Blink;
2366 CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
2367 }
2368
2369 return CurrentPart;
2370 }
2371 }
2372 }
2373
2374 /* Search for the last partition entry on the previous disk */
2375 for (DiskListEntry = (CurrentPart ? CurrentDisk->ListEntry.Blink
2376 : List->DiskListHead.Blink);
2377 DiskListEntry != &List->DiskListHead;
2378 DiskListEntry = DiskListEntry->Blink)
2379 {
2380 CurrentDisk = CONTAINING_RECORD(DiskListEntry, DISKENTRY, ListEntry);
2381
2383 {
2384 DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
2385 continue;
2386 }
2387
2388 PartListEntry = CurrentDisk->PrimaryPartListHead.Blink;
2389 if (PartListEntry != &CurrentDisk->PrimaryPartListHead)
2390 {
2391 CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
2392
2393 if (CurrentPart->IsPartitioned &&
2394 IsContainerPartition(CurrentPart->PartitionType))
2395 {
2396 PartListEntry = CurrentDisk->LogicalPartListHead.Blink;
2397 if (PartListEntry != &CurrentDisk->LogicalPartListHead)
2398 {
2399 CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
2400 return CurrentPart;
2401 }
2402 }
2403 else
2404 {
2405 return CurrentPart;
2406 }
2407 }
2408 }
2409
2410 return NULL;
2411}
2412
2413static inline
2414BOOLEAN
2417{
2418 return (PartitionInfo->StartingOffset.QuadPart == 0 &&
2419 PartitionInfo->PartitionLength.QuadPart == 0);
2420}
2421
2422static inline
2423BOOLEAN
2426 _In_ PPARTENTRY PartEntry)
2427{
2428 return ((PartitionInfo->StartingOffset.QuadPart == GetPartEntryOffsetInBytes(PartEntry)) &&
2429 (PartitionInfo->PartitionLength.QuadPart == GetPartEntrySizeInBytes(PartEntry)));
2430// PartitionInfo->PartitionType == PartEntry->PartitionType
2431}
2432
2433static
2434ULONG
2436 IN PDISKENTRY DiskEntry)
2437{
2439 PPARTENTRY PartEntry;
2440 ULONG Count = 0;
2441
2442 if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
2443 {
2444 DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
2445 return 0;
2446 }
2447
2448 for (Entry = DiskEntry->PrimaryPartListHead.Flink;
2449 Entry != &DiskEntry->PrimaryPartListHead;
2450 Entry = Entry->Flink)
2451 {
2452 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
2453 if (PartEntry->IsPartitioned)
2454 Count++;
2455 }
2456
2457 return Count;
2458}
2459
2460static
2461ULONG
2463 IN PDISKENTRY DiskEntry)
2464{
2465 PLIST_ENTRY ListEntry;
2466 PPARTENTRY PartEntry;
2467 ULONG Count = 0;
2468
2469 if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
2470 {
2471 DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
2472 return 0;
2473 }
2474
2475 for (ListEntry = DiskEntry->LogicalPartListHead.Flink;
2476 ListEntry != &DiskEntry->LogicalPartListHead;
2477 ListEntry = ListEntry->Flink)
2478 {
2479 PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
2480 if (PartEntry->IsPartitioned)
2481 Count++;
2482 }
2483
2484 return Count;
2485}
2486
2487static
2488BOOLEAN
2490 IN PDISKENTRY DiskEntry)
2491{
2492 PDRIVE_LAYOUT_INFORMATION NewLayoutBuffer;
2493 ULONG NewPartitionCount;
2494 ULONG CurrentPartitionCount = 0;
2495 ULONG LayoutBufferSize;
2496 ULONG i;
2497
2498 DPRINT1("ReAllocateLayoutBuffer()\n");
2499
2500 NewPartitionCount = 4 + GetLogicalPartitionCount(DiskEntry) * 4;
2501
2502 if (DiskEntry->LayoutBuffer)
2503 CurrentPartitionCount = DiskEntry->LayoutBuffer->PartitionCount;
2504
2505 DPRINT1("CurrentPartitionCount: %lu ; NewPartitionCount: %lu\n",
2506 CurrentPartitionCount, NewPartitionCount);
2507
2508 if (CurrentPartitionCount == NewPartitionCount)
2509 return TRUE;
2510
2511 LayoutBufferSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
2512 ((NewPartitionCount - ANYSIZE_ARRAY) * sizeof(PARTITION_INFORMATION));
2513 NewLayoutBuffer = RtlReAllocateHeap(ProcessHeap,
2515 DiskEntry->LayoutBuffer,
2516 LayoutBufferSize);
2517 if (NewLayoutBuffer == NULL)
2518 {
2519 DPRINT1("Failed to allocate the new layout buffer (size: %lu)\n", LayoutBufferSize);
2520 return FALSE;
2521 }
2522
2523 NewLayoutBuffer->PartitionCount = NewPartitionCount;
2524
2525 /* If the layout buffer grows, make sure the new (empty) entries are written to the disk */
2526 if (NewPartitionCount > CurrentPartitionCount)
2527 {
2528 for (i = CurrentPartitionCount; i < NewPartitionCount; i++)
2529 {
2530 NewLayoutBuffer->PartitionEntry[i].RewritePartition = TRUE;
2531 }
2532 }
2533
2534 DiskEntry->LayoutBuffer = NewLayoutBuffer;
2535
2536 return TRUE;
2537}
2538
2539static
2540VOID
2542 IN PDISKENTRY DiskEntry)
2543{
2545 PPARTITION_INFORMATION LinkInfo = NULL;
2546 PLIST_ENTRY ListEntry;
2547 PPARTENTRY PartEntry;
2548 LARGE_INTEGER HiddenSectors64;
2549 ULONG Index;
2551
2552 DPRINT1("UpdateDiskLayout()\n");
2553
2554 if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
2555 {
2556 DPRINT1("GPT-partitioned disk detected, not currently supported by SETUP!\n");
2557 return;
2558 }
2559
2560 /* Resize the layout buffer if necessary */
2561 if (ReAllocateLayoutBuffer(DiskEntry) == FALSE)
2562 {
2563 DPRINT("ReAllocateLayoutBuffer() failed.\n");
2564 return;
2565 }
2566
2567 /* Update the primary partition table */
2568 Index = 0;
2569 for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
2570 ListEntry != &DiskEntry->PrimaryPartListHead;
2571 ListEntry = ListEntry->Flink)
2572 {
2573 PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
2574
2575 if (PartEntry->IsPartitioned)
2576 {
2578
2579 PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
2580 PartEntry->PartitionIndex = Index;
2581
2582 /* Reset the current partition number only for newly-created (unmounted) partitions */
2583 if (PartEntry->New)
2584 PartEntry->PartitionNumber = 0;
2585
2587
2588 if (!IsSamePrimaryLayoutEntry(PartitionInfo, PartEntry))
2589 {
2590 DPRINT1("Updating primary partition entry %lu\n", Index);
2591
2592 PartitionInfo->StartingOffset.QuadPart = GetPartEntryOffsetInBytes(PartEntry);
2593 PartitionInfo->PartitionLength.QuadPart = GetPartEntrySizeInBytes(PartEntry);
2594 PartitionInfo->HiddenSectors = PartEntry->StartSector.LowPart;
2595 PartitionInfo->PartitionNumber = PartEntry->PartitionNumber;
2596 PartitionInfo->PartitionType = PartEntry->PartitionType;
2597 PartitionInfo->BootIndicator = PartEntry->BootIndicator;
2598 PartitionInfo->RecognizedPartition = IsRecognizedPartition(PartEntry->PartitionType);
2599 PartitionInfo->RewritePartition = TRUE;
2600 }
2601
2602 if (!IsContainerPartition(PartEntry->PartitionType))
2604
2605 Index++;
2606 }
2607 }
2608
2609 ASSERT(Index <= 4);
2610
2611 /* Update the logical partition table */
2612 Index = 4;
2613 for (ListEntry = DiskEntry->LogicalPartListHead.Flink;
2614 ListEntry != &DiskEntry->LogicalPartListHead;
2615 ListEntry = ListEntry->Flink)
2616 {
2617 PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
2618
2619 if (PartEntry->IsPartitioned)
2620 {
2622
2623 PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
2624 PartEntry->PartitionIndex = Index;
2625
2626 /* Reset the current partition number only for newly-created (unmounted) partitions */
2627 if (PartEntry->New)
2628 PartEntry->PartitionNumber = 0;
2629
2631
2632 DPRINT1("Updating logical partition entry %lu\n", Index);
2633
2634 PartitionInfo->StartingOffset.QuadPart = GetPartEntryOffsetInBytes(PartEntry);
2635 PartitionInfo->PartitionLength.QuadPart = GetPartEntrySizeInBytes(PartEntry);
2636 PartitionInfo->HiddenSectors = DiskEntry->SectorAlignment;
2637 PartitionInfo->PartitionNumber = PartEntry->PartitionNumber;
2638 PartitionInfo->PartitionType = PartEntry->PartitionType;
2639 PartitionInfo->BootIndicator = FALSE;
2640 PartitionInfo->RecognizedPartition = IsRecognizedPartition(PartEntry->PartitionType);
2641 PartitionInfo->RewritePartition = TRUE;
2642
2643 /* Fill the link entry of the previous partition entry */
2644 if (LinkInfo != NULL)
2645 {
2646 LinkInfo->StartingOffset.QuadPart = (PartEntry->StartSector.QuadPart - DiskEntry->SectorAlignment) * DiskEntry->BytesPerSector;
2647 LinkInfo->PartitionLength.QuadPart = (PartEntry->StartSector.QuadPart + DiskEntry->SectorAlignment) * DiskEntry->BytesPerSector;
2648 HiddenSectors64.QuadPart = PartEntry->StartSector.QuadPart - DiskEntry->SectorAlignment - DiskEntry->ExtendedPartition->StartSector.QuadPart;
2649 LinkInfo->HiddenSectors = HiddenSectors64.LowPart;
2650 LinkInfo->PartitionNumber = 0;
2652 LinkInfo->BootIndicator = FALSE;
2653 LinkInfo->RecognizedPartition = FALSE;
2654 LinkInfo->RewritePartition = TRUE;
2655 }
2656
2657 /* Save a pointer to the link entry of the current partition entry */
2658 LinkInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index + 1];
2659
2661 Index += 4;
2662 }
2663 }
2664
2665 /* Wipe unused primary partition entries */
2666 for (Index = GetPrimaryPartitionCount(DiskEntry); Index < 4; Index++)
2667 {
2668 DPRINT1("Primary partition entry %lu\n", Index);
2669
2670 PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
2671
2673 {
2674 DPRINT1("Wiping primary partition entry %lu\n", Index);
2675
2676 PartitionInfo->StartingOffset.QuadPart = 0;
2677 PartitionInfo->PartitionLength.QuadPart = 0;
2678 PartitionInfo->HiddenSectors = 0;
2679 PartitionInfo->PartitionNumber = 0;
2680 PartitionInfo->PartitionType = PARTITION_ENTRY_UNUSED;
2681 PartitionInfo->BootIndicator = FALSE;
2682 PartitionInfo->RecognizedPartition = FALSE;
2683 PartitionInfo->RewritePartition = TRUE;
2684 }
2685 }
2686
2687 /* Wipe unused logical partition entries */
2688 for (Index = 4; Index < DiskEntry->LayoutBuffer->PartitionCount; Index++)
2689 {
2690 if (Index % 4 >= 2)
2691 {
2692 DPRINT1("Logical partition entry %lu\n", Index);
2693
2694 PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
2695
2697 {
2698 DPRINT1("Wiping partition entry %lu\n", Index);
2699
2700 PartitionInfo->StartingOffset.QuadPart = 0;
2701 PartitionInfo->PartitionLength.QuadPart = 0;
2702 PartitionInfo->HiddenSectors = 0;
2703 PartitionInfo->PartitionNumber = 0;
2704 PartitionInfo->PartitionType = PARTITION_ENTRY_UNUSED;
2705 PartitionInfo->BootIndicator = FALSE;
2706 PartitionInfo->RecognizedPartition = FALSE;
2707 PartitionInfo->RewritePartition = TRUE;
2708 }
2709 }
2710 }
2711
2712 // HACK: See the FIXMEs in WritePartitions(): (Re)set the PartitionStyle to MBR.
2713 DiskEntry->DiskStyle = PARTITION_STYLE_MBR;
2714
2715 DiskEntry->Dirty = TRUE;
2716
2717#ifdef DUMP_PARTITION_TABLE
2718 DumpPartitionTable(DiskEntry);
2719#endif
2720}
2721
2722static
2725 IN PPARTENTRY PartEntry)
2726{
2727 PDISKENTRY DiskEntry = PartEntry->DiskEntry;
2728 PPARTENTRY PrevPartEntry;
2729 PLIST_ENTRY ListHead;
2730
2731 if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
2732 {
2733 DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
2734 return NULL;
2735 }
2736
2737 if (PartEntry->LogicalPartition)
2738 ListHead = &DiskEntry->LogicalPartListHead;
2739 else
2740 ListHead = &DiskEntry->PrimaryPartListHead;
2741
2742 if (PartEntry->ListEntry.Blink != ListHead)
2743 {
2744 PrevPartEntry = CONTAINING_RECORD(PartEntry->ListEntry.Blink,
2745 PARTENTRY,
2746 ListEntry);
2747 if (!PrevPartEntry->IsPartitioned)
2748 {
2749 ASSERT(PrevPartEntry->PartitionType == PARTITION_ENTRY_UNUSED);
2750 return PrevPartEntry;
2751 }
2752 }
2753
2754 return NULL;
2755}
2756
2757static
2760 IN PPARTENTRY PartEntry)
2761{
2762 PDISKENTRY DiskEntry = PartEntry->DiskEntry;
2763 PPARTENTRY NextPartEntry;
2764 PLIST_ENTRY ListHead;
2765
2766 if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
2767 {
2768 DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
2769 return NULL;
2770 }
2771
2772 if (PartEntry->LogicalPartition)
2773 ListHead = &DiskEntry->LogicalPartListHead;
2774 else
2775 ListHead = &DiskEntry->PrimaryPartListHead;
2776
2777 if (PartEntry->ListEntry.Flink != ListHead)
2778 {
2779 NextPartEntry = CONTAINING_RECORD(PartEntry->ListEntry.Flink,
2780 PARTENTRY,
2781 ListEntry);
2782 if (!NextPartEntry->IsPartitioned)
2783 {
2784 ASSERT(NextPartEntry->PartitionType == PARTITION_ENTRY_UNUSED);
2785 return NextPartEntry;
2786 }
2787 }
2788
2789 return NULL;
2790}
2791
2794 _In_ PPARTENTRY PartEntry)
2795{
2796 PDISKENTRY DiskEntry = PartEntry->DiskEntry;
2797
2798 if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
2799 {
2800 DPRINT1("GPT-partitioned disk detected, not currently supported by SETUP!\n");
2801 return ERROR_WARN_PARTITION;
2802 }
2803
2804 /* Fail if the partition is already in use */
2805 if (PartEntry->IsPartitioned)
2806 return ERROR_NEW_PARTITION;
2807
2808 /*
2809 * For primary partitions
2810 */
2811 if (!PartEntry->LogicalPartition)
2812 {
2813 /* Only one primary partition is allowed on super-floppy */
2814 if (IsSuperFloppy(DiskEntry))
2816
2817 /* Fail if there are already 4 primary partitions in the list */
2818 if (GetPrimaryPartitionCount(DiskEntry) >= 4)
2820 }
2821 /*
2822 * For logical partitions
2823 */
2824 else
2825 {
2826 // TODO: Check that we are inside an extended partition!!
2827 // Then the following check will be useless.
2828
2829 /* Only one (primary) partition is allowed on super-floppy */
2830 if (IsSuperFloppy(DiskEntry))
2832 }
2833
2834 return ERROR_SUCCESS;
2835}
2836
2839 _In_ PPARTENTRY PartEntry)
2840{
2841 PDISKENTRY DiskEntry = PartEntry->DiskEntry;
2842
2843 if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
2844 {
2845 DPRINT1("GPT-partitioned disk detected, not currently supported by SETUP!\n");
2846 return ERROR_WARN_PARTITION;
2847 }
2848
2849 /* Fail if the partition is already in use */
2850 if (PartEntry->IsPartitioned)
2851 return ERROR_NEW_PARTITION;
2852
2853 /* Only one primary partition is allowed on super-floppy */
2854 if (IsSuperFloppy(DiskEntry))
2856
2857 /* Fail if there are already 4 primary partitions in the list */
2858 if (GetPrimaryPartitionCount(DiskEntry) >= 4)
2860
2861 /* Fail if there is another extended partition in the list */
2862 if (DiskEntry->ExtendedPartition != NULL)
2864
2865 return ERROR_SUCCESS;
2866}
2867
2868BOOLEAN
2871 _Inout_ PPARTENTRY PartEntry,
2872 _In_opt_ ULONGLONG SizeBytes)
2873{
2875
2876 DPRINT1("CreatePartition(%I64u bytes)\n", SizeBytes);
2877
2878 if (List == NULL || PartEntry == NULL ||
2879 PartEntry->DiskEntry == NULL || PartEntry->IsPartitioned)
2880 {
2881 return FALSE;
2882 }
2883
2884 Error = PartitionCreationChecks(PartEntry);
2885 if (Error != NOT_AN_ERROR)
2886 {
2887 DPRINT1("PartitionCreationChecks() failed with error %lu\n", Error);
2888 return FALSE;
2889 }
2890
2891 /* Initialize the partition entry, inserting a new blank region if needed */
2892 if (!InitializePartitionEntry(PartEntry, SizeBytes))
2893 return FALSE;
2894
2895 UpdateDiskLayout(PartEntry->DiskEntry);
2897
2898 return TRUE;
2899}
2900
2901static
2902VOID
2904 _In_ PDISKENTRY DiskEntry)
2905{
2906 ULONGLONG StartSector;
2908 PPARTENTRY NewPartEntry;
2909
2910 DPRINT1("AddLogicalDiskSpace()\n");
2911
2912 /* Create a partition entry that represents the empty space in the container partition */
2913
2914 StartSector = DiskEntry->ExtendedPartition->StartSector.QuadPart + (ULONGLONG)DiskEntry->SectorAlignment;
2915 SectorCount = DiskEntry->ExtendedPartition->SectorCount.QuadPart - (ULONGLONG)DiskEntry->SectorAlignment;
2916
2917 NewPartEntry = CreateInsertBlankRegion(DiskEntry,
2918 &DiskEntry->LogicalPartListHead,
2919 StartSector,
2921 TRUE);
2922 if (NewPartEntry == NULL)
2923 {
2924 DPRINT1("Failed to create a new empty region for extended partition space!\n");
2925 return;
2926 }
2927}
2928
2929BOOLEAN
2932 _Inout_ PPARTENTRY PartEntry,
2933 _In_opt_ ULONGLONG SizeBytes)
2934{
2936
2937 DPRINT1("CreateExtendedPartition(%I64u bytes)\n", SizeBytes);
2938
2939 if (List == NULL || PartEntry == NULL ||
2940 PartEntry->DiskEntry == NULL || PartEntry->IsPartitioned)
2941 {
2942 return FALSE;
2943 }
2944
2946 if (Error != NOT_AN_ERROR)
2947 {
2948 DPRINT1("ExtendedPartitionCreationChecks() failed with error %lu\n", Error);
2949 return FALSE;
2950 }
2951
2952 /* Initialize the partition entry, inserting a new blank region if needed */
2953 if (!InitializePartitionEntry(PartEntry, SizeBytes))
2954 return FALSE;
2955
2956 ASSERT(PartEntry->LogicalPartition == FALSE);
2957
2958 if (PartEntry->StartSector.QuadPart < 1450560)
2959 {
2960 /* Partition starts below the 8.4GB boundary ==> CHS partition */
2961 PartEntry->PartitionType = PARTITION_EXTENDED;
2962 }
2963 else
2964 {
2965 /* Partition starts above the 8.4GB boundary ==> LBA partition */
2966 PartEntry->PartitionType = PARTITION_XINT13_EXTENDED;
2967 }
2968
2969 // FIXME? Possibly to make GetNextUnformattedPartition work (i.e. skip the extended partition container)
2970 PartEntry->New = FALSE;
2971 PartEntry->FormatState = Formatted;
2972
2973 PartEntry->DiskEntry->ExtendedPartition = PartEntry;
2974
2975 AddLogicalDiskSpace(PartEntry->DiskEntry);
2976
2977 UpdateDiskLayout(PartEntry->DiskEntry);
2979
2980 return TRUE;
2981}
2982
2985 IN PPARTENTRY PartEntry)
2986{
2988 NTSTATUS LockStatus;
2992 HANDLE PartitionHandle;
2994
2995 /* Check whether the partition is valid and was mounted by the system */
2996 if (!PartEntry->IsPartitioned ||
2997 IsContainerPartition(PartEntry->PartitionType) ||
2998 !IsRecognizedPartition(PartEntry->PartitionType) ||
2999 PartEntry->FormatState == UnknownFormat ||
3000 // NOTE: If FormatState == Unformatted but *FileSystem != 0 this means
3001 // it has been usually mounted with RawFS and thus needs to be dismounted.
3002 !*PartEntry->FileSystem ||
3003 PartEntry->PartitionNumber == 0)
3004 {
3005 /* The partition is not mounted, so just return success */
3006 return STATUS_SUCCESS;
3007 }
3008
3009 ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
3010
3011 /* Open the volume */
3013 L"\\Device\\Harddisk%lu\\Partition%lu",
3014 PartEntry->DiskEntry->DiskNumber,
3015 PartEntry->PartitionNumber);
3017
3019 &Name,
3021 NULL,
3022 NULL);
3023
3024 Status = NtOpenFile(&PartitionHandle,
3030 if (!NT_SUCCESS(Status))
3031 {
3032 DPRINT1("ERROR: Cannot open volume %wZ for dismounting! (Status 0x%lx)\n", &Name, Status);
3033 return Status;
3034 }
3035
3036 /* Lock the volume */
3037 LockStatus = NtFsControlFile(PartitionHandle,
3038 NULL,
3039 NULL,
3040 NULL,
3043 NULL,
3044 0,
3045 NULL,
3046 0);
3047 if (!NT_SUCCESS(LockStatus))
3048 {
3049 DPRINT1("WARNING: Failed to lock volume! Operations may fail! (Status 0x%lx)\n", LockStatus);
3050 }
3051
3052 /* Dismount the volume */
3053 Status = NtFsControlFile(PartitionHandle,
3054 NULL,
3055 NULL,
3056 NULL,
3059 NULL,
3060 0,
3061 NULL,
3062 0);
3063 if (!NT_SUCCESS(Status))
3064 {
3065 DPRINT1("Failed to unmount volume (Status 0x%lx)\n", Status);
3066 }
3067
3068 /* Unlock the volume */
3069 LockStatus = NtFsControlFile(PartitionHandle,
3070 NULL,
3071 NULL,
3072 NULL,
3075 NULL,
3076 0,
3077 NULL,
3078 0);
3079 if (!NT_SUCCESS(LockStatus))
3080 {
3081 DPRINT1("Failed to unlock volume (Status 0x%lx)\n", LockStatus);
3082 }
3083
3084 /* Close the volume */
3085 NtClose(PartitionHandle);
3086
3087 return Status;
3088}
3089
3090BOOLEAN
3093 IN PPARTENTRY PartEntry,
3094 OUT PPARTENTRY* FreeRegion OPTIONAL)
3095{
3096 PDISKENTRY DiskEntry;
3097 PPARTENTRY PrevPartEntry;
3098 PPARTENTRY NextPartEntry;
3099 PPARTENTRY LogicalPartEntry;
3101
3102 if (List == NULL || PartEntry == NULL ||
3103 PartEntry->DiskEntry == NULL || PartEntry->IsPartitioned == FALSE)
3104 {
3105 return FALSE;
3106 }
3107
3108 ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
3109
3110 /* Clear the system partition if it is being deleted */
3111 if (List->SystemPartition == PartEntry)
3112 {
3113 ASSERT(List->SystemPartition);
3114 List->SystemPartition = NULL;
3115 }
3116
3117 DiskEntry = PartEntry->DiskEntry;
3118
3119 /* Check which type of partition (primary/logical or extended) is being deleted */
3120 if (DiskEntry->ExtendedPartition == PartEntry)
3121 {
3122 /* An extended partition is being deleted: delete all logical partition entries */
3123 while (!IsListEmpty(&DiskEntry->LogicalPartListHead))
3124 {
3126 LogicalPartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
3127
3128 /* Dismount the logical partition */
3129 DismountVolume(LogicalPartEntry);
3130
3131 /* Delete it */
3132 RtlFreeHeap(ProcessHeap, 0, LogicalPartEntry);
3133 }
3134
3135 DiskEntry->ExtendedPartition = NULL;
3136 }
3137 else
3138 {
3139 /* A primary partition is being deleted: dismount it */
3140 DismountVolume(PartEntry);
3141 }
3142
3143 /* Adjust the unpartitioned disk space entries */
3144
3145 /* Get pointer to previous and next unpartitioned entries */
3146 PrevPartEntry = GetPrevUnpartitionedEntry(PartEntry);
3147 NextPartEntry = GetNextUnpartitionedEntry(PartEntry);
3148
3149 if (PrevPartEntry != NULL && NextPartEntry != NULL)
3150 {
3151 /* Merge the previous, current and next unpartitioned entries */
3152
3153 /* Adjust the previous entry length */
3154 PrevPartEntry->SectorCount.QuadPart += (PartEntry->SectorCount.QuadPart + NextPartEntry->SectorCount.QuadPart);
3155
3156 /* Remove the current and next entries */
3157 RemoveEntryList(&PartEntry->ListEntry);
3158 RtlFreeHeap(ProcessHeap, 0, PartEntry);
3159 RemoveEntryList(&NextPartEntry->ListEntry);
3160 RtlFreeHeap(ProcessHeap, 0, NextPartEntry);
3161
3162 /* Optionally return the freed region */
3163 if (FreeRegion)
3164 *FreeRegion = PrevPartEntry;
3165 }
3166 else if (PrevPartEntry != NULL && NextPartEntry == NULL)
3167 {
3168 /* Merge the current and the previous unpartitioned entries */
3169
3170 /* Adjust the previous entry length */
3171 PrevPartEntry->SectorCount.QuadPart += PartEntry->SectorCount.QuadPart;
3172
3173 /* Remove the current entry */
3174 RemoveEntryList(&PartEntry->ListEntry);
3175 RtlFreeHeap(ProcessHeap, 0, PartEntry);
3176
3177 /* Optionally return the freed region */
3178 if (FreeRegion)
3179 *FreeRegion = PrevPartEntry;
3180 }
3181 else if (PrevPartEntry == NULL && NextPartEntry != NULL)
3182 {
3183 /* Merge the current and the next unpartitioned entries */
3184
3185 /* Adjust the next entry offset and length */
3186 NextPartEntry->StartSector.QuadPart = PartEntry->StartSector.QuadPart;
3187 NextPartEntry->SectorCount.QuadPart += PartEntry->SectorCount.QuadPart;
3188
3189 /* Remove the current entry */
3190 RemoveEntryList(&PartEntry->ListEntry);
3191 RtlFreeHeap(ProcessHeap, 0, PartEntry);
3192
3193 /* Optionally return the freed region */
3194 if (FreeRegion)
3195 *FreeRegion = NextPartEntry;
3196 }
3197 else
3198 {
3199 /* Nothing to merge but change the current entry */
3200 PartEntry->IsPartitioned = FALSE;
3201 PartEntry->OnDiskPartitionNumber = 0;
3202 PartEntry->PartitionNumber = 0;
3203 // PartEntry->PartitionIndex = 0;
3204 PartEntry->BootIndicator = FALSE;
3205 PartEntry->PartitionType = PARTITION_ENTRY_UNUSED;
3206 PartEntry->FormatState = Unformatted;
3207 PartEntry->FileSystem[0] = L'\0';
3208 PartEntry->DriveLetter = 0;
3209 RtlZeroMemory(PartEntry->VolumeLabel, sizeof(PartEntry->VolumeLabel));
3210
3211 /* Optionally return the freed region */
3212 if (FreeRegion)
3213 *FreeRegion = PartEntry;
3214 }
3215
3216 UpdateDiskLayout(DiskEntry);
3218
3219 return TRUE;
3220}
3221
3222static
3223BOOLEAN
3225 IN PPARTENTRY PartEntry)
3226{
3227 /* Check the type and the file system of this partition */
3228
3229 /*
3230 * We do not support extended partition containers (on MBR disks) marked
3231 * as active, and containing code inside their extended boot records.
3232 */
3233 if (IsContainerPartition(PartEntry->PartitionType))
3234 {
3235 DPRINT1("System partition %lu in disk %lu is an extended partition container?!\n",
3236 PartEntry->PartitionNumber, PartEntry->DiskEntry->DiskNumber);
3237 return FALSE;
3238 }
3239
3240 /*
3241 * ADDITIONAL CHECKS / BIG HACK:
3242 *
3243 * Retrieve its file system and check whether we have
3244 * write support for it. If that is the case we are fine
3245 * and we can use it directly. However if we don't have
3246 * write support we will need to change the active system
3247 * partition.
3248 *
3249 * NOTE that this is completely useless on architectures
3250 * where a real system partition is required, as on these
3251 * architectures the partition uses the FAT FS, for which
3252 * we do have write support.
3253 * NOTE also that for those architectures looking for a
3254 * partition boot indicator is insufficient.
3255 */
3256 if (PartEntry->FormatState == Unformatted)
3257 {
3258 /* If this partition is mounted, it would use RawFS ("RAW") */
3259 return TRUE;
3260 }
3261 else if ((PartEntry->FormatState == Preformatted) ||
3262 (PartEntry->FormatState == Formatted))
3263 {
3264 ASSERT(*PartEntry->FileSystem);
3265
3266 /* NOTE: Please keep in sync with the RegisteredFileSystems list! */
3267 if (wcsicmp(PartEntry->FileSystem, L"FAT") == 0 ||
3268 wcsicmp(PartEntry->FileSystem, L"FAT32") == 0 ||
3269 // wcsicmp(PartEntry->FileSystem, L"NTFS") == 0 ||
3270 wcsicmp(PartEntry->FileSystem, L"BTRFS") == 0)
3271 {
3272 return TRUE;
3273 }
3274 else
3275 {
3276 // WARNING: We cannot write on this FS yet!
3277 DPRINT1("Recognized file system '%S' that doesn't have write support yet!\n",
3278 PartEntry->FileSystem);
3279 return FALSE;
3280 }
3281 }
3282 else // if (PartEntry->FormatState == UnknownFormat)
3283 {
3284 ASSERT(!*PartEntry->FileSystem);
3285
3286 DPRINT1("System partition %lu in disk %lu with no or unknown FS?!\n",
3287 PartEntry->PartitionNumber, PartEntry->DiskEntry->DiskNumber);
3288 return FALSE;
3289 }
3290
3291 // HACK: WARNING: We cannot write on this FS yet!
3292 // See fsutil.c:InferFileSystem()
3293 if (PartEntry->PartitionType == PARTITION_IFS)
3294 {
3295 DPRINT1("Recognized file system '%S' that doesn't have write support yet!\n",
3296 PartEntry->FileSystem);
3297 return FALSE;
3298 }
3299
3300 return TRUE;
3301}
3302
3306 IN BOOLEAN ForceSelect,
3307 IN PDISKENTRY AlternativeDisk OPTIONAL,
3308 IN PPARTENTRY AlternativePart OPTIONAL)
3309{
3310 PLIST_ENTRY ListEntry;
3311 PDISKENTRY DiskEntry;
3312 PPARTENTRY PartEntry;
3313 PPARTENTRY ActivePartition;
3314 PPARTENTRY CandidatePartition = NULL;
3315
3316 /* Check for empty disk list */
3317 if (IsListEmpty(&List->DiskListHead))
3318 {
3319 /* No system partition! */
3320 ASSERT(List->SystemPartition == NULL);
3321 goto NoSystemPartition;
3322 }
3323
3324 /* Adjust the optional alternative disk if needed */
3325 if (!AlternativeDisk && AlternativePart)
3326 AlternativeDisk = AlternativePart->DiskEntry;
3327
3328 /* Ensure that the alternative partition is on the alternative disk */
3329 if (AlternativePart)
3330 ASSERT(AlternativeDisk && (AlternativePart->DiskEntry == AlternativeDisk));
3331
3332 /* Ensure that the alternative disk is in the list */
3333 if (AlternativeDisk)
3334 ASSERT(AlternativeDisk->PartList == List);
3335
3336 /* Start fresh */
3337 CandidatePartition = NULL;
3338
3339//
3340// Step 1 : Check the system disk.
3341//
3342
3343 /*
3344 * First, check whether the system disk, i.e. the one that will be booted
3345 * by default by the hardware, contains an active partition. If so this
3346 * should be our system partition.
3347 */
3348 DiskEntry = GetSystemDisk(List);
3349
3350 if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
3351 {
3352 DPRINT1("System disk -- GPT-partitioned disk detected, not currently supported by SETUP!\n");
3353 goto UseAlternativeDisk;
3354 }
3355
3356 /* If we have a system partition (in the system disk), validate it */
3357 ActivePartition = List->SystemPartition;
3358 if (ActivePartition && IsSupportedActivePartition(ActivePartition))
3359 {
3360 CandidatePartition = ActivePartition;
3361
3362 DPRINT1("Use the current system partition %lu in disk %lu, drive letter %C\n",
3363 CandidatePartition->PartitionNumber,
3364 CandidatePartition->DiskEntry->DiskNumber,
3365 (CandidatePartition->DriveLetter == 0) ? L'-' : CandidatePartition->DriveLetter);
3366
3367 /* Return the candidate system partition */
3368 return CandidatePartition;
3369 }
3370
3371 /* If the system disk is not the optional alternative disk, perform the minimal checks */
3372 if (DiskEntry != AlternativeDisk)
3373 {
3374 /*
3375 * No active partition has been recognized. Enumerate all the (primary)
3376 * partitions in the system disk, excluding the possible current active
3377 * partition, to find a new candidate.
3378 */
3379 for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
3380 ListEntry != &DiskEntry->PrimaryPartListHead;
3381 ListEntry = ListEntry->Flink)
3382 {
3383 /* Retrieve the partition */
3384 PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
3385
3386 /* Skip the current active partition */
3387 if (PartEntry == ActivePartition)
3388 continue;
3389
3390 /* Check if the partition is partitioned and used */
3391 if (PartEntry->IsPartitioned &&
3393 {
3395
3396 /* If we get a candidate active partition in the disk, validate it */
3397 if (IsSupportedActivePartition(PartEntry))
3398 {
3399 CandidatePartition = PartEntry;
3400 goto UseAlternativePartition;
3401 }
3402 }
3403
3404#if 0
3405 /* Check if the partition is partitioned and used */
3406 if (!PartEntry->IsPartitioned)
3407 {
3409
3410 // TODO: Check for minimal size!!
3411 CandidatePartition = PartEntry;
3412 goto UseAlternativePartition;
3413 }
3414#endif
3415 }
3416
3417 /*
3418 * Still nothing, look whether there is some free space that we can use
3419 * for the new system partition. We must be sure that the total number
3420 * of partition is less than the maximum allowed, and that the minimal
3421 * size is fine.
3422 */
3423//
3424// TODO: Fix the handling of system partition being created in unpartitioned space!!
3425// --> When to partition it? etc...
3426//
3427 if (GetPrimaryPartitionCount(DiskEntry) < 4)
3428 {
3429 for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
3430 ListEntry != &DiskEntry->PrimaryPartListHead;
3431 ListEntry = ListEntry->Flink)
3432 {
3433 /* Retrieve the partition */
3434 PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
3435
3436 /* Skip the current active partition */
3437 if (PartEntry == ActivePartition)
3438 continue;
3439
3440 /* Check for unpartitioned space */
3441 if (!PartEntry->IsPartitioned)
3442 {
3444
3445 // TODO: Check for minimal size!!
3446 CandidatePartition = PartEntry;
3447 goto UseAlternativePartition;
3448 }
3449 }
3450 }
3451 }
3452
3453
3454//
3455// Step 2 : No active partition found: Check the alternative disk if specified.
3456//
3457
3458UseAlternativeDisk:
3459 if (!AlternativeDisk || (!ForceSelect && (DiskEntry != AlternativeDisk)))
3460 goto NoSystemPartition;
3461
3462 if (AlternativeDisk->DiskStyle == PARTITION_STYLE_GPT)
3463 {
3464 DPRINT1("Alternative disk -- GPT-partitioned disk detected, not currently supported by SETUP!\n");
3465 goto NoSystemPartition;
3466 }
3467
3468 if (DiskEntry != AlternativeDisk)
3469 {
3470 /* Choose the alternative disk */
3471 DiskEntry = AlternativeDisk;
3472
3473 /* If we get a candidate active partition, validate it */
3474 ActivePartition = GetActiveDiskPartition(DiskEntry);
3475 if (ActivePartition && IsSupportedActivePartition(ActivePartition))
3476 {
3477 CandidatePartition = ActivePartition;
3478 goto UseAlternativePartition;
3479 }
3480 }
3481
3482 /* We now may have an unsupported active partition, or none */
3483
3484/***
3485 *** TODO: Improve the selection:
3486 *** - If we want a really separate system partition from the partition where
3487 *** we install, do something similar to what's done below in the code.
3488 *** - Otherwise if we allow for the system partition to be also the partition
3489 *** where we install, just directly fall down to using AlternativePart.
3490 ***/
3491
3492 /* Retrieve the first partition of the disk */
3493 PartEntry = CONTAINING_RECORD(DiskEntry->PrimaryPartListHead.Flink,
3494 PARTENTRY, ListEntry);
3495 ASSERT(DiskEntry == PartEntry->DiskEntry);
3496
3497 CandidatePartition = PartEntry;
3498
3499 //
3500 // See: https://svn.reactos.org/svn/reactos/trunk/reactos/base/setup/usetup/partlist.c?r1=63355&r2=63354&pathrev=63355#l2318
3501 //
3502
3503 /* Check if the disk is new and if so, use its first partition as the active system partition */
3504 if (DiskEntry->NewDisk)
3505 {
3506 // !IsContainerPartition(PartEntry->PartitionType);
3507 if (!CandidatePartition->IsPartitioned || !CandidatePartition->BootIndicator) /* CandidatePartition != ActivePartition */
3508 {
3509 ASSERT(DiskEntry == CandidatePartition->DiskEntry);
3510
3511 DPRINT1("Use new first active system partition %lu in disk %lu, drive letter %C\n",
3512 CandidatePartition->PartitionNumber,
3513 CandidatePartition->DiskEntry->DiskNumber,
3514 (CandidatePartition->DriveLetter == 0) ? L'-' : CandidatePartition->DriveLetter);
3515
3516 /* Return the candidate system partition */
3517 return CandidatePartition;
3518 }
3519
3520 // FIXME: What to do??
3521 DPRINT1("NewDisk TRUE but first partition is used?\n");
3522 }
3523
3524 /*
3525 * The disk is not new, check if any partition is initialized;
3526 * if not, the first one becomes the system partition.
3527 */
3528 for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
3529 ListEntry != &DiskEntry->PrimaryPartListHead;
3530 ListEntry = ListEntry->Flink)
3531 {
3532 /* Retrieve the partition */
3533 PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
3534
3535 /* Check if the partition is partitioned and is used */
3536 // !IsContainerPartition(PartEntry->PartitionType);
3537 if (/* PartEntry->IsPartitioned && */
3538 PartEntry->PartitionType != PARTITION_ENTRY_UNUSED || PartEntry->BootIndicator)
3539 {
3540 break;
3541 }
3542 }
3543 if (ListEntry == &DiskEntry->PrimaryPartListHead)
3544 {
3545 /*
3546 * OK we haven't encountered any used and active partition,
3547 * so use the first one as the system partition.
3548 */
3549 ASSERT(DiskEntry == CandidatePartition->DiskEntry);
3550
3551 DPRINT1("Use first active system partition %lu in disk %lu, drive letter %C\n",
3552 CandidatePartition->PartitionNumber,
3553 CandidatePartition->DiskEntry->DiskNumber,
3554 (CandidatePartition->DriveLetter == 0) ? L'-' : CandidatePartition->DriveLetter);
3555
3556 /* Return the candidate system partition */
3557 return CandidatePartition;
3558 }
3559
3560 /*
3561 * The disk is not new, we did not find any actual active partition,
3562 * or the one we found was not supported, or any possible other candidate
3563 * is not supported. We then use the alternative partition if specified.
3564 */
3565 if (AlternativePart)
3566 {
3567 DPRINT1("No valid or supported system partition has been found, use the alternative partition!\n");
3568 CandidatePartition = AlternativePart;
3569 goto UseAlternativePartition;
3570 }
3571 else
3572 {
3573NoSystemPartition:
3574 DPRINT1("No valid or supported system partition has been found on this system!\n");
3575 return NULL;
3576 }
3577
3578UseAlternativePartition:
3579 /*
3580 * We are here because we did not find any (active) candidate system
3581 * partition that we know how to support. What we are going to do is
3582 * to change the existing system partition and use the alternative partition
3583 * (e.g. on which we install ReactOS) as the new system partition.
3584 * Then we will need to add in FreeLdr's boot menu an entry for booting
3585 * from the original system partition.
3586 */
3587 ASSERT(CandidatePartition);
3588
3589 DPRINT1("Use alternative active system partition %lu in disk %lu, drive letter %C\n",
3590 CandidatePartition->PartitionNumber,
3591 CandidatePartition->DiskEntry->DiskNumber,
3592 (CandidatePartition->DriveLetter == 0) ? L'-' : CandidatePartition->DriveLetter);
3593
3594 /* Return the candidate system partition */
3595 return CandidatePartition;
3596}
3597
3598BOOLEAN
3601 IN PPARTENTRY PartEntry,
3602 IN PPARTENTRY OldActivePart OPTIONAL)
3603{
3604 /* Check for empty disk list */
3605 if (IsListEmpty(&List->DiskListHead))
3606 return FALSE;
3607
3608 /* Validate the partition entry */
3609 if (!PartEntry)
3610 return FALSE;
3611
3612 /*
3613 * If the partition entry is already the system partition, or if it is
3614 * the same as the old active partition hint the user provided (and if
3615 * it is already active), just return success.
3616 */
3617 if ((PartEntry == List->SystemPartition) ||
3618 ((PartEntry == OldActivePart) && IsPartitionActive(OldActivePart)))
3619 {
3620 return TRUE;
3621 }
3622
3623 ASSERT(PartEntry->DiskEntry);
3624
3625 /* Ensure that the partition's disk is in the list */
3626 ASSERT(PartEntry->DiskEntry->PartList == List);
3627
3628 /*
3629 * If the user provided an old active partition hint, verify that it is
3630 * indeeed active and belongs to the same disk where the new partition
3631 * belongs. Otherwise determine the current active partition on the disk
3632 * where the new partition belongs.
3633 */
3634 if (!(OldActivePart && IsPartitionActive(OldActivePart) && (OldActivePart->DiskEntry == PartEntry->DiskEntry)))
3635 {
3636 /* It's not, determine the current active partition for the disk */
3637 OldActivePart = GetActiveDiskPartition(PartEntry->DiskEntry);
3638 }
3639
3640 /* Unset the old active partition if it exists */
3641 if (OldActivePart)
3642 {
3643 OldActivePart->BootIndicator = FALSE;
3644 OldActivePart->DiskEntry->LayoutBuffer->PartitionEntry[OldActivePart->PartitionIndex].BootIndicator = FALSE;
3645 OldActivePart->DiskEntry->LayoutBuffer->PartitionEntry[OldActivePart->PartitionIndex].RewritePartition = TRUE;
3646 OldActivePart->DiskEntry->Dirty = TRUE;
3647 }
3648
3649 /* Modify the system partition if the new partition is on the system disk */
3650 if (PartEntry->DiskEntry == GetSystemDisk(List))
3651 List->SystemPartition = PartEntry;
3652
3653 /* Set the new active partition */
3654 PartEntry->BootIndicator = TRUE;
3655 PartEntry->DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].BootIndicator = TRUE;
3656 PartEntry->DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].RewritePartition = TRUE;
3657 PartEntry->DiskEntry->Dirty = TRUE;
3658
3659 return TRUE;
3660}
3661
3664 IN PDISKENTRY DiskEntry)
3665{
3673 ULONG PartitionCount;
3674 PLIST_ENTRY ListEntry;
3675 PPARTENTRY PartEntry;
3677
3678 DPRINT("WritePartitions() Disk: %lu\n", DiskEntry->DiskNumber);
3679
3680 /* If the disk is not dirty, there is nothing to do */
3681 if (!DiskEntry->Dirty)
3682 return STATUS_SUCCESS;
3683
3685 L"\\Device\\Harddisk%lu\\Partition0",
3686 DiskEntry->DiskNumber);
3688
3690 &Name,
3692 NULL,
3693 NULL);
3694
3698 &Iosb,
3699 0,
3701 if (!NT_SUCCESS(Status))
3702 {
3703 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
3704 return Status;
3705 }
3706
3707#ifdef DUMP_PARTITION_TABLE
3708 DumpPartitionTable(DiskEntry);
3709#endif
3710
3711 //
3712 // FIXME: We first *MUST* use IOCTL_DISK_CREATE_DISK to initialize
3713 // the disk in MBR or GPT format in case the disk was not initialized!!
3714 // For this we must ask the user which format to use.
3715 //
3716
3717 /* Save the original partition count to be restored later (see comment below) */
3718 PartitionCount = DiskEntry->LayoutBuffer->PartitionCount;
3719
3720 /* Set the new disk layout and retrieve its updated version with possibly modified partition numbers */
3722 ((PartitionCount - 1) * sizeof(PARTITION_INFORMATION));
3724 NULL,
3725 NULL,
3726 NULL,
3727 &Iosb,
3729 DiskEntry->LayoutBuffer,
3730 BufferSize,
3731 DiskEntry->LayoutBuffer,
3732 BufferSize);
3734
3735 /*
3736 * IOCTL_DISK_SET_DRIVE_LAYOUT calls IoWritePartitionTable(), which converts
3737 * DiskEntry->LayoutBuffer->PartitionCount into a partition *table* count,
3738 * where such a table is expected to enumerate up to 4 partitions:
3739 * partition *table* count == ROUND_UP(PartitionCount, 4) / 4 .
3740 * Due to this we need to restore the original PartitionCount number.
3741 */
3742 DiskEntry->LayoutBuffer->PartitionCount = PartitionCount;
3743
3744 /* Check whether the IOCTL_DISK_SET_DRIVE_LAYOUT call succeeded */
3745 if (!NT_SUCCESS(Status))
3746 {
3747 DPRINT1("IOCTL_DISK_SET_DRIVE_LAYOUT failed (Status 0x%08lx)\n", Status);
3748 return Status;
3749 }
3750
3751#ifdef DUMP_PARTITION_TABLE
3752 DumpPartitionTable(DiskEntry);
3753#endif
3754
3755 /* Update the partition numbers */
3756
3757 /* Update the primary partition table */
3758 for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
3759 ListEntry != &DiskEntry->PrimaryPartListHead;
3760 ListEntry = ListEntry->Flink)
3761 {
3762 PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
3763
3764 if (PartEntry->IsPartitioned)
3765 {
3767 PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex];
3768 PartEntry->PartitionNumber = PartitionInfo->PartitionNumber;
3769 }
3770 }
3771
3772 /* Update the logical partition table */
3773 for (ListEntry = DiskEntry->LogicalPartListHead.Flink;
3774 ListEntry != &DiskEntry->LogicalPartListHead;
3775 ListEntry = ListEntry->Flink)
3776 {
3777 PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
3778
3779 if (PartEntry->IsPartitioned)
3780 {
3782 PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex];
3783 PartEntry->PartitionNumber = PartitionInfo->PartitionNumber;
3784 }
3785 }
3786
3787 //
3788 // NOTE: Originally (see r40437), we used to install here also a new MBR
3789 // for this disk (by calling InstallMbrBootCodeToDisk), only if:
3790 // DiskEntry->NewDisk == TRUE and DiskEntry->HwDiskNumber == 0.
3791 // Then after that, both DiskEntry->NewDisk and DiskEntry->NoMbr were set
3792 // to FALSE. In the other place (in usetup.c) where InstallMbrBootCodeToDisk
3793 // was called too, the installation test was modified by checking whether
3794 // DiskEntry->NoMbr was TRUE (instead of NewDisk).
3795 //
3796
3797 // HACK: Parts of FIXMEs described above: (Re)set the PartitionStyle to MBR.
3798 DiskEntry->DiskStyle = PARTITION_STYLE_MBR;
3799
3800 /* The layout has been successfully updated, the disk is not dirty anymore */
3801 DiskEntry->Dirty = FALSE;
3802
3803 return Status;
3804}
3805
3806BOOLEAN
3809{
3812 PDISKENTRY DiskEntry;
3813
3814 if (List == NULL)
3815 return TRUE;
3816
3817 for (Entry = List->DiskListHead.Flink;
3818 Entry != &List->DiskListHead;
3819 Entry = Entry->Flink)
3820 {
3821 DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
3822
3823 if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
3824 {
3825 DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
3826 continue;
3827 }
3828
3829 if (DiskEntry->Dirty != FALSE)
3830 {
3831 Status = WritePartitions(DiskEntry);
3832 if (!NT_SUCCESS(Status))
3833 {
3834 DPRINT1("WritePartitionsToDisk() failed to update disk %lu, Status 0x%08lx\n",
3835 DiskEntry->DiskNumber, Status);
3836 }
3837 }
3838 }
3839
3840 return TRUE;
3841}
3842
3843BOOLEAN
3845 IN WCHAR Letter,
3848{
3851 UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"SYSTEM\\MountedDevices");
3853 WCHAR ValueNameBuffer[16];
3855 REG_DISK_MOUNT_INFO MountInfo;
3856
3857 RtlStringCchPrintfW(ValueNameBuffer, ARRAYSIZE(ValueNameBuffer),
3858 L"\\DosDevices\\%c:", Letter);
3859 RtlInitUnicodeString(&ValueName, ValueNameBuffer);
3860
3862 &KeyName,
3865 NULL);
3866
3870 if (!NT_SUCCESS(Status))
3871 {
3875 0,
3876 NULL,
3878 NULL);
3879 }
3880 if (!NT_SUCCESS(Status))
3881 {
3882 DPRINT1("NtCreateKey() failed (Status %lx)\n", Status);
3883 return FALSE;
3884 }
3885
3886 MountInfo.Signature = Signature;
3887 MountInfo.StartingOffset = StartingOffset;
3889 &ValueName,
3890 0,
3891 REG_BINARY,
3892 (PVOID)&MountInfo,
3893 sizeof(MountInfo));
3895 if (!NT_SUCCESS(Status))
3896 {
3897 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status);
3898 return FALSE;
3899 }
3900
3901 return TRUE;
3902}
3903
3904BOOLEAN
3907{
3908 PLIST_ENTRY Entry1, Entry2;
3909 PDISKENTRY DiskEntry;
3910 PPARTENTRY PartEntry;
3912
3913 if (List == NULL)
3914 return FALSE;
3915
3916 for (Entry1 = List->DiskListHead.Flink;
3917 Entry1 != &List->DiskListHead;
3918 Entry1 = Entry1->Flink)
3919 {
3920 DiskEntry = CONTAINING_RECORD(Entry1,
3921 DISKENTRY,
3922 ListEntry);
3923
3924 if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
3925 {
3926 DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
3927 continue;
3928 }
3929
3930 for (Entry2 = DiskEntry->PrimaryPartListHead.Flink;
3931 Entry2 != &DiskEntry->PrimaryPartListHead;
3932 Entry2 = Entry2->Flink)
3933 {
3934 PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
3935 if (PartEntry->IsPartitioned) // && !IsContainerPartition(PartEntry->PartitionType)
3936 {
3938
3939 /* Assign a "\DosDevices\#:" mount point to this partition */
3940 if (PartEntry->DriveLetter)
3941 {
3942 StartingOffset.QuadPart = GetPartEntryOffsetInBytes(PartEntry);
3943 if (!SetMountedDeviceValue(PartEntry->DriveLetter,
3944 DiskEntry->LayoutBuffer->Signature,
3946 {
3947 return FALSE;
3948 }
3949 }
3950 }
3951 }
3952
3953 for (Entry2 = DiskEntry->LogicalPartListHead.Flink;
3954 Entry2 != &DiskEntry->LogicalPartListHead;
3955 Entry2 = Entry2->Flink)
3956 {
3957 PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
3958 if (PartEntry->IsPartitioned) // && !IsContainerPartition(PartEntry->PartitionType)
3959 {
3961
3962 /* Assign a "\DosDevices\#:" mount point to this partition */
3963 if (PartEntry->DriveLetter)
3964 {
3965 StartingOffset.QuadPart = GetPartEntryOffsetInBytes(PartEntry);
3966 if (!SetMountedDeviceValue(PartEntry->DriveLetter,
3967 DiskEntry->LayoutBuffer->Signature,
3969 {
3970 return FALSE;
3971 }
3972 }
3973 }
3974 }
3975 }
3976
3977 return TRUE;
3978}
3979
3980VOID
3982 IN PPARTENTRY PartEntry,
3984{
3985 PDISKENTRY DiskEntry = PartEntry->DiskEntry;
3986
3987 ASSERT(DiskEntry->DiskStyle == PARTITION_STYLE_MBR);
3988
3989 PartEntry->PartitionType = PartitionType;
3990
3991 DiskEntry->Dirty = TRUE;
3992 DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].PartitionType = PartitionType;
3993 DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].RecognizedPartition = IsRecognizedPartition(PartitionType);
3994 DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].RewritePartition = TRUE;
3995}
3996
3997BOOLEAN
4000 OUT PDISKENTRY *pDiskEntry OPTIONAL,
4001 OUT PPARTENTRY *pPartEntry)
4002{
4003 PLIST_ENTRY Entry1, Entry2;
4004 PDISKENTRY DiskEntry;
4005 PPARTENTRY PartEntry;
4006
4007 for (Entry1 = List->DiskListHead.Flink;
4008 Entry1 != &List->DiskListHead;
4009 Entry1 = Entry1->Flink)
4010 {
4011 DiskEntry = CONTAINING_RECORD(Entry1,
4012 DISKENTRY,
4013 ListEntry);
4014
4015 if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
4016 {
4017 DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
4018 continue;
4019 }
4020
4021 for (Entry2 = DiskEntry->PrimaryPartListHead.Flink;
4022 Entry2 != &DiskEntry->PrimaryPartListHead;
4023 Entry2 = Entry2->Flink)
4024 {
4025 PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
4026 if (PartEntry->IsPartitioned && PartEntry->New)
4027 {
4028 ASSERT(DiskEntry == PartEntry->DiskEntry);
4029 if (pDiskEntry) *pDiskEntry = DiskEntry;
4030 *pPartEntry = PartEntry;
4031 return TRUE;
4032 }
4033 }
4034
4035 for (Entry2 = DiskEntry->LogicalPartListHead.Flink;
4036 Entry2 != &DiskEntry->LogicalPartListHead;
4037 Entry2 = Entry2->Flink)
4038 {
4039 PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
4040 if (PartEntry->IsPartitioned && PartEntry->New)
4041 {
4042 ASSERT(DiskEntry == PartEntry->DiskEntry);
4043 if (pDiskEntry) *pDiskEntry = DiskEntry;
4044 *pPartEntry = PartEntry;
4045 return TRUE;
4046 }
4047 }
4048 }
4049
4050 if (pDiskEntry) *pDiskEntry = NULL;
4051 *pPartEntry = NULL;
4052
4053 return FALSE;
4054}
4055
4056BOOLEAN
4059 OUT PDISKENTRY *pDiskEntry OPTIONAL,
4060 OUT PPARTENTRY *pPartEntry)
4061{
4062 PLIST_ENTRY Entry1, Entry2;
4063 PDISKENTRY DiskEntry;
4064 PPARTENTRY PartEntry;
4065
4066 for (Entry1 = List->DiskListHead.Flink;
4067 Entry1 != &List->DiskListHead;
4068 Entry1 = Entry1->Flink)
4069 {
4070 DiskEntry = CONTAINING_RECORD(Entry1,
4071 DISKENTRY,
4072 ListEntry);
4073
4074 if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
4075 {
4076 DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
4077 continue;
4078 }
4079
4080 for (Entry2 = DiskEntry->PrimaryPartListHead.Flink;
4081 Entry2 != &DiskEntry->PrimaryPartListHead;
4082 Entry2 = Entry2->Flink)
4083 {
4084 PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
4085 if (PartEntry->IsPartitioned && PartEntry->NeedsCheck)
4086 {
4087 ASSERT(DiskEntry == PartEntry->DiskEntry);
4088 if (pDiskEntry) *pDiskEntry = DiskEntry;
4089 *pPartEntry = PartEntry;
4090 return TRUE;
4091 }
4092 }
4093
4094 for (Entry2 = DiskEntry->LogicalPartListHead.Flink;
4095 Entry2 != &DiskEntry->LogicalPartListHead;
4096 Entry2 = Entry2->Flink)
4097 {
4098 PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
4099 if (PartEntry->IsPartitioned && PartEntry->NeedsCheck)
4100 {
4101 ASSERT(DiskEntry == PartEntry->DiskEntry);
4102 if (pDiskEntry) *pDiskEntry = DiskEntry;
4103 *pPartEntry = PartEntry;
4104 return TRUE;
4105 }
4106 }
4107 }
4108
4109 if (pDiskEntry) *pDiskEntry = NULL;
4110 *pPartEntry = NULL;
4111
4112 return FALSE;
4113}
4114
4115/* EOF */
DWORD Id
WCHAR Letter
unsigned char BOOLEAN
struct NameRec_ * Name
Definition: cdprocs.h:460
@ Identifier
Definition: asmpp.cpp:95
LONG NTSTATUS
Definition: precomp.h:26
HANDLE ProcessHeap
Definition: servman.c:15
#define DPRINT1
Definition: precomp.h:8
HANDLE GetRootKeyByPredefKey(IN HANDLE KeyHandle, OUT PCWSTR *RootKeyMountPoint OPTIONAL)
Definition: registry.c:90
BOOL Error
Definition: chkdsk.c:66
#define PARTITION_IFS
Definition: disk.h:93
#define PARTITION_ENTRY_UNUSED
Definition: disk.h:86
#define PARTITION_XINT13
Definition: disk.h:97
#define PARTITION_FAT32
Definition: disk.h:95
#define PARTITION_FAT_12
Definition: disk.h:87
#define PARTITION_EXTENDED
Definition: disk.h:91
#define PARTITION_HUGE
Definition: disk.h:92
#define PARTITION_FAT_16
Definition: disk.h:90
#define PARTITION_XINT13_EXTENDED
Definition: disk.h:98
#define PARTITION_FAT32_XINT13
Definition: disk.h:96
PVOID NTAPI RtlAllocateHeap(IN PVOID HeapHandle, IN ULONG Flags, IN SIZE_T Size)
Definition: heap.c:590
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:608
while(CdLookupNextInitialFileDirent(IrpContext, Fcb, FileContext))
_In_ PFCB _In_ LONGLONG FileOffset
Definition: cdprocs.h:160
_In_ PFCB _In_ LONGLONG StartingOffset
Definition: cdprocs.h:291
#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 BufferSize
Definition: mmc.h:75
#define ERROR_SUCCESS
Definition: deptool.c:10
PDISKENTRY CurrentDisk
Definition: partlist.c:74
@ 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:32
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define GENERIC_READ
Definition: compat.h:135
#define MAX_PATH
Definition: compat.h:34
#define FILE_SHARE_READ
Definition: compat.h:136
#define HEAP_ZERO_MEMORY
Definition: compat.h:134
#define wcsicmp
Definition: compat.h:15
static const WCHAR Signature[]
Definition: parser.c:141
return Iosb
Definition: create.c:4402
BOOLEAN RtlTimeToTimeFields(IN PLARGE_INTEGER Time, IN PTIME_FIELDS TimeFields)
#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
enum _ERROR_NUMBER ERROR_NUMBER
@ NOT_AN_ERROR
Definition: errorcode.h:17
@ ERROR_WARN_PARTITION
Definition: errorcode.h:33
@ ERROR_NEW_PARTITION
Definition: errorcode.h:34
@ ERROR_ONLY_ONE_EXTENDED
Definition: errorcode.h:59
@ ERROR_PARTITION_TABLE_FULL
Definition: errorcode.h:58
ULONG ControllerCount
Definition: fdc.c:18
@ SystemDeviceInformation
Definition: ntddk_ex.h:18
_Must_inspect_result_ _In_opt_ PFLT_INSTANCE _Out_ PHANDLE FileHandle
Definition: fltkernel.h:1231
#define FILE_SYNCHRONOUS_IO_NONALERT
Definition: from_kernel.h:31
@ FileFsDeviceInformation
Definition: from_kernel.h:222
@ FileFsVolumeInformation
Definition: from_kernel.h:219
NTSTATUS InferFileSystem(IN PCWSTR PartitionPath OPTIONAL, IN HANDLE PartitionHandle OPTIONAL, IN OUT PWSTR FileSystemName, IN SIZE_T FileSystemNameSize)
Definition: fsrec.c:269
UCHAR FileSystemToMBRPartitionType(IN PCWSTR FileSystem, IN ULONGLONG StartSector, IN ULONGLONG SectorCount)
Definition: fsrec.c:333
union Alignment_ Alignment
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
CPPORT Port[4]
Definition: headless.c:35
_In_ GUID _In_ PVOID ValueData
Definition: hubbusif.h:312
struct _CM_FULL_RESOURCE_DESCRIPTOR * PCM_FULL_RESOURCE_DESCRIPTOR
#define CmResourceTypeDeviceSpecific
Definition: hwresource.cpp:127
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
NTSYSAPI PVOID WINAPI RtlReAllocateHeap(HANDLE, ULONG, PVOID, SIZE_T)
Definition: heap.c:2667
NTSYSAPI NTSTATUS WINAPI RtlQueryRegistryValues(ULONG, PCWSTR, PRTL_QUERY_REGISTRY_TABLE, PVOID, PVOID)
#define REG_SZ
Definition: layer.c:22
struct _PARTLIST * PPARTLIST
struct _BIOSDISKENTRY * PBIOSDISKENTRY
@ UnknownFormat
Definition: partlist.h:36
@ Preformatted
Definition: partlist.h:37
@ Formatted
Definition: partlist.h:38
@ Unformatted
Definition: partlist.h:34
#define GetDiskSizeInBytes(DiskEntry)
Definition: partlist.h:233
#define EFI_PMBR_OSTYPE_EFI
Definition: partlist.h:172
#define PARTITION_MAGIC
Definition: partlist.h:169
#define GetPartEntryOffsetInBytes(PartEntry)
Definition: partlist.h:227
#define GetPartEntrySizeInBytes(PartEntry)
Definition: partlist.h:230
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define ASSERT(a)
Definition: mode.c:44
#define for
Definition: utility.h:88
@ PARTITION_STYLE_GPT
Definition: imports.h:202
@ PARTITION_STYLE_MBR
Definition: imports.h:201
#define ULL(a, b)
Definition: format_msg.c:27
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
static PTIME_FIELDS TimeFields
Definition: time.c:104
#define min(a, b)
Definition: monoChain.cc:55
#define _Inout_
Definition: ms_sal.h:378
#define _In_
Definition: ms_sal.h:308
#define _In_opt_
Definition: ms_sal.h:309
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ ULONG _Out_ PNDIS_STRING _Out_ PNDIS_HANDLE KeyHandle
Definition: ndis.h:4715
_In_ PCWSTR _Inout_ _At_ QueryTable EntryContext
Definition: rtlfuncs.h:4207
_In_ PCWSTR _Inout_ _At_ QueryTable _Pre_unknown_ PRTL_QUERY_REGISTRY_TABLE QueryTable
Definition: rtlfuncs.h:4208
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:3952
NTSYSAPI NTSTATUS NTAPI NtOpenKey(OUT PHANDLE KeyHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes)
Definition: ntapi.c:336
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define SYNCHRONIZE
Definition: nt_native.h:61
NTSYSAPI NTSTATUS NTAPI NtSetValueKey(IN HANDLE KeyHandle, IN PUNICODE_STRING ValueName, IN ULONG TitleIndex OPTIONAL, IN ULONG Type, IN PVOID Data, IN ULONG DataSize)
Definition: ntapi.c:859
#define REG_BINARY
Definition: nt_native.h:1496
#define FILE_READ_DATA
Definition: nt_native.h:628
#define FSCTL_LOCK_VOLUME
Definition: nt_native.h:832
#define KEY_ALL_ACCESS
Definition: nt_native.h:1041
#define FILE_READ_ATTRIBUTES
Definition: nt_native.h:647
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define RTL_REGISTRY_ABSOLUTE
Definition: nt_native.h:161
#define REG_OPTION_NON_VOLATILE
Definition: nt_native.h:1057
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 REG_FULL_RESOURCE_DESCRIPTOR
Definition: nt_native.h:1503
NTSTATUS NTAPI NtCreateKey(OUT PHANDLE KeyHandle, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, IN ULONG TitleIndex, IN PUNICODE_STRING Class OPTIONAL, IN ULONG CreateOptions, OUT PULONG Disposition OPTIONAL)
Definition: ntapi.c:240
#define IOCTL_DISK_SET_DRIVE_LAYOUT
Definition: ntdddisk.h:205
#define IsContainerPartition(PartitionType)
Definition: ntdddisk.h:316
#define IsRecognizedPartition(PartitionType)
Definition: ntdddisk.h:342
#define IOCTL_DISK_GET_DRIVE_LAYOUT
Definition: ntdddisk.h:91
struct _PARTITION_INFORMATION PARTITION_INFORMATION
@ RemovableMedia
Definition: ntdddisk.h:387
@ FixedMedia
Definition: ntdddisk.h:388
struct _DRIVE_LAYOUT_INFORMATION DRIVE_LAYOUT_INFORMATION
NTSTATUS NTAPI NtQuerySystemTime(OUT PLARGE_INTEGER SystemTime)
Definition: time.c:483
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
NTSTRSAFEVAPI RtlStringCchPrintfW(_Out_writes_(cchDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest, _In_ size_t cchDest, _In_ _Printf_format_string_ NTSTRSAFE_PCWSTR pszFormat,...)
Definition: ntstrsafe.h:1110
NTSTRSAFEAPI RtlStringCbCopyNW(_Out_writes_bytes_(cbDest) NTSTRSAFE_PWSTR pszDest, _In_ size_t cbDest, _In_reads_bytes_(cbToCopy) STRSAFE_LPCWSTR pszSrc, _In_ size_t cbToCopy)
Definition: ntstrsafe.h:416
#define L(x)
Definition: ntvdm.h:50
ULONG SectorCount
Definition: part_xbox.c:31
CHAR PartitionType
Definition: part_xbox.c:32
unsigned short USHORT
Definition: pedump.c:61
struct _FILE_FS_VOLUME_INFORMATION * PFILE_FS_VOLUME_INFORMATION
struct _FILE_FS_VOLUME_INFORMATION FILE_FS_VOLUME_INFORMATION
#define IOCTL_SCSI_GET_ADDRESS
Definition: scsi_port.h:52
#define memset(x, y, z)
Definition: compat.h:39
IN HANDLE DstPath
Definition: fsutil.h:76
ERROR_NUMBER ExtendedPartitionCreationChecks(_In_ PPARTENTRY PartEntry)
Definition: partlist.c:2838
VOID DestroyPartitionList(IN PPARTLIST List)
Definition: partlist.c:1951
static VOID AddPartitionToDisk(IN ULONG DiskNumber, IN PDISKENTRY DiskEntry, IN ULONG PartitionIndex, IN BOOLEAN LogicalPartition)
Definition: partlist.c:771
ERROR_NUMBER PartitionCreationChecks(_In_ PPARTENTRY PartEntry)
Definition: partlist.c:2793
static BOOLEAN InitializePartitionEntry(_Inout_ PPARTENTRY PartEntry, _In_opt_ ULONGLONG SizeBytes)
Definition: partlist.c:678
PPARTENTRY SelectPartition(IN PPARTLIST List, IN ULONG DiskNumber, IN ULONG PartitionNumber)
Definition: partlist.c:2203
static VOID GetDriverName(IN PDISKENTRY DiskEntry)
Definition: partlist.c:105
struct _REG_DISK_MOUNT_INFO * PREG_DISK_MOUNT_INFO
BOOLEAN SetMountedDeviceValues(IN PPARTLIST List)
Definition: partlist.c:3905
static PDISKENTRY GetSystemDisk(IN PPARTLIST List)
Definition: partlist.c:1738
BOOLEAN GetDiskOrPartition(IN PPARTLIST List, IN ULONG DiskNumber, IN ULONG PartitionNumber OPTIONAL, OUT PDISKENTRY *pDiskEntry, OUT PPARTENTRY *pPartEntry OPTIONAL)
Definition: partlist.c:2163
ULONGLONG AlignUp(IN ULONGLONG Value, IN ULONG Alignment)
Definition: partlist.c:79
static ULONG GetPrimaryPartitionCount(IN PDISKENTRY DiskEntry)
Definition: partlist.c:2435
static VOID UpdateDiskLayout(IN PDISKENTRY DiskEntry)
Definition: partlist.c:2541
BOOLEAN WritePartitionsToDisk(IN PPARTLIST List)
Definition: partlist.c:3807
PPARTENTRY GetPartition(IN PDISKENTRY DiskEntry, IN ULONG PartitionNumber)
Definition: partlist.c:2116
PDISKENTRY GetDiskByNumber(IN PPARTLIST List, IN ULONG DiskNumber)
Definition: partlist.c:2034
ULONGLONG RoundingDivide(IN ULONGLONG Dividend, IN ULONGLONG Divisor)
Definition: partlist.c:95
VOID SetMBRPartitionType(IN PPARTENTRY PartEntry, IN UCHAR PartitionType)
Definition: partlist.c:3981
static VOID AssignDriveLetters(IN PPARTLIST List)
Definition: partlist.c:138
static BOOLEAN IsSamePrimaryLayoutEntry(_In_ PPARTITION_INFORMATION PartitionInfo, _In_ PPARTENTRY PartEntry)
Definition: partlist.c:2424
PPARTENTRY GetPrevPartition(IN PPARTLIST List, IN PPARTENTRY CurrentPart OPTIONAL)
Definition: partlist.c:2319
ULONGLONG AlignDown(IN ULONGLONG Value, IN ULONG Alignment)
Definition: partlist.c:67
BOOLEAN GetNextUncheckedPartition(IN PPARTLIST List, OUT PDISKENTRY *pDiskEntry OPTIONAL, OUT PPARTENTRY *pPartEntry)
Definition: partlist.c:4057
BOOLEAN DeletePartition(IN PPARTLIST List, IN PPARTENTRY PartEntry, OUT PPARTENTRY *FreeRegion OPTIONAL)
Definition: partlist.c:3091
BOOLEAN IsSuperFloppy(IN PDISKENTRY DiskEntry)
Definition: partlist.c:501
static PPARTENTRY GetPrevUnpartitionedEntry(IN PPARTENTRY PartEntry)
Definition: partlist.c:2724
static VOID SetDiskSignature(IN PPARTLIST List, IN PDISKENTRY DiskEntry)
Definition: partlist.c:1173
static PPARTENTRY GetNextUnpartitionedEntry(IN PPARTENTRY PartEntry)
Definition: partlist.c:2759
static ULONG GetLogicalPartitionCount(IN PDISKENTRY DiskEntry)
Definition: partlist.c:2462
static NTSTATUS NTAPI DiskConfigurationDataQueryRoutine(PWSTR ValueName, ULONG ValueType, PVOID ValueData, ULONG ValueLength, PVOID Context, PVOID EntryContext)
Definition: partlist.c:247
PPARTLIST CreatePartitionList(VOID)
Definition: partlist.c:1867
#define ROOT_NAME
PPARTENTRY GetNextPartition(IN PPARTLIST List, IN PPARTENTRY CurrentPart OPTIONAL)
Definition: partlist.c:2227
static VOID AddDiskToList(IN HANDLE FileHandle, IN ULONG DiskNumber, IN PPARTLIST List)
Definition: partlist.c:1326
static VOID ScanForUnpartitionedDiskSpace(IN PDISKENTRY DiskEntry)
Definition: partlist.c:962
static NTSTATUS NTAPI SystemConfigurationDataQueryRoutine(PWSTR ValueName, ULONG ValueType, PVOID ValueData, ULONG ValueLength, PVOID Context, PVOID EntryContext)
Definition: partlist.c:290
BOOLEAN IsPartitionActive(IN PPARTENTRY PartEntry)
Definition: partlist.c:1788
PDISKENTRY GetDiskByBiosNumber(IN PPARTLIST List, IN ULONG HwDiskNumber)
Definition: partlist.c:2008
static VOID UpdateDiskSignatures(IN PPARTLIST List)
Definition: partlist.c:1235
BOOLEAN SetActivePartition(IN PPARTLIST List, IN PPARTENTRY PartEntry, IN PPARTENTRY OldActivePart OPTIONAL)
Definition: partlist.c:3599
static VOID EnumerateBiosDiskEntries(IN PPARTLIST PartList)
Definition: partlist.c:337
static PPARTENTRY CreateInsertBlankRegion(IN PDISKENTRY DiskEntry, IN OUT PLIST_ENTRY ListHead, IN ULONGLONG StartSector, IN ULONGLONG SectorCount, IN BOOLEAN LogicalSpace)
Definition: partlist.c:640
static PPARTENTRY GetActiveDiskPartition(IN PDISKENTRY DiskEntry)
Definition: partlist.c:1811
BOOLEAN GetNextUnformattedPartition(IN PPARTLIST List, OUT PDISKENTRY *pDiskEntry OPTIONAL, OUT PPARTENTRY *pPartEntry)
Definition: partlist.c:3998
struct _REG_DISK_MOUNT_INFO REG_DISK_MOUNT_INFO
static BOOLEAN InsertDiskRegion(IN PDISKENTRY DiskEntry, IN PPARTENTRY PartEntry, IN BOOLEAN LogicalPartition)
Definition: partlist.c:574
static BOOLEAN IsEmptyLayoutEntry(_In_ PPARTITION_INFORMATION PartitionInfo)
Definition: partlist.c:2415
BOOLEAN SetMountedDeviceValue(IN WCHAR Letter, IN ULONG Signature, IN LARGE_INTEGER StartingOffset)
Definition: partlist.c:3844
static VOID UpdateHwDiskNumbers(IN PPARTLIST List)
Definition: partlist.c:1265
static BOOLEAN ReAllocateLayoutBuffer(IN PDISKENTRY DiskEntry)
Definition: partlist.c:2489
PPARTENTRY FindSupportedSystemPartition(IN PPARTLIST List, IN BOOLEAN ForceSelect, IN PDISKENTRY AlternativeDisk OPTIONAL, IN PPARTENTRY AlternativePart OPTIONAL)
Definition: partlist.c:3304
static BOOLEAN IsSupportedActivePartition(IN PPARTENTRY PartEntry)
Definition: partlist.c:3224
PDISKENTRY GetDiskBySignature(IN PPARTLIST List, IN ULONG Signature)
Definition: partlist.c:2090
NTSTATUS DismountVolume(IN PPARTENTRY PartEntry)
Definition: partlist.c:2984
BOOLEAN CreatePartition(_In_ PPARTLIST List, _Inout_ PPARTENTRY PartEntry, _In_opt_ ULONGLONG SizeBytes)
Definition: partlist.c:2869
static NTSTATUS NTAPI DiskIdentifierQueryRoutine(PWSTR ValueName, ULONG ValueType, PVOID ValueData, ULONG ValueLength, PVOID Context, PVOID EntryContext)
Definition: partlist.c:217
NTSTATUS WritePartitions(IN PDISKENTRY DiskEntry)
Definition: partlist.c:3663
PDISKENTRY GetDiskBySCSI(IN PPARTLIST List, IN USHORT Port, IN USHORT Bus, IN USHORT Id)
Definition: partlist.c:2060
static VOID AddLogicalDiskSpace(_In_ PDISKENTRY DiskEntry)
Definition: partlist.c:2903
BOOLEAN CreateExtendedPartition(_In_ PPARTLIST List, _Inout_ PPARTENTRY PartEntry, _In_opt_ ULONGLONG SizeBytes)
Definition: partlist.c:2930
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:71
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
NTSYSAPI NTSTATUS NTAPI NtQuerySystemInformation(IN SYSTEM_INFORMATION_CLASS SystemInfoClass, OUT PVOID SystemInfoBuffer, IN ULONG SystemInfoBufferSize, OUT PULONG BytesReturned OPTIONAL)
base of all file and directory entries
Definition: entries.h:83
ULONG AdapterNumber
Definition: partlist.h:139
ULONG ControllerNumber
Definition: partlist.h:140
ULONG DiskNumber
Definition: partlist.h:141
ULONG Checksum
Definition: partlist.h:143
ULONG Signature
Definition: partlist.h:142
PDISKENTRY DiskEntry
Definition: partlist.h:144
CM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry
Definition: partlist.h:145
CM_PARTIAL_RESOURCE_LIST PartialResourceList
Definition: hwresource.cpp:160
union _CM_PARTIAL_RESOURCE_DESCRIPTOR::@393 u
struct _CM_PARTIAL_RESOURCE_DESCRIPTOR::@393::@402 DeviceSpecificData
CM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptors[1]
Definition: hwresource.cpp:119
ULONG HwAdapterNumber
Definition: partlist.h:100
ULONG SectorAlignment
Definition: partlist.h:95
ULARGE_INTEGER SectorCount
Definition: partlist.h:94
UNICODE_STRING DriverName
Definition: partlist.h:120
ULONG HwControllerNumber
Definition: partlist.h:101
ULONG HwDiskNumber
Definition: partlist.h:102
ULONG SectorsPerTrack
Definition: partlist.h:91
PPARTENTRY ExtendedPartition
Definition: partlist.h:132
LIST_ENTRY LogicalPartListHead
Definition: partlist.h:129
struct _PARTLIST * PartList
Definition: partlist.h:83
BOOLEAN NewDisk
Definition: partlist.h:117
ULONG DiskNumber
Definition: partlist.h:108
ULONG BytesPerSector
Definition: partlist.h:92
BOOLEAN BiosFound
Definition: partlist.h:99
ULONGLONG Cylinders
Definition: partlist.h:89
USHORT Bus
Definition: partlist.h:111
USHORT Id
Definition: partlist.h:112
LIST_ENTRY ListEntry
Definition: partlist.h:80
BOOLEAN Dirty
Definition: partlist.h:115
USHORT Port
Definition: partlist.h:110
PARTITION_STYLE DiskStyle
Definition: partlist.h:118
ULONG TracksPerCylinder
Definition: partlist.h:90
LIST_ENTRY PrimaryPartListHead
Definition: partlist.h:128
MEDIA_TYPE MediaType
Definition: partlist.h:85
ULONG HwFixedDiskNumber
Definition: partlist.h:103
ULONG CylinderAlignment
Definition: partlist.h:96
PDRIVE_LAYOUT_INFORMATION LayoutBuffer
Definition: partlist.h:122
MEDIA_TYPE MediaType
Definition: ntdddisk.h:406
LARGE_INTEGER Cylinders
Definition: ntdddisk.h:405
ULONG TracksPerCylinder
Definition: ntdddisk.h:407
ULONG SectorsPerTrack
Definition: ntdddisk.h:408
ULONG BytesPerSector
Definition: ntdddisk.h:409
PARTITION_INFORMATION PartitionEntry[1]
Definition: ntdddisk.h:426
Definition: typedefs.h:120
struct _LIST_ENTRY * Blink
Definition: typedefs.h:122
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
BOOLEAN IsPartitioned
Definition: partlist.h:66
UCHAR PartitionType
Definition: partlist.h:53
BOOLEAN New
Definition: partlist.h:71
ULARGE_INTEGER SectorCount
Definition: partlist.h:50
BOOLEAN BootIndicator
Definition: partlist.h:52
WCHAR VolumeLabel[20]
Definition: partlist.h:59
WCHAR FileSystem[MAX_PATH+1]
Definition: partlist.h:60
struct _DISKENTRY * DiskEntry
Definition: partlist.h:46
BOOLEAN LogicalPartition
Definition: partlist.h:63
FORMATSTATE FormatState
Definition: partlist.h:61
WCHAR DriveLetter
Definition: partlist.h:58
ULONG OnDiskPartitionNumber
Definition: partlist.h:54
BOOLEAN NeedsCheck
Definition: partlist.h:74
LIST_ENTRY ListEntry
Definition: partlist.h:43
ULONG PartitionNumber
Definition: partlist.h:55
ULARGE_INTEGER StartSector
Definition: partlist.h:49
ULONG PartitionIndex
Definition: partlist.h:56
LARGE_INTEGER StartingOffset
Definition: ntdddisk.h:413