ReactOS 0.4.15-dev-6661-gcc6e444
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 = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
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 IN OUT PPARTENTRY PartEntry,
681 IN BOOLEAN AutoCreate)
682{
683 PDISKENTRY DiskEntry = PartEntry->DiskEntry;
684
685 DPRINT1("Current partition sector count: %I64u\n", PartEntry->SectorCount.QuadPart);
686
687 /* Fail if we try to initialize this partition entry with more sectors than what it actually contains */
688 if (SectorCount > PartEntry->SectorCount.QuadPart)
689 return FALSE;
690
691 /* Fail if the partition is already in use */
692 ASSERT(!PartEntry->IsPartitioned);
693
694 if ((AutoCreate != FALSE) ||
695 (AlignDown(PartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) -
696 PartEntry->StartSector.QuadPart == PartEntry->SectorCount.QuadPart))
697 {
698 PartEntry->AutoCreate = AutoCreate;
699 }
700 else
701 {
702 ULONGLONG StartSector;
703 ULONGLONG SectorCount2;
704 PPARTENTRY NewPartEntry;
705
706 /* Create a partition entry that represents the remaining space after the partition to be initialized */
707
708 StartSector = AlignDown(PartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment);
709 SectorCount2 = PartEntry->StartSector.QuadPart + PartEntry->SectorCount.QuadPart - StartSector;
710
711 NewPartEntry = CreateInsertBlankRegion(DiskEntry,
712 PartEntry->ListEntry.Flink,
713 StartSector,
714 SectorCount2,
715 PartEntry->LogicalPartition);
716 if (NewPartEntry == NULL)
717 {
718 DPRINT1("Failed to create a new empty region for disk space!\n");
719 return FALSE;
720 }
721
722 /* Resize down the partition entry; its StartSector remains the same */
723 PartEntry->SectorCount.QuadPart = StartSector - PartEntry->StartSector.QuadPart;
724 }
725
726 /* Convert the partition entry to 'New (Unformatted)' */
727 PartEntry->New = TRUE;
728 PartEntry->IsPartitioned = TRUE;
729
730// FIXME: Use FileSystemToMBRPartitionType() only for MBR, otherwise use PARTITION_BASIC_DATA_GUID.
731 PartEntry->PartitionType = FileSystemToMBRPartitionType(L"RAW",
732 PartEntry->StartSector.QuadPart,
733 PartEntry->SectorCount.QuadPart);
734 ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
735
736 PartEntry->FormatState = Unformatted;
737 PartEntry->FileSystem[0] = L'\0';
738 // PartEntry->AutoCreate = AutoCreate;
739 PartEntry->BootIndicator = FALSE;
740
741 DPRINT1("First Sector : %I64u\n", PartEntry->StartSector.QuadPart);
742 DPRINT1("Last Sector : %I64u\n", PartEntry->StartSector.QuadPart + PartEntry->SectorCount.QuadPart - 1);
743 DPRINT1("Total Sectors: %I64u\n", PartEntry->SectorCount.QuadPart);
744
745 return TRUE;
746}
747
748
749static
750VOID
752 IN ULONG DiskNumber,
753 IN PDISKENTRY DiskEntry,
754 IN ULONG PartitionIndex,
756{
759 PPARTENTRY PartEntry;
760 HANDLE PartitionHandle;
763 WCHAR PathBuffer[MAX_PATH];
765 UCHAR LabelBuffer[sizeof(FILE_FS_VOLUME_INFORMATION) + 256 * sizeof(WCHAR)];
767
768 PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[PartitionIndex];
769
770 if (PartitionInfo->PartitionType == PARTITION_ENTRY_UNUSED ||
772 {
773 return;
774 }
775
776 PartEntry = RtlAllocateHeap(ProcessHeap,
778 sizeof(PARTENTRY));
779 if (PartEntry == NULL)
780 return;
781
782 PartEntry->DiskEntry = DiskEntry;
783
784 PartEntry->StartSector.QuadPart = (ULONGLONG)PartitionInfo->StartingOffset.QuadPart / DiskEntry->BytesPerSector;
785 PartEntry->SectorCount.QuadPart = (ULONGLONG)PartitionInfo->PartitionLength.QuadPart / DiskEntry->BytesPerSector;
786
787 PartEntry->BootIndicator = PartitionInfo->BootIndicator;
788 PartEntry->PartitionType = PartitionInfo->PartitionType;
789
791 PartEntry->IsPartitioned = TRUE;
792 PartEntry->OnDiskPartitionNumber = PartitionInfo->PartitionNumber;
793 PartEntry->PartitionNumber = PartitionInfo->PartitionNumber;
794 PartEntry->PartitionIndex = PartitionIndex;
795
796 /* Specify the partition as initially unformatted */
797 PartEntry->FormatState = Unformatted;
798 PartEntry->FileSystem[0] = L'\0';
799
800 /* Initialize the partition volume label */
801 RtlZeroMemory(PartEntry->VolumeLabel, sizeof(PartEntry->VolumeLabel));
802
803 if (IsContainerPartition(PartEntry->PartitionType))
804 {
805 PartEntry->FormatState = Unformatted;
806
807 if (LogicalPartition == FALSE && DiskEntry->ExtendedPartition == NULL)
808 DiskEntry->ExtendedPartition = PartEntry;
809 }
810 else if (IsRecognizedPartition(PartEntry->PartitionType))
811 {
812 ASSERT(PartitionInfo->RecognizedPartition);
813 ASSERT(PartEntry->IsPartitioned && PartEntry->PartitionNumber != 0);
814
815 /* Try to open the volume so as to mount it */
816 RtlStringCchPrintfW(PathBuffer, ARRAYSIZE(PathBuffer),
817 L"\\Device\\Harddisk%lu\\Partition%lu",
818 DiskEntry->DiskNumber,
819 PartEntry->PartitionNumber);
820 RtlInitUnicodeString(&Name, PathBuffer);
821
823 &Name,
825 NULL,
826 NULL);
827
828 PartitionHandle = NULL;
829 Status = NtOpenFile(&PartitionHandle,
835 if (!NT_SUCCESS(Status))
836 {
837 DPRINT1("NtOpenFile() failed, Status 0x%08lx\n", Status);
838 }
839
840 if (PartitionHandle)
841 {
843
844 /* We don't have a FS, try to guess one */
845 Status = InferFileSystem(NULL, PartitionHandle,
846 PartEntry->FileSystem,
847 sizeof(PartEntry->FileSystem));
848 if (!NT_SUCCESS(Status))
849 DPRINT1("InferFileSystem() failed, Status 0x%08lx\n", Status);
850 }
851 if (*PartEntry->FileSystem)
852 {
853 ASSERT(PartitionHandle);
854
855 /*
856 * Handle partition mounted with RawFS: it is
857 * either unformatted or has an unknown format.
858 */
859 if (wcsicmp(PartEntry->FileSystem, L"RAW") == 0)
860 {
861 /*
862 * True unformatted partitions on NT are created with their
863 * partition type set to either one of the following values,
864 * and are mounted with RawFS. This is done this way since we
865 * are assured to have FAT support, which is the only FS that
866 * uses these partition types. Therefore, having a partition
867 * mounted with RawFS and with these partition types means that
868 * the FAT FS was unable to mount it beforehand and thus the
869 * partition is unformatted.
870 * However, any partition mounted by RawFS that does NOT have
871 * any of these partition types must be considered as having
872 * an unknown format.
873 */
874 if (PartEntry->PartitionType == PARTITION_FAT_12 ||
875 PartEntry->PartitionType == PARTITION_FAT_16 ||
876 PartEntry->PartitionType == PARTITION_HUGE ||
877 PartEntry->PartitionType == PARTITION_XINT13 ||
878 PartEntry->PartitionType == PARTITION_FAT32 ||
880 {
881 PartEntry->FormatState = Unformatted;
882 }
883 else
884 {
885 /* Close the partition before dismounting */
886 NtClose(PartitionHandle);
887 PartitionHandle = NULL;
888 /*
889 * Dismount the partition since RawFS owns it, and set its
890 * format to unknown (may or may not be actually formatted).
891 */
892 DismountVolume(PartEntry);
893 PartEntry->FormatState = UnknownFormat;
894 PartEntry->FileSystem[0] = L'\0';
895 }
896 }
897 else
898 {
899 PartEntry->FormatState = Preformatted;
900 }
901 }
902 else
903 {
904 PartEntry->FormatState = UnknownFormat;
905 }
906
907 /* Retrieve the partition volume label */
908 if (PartitionHandle)
909 {
910 Status = NtQueryVolumeInformationFile(PartitionHandle,
912 &LabelBuffer,
913 sizeof(LabelBuffer),
915 if (NT_SUCCESS(Status))
916 {
917 /* Copy the (possibly truncated) volume label and NULL-terminate it */
918 RtlStringCbCopyNW(PartEntry->VolumeLabel, sizeof(PartEntry->VolumeLabel),
919 LabelInfo->VolumeLabel, LabelInfo->VolumeLabelLength);
920 }
921 else
922 {
923 DPRINT1("NtQueryVolumeInformationFile() failed, Status 0x%08lx\n", Status);
924 }
925 }
926
927 /* Close the partition */
928 if (PartitionHandle)
929 NtClose(PartitionHandle);
930 }
931 else
932 {
933 /* Unknown partition, hence unknown format (may or may not be actually formatted) */
934 PartEntry->FormatState = UnknownFormat;
935 }
936
937 InsertDiskRegion(DiskEntry, PartEntry, LogicalPartition);
938}
939
940static
941VOID
943 IN PDISKENTRY DiskEntry)
944{
945 ULONGLONG StartSector;
947 ULONGLONG LastStartSector;
948 ULONGLONG LastSectorCount;
949 ULONGLONG LastUnusedSectorCount;
950 PPARTENTRY PartEntry;
951 PPARTENTRY NewPartEntry;
953
954 DPRINT("ScanForUnpartitionedDiskSpace()\n");
955
956 if (IsListEmpty(&DiskEntry->PrimaryPartListHead))
957 {
958 DPRINT1("No primary partition!\n");
959
960 /* Create a partition entry that represents the empty disk */
961
962 if (DiskEntry->SectorAlignment < 2048)
963 StartSector = 2048ULL;
964 else
965 StartSector = (ULONGLONG)DiskEntry->SectorAlignment;
966 SectorCount = AlignDown(DiskEntry->SectorCount.QuadPart, DiskEntry->SectorAlignment) - StartSector;
967
968 NewPartEntry = CreateInsertBlankRegion(DiskEntry,
969 &DiskEntry->PrimaryPartListHead,
970 StartSector,
972 FALSE);
973 if (NewPartEntry == NULL)
974 DPRINT1("Failed to create a new empty region for full disk space!\n");
975
976 return;
977 }
978
979 /* Start partition at head 1, cylinder 0 */
980 if (DiskEntry->SectorAlignment < 2048)
981 LastStartSector = 2048ULL;
982 else
983 LastStartSector = (ULONGLONG)DiskEntry->SectorAlignment;
984 LastSectorCount = 0ULL;
985 LastUnusedSectorCount = 0ULL;
986
987 for (Entry = DiskEntry->PrimaryPartListHead.Flink;
988 Entry != &DiskEntry->PrimaryPartListHead;
989 Entry = Entry->Flink)
990 {
991 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
992
993 if (PartEntry->PartitionType != PARTITION_ENTRY_UNUSED ||
994 PartEntry->SectorCount.QuadPart != 0ULL)
995 {
996 LastUnusedSectorCount =
997 PartEntry->StartSector.QuadPart - (LastStartSector + LastSectorCount);
998
999 if (PartEntry->StartSector.QuadPart > (LastStartSector + LastSectorCount) &&
1000 LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment)
1001 {
1002 DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount);
1003
1004 StartSector = LastStartSector + LastSectorCount;
1005 SectorCount = AlignDown(StartSector + LastUnusedSectorCount, DiskEntry->SectorAlignment) - StartSector;
1006
1007 /* Insert the table into the list */
1008 NewPartEntry = CreateInsertBlankRegion(DiskEntry,
1009 &PartEntry->ListEntry,
1010 StartSector,
1012 FALSE);
1013 if (NewPartEntry == NULL)
1014 {
1015 DPRINT1("Failed to create a new empty region for disk space!\n");
1016 return;
1017 }
1018 }
1019
1020 LastStartSector = PartEntry->StartSector.QuadPart;
1021 LastSectorCount = PartEntry->SectorCount.QuadPart;
1022 }
1023 }
1024
1025 /* Check for trailing unpartitioned disk space */
1026 if ((LastStartSector + LastSectorCount) < DiskEntry->SectorCount.QuadPart)
1027 {
1028 LastUnusedSectorCount = AlignDown(DiskEntry->SectorCount.QuadPart - (LastStartSector + LastSectorCount), DiskEntry->SectorAlignment);
1029
1030 if (LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment)
1031 {
1032 DPRINT("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount);
1033
1034 StartSector = LastStartSector + LastSectorCount;
1035 SectorCount = AlignDown(StartSector + LastUnusedSectorCount, DiskEntry->SectorAlignment) - StartSector;
1036
1037 /* Append the table to the list */
1038 NewPartEntry = CreateInsertBlankRegion(DiskEntry,
1039 &DiskEntry->PrimaryPartListHead,
1040 StartSector,
1042 FALSE);
1043 if (NewPartEntry == NULL)
1044 {
1045 DPRINT1("Failed to create a new empty region for trailing disk space!\n");
1046 return;
1047 }
1048 }
1049 }
1050
1051 if (DiskEntry->ExtendedPartition != NULL)
1052 {
1053 if (IsListEmpty(&DiskEntry->LogicalPartListHead))
1054 {
1055 DPRINT1("No logical partition!\n");
1056
1057 /* Create a partition entry that represents the empty extended partition */
1058
1059 StartSector = DiskEntry->ExtendedPartition->StartSector.QuadPart + (ULONGLONG)DiskEntry->SectorAlignment;
1060 SectorCount = DiskEntry->ExtendedPartition->SectorCount.QuadPart - (ULONGLONG)DiskEntry->SectorAlignment;
1061
1062 NewPartEntry = CreateInsertBlankRegion(DiskEntry,
1063 &DiskEntry->LogicalPartListHead,
1064 StartSector,
1066 TRUE);
1067 if (NewPartEntry == NULL)
1068 {
1069 DPRINT1("Failed to create a new empty region for full extended partition space!\n");
1070 return;
1071 }
1072
1073 return;
1074 }
1075
1076 /* Start partition at head 1, cylinder 0 */
1077 LastStartSector = DiskEntry->ExtendedPartition->StartSector.QuadPart + (ULONGLONG)DiskEntry->SectorAlignment;
1078 LastSectorCount = 0ULL;
1079 LastUnusedSectorCount = 0ULL;
1080
1081 for (Entry = DiskEntry->LogicalPartListHead.Flink;
1082 Entry != &DiskEntry->LogicalPartListHead;
1083 Entry = Entry->Flink)
1084 {
1085 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
1086
1087 if (PartEntry->PartitionType != PARTITION_ENTRY_UNUSED ||
1088 PartEntry->SectorCount.QuadPart != 0ULL)
1089 {
1090 LastUnusedSectorCount =
1091 PartEntry->StartSector.QuadPart - (ULONGLONG)DiskEntry->SectorAlignment - (LastStartSector + LastSectorCount);
1092
1093 if ((PartEntry->StartSector.QuadPart - (ULONGLONG)DiskEntry->SectorAlignment) > (LastStartSector + LastSectorCount) &&
1094 LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment)
1095 {
1096 DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount);
1097
1098 StartSector = LastStartSector + LastSectorCount;
1099 SectorCount = AlignDown(StartSector + LastUnusedSectorCount, DiskEntry->SectorAlignment) - StartSector;
1100
1101 /* Insert the table into the list */
1102 NewPartEntry = CreateInsertBlankRegion(DiskEntry,
1103 &PartEntry->ListEntry,
1104 StartSector,
1106 TRUE);
1107 if (NewPartEntry == NULL)
1108 {
1109 DPRINT1("Failed to create a new empty region for extended partition space!\n");
1110 return;
1111 }
1112 }
1113
1114 LastStartSector = PartEntry->StartSector.QuadPart;
1115 LastSectorCount = PartEntry->SectorCount.QuadPart;
1116 }
1117 }
1118
1119 /* Check for trailing unpartitioned disk space */
1120 if ((LastStartSector + LastSectorCount) < DiskEntry->ExtendedPartition->StartSector.QuadPart + DiskEntry->ExtendedPartition->SectorCount.QuadPart)
1121 {
1122 LastUnusedSectorCount = AlignDown(DiskEntry->ExtendedPartition->StartSector.QuadPart +
1123 DiskEntry->ExtendedPartition->SectorCount.QuadPart - (LastStartSector + LastSectorCount),
1124 DiskEntry->SectorAlignment);
1125
1126 if (LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment)
1127 {
1128 DPRINT("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount);
1129
1130 StartSector = LastStartSector + LastSectorCount;
1131 SectorCount = AlignDown(StartSector + LastUnusedSectorCount, DiskEntry->SectorAlignment) - StartSector;
1132
1133 /* Append the table to the list */
1134 NewPartEntry = CreateInsertBlankRegion(DiskEntry,
1135 &DiskEntry->LogicalPartListHead,
1136 StartSector,
1138 TRUE);
1139 if (NewPartEntry == NULL)
1140 {
1141 DPRINT1("Failed to create a new empty region for extended partition space!\n");
1142 return;
1143 }
1144 }
1145 }
1146 }
1147
1148 DPRINT("ScanForUnpartitionedDiskSpace() done\n");
1149}
1150
1151static
1152VOID
1155 IN PDISKENTRY DiskEntry)
1156{
1157 LARGE_INTEGER SystemTime;
1159 PLIST_ENTRY Entry2;
1160 PDISKENTRY DiskEntry2;
1161 PUCHAR Buffer;
1162
1163 if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
1164 {
1165 DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
1166 return;
1167 }
1168
1169 Buffer = (PUCHAR)&DiskEntry->LayoutBuffer->Signature;
1170
1171 while (TRUE)
1172 {
1173 NtQuerySystemTime(&SystemTime);
1174 RtlTimeToTimeFields(&SystemTime, &TimeFields);
1175
1176 Buffer[0] = (UCHAR)(TimeFields.Year & 0xFF) + (UCHAR)(TimeFields.Hour & 0xFF);
1177 Buffer[1] = (UCHAR)(TimeFields.Year >> 8) + (UCHAR)(TimeFields.Minute & 0xFF);
1178 Buffer[2] = (UCHAR)(TimeFields.Month & 0xFF) + (UCHAR)(TimeFields.Second & 0xFF);
1179 Buffer[3] = (UCHAR)(TimeFields.Day & 0xFF) + (UCHAR)(TimeFields.Milliseconds & 0xFF);
1180
1181 if (DiskEntry->LayoutBuffer->Signature == 0)
1182 {
1183 continue;
1184 }
1185
1186 /* Check if the signature already exist */
1187 /* FIXME:
1188 * Check also signatures from disks, which are
1189 * not visible (bootable) by the bios.
1190 */
1191 for (Entry2 = List->DiskListHead.Flink;
1192 Entry2 != &List->DiskListHead;
1193 Entry2 = Entry2->Flink)
1194 {
1195 DiskEntry2 = CONTAINING_RECORD(Entry2, DISKENTRY, ListEntry);
1196
1197 if (DiskEntry2->DiskStyle == PARTITION_STYLE_GPT)
1198 {
1199 DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
1200 continue;
1201 }
1202
1203 if (DiskEntry != DiskEntry2 &&
1204 DiskEntry->LayoutBuffer->Signature == DiskEntry2->LayoutBuffer->Signature)
1205 break;
1206 }
1207
1208 if (Entry2 == &List->DiskListHead)
1209 break;
1210 }
1211}
1212
1213static
1214VOID
1217{
1219 PDISKENTRY DiskEntry;
1220
1221 /* Update each disk */
1222 for (Entry = List->DiskListHead.Flink;
1223 Entry != &List->DiskListHead;
1224 Entry = Entry->Flink)
1225 {
1226 DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
1227
1228 if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
1229 {
1230 DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
1231 continue;
1232 }
1233
1234 if (DiskEntry->LayoutBuffer &&
1235 DiskEntry->LayoutBuffer->Signature == 0)
1236 {
1237 SetDiskSignature(List, DiskEntry);
1239 }
1240 }
1241}
1242
1243static
1244VOID
1247{
1248 PLIST_ENTRY ListEntry;
1249 PBIOSDISKENTRY BiosDiskEntry;
1250 PDISKENTRY DiskEntry;
1251 ULONG HwAdapterNumber = 0;
1252 ULONG HwControllerNumber = 0;
1253 ULONG RemovableDiskCount = 0;
1254
1255 /*
1256 * Enumerate the disks recognized by the BIOS and recompute the disk
1257 * numbers on the system when *ALL* removable disks are not connected.
1258 * The entries are inserted in increasing order of AdapterNumber,
1259 * ControllerNumber and DiskNumber.
1260 */
1261 for (ListEntry = List->BiosDiskListHead.Flink;
1262 ListEntry != &List->BiosDiskListHead;
1263 ListEntry = ListEntry->Flink)
1264 {
1265 BiosDiskEntry = CONTAINING_RECORD(ListEntry, BIOSDISKENTRY, ListEntry);
1266 DiskEntry = BiosDiskEntry->DiskEntry;
1267
1268 /*
1269 * If the adapter or controller numbers change, update them and reset
1270 * the number of removable disks on this adapter/controller.
1271 */
1272 if (HwAdapterNumber != BiosDiskEntry->AdapterNumber ||
1273 HwControllerNumber != BiosDiskEntry->ControllerNumber)
1274 {
1275 HwAdapterNumber = BiosDiskEntry->AdapterNumber;
1276 HwControllerNumber = BiosDiskEntry->ControllerNumber;
1277 RemovableDiskCount = 0;
1278 }
1279
1280 /* Adjust the actual hardware disk number */
1281 if (DiskEntry)
1282 {
1283 ASSERT(DiskEntry->HwDiskNumber == BiosDiskEntry->DiskNumber);
1284
1285 if (DiskEntry->MediaType == RemovableMedia)
1286 {
1287 /* Increase the number of removable disks and set the disk number to zero */
1288 ++RemovableDiskCount;
1289 DiskEntry->HwFixedDiskNumber = 0;
1290 }
1291 else // if (DiskEntry->MediaType == FixedMedia)
1292 {
1293 /* Adjust the fixed disk number, offset by the number of removable disks found before this one */
1294 DiskEntry->HwFixedDiskNumber = BiosDiskEntry->DiskNumber - RemovableDiskCount;
1295 }
1296 }
1297 else
1298 {
1299 DPRINT1("BIOS disk %lu is not recognized by NTOS!\n", BiosDiskEntry->DiskNumber);
1300 }
1301 }
1302}
1303
1304static
1305VOID
1308 IN ULONG DiskNumber,
1310{
1311 DISK_GEOMETRY DiskGeometry;
1312 SCSI_ADDRESS ScsiAddress;
1313 PDISKENTRY DiskEntry;
1317 PULONG Buffer;
1319 WCHAR Identifier[20];
1320 ULONG Checksum;
1322 ULONG i;
1323 PLIST_ENTRY ListEntry;
1324 PBIOSDISKENTRY BiosDiskEntry;
1325 ULONG LayoutBufferSize;
1326 PDRIVE_LAYOUT_INFORMATION NewLayoutBuffer;
1327
1328 /* Retrieve the drive geometry */
1330 NULL,
1331 NULL,
1332 NULL,
1333 &Iosb,
1335 NULL,
1336 0,
1337 &DiskGeometry,
1338 sizeof(DiskGeometry));
1339 if (!NT_SUCCESS(Status))
1340 return;
1341
1342 if (DiskGeometry.MediaType != FixedMedia &&
1343 DiskGeometry.MediaType != RemovableMedia)
1344 {
1345 return;
1346 }
1347
1348 /*
1349 * FIXME: Here we suppose the disk is always SCSI. What if it is
1350 * of another type? To check this we need to retrieve the name of
1351 * the driver the disk device belongs to.
1352 */
1354 NULL,
1355 NULL,
1356 NULL,
1357 &Iosb,
1359 NULL,
1360 0,
1361 &ScsiAddress,
1362 sizeof(ScsiAddress));
1363 if (!NT_SUCCESS(Status))
1364 return;
1365
1366 /*
1367 * Check whether the disk is initialized, by looking at its MBR.
1368 * NOTE that this must be generalized to GPT disks as well!
1369 */
1370
1372 0,
1373 DiskGeometry.BytesPerSector);
1374 if (Mbr == NULL)
1375 return;
1376
1377 FileOffset.QuadPart = 0;
1379 NULL,
1380 NULL,
1381 NULL,
1382 &Iosb,
1383 (PVOID)Mbr,
1384 DiskGeometry.BytesPerSector,
1385 &FileOffset,
1386 NULL);
1387 if (!NT_SUCCESS(Status))
1388 {
1389 RtlFreeHeap(ProcessHeap, 0, Mbr);
1390 DPRINT1("NtReadFile failed, status=%x\n", Status);
1391 return;
1392 }
1393 Signature = Mbr->Signature;
1394
1395 /* Calculate the MBR checksum */
1396 Checksum = 0;
1397 Buffer = (PULONG)Mbr;
1398 for (i = 0; i < 128; i++)
1399 {
1400 Checksum += Buffer[i];
1401 }
1402 Checksum = ~Checksum + 1;
1403
1405 L"%08x-%08x-%c",
1406 Checksum, Signature,
1407 (Mbr->Magic == PARTITION_MAGIC) ? L'A' : L'X');
1408 DPRINT("Identifier: %S\n", Identifier);
1409
1410 DiskEntry = RtlAllocateHeap(ProcessHeap,
1412 sizeof(DISKENTRY));
1413 if (DiskEntry == NULL)
1414 {
1415 RtlFreeHeap(ProcessHeap, 0, Mbr);
1416 DPRINT1("Failed to allocate a new disk entry.\n");
1417 return;
1418 }
1419
1420 DiskEntry->PartList = List;
1421
1422#if 0
1423 {
1424 FILE_FS_DEVICE_INFORMATION FileFsDevice;
1425
1426 /* Query the device for its type */
1428 &Iosb,
1429 &FileFsDevice,
1430 sizeof(FileFsDevice),
1432 if (!NT_SUCCESS(Status))
1433 {
1434 DPRINT1("Couldn't detect device type for disk %lu of identifier '%S'...\n", DiskNumber, Identifier);
1435 }
1436 else
1437 {
1438 DPRINT1("Disk %lu : DeviceType: 0x%08x ; Characteristics: 0x%08x\n", DiskNumber, FileFsDevice.DeviceType, FileFsDevice.Characteristics);
1439 }
1440 }
1441 // NOTE: We may also use NtQueryVolumeInformationFile(FileFsDeviceInformation).
1442#endif
1443 DiskEntry->MediaType = DiskGeometry.MediaType;
1444 if (DiskEntry->MediaType == RemovableMedia)
1445 {
1446 DPRINT1("Disk %lu of identifier '%S' is removable\n", DiskNumber, Identifier);
1447 }
1448 else // if (DiskEntry->MediaType == FixedMedia)
1449 {
1450 DPRINT1("Disk %lu of identifier '%S' is fixed\n", DiskNumber, Identifier);
1451 }
1452
1453// DiskEntry->Checksum = Checksum;
1454// DiskEntry->Signature = Signature;
1455 DiskEntry->BiosFound = FALSE;
1456
1457 /*
1458 * Check if this disk has a valid MBR: verify its signature,
1459 * and whether its two first bytes are a valid instruction
1460 * (related to this, see IsThereAValidBootSector() in partlist.c).
1461 *
1462 * See also ntoskrnl/fstub/fstubex.c!FstubDetectPartitionStyle().
1463 */
1464
1465 // DiskEntry->NoMbr = (Mbr->Magic != PARTITION_MAGIC || (*(PUSHORT)Mbr->BootCode) == 0x0000);
1466
1467 /* If we have not the 0xAA55 then it's raw partition */
1468 if (Mbr->Magic != PARTITION_MAGIC)
1469 {
1470 DiskEntry->DiskStyle = PARTITION_STYLE_RAW;
1471 }
1472 /* Check partitions types: if first is 0xEE and all the others 0, we have GPT */
1473 else if (Mbr->Partition[0].PartitionType == EFI_PMBR_OSTYPE_EFI &&
1474 Mbr->Partition[1].PartitionType == 0 &&
1475 Mbr->Partition[2].PartitionType == 0 &&
1476 Mbr->Partition[3].PartitionType == 0)
1477 {
1478 DiskEntry->DiskStyle = PARTITION_STYLE_GPT;
1479 }
1480 /* Otherwise, partition table is in MBR */
1481 else
1482 {
1483 DiskEntry->DiskStyle = PARTITION_STYLE_MBR;
1484 }
1485
1486 /* Free the MBR sector buffer */
1487 RtlFreeHeap(ProcessHeap, 0, Mbr);
1488
1489
1490 for (ListEntry = List->BiosDiskListHead.Flink;
1491 ListEntry != &List->BiosDiskListHead;
1492 ListEntry = ListEntry->Flink)
1493 {
1494 BiosDiskEntry = CONTAINING_RECORD(ListEntry, BIOSDISKENTRY, ListEntry);
1495 /* FIXME:
1496 * Compare the size from bios and the reported size from driver.
1497 * If we have more than one disk with a zero or with the same signature
1498 * we must create new signatures and reboot. After the reboot,
1499 * it is possible to identify the disks.
1500 */
1501 if (BiosDiskEntry->Signature == Signature &&
1502 BiosDiskEntry->Checksum == Checksum &&
1503 BiosDiskEntry->DiskEntry == NULL)
1504 {
1505 if (!DiskEntry->BiosFound)
1506 {
1507 DiskEntry->HwAdapterNumber = BiosDiskEntry->AdapterNumber;
1508 DiskEntry->HwControllerNumber = BiosDiskEntry->ControllerNumber;
1509 DiskEntry->HwDiskNumber = BiosDiskEntry->DiskNumber;
1510
1511 if (DiskEntry->MediaType == RemovableMedia)
1512 {
1513 /* Set the removable disk number to zero */
1514 DiskEntry->HwFixedDiskNumber = 0;
1515 }
1516 else // if (DiskEntry->MediaType == FixedMedia)
1517 {
1518 /* The fixed disk number will later be adjusted using the number of removable disks */
1519 DiskEntry->HwFixedDiskNumber = BiosDiskEntry->DiskNumber;
1520 }
1521
1522 DiskEntry->BiosFound = TRUE;
1523 BiosDiskEntry->DiskEntry = DiskEntry;
1524 break;
1525 }
1526 else
1527 {
1528 // FIXME: What to do?
1529 DPRINT1("Disk %lu of identifier '%S' has already been found?!\n", DiskNumber, Identifier);
1530 }
1531 }
1532 }
1533
1534 if (!DiskEntry->BiosFound)
1535 {
1536 DPRINT1("WARNING: Setup could not find a matching BIOS disk entry. Disk %lu may not be bootable by the BIOS!\n", DiskNumber);
1537 }
1538
1539 DiskEntry->Cylinders = DiskGeometry.Cylinders.QuadPart;
1540 DiskEntry->TracksPerCylinder = DiskGeometry.TracksPerCylinder;
1541 DiskEntry->SectorsPerTrack = DiskGeometry.SectorsPerTrack;
1542 DiskEntry->BytesPerSector = DiskGeometry.BytesPerSector;
1543
1544 DPRINT("Cylinders %I64u\n", DiskEntry->Cylinders);
1545 DPRINT("TracksPerCylinder %lu\n", DiskEntry->TracksPerCylinder);
1546 DPRINT("SectorsPerTrack %lu\n", DiskEntry->SectorsPerTrack);
1547 DPRINT("BytesPerSector %lu\n", DiskEntry->BytesPerSector);
1548
1549 DiskEntry->SectorCount.QuadPart = DiskGeometry.Cylinders.QuadPart *
1550 (ULONGLONG)DiskGeometry.TracksPerCylinder *
1551 (ULONGLONG)DiskGeometry.SectorsPerTrack;
1552
1553 DiskEntry->SectorAlignment = DiskGeometry.SectorsPerTrack;
1554 DiskEntry->CylinderAlignment = DiskGeometry.TracksPerCylinder *
1555 DiskGeometry.SectorsPerTrack;
1556
1557 DPRINT("SectorCount %I64u\n", DiskEntry->SectorCount.QuadPart);
1558 DPRINT("SectorAlignment %lu\n", DiskEntry->SectorAlignment);
1559
1560 DiskEntry->DiskNumber = DiskNumber;
1561 DiskEntry->Port = ScsiAddress.PortNumber;
1562 DiskEntry->Bus = ScsiAddress.PathId;
1563 DiskEntry->Id = ScsiAddress.TargetId;
1564
1565 GetDriverName(DiskEntry);
1566 /*
1567 * Actually it would be more correct somehow to use:
1568 *
1569 * OBJECT_NAME_INFORMATION NameInfo; // ObjectNameInfo;
1570 * ULONG ReturnedLength;
1571 *
1572 * Status = NtQueryObject(SomeHandleToTheDisk,
1573 * ObjectNameInformation,
1574 * &NameInfo,
1575 * sizeof(NameInfo),
1576 * &ReturnedLength);
1577 * etc...
1578 *
1579 * See examples in https://git.reactos.org/?p=reactos.git;a=blob;f=reactos/ntoskrnl/io/iomgr/error.c;hb=2f3a93ee9cec8322a86bf74b356f1ad83fc912dc#l267
1580 */
1581
1584
1585 InsertAscendingList(&List->DiskListHead, DiskEntry, DISKENTRY, ListEntry, DiskNumber);
1586
1587
1588 /*
1589 * We now retrieve the disk partition layout
1590 */
1591
1592 /*
1593 * Stop there now if the disk is GPT-partitioned,
1594 * since we currently do not support such disks.
1595 */
1596 if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
1597 {
1598 DPRINT1("GPT-partitioned disk detected, not currently supported by SETUP!\n");
1599 return;
1600 }
1601
1602 /* Allocate a layout buffer with 4 partition entries first */
1603 LayoutBufferSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
1604 ((4 - ANYSIZE_ARRAY) * sizeof(PARTITION_INFORMATION));
1607 LayoutBufferSize);
1608 if (DiskEntry->LayoutBuffer == NULL)
1609 {
1610 DPRINT1("Failed to allocate the disk layout buffer!\n");
1611 return;
1612 }
1613
1614 /* Keep looping while the drive layout buffer is too small */
1615 for (;;)
1616 {
1617 DPRINT1("Buffer size: %lu\n", LayoutBufferSize);
1619 NULL,
1620 NULL,
1621 NULL,
1622 &Iosb,
1624 NULL,
1625 0,
1626 DiskEntry->LayoutBuffer,
1627 LayoutBufferSize);
1628 if (NT_SUCCESS(Status))
1629 break;
1630
1632 {
1633 DPRINT1("NtDeviceIoControlFile() failed (Status: 0x%08lx)\n", Status);
1634 return;
1635 }
1636
1637 LayoutBufferSize += 4 * sizeof(PARTITION_INFORMATION);
1638 NewLayoutBuffer = RtlReAllocateHeap(ProcessHeap,
1640 DiskEntry->LayoutBuffer,
1641 LayoutBufferSize);
1642 if (NewLayoutBuffer == NULL)
1643 {
1644 DPRINT1("Failed to reallocate the disk layout buffer!\n");
1645 return;
1646 }
1647
1648 DiskEntry->LayoutBuffer = NewLayoutBuffer;
1649 }
1650
1651 DPRINT1("PartitionCount: %lu\n", DiskEntry->LayoutBuffer->PartitionCount);
1652
1653#ifdef DUMP_PARTITION_TABLE
1654 DumpPartitionTable(DiskEntry);
1655#endif
1656
1657 if (IsSuperFloppy(DiskEntry))
1658 DPRINT1("Disk %lu is a super-floppy\n", DiskNumber);
1659
1660 if (DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart != 0 &&
1663 {
1664 if ((DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart / DiskEntry->BytesPerSector) % DiskEntry->SectorsPerTrack == 0)
1665 {
1666 DPRINT("Use %lu Sector alignment!\n", DiskEntry->SectorsPerTrack);
1667 }
1668 else if (DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart % (1024 * 1024) == 0)
1669 {
1670 DPRINT1("Use megabyte (%lu Sectors) alignment!\n", (1024 * 1024) / DiskEntry->BytesPerSector);
1671 }
1672 else
1673 {
1674 DPRINT1("No matching alignment found! Partition 1 starts at %I64u\n", DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart);
1675 }
1676 }
1677 else
1678 {
1679 DPRINT1("No valid partition table found! Use megabyte (%lu Sectors) alignment!\n", (1024 * 1024) / DiskEntry->BytesPerSector);
1680 }
1681
1682 if (DiskEntry->LayoutBuffer->PartitionCount == 0)
1683 {
1684 DiskEntry->NewDisk = TRUE;
1685 DiskEntry->LayoutBuffer->PartitionCount = 4;
1686
1687 for (i = 0; i < 4; i++)
1688 {
1690 }
1691 }
1692 else
1693 {
1694 /* Enumerate and add the first four primary partitions */
1695 for (i = 0; i < 4; i++)
1696 {
1697 AddPartitionToDisk(DiskNumber, DiskEntry, i, FALSE);
1698 }
1699
1700 /* Enumerate and add the remaining partitions as logical ones */
1701 for (i = 4; i < DiskEntry->LayoutBuffer->PartitionCount; i += 4)
1702 {
1703 AddPartitionToDisk(DiskNumber, DiskEntry, i, TRUE);
1704 }
1705 }
1706
1708}
1709
1710/*
1711 * Retrieve the system disk, i.e. the fixed disk that is accessible by the
1712 * firmware during boot time and where the system partition resides.
1713 * If no system partition has been determined, we retrieve the first disk
1714 * that verifies the mentioned criteria above.
1715 */
1716static
1720{
1722 PDISKENTRY DiskEntry;
1723
1724 /* Check for empty disk list */
1725 if (IsListEmpty(&List->DiskListHead))
1726 return NULL;
1727
1728 /*
1729 * If we already have a system partition, the system disk
1730 * is the one on which the system partition resides.
1731 */
1732 if (List->SystemPartition)
1733 return List->SystemPartition->DiskEntry;
1734
1735 /* Loop over the disks and find the correct one */
1736 for (Entry = List->DiskListHead.Flink;
1737 Entry != &List->DiskListHead;
1738 Entry = Entry->Flink)
1739 {
1740 DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
1741
1742 /* The disk must be a fixed disk and be found by the firmware */
1743 if (DiskEntry->MediaType == FixedMedia && DiskEntry->BiosFound)
1744 {
1745 break;
1746 }
1747 }
1748 if (Entry == &List->DiskListHead)
1749 {
1750 /* We haven't encountered any suitable disk */
1751 return NULL;
1752 }
1753
1754 if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
1755 {
1756 DPRINT1("System disk -- GPT-partitioned disk detected, not currently supported by SETUP!\n");
1757 }
1758
1759 return DiskEntry;
1760}
1761
1762/*
1763 * Retrieve the actual "active" partition of the given disk.
1764 * On MBR disks, partition with the Active/Boot flag set;
1765 * on GPT disks, partition with the correct GUID.
1766 */
1767BOOLEAN
1769 IN PPARTENTRY PartEntry)
1770{
1771 // TODO: Support for GPT disks!
1772
1773 if (IsContainerPartition(PartEntry->PartitionType))
1774 return FALSE;
1775
1776 /* Check if the partition is partitioned, used and active */
1777 if (PartEntry->IsPartitioned &&
1778 // !IsContainerPartition(PartEntry->PartitionType) &&
1779 PartEntry->BootIndicator)
1780 {
1781 /* Yes it is */
1782 ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
1783 return TRUE;
1784 }
1785
1786 return FALSE;
1787}
1788
1789static
1792 IN PDISKENTRY DiskEntry)
1793{
1794 PLIST_ENTRY ListEntry;
1795 PPARTENTRY PartEntry;
1796 PPARTENTRY ActivePartition = NULL;
1797
1798 /* Check for empty disk list */
1799 // ASSERT(DiskEntry);
1800 if (!DiskEntry)
1801 return NULL;
1802
1803 /* Check for empty partition list */
1804 if (IsListEmpty(&DiskEntry->PrimaryPartListHead))
1805 return NULL;
1806
1807 if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
1808 {
1809 DPRINT1("GPT-partitioned disk detected, not currently supported by SETUP!\n");
1810 return NULL;
1811 }
1812
1813 /* Scan all (primary) partitions to find the active disk partition */
1814 for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
1815 ListEntry != &DiskEntry->PrimaryPartListHead;
1816 ListEntry = ListEntry->Flink)
1817 {
1818 /* Retrieve the partition */
1819 PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
1820 if (IsPartitionActive(PartEntry))
1821 {
1822 /* Yes, we've found it */
1823 ASSERT(DiskEntry == PartEntry->DiskEntry);
1824 ASSERT(PartEntry->IsPartitioned);
1825
1826 ActivePartition = PartEntry;
1827
1828 DPRINT1("Found active system partition %lu in disk %lu, drive letter %C\n",
1829 PartEntry->PartitionNumber, DiskEntry->DiskNumber,
1830 (PartEntry->DriveLetter == 0) ? L'-' : PartEntry->DriveLetter);
1831 break;
1832 }
1833 }
1834
1835 /* Check if the disk is new and if so, use its first partition as the active system partition */
1836 if (DiskEntry->NewDisk && ActivePartition != NULL)
1837 {
1838 // FIXME: What to do??
1839 DPRINT1("NewDisk TRUE but already existing active partition?\n");
1840 }
1841
1842 /* Return the active partition found (or none) */
1843 return ActivePartition;
1844}
1845
1848{
1850 PDISKENTRY SystemDisk;
1854 ULONG ReturnSize;
1856 ULONG DiskNumber;
1860
1862 0,
1863 sizeof(PARTLIST));
1864 if (List == NULL)
1865 return NULL;
1866
1867 List->SystemPartition = NULL;
1868
1869 InitializeListHead(&List->DiskListHead);
1870 InitializeListHead(&List->BiosDiskListHead);
1871
1872 /*
1873 * Enumerate the disks seen by the BIOS; this will be used later
1874 * to map drives seen by NTOS with their corresponding BIOS names.
1875 */
1877
1878 /* Enumerate disks seen by NTOS */
1880 &Sdi,
1881 sizeof(Sdi),
1882 &ReturnSize);
1883 if (!NT_SUCCESS(Status))
1884 {
1885 DPRINT1("NtQuerySystemInformation() failed, Status 0x%08lx", Status);
1887 return NULL;
1888 }
1889
1890 for (DiskNumber = 0; DiskNumber < Sdi.NumberOfDisks; DiskNumber++)
1891 {
1893 L"\\Device\\Harddisk%lu\\Partition0",
1894 DiskNumber);
1896
1898 &Name,
1900 NULL,
1901 NULL);
1902
1906 &Iosb,
1909 if (NT_SUCCESS(Status))
1910 {
1911 AddDiskToList(FileHandle, DiskNumber, List);
1913 }
1914 }
1915
1919
1920 /*
1921 * Retrieve the system partition: the active partition on the system
1922 * disk (the one that will be booted by default by the hardware).
1923 */
1924 SystemDisk = GetSystemDisk(List);
1925 List->SystemPartition = (SystemDisk ? GetActiveDiskPartition(SystemDisk) : NULL);
1926
1927 return List;
1928}
1929
1930VOID
1933{
1934 PDISKENTRY DiskEntry;
1935 PBIOSDISKENTRY BiosDiskEntry;
1936 PPARTENTRY PartEntry;
1938
1939 /* Release disk and partition info */
1940 while (!IsListEmpty(&List->DiskListHead))
1941 {
1942 Entry = RemoveHeadList(&List->DiskListHead);
1943 DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
1944
1945 /* Release driver name */
1946 RtlFreeUnicodeString(&DiskEntry->DriverName);
1947
1948 /* Release primary partition list */
1949 while (!IsListEmpty(&DiskEntry->PrimaryPartListHead))
1950 {
1952 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
1953
1954 RtlFreeHeap(ProcessHeap, 0, PartEntry);
1955 }
1956
1957 /* Release logical partition list */
1958 while (!IsListEmpty(&DiskEntry->LogicalPartListHead))
1959 {
1961 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
1962
1963 RtlFreeHeap(ProcessHeap, 0, PartEntry);
1964 }
1965
1966 /* Release layout buffer */
1967 if (DiskEntry->LayoutBuffer != NULL)
1968 RtlFreeHeap(ProcessHeap, 0, DiskEntry->LayoutBuffer);
1969
1970 /* Release disk entry */
1971 RtlFreeHeap(ProcessHeap, 0, DiskEntry);
1972 }
1973
1974 /* Release the bios disk info */
1975 while (!IsListEmpty(&List->BiosDiskListHead))
1976 {
1977 Entry = RemoveHeadList(&List->BiosDiskListHead);
1978 BiosDiskEntry = CONTAINING_RECORD(Entry, BIOSDISKENTRY, ListEntry);
1979
1980 RtlFreeHeap(ProcessHeap, 0, BiosDiskEntry);
1981 }
1982
1983 /* Release list head */
1985}
1986
1990 IN ULONG HwDiskNumber)
1991{
1992 PDISKENTRY DiskEntry;
1994
1995 /* Loop over the disks and find the correct one */
1996 for (Entry = List->DiskListHead.Flink;
1997 Entry != &List->DiskListHead;
1998 Entry = Entry->Flink)
1999 {
2000 DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
2001
2002 if (DiskEntry->HwDiskNumber == HwDiskNumber)
2003 {
2004 /* Disk found */
2005 return DiskEntry;
2006 }
2007 }
2008
2009 /* Disk not found, stop there */
2010 return NULL;
2011}
2012
2016 IN ULONG DiskNumber)
2017{
2018 PDISKENTRY DiskEntry;
2020
2021 /* Loop over the disks and find the correct one */
2022 for (Entry = List->DiskListHead.Flink;
2023 Entry != &List->DiskListHead;
2024 Entry = Entry->Flink)
2025 {
2026 DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
2027
2028 if (DiskEntry->DiskNumber == DiskNumber)
2029 {
2030 /* Disk found */
2031 return DiskEntry;
2032 }
2033 }
2034
2035 /* Disk not found, stop there */
2036 return NULL;
2037}
2038
2042 IN USHORT Port,
2043 IN USHORT Bus,
2044 IN USHORT Id)
2045{
2046 PDISKENTRY DiskEntry;
2048
2049 /* Loop over the disks and find the correct one */
2050 for (Entry = List->DiskListHead.Flink;
2051 Entry != &List->DiskListHead;
2052 Entry = Entry->Flink)
2053 {
2054 DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
2055
2056 if (DiskEntry->Port == Port &&
2057 DiskEntry->Bus == Bus &&
2058 DiskEntry->Id == Id)
2059 {
2060 /* Disk found */
2061 return DiskEntry;
2062 }
2063 }
2064
2065 /* Disk not found, stop there */
2066 return NULL;
2067}
2068
2073{
2074 PDISKENTRY DiskEntry;
2076
2077 /* Loop over the disks and find the correct one */
2078 for (Entry = List->DiskListHead.Flink;
2079 Entry != &List->DiskListHead;
2080 Entry = Entry->Flink)
2081 {
2082 DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
2083
2084 if (DiskEntry->LayoutBuffer->Signature == Signature)
2085 {
2086 /* Disk found */
2087 return DiskEntry;
2088 }
2089 }
2090
2091 /* Disk not found, stop there */
2092 return NULL;
2093}
2094
2097 // IN PPARTLIST List,
2098 IN PDISKENTRY DiskEntry,
2100{
2101 PPARTENTRY PartEntry;
2103
2104 if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
2105 {
2106 DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
2107 return NULL;
2108 }
2109
2110 /* Disk found, loop over the primary partitions first... */
2111 for (Entry = DiskEntry->PrimaryPartListHead.Flink;
2112 Entry != &DiskEntry->PrimaryPartListHead;
2113 Entry = Entry->Flink)
2114 {
2115 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
2116
2117 if (PartEntry->PartitionNumber == PartitionNumber)
2118 {
2119 /* Partition found */
2120 return PartEntry;
2121 }
2122 }
2123
2124 /* ... then over the logical partitions if needed */
2125 for (Entry = DiskEntry->LogicalPartListHead.Flink;
2126 Entry != &DiskEntry->LogicalPartListHead;
2127 Entry = Entry->Flink)
2128 {
2129 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
2130
2131 if (PartEntry->PartitionNumber == PartitionNumber)
2132 {
2133 /* Partition found */
2134 return PartEntry;
2135 }
2136 }
2137
2138 /* The partition was not found on the disk, stop there */
2139 return NULL;
2140}
2141
2142BOOLEAN
2145 IN ULONG DiskNumber,
2147 OUT PDISKENTRY* pDiskEntry,
2148 OUT PPARTENTRY* pPartEntry OPTIONAL)
2149{
2150 PDISKENTRY DiskEntry;
2151 PPARTENTRY PartEntry = NULL;
2152
2153 /* Find the disk */
2154 DiskEntry = GetDiskByNumber(List, DiskNumber);
2155 if (!DiskEntry)
2156 return FALSE;
2157
2158 /* If we have a partition (PartitionNumber != 0), find it */
2159 if (PartitionNumber != 0)
2160 {
2161 if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
2162 {
2163 DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
2164 return FALSE;
2165 }
2166
2167 PartEntry = GetPartition(/*List,*/ DiskEntry, PartitionNumber);
2168 if (!PartEntry)
2169 return FALSE;
2170 ASSERT(PartEntry->DiskEntry == DiskEntry);
2171 }
2172
2173 /* Return the disk (and optionally the partition) */
2174 *pDiskEntry = DiskEntry;
2175 if (pPartEntry) *pPartEntry = PartEntry;
2176 return TRUE;
2177}
2178
2179//
2180// NOTE: Was introduced broken in r6258 by Casper
2181//
2185 IN ULONG DiskNumber,
2187{
2188 PDISKENTRY DiskEntry;
2189 PPARTENTRY PartEntry;
2190
2191 DiskEntry = GetDiskByNumber(List, DiskNumber);
2192 if (!DiskEntry)
2193 return NULL;
2194
2195 PartEntry = GetPartition(/*List,*/ DiskEntry, PartitionNumber);
2196 if (!PartEntry)
2197 return NULL;
2198
2199 ASSERT(PartEntry->DiskEntry == DiskEntry);
2200 ASSERT(DiskEntry->DiskNumber == DiskNumber);
2201 ASSERT(PartEntry->PartitionNumber == PartitionNumber);
2202
2203 return PartEntry;
2204}
2205
2209 IN PPARTENTRY CurrentPart OPTIONAL)
2210{
2211 PLIST_ENTRY DiskListEntry;
2212 PLIST_ENTRY PartListEntry;
2214
2215 /* Fail if no disks are available */
2216 if (IsListEmpty(&List->DiskListHead))
2217 return NULL;
2218
2219 /* Check for the next usable entry on the current partition's disk */
2220 if (CurrentPart != NULL)
2221 {
2222 CurrentDisk = CurrentPart->DiskEntry;
2223
2224 if (CurrentPart->LogicalPartition)
2225 {
2226 /* Logical partition */
2227
2228 PartListEntry = CurrentPart->ListEntry.Flink;
2229 if (PartListEntry != &CurrentDisk->LogicalPartListHead)
2230 {
2231 /* Next logical partition */
2232 CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
2233 return CurrentPart;
2234 }
2235 else
2236 {
2237 PartListEntry = CurrentDisk->ExtendedPartition->ListEntry.Flink;
2238 if (PartListEntry != &CurrentDisk->PrimaryPartListHead)
2239 {
2240 CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
2241 return CurrentPart;
2242 }
2243 }
2244 }
2245 else
2246 {
2247 /* Primary or extended partition */
2248
2249 if (CurrentPart->IsPartitioned &&
2250 IsContainerPartition(CurrentPart->PartitionType))
2251 {
2252 /* First logical partition */
2253 PartListEntry = CurrentDisk->LogicalPartListHead.Flink;
2254 if (PartListEntry != &CurrentDisk->LogicalPartListHead)
2255 {
2256 CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
2257 return CurrentPart;
2258 }
2259 }
2260 else
2261 {
2262 /* Next primary partition */
2263 PartListEntry = CurrentPart->ListEntry.Flink;
2264 if (PartListEntry != &CurrentDisk->PrimaryPartListHead)
2265 {
2266 CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
2267 return CurrentPart;
2268 }
2269 }
2270 }
2271 }
2272
2273 /* Search for the first partition entry on the next disk */
2274 for (DiskListEntry = (CurrentPart ? CurrentDisk->ListEntry.Flink
2275 : List->DiskListHead.Flink);
2276 DiskListEntry != &List->DiskListHead;
2277 DiskListEntry = DiskListEntry->Flink)
2278 {
2279 CurrentDisk = CONTAINING_RECORD(DiskListEntry, DISKENTRY, ListEntry);
2280
2282 {
2283 DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
2284 continue;
2285 }
2286
2287 PartListEntry = CurrentDisk->PrimaryPartListHead.Flink;
2288 if (PartListEntry != &CurrentDisk->PrimaryPartListHead)
2289 {
2290 CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
2291 return CurrentPart;
2292 }
2293 }
2294
2295 return NULL;
2296}
2297
2301 IN PPARTENTRY CurrentPart OPTIONAL)
2302{
2303 PLIST_ENTRY DiskListEntry;
2304 PLIST_ENTRY PartListEntry;
2306
2307 /* Fail if no disks are available */
2308 if (IsListEmpty(&List->DiskListHead))
2309 return NULL;
2310
2311 /* Check for the previous usable entry on the current partition's disk */
2312 if (CurrentPart != NULL)
2313 {
2314 CurrentDisk = CurrentPart->DiskEntry;
2315
2316 if (CurrentPart->LogicalPartition)
2317 {
2318 /* Logical partition */
2319
2320 PartListEntry = CurrentPart->ListEntry.Blink;
2321 if (PartListEntry != &CurrentDisk->LogicalPartListHead)
2322 {
2323 /* Previous logical partition */
2324 CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
2325 }
2326 else
2327 {
2328 /* Extended partition */
2329 CurrentPart = CurrentDisk->ExtendedPartition;
2330 }
2331 return CurrentPart;
2332 }
2333 else
2334 {
2335 /* Primary or extended partition */
2336
2337 PartListEntry = CurrentPart->ListEntry.Blink;
2338 if (PartListEntry != &CurrentDisk->PrimaryPartListHead)
2339 {
2340 CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
2341
2342 if (CurrentPart->IsPartitioned &&
2343 IsContainerPartition(CurrentPart->PartitionType))
2344 {
2345 PartListEntry = CurrentDisk->LogicalPartListHead.Blink;
2346 CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
2347 }
2348
2349 return CurrentPart;
2350 }
2351 }
2352 }
2353
2354 /* Search for the last partition entry on the previous disk */
2355 for (DiskListEntry = (CurrentPart ? CurrentDisk->ListEntry.Blink
2356 : List->DiskListHead.Blink);
2357 DiskListEntry != &List->DiskListHead;
2358 DiskListEntry = DiskListEntry->Blink)
2359 {
2360 CurrentDisk = CONTAINING_RECORD(DiskListEntry, DISKENTRY, ListEntry);
2361
2363 {
2364 DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
2365 continue;
2366 }
2367
2368 PartListEntry = CurrentDisk->PrimaryPartListHead.Blink;
2369 if (PartListEntry != &CurrentDisk->PrimaryPartListHead)
2370 {
2371 CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
2372
2373 if (CurrentPart->IsPartitioned &&
2374 IsContainerPartition(CurrentPart->PartitionType))
2375 {
2376 PartListEntry = CurrentDisk->LogicalPartListHead.Blink;
2377 if (PartListEntry != &CurrentDisk->LogicalPartListHead)
2378 {
2379 CurrentPart = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
2380 return CurrentPart;
2381 }
2382 }
2383 else
2384 {
2385 return CurrentPart;
2386 }
2387 }
2388 }
2389
2390 return NULL;
2391}
2392
2393// static
2395BOOLEAN
2398{
2399 if (PartitionInfo->StartingOffset.QuadPart == 0 &&
2400 PartitionInfo->PartitionLength.QuadPart == 0)
2401 {
2402 return TRUE;
2403 }
2404
2405 return FALSE;
2406}
2407
2408// static
2410BOOLEAN
2413 IN PDISKENTRY DiskEntry,
2414 IN PPARTENTRY PartEntry)
2415{
2416 if (PartitionInfo->StartingOffset.QuadPart == PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector &&
2417 PartitionInfo->PartitionLength.QuadPart == PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector)
2418// PartitionInfo->PartitionType == PartEntry->PartitionType
2419 {
2420 return TRUE;
2421 }
2422
2423 return FALSE;
2424}
2425
2426static
2427ULONG
2429 IN PDISKENTRY DiskEntry)
2430{
2432 PPARTENTRY PartEntry;
2433 ULONG Count = 0;
2434
2435 if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
2436 {
2437 DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
2438 return 0;
2439 }
2440
2441 for (Entry = DiskEntry->PrimaryPartListHead.Flink;
2442 Entry != &DiskEntry->PrimaryPartListHead;
2443 Entry = Entry->Flink)
2444 {
2445 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
2446 if (PartEntry->IsPartitioned)
2447 Count++;
2448 }
2449
2450 return Count;
2451}
2452
2453static
2454ULONG
2456 IN PDISKENTRY DiskEntry)
2457{
2458 PLIST_ENTRY ListEntry;
2459 PPARTENTRY PartEntry;
2460 ULONG Count = 0;
2461
2462 if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
2463 {
2464 DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
2465 return 0;
2466 }
2467
2468 for (ListEntry = DiskEntry->LogicalPartListHead.Flink;
2469 ListEntry != &DiskEntry->LogicalPartListHead;
2470 ListEntry = ListEntry->Flink)
2471 {
2472 PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
2473 if (PartEntry->IsPartitioned)
2474 Count++;
2475 }
2476
2477 return Count;
2478}
2479
2480static
2481BOOLEAN
2483 IN PDISKENTRY DiskEntry)
2484{
2485 PDRIVE_LAYOUT_INFORMATION NewLayoutBuffer;
2486 ULONG NewPartitionCount;
2487 ULONG CurrentPartitionCount = 0;
2488 ULONG LayoutBufferSize;
2489 ULONG i;
2490
2491 DPRINT1("ReAllocateLayoutBuffer()\n");
2492
2493 NewPartitionCount = 4 + GetLogicalPartitionCount(DiskEntry) * 4;
2494
2495 if (DiskEntry->LayoutBuffer)
2496 CurrentPartitionCount = DiskEntry->LayoutBuffer->PartitionCount;
2497
2498 DPRINT1("CurrentPartitionCount: %lu ; NewPartitionCount: %lu\n",
2499 CurrentPartitionCount, NewPartitionCount);
2500
2501 if (CurrentPartitionCount == NewPartitionCount)
2502 return TRUE;
2503
2504 LayoutBufferSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
2505 ((NewPartitionCount - ANYSIZE_ARRAY) * sizeof(PARTITION_INFORMATION));
2506 NewLayoutBuffer = RtlReAllocateHeap(ProcessHeap,
2508 DiskEntry->LayoutBuffer,
2509 LayoutBufferSize);
2510 if (NewLayoutBuffer == NULL)
2511 {
2512 DPRINT1("Failed to allocate the new layout buffer (size: %lu)\n", LayoutBufferSize);
2513 return FALSE;
2514 }
2515
2516 NewLayoutBuffer->PartitionCount = NewPartitionCount;
2517
2518 /* If the layout buffer grows, make sure the new (empty) entries are written to the disk */
2519 if (NewPartitionCount > CurrentPartitionCount)
2520 {
2521 for (i = CurrentPartitionCount; i < NewPartitionCount; i++)
2522 {
2523 NewLayoutBuffer->PartitionEntry[i].RewritePartition = TRUE;
2524 }
2525 }
2526
2527 DiskEntry->LayoutBuffer = NewLayoutBuffer;
2528
2529 return TRUE;
2530}
2531
2532static
2533VOID
2535 IN PDISKENTRY DiskEntry)
2536{
2538 PPARTITION_INFORMATION LinkInfo = NULL;
2539 PLIST_ENTRY ListEntry;
2540 PPARTENTRY PartEntry;
2541 LARGE_INTEGER HiddenSectors64;
2542 ULONG Index;
2544
2545 DPRINT1("UpdateDiskLayout()\n");
2546
2547 if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
2548 {
2549 DPRINT1("GPT-partitioned disk detected, not currently supported by SETUP!\n");
2550 return;
2551 }
2552
2553 /* Resize the layout buffer if necessary */
2554 if (ReAllocateLayoutBuffer(DiskEntry) == FALSE)
2555 {
2556 DPRINT("ReAllocateLayoutBuffer() failed.\n");
2557 return;
2558 }
2559
2560 /* Update the primary partition table */
2561 Index = 0;
2562 for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
2563 ListEntry != &DiskEntry->PrimaryPartListHead;
2564 ListEntry = ListEntry->Flink)
2565 {
2566 PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
2567
2568 if (PartEntry->IsPartitioned)
2569 {
2571
2572 PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
2573 PartEntry->PartitionIndex = Index;
2574
2575 /* Reset the current partition number only for newly-created (unmounted) partitions */
2576 if (PartEntry->New)
2577 PartEntry->PartitionNumber = 0;
2578
2580
2581 if (!IsSamePrimaryLayoutEntry(PartitionInfo, DiskEntry, PartEntry))
2582 {
2583 DPRINT1("Updating primary partition entry %lu\n", Index);
2584
2585 PartitionInfo->StartingOffset.QuadPart = PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector;
2586 PartitionInfo->PartitionLength.QuadPart = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
2587 PartitionInfo->HiddenSectors = PartEntry->StartSector.LowPart;
2588 PartitionInfo->PartitionNumber = PartEntry->PartitionNumber;
2589 PartitionInfo->PartitionType = PartEntry->PartitionType;
2590 PartitionInfo->BootIndicator = PartEntry->BootIndicator;
2591 PartitionInfo->RecognizedPartition = IsRecognizedPartition(PartEntry->PartitionType);
2592 PartitionInfo->RewritePartition = TRUE;
2593 }
2594
2595 if (!IsContainerPartition(PartEntry->PartitionType))
2597
2598 Index++;
2599 }
2600 }
2601
2602 ASSERT(Index <= 4);
2603
2604 /* Update the logical partition table */
2605 Index = 4;
2606 for (ListEntry = DiskEntry->LogicalPartListHead.Flink;
2607 ListEntry != &DiskEntry->LogicalPartListHead;
2608 ListEntry = ListEntry->Flink)
2609 {
2610 PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
2611
2612 if (PartEntry->IsPartitioned)
2613 {
2615
2616 PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
2617 PartEntry->PartitionIndex = Index;
2618
2619 /* Reset the current partition number only for newly-created (unmounted) partitions */
2620 if (PartEntry->New)
2621 PartEntry->PartitionNumber = 0;
2622
2624
2625 DPRINT1("Updating logical partition entry %lu\n", Index);
2626
2627 PartitionInfo->StartingOffset.QuadPart = PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector;
2628 PartitionInfo->PartitionLength.QuadPart = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
2629 PartitionInfo->HiddenSectors = DiskEntry->SectorAlignment;
2630 PartitionInfo->PartitionNumber = PartEntry->PartitionNumber;
2631 PartitionInfo->PartitionType = PartEntry->PartitionType;
2632 PartitionInfo->BootIndicator = FALSE;
2633 PartitionInfo->RecognizedPartition = IsRecognizedPartition(PartEntry->PartitionType);
2634 PartitionInfo->RewritePartition = TRUE;
2635
2636 /* Fill the link entry of the previous partition entry */
2637 if (LinkInfo != NULL)
2638 {
2639 LinkInfo->StartingOffset.QuadPart = (PartEntry->StartSector.QuadPart - DiskEntry->SectorAlignment) * DiskEntry->BytesPerSector;
2640 LinkInfo->PartitionLength.QuadPart = (PartEntry->StartSector.QuadPart + DiskEntry->SectorAlignment) * DiskEntry->BytesPerSector;
2641 HiddenSectors64.QuadPart = PartEntry->StartSector.QuadPart - DiskEntry->SectorAlignment - DiskEntry->ExtendedPartition->StartSector.QuadPart;
2642 LinkInfo->HiddenSectors = HiddenSectors64.LowPart;
2643 LinkInfo->PartitionNumber = 0;
2645 LinkInfo->BootIndicator = FALSE;
2646 LinkInfo->RecognizedPartition = FALSE;
2647 LinkInfo->RewritePartition = TRUE;
2648 }
2649
2650 /* Save a pointer to the link entry of the current partition entry */
2651 LinkInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index + 1];
2652
2654 Index += 4;
2655 }
2656 }
2657
2658 /* Wipe unused primary partition entries */
2659 for (Index = GetPrimaryPartitionCount(DiskEntry); Index < 4; Index++)
2660 {
2661 DPRINT1("Primary partition entry %lu\n", Index);
2662
2663 PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
2664
2666 {
2667 DPRINT1("Wiping primary partition entry %lu\n", Index);
2668
2669 PartitionInfo->StartingOffset.QuadPart = 0;
2670 PartitionInfo->PartitionLength.QuadPart = 0;
2671 PartitionInfo->HiddenSectors = 0;
2672 PartitionInfo->PartitionNumber = 0;
2673 PartitionInfo->PartitionType = PARTITION_ENTRY_UNUSED;
2674 PartitionInfo->BootIndicator = FALSE;
2675 PartitionInfo->RecognizedPartition = FALSE;
2676 PartitionInfo->RewritePartition = TRUE;
2677 }
2678 }
2679
2680 /* Wipe unused logical partition entries */
2681 for (Index = 4; Index < DiskEntry->LayoutBuffer->PartitionCount; Index++)
2682 {
2683 if (Index % 4 >= 2)
2684 {
2685 DPRINT1("Logical partition entry %lu\n", Index);
2686
2687 PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
2688
2690 {
2691 DPRINT1("Wiping partition entry %lu\n", Index);
2692
2693 PartitionInfo->StartingOffset.QuadPart = 0;
2694 PartitionInfo->PartitionLength.QuadPart = 0;
2695 PartitionInfo->HiddenSectors = 0;
2696 PartitionInfo->PartitionNumber = 0;
2697 PartitionInfo->PartitionType = PARTITION_ENTRY_UNUSED;
2698 PartitionInfo->BootIndicator = FALSE;
2699 PartitionInfo->RecognizedPartition = FALSE;
2700 PartitionInfo->RewritePartition = TRUE;
2701 }
2702 }
2703 }
2704
2705 // HACK: See the FIXMEs in WritePartitions(): (Re)set the PartitionStyle to MBR.
2706 DiskEntry->DiskStyle = PARTITION_STYLE_MBR;
2707
2708 DiskEntry->Dirty = TRUE;
2709
2710#ifdef DUMP_PARTITION_TABLE
2711 DumpPartitionTable(DiskEntry);
2712#endif
2713}
2714
2715static
2718 IN PPARTENTRY PartEntry)
2719{
2720 PDISKENTRY DiskEntry = PartEntry->DiskEntry;
2721 PPARTENTRY PrevPartEntry;
2722 PLIST_ENTRY ListHead;
2723
2724 if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
2725 {
2726 DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
2727 return NULL;
2728 }
2729
2730 if (PartEntry->LogicalPartition)
2731 ListHead = &DiskEntry->LogicalPartListHead;
2732 else
2733 ListHead = &DiskEntry->PrimaryPartListHead;
2734
2735 if (PartEntry->ListEntry.Blink != ListHead)
2736 {
2737 PrevPartEntry = CONTAINING_RECORD(PartEntry->ListEntry.Blink,
2738 PARTENTRY,
2739 ListEntry);
2740 if (!PrevPartEntry->IsPartitioned)
2741 {
2742 ASSERT(PrevPartEntry->PartitionType == PARTITION_ENTRY_UNUSED);
2743 return PrevPartEntry;
2744 }
2745 }
2746
2747 return NULL;
2748}
2749
2750static
2753 IN PPARTENTRY PartEntry)
2754{
2755 PDISKENTRY DiskEntry = PartEntry->DiskEntry;
2756 PPARTENTRY NextPartEntry;
2757 PLIST_ENTRY ListHead;
2758
2759 if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
2760 {
2761 DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
2762 return NULL;
2763 }
2764
2765 if (PartEntry->LogicalPartition)
2766 ListHead = &DiskEntry->LogicalPartListHead;
2767 else
2768 ListHead = &DiskEntry->PrimaryPartListHead;
2769
2770 if (PartEntry->ListEntry.Flink != ListHead)
2771 {
2772 NextPartEntry = CONTAINING_RECORD(PartEntry->ListEntry.Flink,
2773 PARTENTRY,
2774 ListEntry);
2775 if (!NextPartEntry->IsPartitioned)
2776 {
2777 ASSERT(NextPartEntry->PartitionType == PARTITION_ENTRY_UNUSED);
2778 return NextPartEntry;
2779 }
2780 }
2781
2782 return NULL;
2783}
2784
2785BOOLEAN
2788 IN OUT PPARTENTRY PartEntry,
2790 IN BOOLEAN AutoCreate)
2791{
2793
2794 DPRINT1("CreatePrimaryPartition(%I64u)\n", SectorCount);
2795
2796 if (List == NULL || PartEntry == NULL ||
2797 PartEntry->DiskEntry == NULL || PartEntry->IsPartitioned)
2798 {
2799 return FALSE;
2800 }
2801
2803 if (Error != NOT_AN_ERROR)
2804 {
2805 DPRINT1("PrimaryPartitionCreationChecks() failed with error %lu\n", Error);
2806 return FALSE;
2807 }
2808
2809 /* Initialize the partition entry, inserting a new blank region if needed */
2810 if (!InitializePartitionEntry(PartEntry, SectorCount, AutoCreate))
2811 return FALSE;
2812
2813 ASSERT(PartEntry->LogicalPartition == FALSE);
2814
2815 UpdateDiskLayout(PartEntry->DiskEntry);
2817
2818 return TRUE;
2819}
2820
2821static
2822VOID
2824 IN PDISKENTRY DiskEntry)
2825{
2826 ULONGLONG StartSector;
2828 PPARTENTRY NewPartEntry;
2829
2830 DPRINT1("AddLogicalDiskSpace()\n");
2831
2832 /* Create a partition entry that represents the empty space in the container partition */
2833
2834 StartSector = DiskEntry->ExtendedPartition->StartSector.QuadPart + (ULONGLONG)DiskEntry->SectorAlignment;
2835 SectorCount = DiskEntry->ExtendedPartition->SectorCount.QuadPart - (ULONGLONG)DiskEntry->SectorAlignment;
2836
2837 NewPartEntry = CreateInsertBlankRegion(DiskEntry,
2838 &DiskEntry->LogicalPartListHead,
2839 StartSector,
2841 TRUE);
2842 if (NewPartEntry == NULL)
2843 {
2844 DPRINT1("Failed to create a new empty region for extended partition space!\n");
2845 return;
2846 }
2847}
2848
2849BOOLEAN
2852 IN OUT PPARTENTRY PartEntry,
2854{
2856
2857 DPRINT1("CreateExtendedPartition(%I64u)\n", SectorCount);
2858
2859 if (List == NULL || PartEntry == NULL ||
2860 PartEntry->DiskEntry == NULL || PartEntry->IsPartitioned)
2861 {
2862 return FALSE;
2863 }
2864
2866 if (Error != NOT_AN_ERROR)
2867 {
2868 DPRINT1("ExtendedPartitionCreationChecks() failed with error %lu\n", Error);
2869 return FALSE;
2870 }
2871
2872 /* Initialize the partition entry, inserting a new blank region if needed */
2873 if (!InitializePartitionEntry(PartEntry, SectorCount, FALSE))
2874 return FALSE;
2875
2876 ASSERT(PartEntry->LogicalPartition == FALSE);
2877
2878 if (PartEntry->StartSector.QuadPart < 1450560)
2879 {
2880 /* Partition starts below the 8.4GB boundary ==> CHS partition */
2881 PartEntry->PartitionType = PARTITION_EXTENDED;
2882 }
2883 else
2884 {
2885 /* Partition starts above the 8.4GB boundary ==> LBA partition */
2886 PartEntry->PartitionType = PARTITION_XINT13_EXTENDED;
2887 }
2888
2889 // FIXME? Possibly to make GetNextUnformattedPartition work (i.e. skip the extended partition container)
2890 PartEntry->New = FALSE;
2891 PartEntry->FormatState = Formatted;
2892
2893 PartEntry->DiskEntry->ExtendedPartition = PartEntry;
2894
2895 AddLogicalDiskSpace(PartEntry->DiskEntry);
2896
2897 UpdateDiskLayout(PartEntry->DiskEntry);
2899
2900 return TRUE;
2901}
2902
2903BOOLEAN
2906 IN OUT PPARTENTRY PartEntry,
2908 IN BOOLEAN AutoCreate)
2909{
2911
2912 DPRINT1("CreateLogicalPartition(%I64u)\n", SectorCount);
2913
2914 if (List == NULL || PartEntry == NULL ||
2915 PartEntry->DiskEntry == NULL || PartEntry->IsPartitioned)
2916 {
2917 return FALSE;
2918 }
2919
2921 if (Error != NOT_AN_ERROR)
2922 {
2923 DPRINT1("LogicalPartitionCreationChecks() failed with error %lu\n", Error);
2924 return FALSE;
2925 }
2926
2927 /* Initialize the partition entry, inserting a new blank region if needed */
2928 if (!InitializePartitionEntry(PartEntry, SectorCount, AutoCreate))
2929 return FALSE;
2930
2931 ASSERT(PartEntry->LogicalPartition == TRUE);
2932
2933 UpdateDiskLayout(PartEntry->DiskEntry);
2935
2936 return TRUE;
2937}
2938
2941 IN PPARTENTRY PartEntry)
2942{
2944 NTSTATUS LockStatus;
2948 HANDLE PartitionHandle;
2950
2951 /* Check whether the partition is valid and was mounted by the system */
2952 if (!PartEntry->IsPartitioned ||
2953 IsContainerPartition(PartEntry->PartitionType) ||
2954 !IsRecognizedPartition(PartEntry->PartitionType) ||
2955 PartEntry->FormatState == UnknownFormat ||
2956 // NOTE: If FormatState == Unformatted but *FileSystem != 0 this means
2957 // it has been usually mounted with RawFS and thus needs to be dismounted.
2958 !*PartEntry->FileSystem ||
2959 PartEntry->PartitionNumber == 0)
2960 {
2961 /* The partition is not mounted, so just return success */
2962 return STATUS_SUCCESS;
2963 }
2964
2965 ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
2966
2967 /* Open the volume */
2969 L"\\Device\\Harddisk%lu\\Partition%lu",
2970 PartEntry->DiskEntry->DiskNumber,
2971 PartEntry->PartitionNumber);
2973
2975 &Name,
2977 NULL,
2978 NULL);
2979
2980 Status = NtOpenFile(&PartitionHandle,
2986 if (!NT_SUCCESS(Status))
2987 {
2988 DPRINT1("ERROR: Cannot open volume %wZ for dismounting! (Status 0x%lx)\n", &Name, Status);
2989 return Status;
2990 }
2991
2992 /* Lock the volume */
2993 LockStatus = NtFsControlFile(PartitionHandle,
2994 NULL,
2995 NULL,
2996 NULL,
2999 NULL,
3000 0,
3001 NULL,
3002 0);
3003 if (!NT_SUCCESS(LockStatus))
3004 {
3005 DPRINT1("WARNING: Failed to lock volume! Operations may fail! (Status 0x%lx)\n", LockStatus);
3006 }
3007
3008 /* Dismount the volume */
3009 Status = NtFsControlFile(PartitionHandle,
3010 NULL,
3011 NULL,
3012 NULL,
3015 NULL,
3016 0,
3017 NULL,
3018 0);
3019 if (!NT_SUCCESS(Status))
3020 {
3021 DPRINT1("Failed to unmount volume (Status 0x%lx)\n", Status);
3022 }
3023
3024 /* Unlock the volume */
3025 LockStatus = NtFsControlFile(PartitionHandle,
3026 NULL,
3027 NULL,
3028 NULL,
3031 NULL,
3032 0,
3033 NULL,
3034 0);
3035 if (!NT_SUCCESS(LockStatus))
3036 {
3037 DPRINT1("Failed to unlock volume (Status 0x%lx)\n", LockStatus);
3038 }
3039
3040 /* Close the volume */
3041 NtClose(PartitionHandle);
3042
3043 return Status;
3044}
3045
3046BOOLEAN
3049 IN PPARTENTRY PartEntry,
3050 OUT PPARTENTRY* FreeRegion OPTIONAL)
3051{
3052 PDISKENTRY DiskEntry;
3053 PPARTENTRY PrevPartEntry;
3054 PPARTENTRY NextPartEntry;
3055 PPARTENTRY LogicalPartEntry;
3057
3058 if (List == NULL || PartEntry == NULL ||
3059 PartEntry->DiskEntry == NULL || PartEntry->IsPartitioned == FALSE)
3060 {
3061 return FALSE;
3062 }
3063
3064 ASSERT(PartEntry->PartitionType != PARTITION_ENTRY_UNUSED);
3065
3066 /* Clear the system partition if it is being deleted */
3067 if (List->SystemPartition == PartEntry)
3068 {
3069 ASSERT(List->SystemPartition);
3070 List->SystemPartition = NULL;
3071 }
3072
3073 DiskEntry = PartEntry->DiskEntry;
3074
3075 /* Check which type of partition (primary/logical or extended) is being deleted */
3076 if (DiskEntry->ExtendedPartition == PartEntry)
3077 {
3078 /* An extended partition is being deleted: delete all logical partition entries */
3079 while (!IsListEmpty(&DiskEntry->LogicalPartListHead))
3080 {
3082 LogicalPartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
3083
3084 /* Dismount the logical partition */
3085 DismountVolume(LogicalPartEntry);
3086
3087 /* Delete it */
3088 RtlFreeHeap(ProcessHeap, 0, LogicalPartEntry);
3089 }
3090
3091 DiskEntry->ExtendedPartition = NULL;
3092 }
3093 else
3094 {
3095 /* A primary partition is being deleted: dismount it */
3096 DismountVolume(PartEntry);
3097 }
3098
3099 /* Adjust the unpartitioned disk space entries */
3100
3101 /* Get pointer to previous and next unpartitioned entries */
3102 PrevPartEntry = GetPrevUnpartitionedEntry(PartEntry);
3103 NextPartEntry = GetNextUnpartitionedEntry(PartEntry);
3104
3105 if (PrevPartEntry != NULL && NextPartEntry != NULL)
3106 {
3107 /* Merge the previous, current and next unpartitioned entries */
3108
3109 /* Adjust the previous entry length */
3110 PrevPartEntry->SectorCount.QuadPart += (PartEntry->SectorCount.QuadPart + NextPartEntry->SectorCount.QuadPart);
3111
3112 /* Remove the current and next entries */
3113 RemoveEntryList(&PartEntry->ListEntry);
3114 RtlFreeHeap(ProcessHeap, 0, PartEntry);
3115 RemoveEntryList(&NextPartEntry->ListEntry);
3116 RtlFreeHeap(ProcessHeap, 0, NextPartEntry);
3117
3118 /* Optionally return the freed region */
3119 if (FreeRegion)
3120 *FreeRegion = PrevPartEntry;
3121 }
3122 else if (PrevPartEntry != NULL && NextPartEntry == NULL)
3123 {
3124 /* Merge the current and the previous unpartitioned entries */
3125
3126 /* Adjust the previous entry length */
3127 PrevPartEntry->SectorCount.QuadPart += PartEntry->SectorCount.QuadPart;
3128
3129 /* Remove the current entry */
3130 RemoveEntryList(&PartEntry->ListEntry);
3131 RtlFreeHeap(ProcessHeap, 0, PartEntry);
3132
3133 /* Optionally return the freed region */
3134 if (FreeRegion)
3135 *FreeRegion = PrevPartEntry;
3136 }
3137 else if (PrevPartEntry == NULL && NextPartEntry != NULL)
3138 {
3139 /* Merge the current and the next unpartitioned entries */
3140
3141 /* Adjust the next entry offset and length */
3142 NextPartEntry->StartSector.QuadPart = PartEntry->StartSector.QuadPart;
3143 NextPartEntry->SectorCount.QuadPart += PartEntry->SectorCount.QuadPart;
3144
3145 /* Remove the current entry */
3146 RemoveEntryList(&PartEntry->ListEntry);
3147 RtlFreeHeap(ProcessHeap, 0, PartEntry);
3148
3149 /* Optionally return the freed region */
3150 if (FreeRegion)
3151 *FreeRegion = NextPartEntry;
3152 }
3153 else
3154 {
3155 /* Nothing to merge but change the current entry */
3156 PartEntry->IsPartitioned = FALSE;
3157 PartEntry->OnDiskPartitionNumber = 0;
3158 PartEntry->PartitionNumber = 0;
3159 // PartEntry->PartitionIndex = 0;
3160 PartEntry->BootIndicator = FALSE;
3161 PartEntry->PartitionType = PARTITION_ENTRY_UNUSED;
3162 PartEntry->FormatState = Unformatted;
3163 PartEntry->FileSystem[0] = L'\0';
3164 PartEntry->DriveLetter = 0;
3165 RtlZeroMemory(PartEntry->VolumeLabel, sizeof(PartEntry->VolumeLabel));
3166
3167 /* Optionally return the freed region */
3168 if (FreeRegion)
3169 *FreeRegion = PartEntry;
3170 }
3171
3172 UpdateDiskLayout(DiskEntry);
3174
3175 return TRUE;
3176}
3177
3178static
3179BOOLEAN
3181 IN PPARTENTRY PartEntry)
3182{
3183 /* Check the type and the file system of this partition */
3184
3185 /*
3186 * We do not support extended partition containers (on MBR disks) marked
3187 * as active, and containing code inside their extended boot records.
3188 */
3189 if (IsContainerPartition(PartEntry->PartitionType))
3190 {
3191 DPRINT1("System partition %lu in disk %lu is an extended partition container?!\n",
3192 PartEntry->PartitionNumber, PartEntry->DiskEntry->DiskNumber);
3193 return FALSE;
3194 }
3195
3196 /*
3197 * ADDITIONAL CHECKS / BIG HACK:
3198 *
3199 * Retrieve its file system and check whether we have
3200 * write support for it. If that is the case we are fine
3201 * and we can use it directly. However if we don't have
3202 * write support we will need to change the active system
3203 * partition.
3204 *
3205 * NOTE that this is completely useless on architectures
3206 * where a real system partition is required, as on these
3207 * architectures the partition uses the FAT FS, for which
3208 * we do have write support.
3209 * NOTE also that for those architectures looking for a
3210 * partition boot indicator is insufficient.
3211 */
3212 if (PartEntry->FormatState == Unformatted)
3213 {
3214 /* If this partition is mounted, it would use RawFS ("RAW") */
3215 return TRUE;
3216 }
3217 else if ((PartEntry->FormatState == Preformatted) ||
3218 (PartEntry->FormatState == Formatted))
3219 {
3220 ASSERT(*PartEntry->FileSystem);
3221
3222 /* NOTE: Please keep in sync with the RegisteredFileSystems list! */
3223 if (wcsicmp(PartEntry->FileSystem, L"FAT") == 0 ||
3224 wcsicmp(PartEntry->FileSystem, L"FAT32") == 0 ||
3225 // wcsicmp(PartEntry->FileSystem, L"NTFS") == 0 ||
3226 wcsicmp(PartEntry->FileSystem, L"BTRFS") == 0)
3227 {
3228 return TRUE;
3229 }
3230 else
3231 {
3232 // WARNING: We cannot write on this FS yet!
3233 DPRINT1("Recognized file system '%S' that doesn't have write support yet!\n",
3234 PartEntry->FileSystem);
3235 return FALSE;
3236 }
3237 }
3238 else // if (PartEntry->FormatState == UnknownFormat)
3239 {
3240 ASSERT(!*PartEntry->FileSystem);
3241
3242 DPRINT1("System partition %lu in disk %lu with no or unknown FS?!\n",
3243 PartEntry->PartitionNumber, PartEntry->DiskEntry->DiskNumber);
3244 return FALSE;
3245 }
3246
3247 // HACK: WARNING: We cannot write on this FS yet!
3248 // See fsutil.c:InferFileSystem()
3249 if (PartEntry->PartitionType == PARTITION_IFS)
3250 {
3251 DPRINT1("Recognized file system '%S' that doesn't have write support yet!\n",
3252 PartEntry->FileSystem);
3253 return FALSE;
3254 }
3255
3256 return TRUE;
3257}
3258
3262 IN BOOLEAN ForceSelect,
3263 IN PDISKENTRY AlternativeDisk OPTIONAL,
3264 IN PPARTENTRY AlternativePart OPTIONAL)
3265{
3266 PLIST_ENTRY ListEntry;
3267 PDISKENTRY DiskEntry;
3268 PPARTENTRY PartEntry;
3269 PPARTENTRY ActivePartition;
3270 PPARTENTRY CandidatePartition = NULL;
3271
3272 /* Check for empty disk list */
3273 if (IsListEmpty(&List->DiskListHead))
3274 {
3275 /* No system partition! */
3276 ASSERT(List->SystemPartition == NULL);
3277 goto NoSystemPartition;
3278 }
3279
3280 /* Adjust the optional alternative disk if needed */
3281 if (!AlternativeDisk && AlternativePart)
3282 AlternativeDisk = AlternativePart->DiskEntry;
3283
3284 /* Ensure that the alternative partition is on the alternative disk */
3285 if (AlternativePart)
3286 ASSERT(AlternativeDisk && (AlternativePart->DiskEntry == AlternativeDisk));
3287
3288 /* Ensure that the alternative disk is in the list */
3289 if (AlternativeDisk)
3290 ASSERT(AlternativeDisk->PartList == List);
3291
3292 /* Start fresh */
3293 CandidatePartition = NULL;
3294
3295//
3296// Step 1 : Check the system disk.
3297//
3298
3299 /*
3300 * First, check whether the system disk, i.e. the one that will be booted
3301 * by default by the hardware, contains an active partition. If so this
3302 * should be our system partition.
3303 */
3304 DiskEntry = GetSystemDisk(List);
3305
3306 if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
3307 {
3308 DPRINT1("System disk -- GPT-partitioned disk detected, not currently supported by SETUP!\n");
3309 goto UseAlternativeDisk;
3310 }
3311
3312 /* If we have a system partition (in the system disk), validate it */
3313 ActivePartition = List->SystemPartition;
3314 if (ActivePartition && IsSupportedActivePartition(ActivePartition))
3315 {
3316 CandidatePartition = ActivePartition;
3317
3318 DPRINT1("Use the current system partition %lu in disk %lu, drive letter %C\n",
3319 CandidatePartition->PartitionNumber,
3320 CandidatePartition->DiskEntry->DiskNumber,
3321 (CandidatePartition->DriveLetter == 0) ? L'-' : CandidatePartition->DriveLetter);
3322
3323 /* Return the candidate system partition */
3324 return CandidatePartition;
3325 }
3326
3327 /* If the system disk is not the optional alternative disk, perform the minimal checks */
3328 if (DiskEntry != AlternativeDisk)
3329 {
3330 /*
3331 * No active partition has been recognized. Enumerate all the (primary)
3332 * partitions in the system disk, excluding the possible current active
3333 * partition, to find a new candidate.
3334 */
3335 for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
3336 ListEntry != &DiskEntry->PrimaryPartListHead;
3337 ListEntry = ListEntry->Flink)
3338 {
3339 /* Retrieve the partition */
3340 PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
3341
3342 /* Skip the current active partition */
3343 if (PartEntry == ActivePartition)
3344 continue;
3345
3346 /* Check if the partition is partitioned and used */
3347 if (PartEntry->IsPartitioned &&
3349 {
3351
3352 /* If we get a candidate active partition in the disk, validate it */
3353 if (IsSupportedActivePartition(PartEntry))
3354 {
3355 CandidatePartition = PartEntry;
3356 goto UseAlternativePartition;
3357 }
3358 }
3359
3360#if 0
3361 /* Check if the partition is partitioned and used */
3362 if (!PartEntry->IsPartitioned)
3363 {
3365
3366 // TODO: Check for minimal size!!
3367 CandidatePartition = PartEntry;
3368 goto UseAlternativePartition;
3369 }
3370#endif
3371 }
3372
3373 /*
3374 * Still nothing, look whether there is some free space that we can use
3375 * for the new system partition. We must be sure that the total number
3376 * of partition is less than the maximum allowed, and that the minimal
3377 * size is fine.
3378 */
3379//
3380// TODO: Fix the handling of system partition being created in unpartitioned space!!
3381// --> When to partition it? etc...
3382//
3383 if (GetPrimaryPartitionCount(DiskEntry) < 4)
3384 {
3385 for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
3386 ListEntry != &DiskEntry->PrimaryPartListHead;
3387 ListEntry = ListEntry->Flink)
3388 {
3389 /* Retrieve the partition */
3390 PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
3391
3392 /* Skip the current active partition */
3393 if (PartEntry == ActivePartition)
3394 continue;
3395
3396 /* Check for unpartitioned space */
3397 if (!PartEntry->IsPartitioned)
3398 {
3400
3401 // TODO: Check for minimal size!!
3402 CandidatePartition = PartEntry;
3403 goto UseAlternativePartition;
3404 }
3405 }
3406 }
3407 }
3408
3409
3410//
3411// Step 2 : No active partition found: Check the alternative disk if specified.
3412//
3413
3414UseAlternativeDisk:
3415 if (!AlternativeDisk || (!ForceSelect && (DiskEntry != AlternativeDisk)))
3416 goto NoSystemPartition;
3417
3418 if (AlternativeDisk->DiskStyle == PARTITION_STYLE_GPT)
3419 {
3420 DPRINT1("Alternative disk -- GPT-partitioned disk detected, not currently supported by SETUP!\n");
3421 goto NoSystemPartition;
3422 }
3423
3424 if (DiskEntry != AlternativeDisk)
3425 {
3426 /* Choose the alternative disk */
3427 DiskEntry = AlternativeDisk;
3428
3429 /* If we get a candidate active partition, validate it */
3430 ActivePartition = GetActiveDiskPartition(DiskEntry);
3431 if (ActivePartition && IsSupportedActivePartition(ActivePartition))
3432 {
3433 CandidatePartition = ActivePartition;
3434 goto UseAlternativePartition;
3435 }
3436 }
3437
3438 /* We now may have an unsupported active partition, or none */
3439
3440/***
3441 *** TODO: Improve the selection:
3442 *** - If we want a really separate system partition from the partition where
3443 *** we install, do something similar to what's done below in the code.
3444 *** - Otherwise if we allow for the system partition to be also the partition
3445 *** where we install, just directly fall down to using AlternativePart.
3446 ***/
3447
3448 /* Retrieve the first partition of the disk */
3449 PartEntry = CONTAINING_RECORD(DiskEntry->PrimaryPartListHead.Flink,
3450 PARTENTRY, ListEntry);
3451 ASSERT(DiskEntry == PartEntry->DiskEntry);
3452
3453 CandidatePartition = PartEntry;
3454
3455 //
3456 // See: https://svn.reactos.org/svn/reactos/trunk/reactos/base/setup/usetup/partlist.c?r1=63355&r2=63354&pathrev=63355#l2318
3457 //
3458
3459 /* Check if the disk is new and if so, use its first partition as the active system partition */
3460 if (DiskEntry->NewDisk)
3461 {
3462 // !IsContainerPartition(PartEntry->PartitionType);
3463 if (!CandidatePartition->IsPartitioned || !CandidatePartition->BootIndicator) /* CandidatePartition != ActivePartition */
3464 {
3465 ASSERT(DiskEntry == CandidatePartition->DiskEntry);
3466
3467 DPRINT1("Use new first active system partition %lu in disk %lu, drive letter %C\n",
3468 CandidatePartition->PartitionNumber,
3469 CandidatePartition->DiskEntry->DiskNumber,
3470 (CandidatePartition->DriveLetter == 0) ? L'-' : CandidatePartition->DriveLetter);
3471
3472 /* Return the candidate system partition */
3473 return CandidatePartition;
3474 }
3475
3476 // FIXME: What to do??
3477 DPRINT1("NewDisk TRUE but first partition is used?\n");
3478 }
3479
3480 /*
3481 * The disk is not new, check if any partition is initialized;
3482 * if not, the first one becomes the system partition.
3483 */
3484 for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
3485 ListEntry != &DiskEntry->PrimaryPartListHead;
3486 ListEntry = ListEntry->Flink)
3487 {
3488 /* Retrieve the partition */
3489 PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
3490
3491 /* Check if the partition is partitioned and is used */
3492 // !IsContainerPartition(PartEntry->PartitionType);
3493 if (/* PartEntry->IsPartitioned && */
3494 PartEntry->PartitionType != PARTITION_ENTRY_UNUSED || PartEntry->BootIndicator)
3495 {
3496 break;
3497 }
3498 }
3499 if (ListEntry == &DiskEntry->PrimaryPartListHead)
3500 {
3501 /*
3502 * OK we haven't encountered any used and active partition,
3503 * so use the first one as the system partition.
3504 */
3505 ASSERT(DiskEntry == CandidatePartition->DiskEntry);
3506
3507 DPRINT1("Use first active system partition %lu in disk %lu, drive letter %C\n",
3508 CandidatePartition->PartitionNumber,
3509 CandidatePartition->DiskEntry->DiskNumber,
3510 (CandidatePartition->DriveLetter == 0) ? L'-' : CandidatePartition->DriveLetter);
3511
3512 /* Return the candidate system partition */
3513 return CandidatePartition;
3514 }
3515
3516 /*
3517 * The disk is not new, we did not find any actual active partition,
3518 * or the one we found was not supported, or any possible other candidate
3519 * is not supported. We then use the alternative partition if specified.
3520 */
3521 if (AlternativePart)
3522 {
3523 DPRINT1("No valid or supported system partition has been found, use the alternative partition!\n");
3524 CandidatePartition = AlternativePart;
3525 goto UseAlternativePartition;
3526 }
3527 else
3528 {
3529NoSystemPartition:
3530 DPRINT1("No valid or supported system partition has been found on this system!\n");
3531 return NULL;
3532 }
3533
3534UseAlternativePartition:
3535 /*
3536 * We are here because we did not find any (active) candidate system
3537 * partition that we know how to support. What we are going to do is
3538 * to change the existing system partition and use the alternative partition
3539 * (e.g. on which we install ReactOS) as the new system partition.
3540 * Then we will need to add in FreeLdr's boot menu an entry for booting
3541 * from the original system partition.
3542 */
3543 ASSERT(CandidatePartition);
3544
3545 DPRINT1("Use alternative active system partition %lu in disk %lu, drive letter %C\n",
3546 CandidatePartition->PartitionNumber,
3547 CandidatePartition->DiskEntry->DiskNumber,
3548 (CandidatePartition->DriveLetter == 0) ? L'-' : CandidatePartition->DriveLetter);
3549
3550 /* Return the candidate system partition */
3551 return CandidatePartition;
3552}
3553
3554BOOLEAN
3557 IN PPARTENTRY PartEntry,
3558 IN PPARTENTRY OldActivePart OPTIONAL)
3559{
3560 /* Check for empty disk list */
3561 if (IsListEmpty(&List->DiskListHead))
3562 return FALSE;
3563
3564 /* Validate the partition entry */
3565 if (!PartEntry)
3566 return FALSE;
3567
3568 /*
3569 * If the partition entry is already the system partition, or if it is
3570 * the same as the old active partition hint the user provided (and if
3571 * it is already active), just return success.
3572 */
3573 if ((PartEntry == List->SystemPartition) ||
3574 ((PartEntry == OldActivePart) && IsPartitionActive(OldActivePart)))
3575 {
3576 return TRUE;
3577 }
3578
3579 ASSERT(PartEntry->DiskEntry);
3580
3581 /* Ensure that the partition's disk is in the list */
3582 ASSERT(PartEntry->DiskEntry->PartList == List);
3583
3584 /*
3585 * If the user provided an old active partition hint, verify that it is
3586 * indeeed active and belongs to the same disk where the new partition
3587 * belongs. Otherwise determine the current active partition on the disk
3588 * where the new partition belongs.
3589 */
3590 if (!(OldActivePart && IsPartitionActive(OldActivePart) && (OldActivePart->DiskEntry == PartEntry->DiskEntry)))
3591 {
3592 /* It's not, determine the current active partition for the disk */
3593 OldActivePart = GetActiveDiskPartition(PartEntry->DiskEntry);
3594 }
3595
3596 /* Unset the old active partition if it exists */
3597 if (OldActivePart)
3598 {
3599 OldActivePart->BootIndicator = FALSE;
3600 OldActivePart->DiskEntry->LayoutBuffer->PartitionEntry[OldActivePart->PartitionIndex].BootIndicator = FALSE;
3601 OldActivePart->DiskEntry->LayoutBuffer->PartitionEntry[OldActivePart->PartitionIndex].RewritePartition = TRUE;
3602 OldActivePart->DiskEntry->Dirty = TRUE;
3603 }
3604
3605 /* Modify the system partition if the new partition is on the system disk */
3606 if (PartEntry->DiskEntry == GetSystemDisk(List))
3607 List->SystemPartition = PartEntry;
3608
3609 /* Set the new active partition */
3610 PartEntry->BootIndicator = TRUE;
3611 PartEntry->DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].BootIndicator = TRUE;
3612 PartEntry->DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].RewritePartition = TRUE;
3613 PartEntry->DiskEntry->Dirty = TRUE;
3614
3615 return TRUE;
3616}
3617
3620 IN PDISKENTRY DiskEntry)
3621{
3629 ULONG PartitionCount;
3630 PLIST_ENTRY ListEntry;
3631 PPARTENTRY PartEntry;
3633
3634 DPRINT("WritePartitions() Disk: %lu\n", DiskEntry->DiskNumber);
3635
3636 /* If the disk is not dirty, there is nothing to do */
3637 if (!DiskEntry->Dirty)
3638 return STATUS_SUCCESS;
3639
3641 L"\\Device\\Harddisk%lu\\Partition0",
3642 DiskEntry->DiskNumber);
3644
3646 &Name,
3648 NULL,
3649 NULL);
3650
3654 &Iosb,
3655 0,
3657 if (!NT_SUCCESS(Status))
3658 {
3659 DPRINT1("NtOpenFile() failed (Status %lx)\n", Status);
3660 return Status;
3661 }
3662
3663#ifdef DUMP_PARTITION_TABLE
3664 DumpPartitionTable(DiskEntry);
3665#endif
3666
3667 //
3668 // FIXME: We first *MUST* use IOCTL_DISK_CREATE_DISK to initialize
3669 // the disk in MBR or GPT format in case the disk was not initialized!!
3670 // For this we must ask the user which format to use.
3671 //
3672
3673 /* Save the original partition count to be restored later (see comment below) */
3674 PartitionCount = DiskEntry->LayoutBuffer->PartitionCount;
3675
3676 /* Set the new disk layout and retrieve its updated version with possibly modified partition numbers */
3678 ((PartitionCount - 1) * sizeof(PARTITION_INFORMATION));
3680 NULL,
3681 NULL,
3682 NULL,
3683 &Iosb,
3685 DiskEntry->LayoutBuffer,
3686 BufferSize,
3687 DiskEntry->LayoutBuffer,
3688 BufferSize);
3690
3691 /*
3692 * IOCTL_DISK_SET_DRIVE_LAYOUT calls IoWritePartitionTable(), which converts
3693 * DiskEntry->LayoutBuffer->PartitionCount into a partition *table* count,
3694 * where such a table is expected to enumerate up to 4 partitions:
3695 * partition *table* count == ROUND_UP(PartitionCount, 4) / 4 .
3696 * Due to this we need to restore the original PartitionCount number.
3697 */
3698 DiskEntry->LayoutBuffer->PartitionCount = PartitionCount;
3699
3700 /* Check whether the IOCTL_DISK_SET_DRIVE_LAYOUT call succeeded */
3701 if (!NT_SUCCESS(Status))
3702 {
3703 DPRINT1("IOCTL_DISK_SET_DRIVE_LAYOUT failed (Status 0x%08lx)\n", Status);
3704 return Status;
3705 }
3706
3707#ifdef DUMP_PARTITION_TABLE
3708 DumpPartitionTable(DiskEntry);
3709#endif
3710
3711 /* Update the partition numbers */
3712
3713 /* Update the primary partition table */
3714 for (ListEntry = DiskEntry->PrimaryPartListHead.Flink;
3715 ListEntry != &DiskEntry->PrimaryPartListHead;
3716 ListEntry = ListEntry->Flink)
3717 {
3718 PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
3719
3720 if (PartEntry->IsPartitioned)
3721 {
3723 PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex];
3724 PartEntry->PartitionNumber = PartitionInfo->PartitionNumber;
3725 }
3726 }
3727
3728 /* Update the logical partition table */
3729 for (ListEntry = DiskEntry->LogicalPartListHead.Flink;
3730 ListEntry != &DiskEntry->LogicalPartListHead;
3731 ListEntry = ListEntry->Flink)
3732 {
3733 PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
3734
3735 if (PartEntry->IsPartitioned)
3736 {
3738 PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex];
3739 PartEntry->PartitionNumber = PartitionInfo->PartitionNumber;
3740 }
3741 }
3742
3743 //
3744 // NOTE: Originally (see r40437), we used to install here also a new MBR
3745 // for this disk (by calling InstallMbrBootCodeToDisk), only if:
3746 // DiskEntry->NewDisk == TRUE and DiskEntry->HwDiskNumber == 0.
3747 // Then after that, both DiskEntry->NewDisk and DiskEntry->NoMbr were set
3748 // to FALSE. In the other place (in usetup.c) where InstallMbrBootCodeToDisk
3749 // was called too, the installation test was modified by checking whether
3750 // DiskEntry->NoMbr was TRUE (instead of NewDisk).
3751 //
3752
3753 // HACK: Parts of FIXMEs described above: (Re)set the PartitionStyle to MBR.
3754 DiskEntry->DiskStyle = PARTITION_STYLE_MBR;
3755
3756 /* The layout has been successfully updated, the disk is not dirty anymore */
3757 DiskEntry->Dirty = FALSE;
3758
3759 return Status;
3760}
3761
3762BOOLEAN
3765{
3768 PDISKENTRY DiskEntry;
3769
3770 if (List == NULL)
3771 return TRUE;
3772
3773 for (Entry = List->DiskListHead.Flink;
3774 Entry != &List->DiskListHead;
3775 Entry = Entry->Flink)
3776 {
3777 DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
3778
3779 if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
3780 {
3781 DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
3782 continue;
3783 }
3784
3785 if (DiskEntry->Dirty != FALSE)
3786 {
3787 Status = WritePartitions(DiskEntry);
3788 if (!NT_SUCCESS(Status))
3789 {
3790 DPRINT1("WritePartitionsToDisk() failed to update disk %lu, Status 0x%08lx\n",
3791 DiskEntry->DiskNumber, Status);
3792 }
3793 }
3794 }
3795
3796 return TRUE;
3797}
3798
3799BOOLEAN
3801 IN WCHAR Letter,
3804{
3807 UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"SYSTEM\\MountedDevices");
3809 WCHAR ValueNameBuffer[16];
3811 REG_DISK_MOUNT_INFO MountInfo;
3812
3813 RtlStringCchPrintfW(ValueNameBuffer, ARRAYSIZE(ValueNameBuffer),
3814 L"\\DosDevices\\%c:", Letter);
3815 RtlInitUnicodeString(&ValueName, ValueNameBuffer);
3816
3818 &KeyName,
3821 NULL);
3822
3826 if (!NT_SUCCESS(Status))
3827 {
3831 0,
3832 NULL,
3834 NULL);
3835 }
3836 if (!NT_SUCCESS(Status))
3837 {
3838 DPRINT1("NtCreateKey() failed (Status %lx)\n", Status);
3839 return FALSE;
3840 }
3841
3842 MountInfo.Signature = Signature;
3843 MountInfo.StartingOffset = StartingOffset;
3845 &ValueName,
3846 0,
3847 REG_BINARY,
3848 (PVOID)&MountInfo,
3849 sizeof(MountInfo));
3851 if (!NT_SUCCESS(Status))
3852 {
3853 DPRINT1("NtSetValueKey() failed (Status %lx)\n", Status);
3854 return FALSE;
3855 }
3856
3857 return TRUE;
3858}
3859
3860BOOLEAN
3863{
3864 PLIST_ENTRY Entry1, Entry2;
3865 PDISKENTRY DiskEntry;
3866 PPARTENTRY PartEntry;
3868
3869 if (List == NULL)
3870 return FALSE;
3871
3872 for (Entry1 = List->DiskListHead.Flink;
3873 Entry1 != &List->DiskListHead;
3874 Entry1 = Entry1->Flink)
3875 {
3876 DiskEntry = CONTAINING_RECORD(Entry1,
3877 DISKENTRY,
3878 ListEntry);
3879
3880 if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
3881 {
3882 DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
3883 continue;
3884 }
3885
3886 for (Entry2 = DiskEntry->PrimaryPartListHead.Flink;
3887 Entry2 != &DiskEntry->PrimaryPartListHead;
3888 Entry2 = Entry2->Flink)
3889 {
3890 PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
3891 if (PartEntry->IsPartitioned) // && !IsContainerPartition(PartEntry->PartitionType)
3892 {
3894
3895 /* Assign a "\DosDevices\#:" mount point to this partition */
3896 if (PartEntry->DriveLetter)
3897 {
3898 StartingOffset.QuadPart = PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector;
3899 if (!SetMountedDeviceValue(PartEntry->DriveLetter,
3900 DiskEntry->LayoutBuffer->Signature,
3902 {
3903 return FALSE;
3904 }
3905 }
3906 }
3907 }
3908
3909 for (Entry2 = DiskEntry->LogicalPartListHead.Flink;
3910 Entry2 != &DiskEntry->LogicalPartListHead;
3911 Entry2 = Entry2->Flink)
3912 {
3913 PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
3914 if (PartEntry->IsPartitioned) // && !IsContainerPartition(PartEntry->PartitionType)
3915 {
3917
3918 /* Assign a "\DosDevices\#:" mount point to this partition */
3919 if (PartEntry->DriveLetter)
3920 {
3921 StartingOffset.QuadPart = PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector;
3922 if (!SetMountedDeviceValue(PartEntry->DriveLetter,
3923 DiskEntry->LayoutBuffer->Signature,
3925 {
3926 return FALSE;
3927 }
3928 }
3929 }
3930 }
3931 }
3932
3933 return TRUE;
3934}
3935
3936VOID
3938 IN PPARTENTRY PartEntry,
3940{
3941 PDISKENTRY DiskEntry = PartEntry->DiskEntry;
3942
3943 ASSERT(DiskEntry->DiskStyle == PARTITION_STYLE_MBR);
3944
3945 PartEntry->PartitionType = PartitionType;
3946
3947 DiskEntry->Dirty = TRUE;
3948 DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].PartitionType = PartitionType;
3949 DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].RecognizedPartition = IsRecognizedPartition(PartitionType);
3950 DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].RewritePartition = TRUE;
3951}
3952
3955 IN PPARTENTRY PartEntry)
3956{
3957 PDISKENTRY DiskEntry = PartEntry->DiskEntry;
3958
3959 if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
3960 {
3961 DPRINT1("GPT-partitioned disk detected, not currently supported by SETUP!\n");
3962 return ERROR_WARN_PARTITION;
3963 }
3964
3965 /* Fail if the partition is already in use */
3966 if (PartEntry->IsPartitioned)
3967 return ERROR_NEW_PARTITION;
3968
3969 /* Only one primary partition is allowed on super-floppy */
3970 if (IsSuperFloppy(DiskEntry))
3972
3973 /* Fail if there are already 4 primary partitions in the list */
3974 if (GetPrimaryPartitionCount(DiskEntry) >= 4)
3976
3977 return ERROR_SUCCESS;
3978}
3979
3982 IN PPARTENTRY PartEntry)
3983{
3984 PDISKENTRY DiskEntry = PartEntry->DiskEntry;
3985
3986 if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
3987 {
3988 DPRINT1("GPT-partitioned disk detected, not currently supported by SETUP!\n");
3989 return ERROR_WARN_PARTITION;
3990 }
3991
3992 /* Fail if the partition is already in use */
3993 if (PartEntry->IsPartitioned)
3994 return ERROR_NEW_PARTITION;
3995
3996 /* Only one primary partition is allowed on super-floppy */
3997 if (IsSuperFloppy(DiskEntry))
3999
4000 /* Fail if there are already 4 primary partitions in the list */
4001 if (GetPrimaryPartitionCount(DiskEntry) >= 4)
4003
4004 /* Fail if there is another extended partition in the list */
4005 if (DiskEntry->ExtendedPartition != NULL)
4007
4008 return ERROR_SUCCESS;
4009}
4010
4013 IN PPARTENTRY PartEntry)
4014{
4015 PDISKENTRY DiskEntry = PartEntry->DiskEntry;
4016
4017 if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
4018 {
4019 DPRINT1("GPT-partitioned disk detected, not currently supported by SETUP!\n");
4020 return ERROR_WARN_PARTITION;
4021 }
4022
4023 /* Fail if the partition is already in use */
4024 if (PartEntry->IsPartitioned)
4025 return ERROR_NEW_PARTITION;
4026
4027 /* Only one primary partition is allowed on super-floppy */
4028 if (IsSuperFloppy(DiskEntry))
4030
4031 return ERROR_SUCCESS;
4032}
4033
4034BOOLEAN
4037 OUT PDISKENTRY *pDiskEntry OPTIONAL,
4038 OUT PPARTENTRY *pPartEntry)
4039{
4040 PLIST_ENTRY Entry1, Entry2;
4041 PDISKENTRY DiskEntry;
4042 PPARTENTRY PartEntry;
4043
4044 for (Entry1 = List->DiskListHead.Flink;
4045 Entry1 != &List->DiskListHead;
4046 Entry1 = Entry1->Flink)
4047 {
4048 DiskEntry = CONTAINING_RECORD(Entry1,
4049 DISKENTRY,
4050 ListEntry);
4051
4052 if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
4053 {
4054 DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
4055 continue;
4056 }
4057
4058 for (Entry2 = DiskEntry->PrimaryPartListHead.Flink;
4059 Entry2 != &DiskEntry->PrimaryPartListHead;
4060 Entry2 = Entry2->Flink)
4061 {
4062 PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
4063 if (PartEntry->IsPartitioned && PartEntry->New)
4064 {
4065 ASSERT(DiskEntry == PartEntry->DiskEntry);
4066 if (pDiskEntry) *pDiskEntry = DiskEntry;
4067 *pPartEntry = PartEntry;
4068 return TRUE;
4069 }
4070 }
4071
4072 for (Entry2 = DiskEntry->LogicalPartListHead.Flink;
4073 Entry2 != &DiskEntry->LogicalPartListHead;
4074 Entry2 = Entry2->Flink)
4075 {
4076 PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
4077 if (PartEntry->IsPartitioned && PartEntry->New)
4078 {
4079 ASSERT(DiskEntry == PartEntry->DiskEntry);
4080 if (pDiskEntry) *pDiskEntry = DiskEntry;
4081 *pPartEntry = PartEntry;
4082 return TRUE;
4083 }
4084 }
4085 }
4086
4087 if (pDiskEntry) *pDiskEntry = NULL;
4088 *pPartEntry = NULL;
4089
4090 return FALSE;
4091}
4092
4093BOOLEAN
4096 OUT PDISKENTRY *pDiskEntry OPTIONAL,
4097 OUT PPARTENTRY *pPartEntry)
4098{
4099 PLIST_ENTRY Entry1, Entry2;
4100 PDISKENTRY DiskEntry;
4101 PPARTENTRY PartEntry;
4102
4103 for (Entry1 = List->DiskListHead.Flink;
4104 Entry1 != &List->DiskListHead;
4105 Entry1 = Entry1->Flink)
4106 {
4107 DiskEntry = CONTAINING_RECORD(Entry1,
4108 DISKENTRY,
4109 ListEntry);
4110
4111 if (DiskEntry->DiskStyle == PARTITION_STYLE_GPT)
4112 {
4113 DPRINT("GPT-partitioned disk detected, not currently supported by SETUP!\n");
4114 continue;
4115 }
4116
4117 for (Entry2 = DiskEntry->PrimaryPartListHead.Flink;
4118 Entry2 != &DiskEntry->PrimaryPartListHead;
4119 Entry2 = Entry2->Flink)
4120 {
4121 PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
4122 if (PartEntry->IsPartitioned && PartEntry->NeedsCheck)
4123 {
4124 ASSERT(DiskEntry == PartEntry->DiskEntry);
4125 if (pDiskEntry) *pDiskEntry = DiskEntry;
4126 *pPartEntry = PartEntry;
4127 return TRUE;
4128 }
4129 }
4130
4131 for (Entry2 = DiskEntry->LogicalPartListHead.Flink;
4132 Entry2 != &DiskEntry->LogicalPartListHead;
4133 Entry2 = Entry2->Flink)
4134 {
4135 PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
4136 if (PartEntry->IsPartitioned && PartEntry->NeedsCheck)
4137 {
4138 ASSERT(DiskEntry == PartEntry->DiskEntry);
4139 if (pDiskEntry) *pDiskEntry = DiskEntry;
4140 *pPartEntry = PartEntry;
4141 return TRUE;
4142 }
4143 }
4144 }
4145
4146 if (pDiskEntry) *pDiskEntry = NULL;
4147 *pPartEntry = NULL;
4148
4149 return FALSE;
4150}
4151
4152/* 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:588
BOOLEAN NTAPI RtlFreeHeap(IN PVOID HeapHandle, IN ULONG Flags, IN PVOID HeapBase)
Definition: heap.c:606
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:60
@ ERROR_PARTITION_TABLE_FULL
Definition: errorcode.h:59
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 EFI_PMBR_OSTYPE_EFI
Definition: partlist.h:175
#define PARTITION_MAGIC
Definition: partlist.h:172
#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
_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:4208
_In_ PCWSTR _Inout_ _At_ QueryTable _Pre_unknown_ PRTL_QUERY_REGISTRY_TABLE QueryTable
Definition: rtlfuncs.h:4209
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
static BOOLEAN InitializePartitionEntry(IN OUT PPARTENTRY PartEntry, IN ULONGLONG SectorCount, IN BOOLEAN AutoCreate)
Definition: partlist.c:678
VOID DestroyPartitionList(IN PPARTLIST List)
Definition: partlist.c:1931
static VOID AddPartitionToDisk(IN ULONG DiskNumber, IN PDISKENTRY DiskEntry, IN ULONG PartitionIndex, IN BOOLEAN LogicalPartition)
Definition: partlist.c:751
ERROR_NUMBER PrimaryPartitionCreationChecks(IN PPARTENTRY PartEntry)
Definition: partlist.c:3954
PPARTENTRY SelectPartition(IN PPARTLIST List, IN ULONG DiskNumber, IN ULONG PartitionNumber)
Definition: partlist.c:2183
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:3861
static PDISKENTRY GetSystemDisk(IN PPARTLIST List)
Definition: partlist.c:1718
BOOLEAN GetDiskOrPartition(IN PPARTLIST List, IN ULONG DiskNumber, IN ULONG PartitionNumber OPTIONAL, OUT PDISKENTRY *pDiskEntry, OUT PPARTENTRY *pPartEntry OPTIONAL)
Definition: partlist.c:2143
ULONGLONG AlignUp(IN ULONGLONG Value, IN ULONG Alignment)
Definition: partlist.c:79
static ULONG GetPrimaryPartitionCount(IN PDISKENTRY DiskEntry)
Definition: partlist.c:2428
static VOID UpdateDiskLayout(IN PDISKENTRY DiskEntry)
Definition: partlist.c:2534
BOOLEAN WritePartitionsToDisk(IN PPARTLIST List)
Definition: partlist.c:3763
PPARTENTRY GetPartition(IN PDISKENTRY DiskEntry, IN ULONG PartitionNumber)
Definition: partlist.c:2096
PDISKENTRY GetDiskByNumber(IN PPARTLIST List, IN ULONG DiskNumber)
Definition: partlist.c:2014
ULONGLONG RoundingDivide(IN ULONGLONG Dividend, IN ULONGLONG Divisor)
Definition: partlist.c:95
VOID SetMBRPartitionType(IN PPARTENTRY PartEntry, IN UCHAR PartitionType)
Definition: partlist.c:3937
static VOID AssignDriveLetters(IN PPARTLIST List)
Definition: partlist.c:138
ERROR_NUMBER LogicalPartitionCreationChecks(IN PPARTENTRY PartEntry)
Definition: partlist.c:4012
PPARTENTRY GetPrevPartition(IN PPARTLIST List, IN PPARTENTRY CurrentPart OPTIONAL)
Definition: partlist.c:2299
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:4094
BOOLEAN DeletePartition(IN PPARTLIST List, IN PPARTENTRY PartEntry, OUT PPARTENTRY *FreeRegion OPTIONAL)
Definition: partlist.c:3047
BOOLEAN IsSuperFloppy(IN PDISKENTRY DiskEntry)
Definition: partlist.c:501
static VOID AddLogicalDiskSpace(IN PDISKENTRY DiskEntry)
Definition: partlist.c:2823
static PPARTENTRY GetPrevUnpartitionedEntry(IN PPARTENTRY PartEntry)
Definition: partlist.c:2717
static VOID SetDiskSignature(IN PPARTLIST List, IN PDISKENTRY DiskEntry)
Definition: partlist.c:1153
BOOLEAN CreateLogicalPartition(IN PPARTLIST List, IN OUT PPARTENTRY PartEntry, IN ULONGLONG SectorCount, IN BOOLEAN AutoCreate)
Definition: partlist.c:2904
static PPARTENTRY GetNextUnpartitionedEntry(IN PPARTENTRY PartEntry)
Definition: partlist.c:2752
static ULONG GetLogicalPartitionCount(IN PDISKENTRY DiskEntry)
Definition: partlist.c:2455
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:1847
ERROR_NUMBER ExtendedPartitionCreationChecks(IN PPARTENTRY PartEntry)
Definition: partlist.c:3981
BOOLEAN CreateExtendedPartition(IN PPARTLIST List, IN OUT PPARTENTRY PartEntry, IN ULONGLONG SectorCount)
Definition: partlist.c:2850
#define ROOT_NAME
PPARTENTRY GetNextPartition(IN PPARTLIST List, IN PPARTENTRY CurrentPart OPTIONAL)
Definition: partlist.c:2207
static VOID AddDiskToList(IN HANDLE FileHandle, IN ULONG DiskNumber, IN PPARTLIST List)
Definition: partlist.c:1306
static VOID ScanForUnpartitionedDiskSpace(IN PDISKENTRY DiskEntry)
Definition: partlist.c:942
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:1768
PDISKENTRY GetDiskByBiosNumber(IN PPARTLIST List, IN ULONG HwDiskNumber)
Definition: partlist.c:1988
static VOID UpdateDiskSignatures(IN PPARTLIST List)
Definition: partlist.c:1215
BOOLEAN SetActivePartition(IN PPARTLIST List, IN PPARTENTRY PartEntry, IN PPARTENTRY OldActivePart OPTIONAL)
Definition: partlist.c:3555
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
FORCEINLINE BOOLEAN IsEmptyLayoutEntry(IN PPARTITION_INFORMATION PartitionInfo)
Definition: partlist.c:2396
static PPARTENTRY GetActiveDiskPartition(IN PDISKENTRY DiskEntry)
Definition: partlist.c:1791
BOOLEAN GetNextUnformattedPartition(IN PPARTLIST List, OUT PDISKENTRY *pDiskEntry OPTIONAL, OUT PPARTENTRY *pPartEntry)
Definition: partlist.c:4035
struct _REG_DISK_MOUNT_INFO REG_DISK_MOUNT_INFO
FORCEINLINE BOOLEAN IsSamePrimaryLayoutEntry(IN PPARTITION_INFORMATION PartitionInfo, IN PDISKENTRY DiskEntry, IN PPARTENTRY PartEntry)
Definition: partlist.c:2411
BOOLEAN CreatePrimaryPartition(IN PPARTLIST List, IN OUT PPARTENTRY PartEntry, IN ULONGLONG SectorCount, IN BOOLEAN AutoCreate)
Definition: partlist.c:2786
static BOOLEAN InsertDiskRegion(IN PDISKENTRY DiskEntry, IN PPARTENTRY PartEntry, IN BOOLEAN LogicalPartition)
Definition: partlist.c:574
BOOLEAN SetMountedDeviceValue(IN WCHAR Letter, IN ULONG Signature, IN LARGE_INTEGER StartingOffset)
Definition: partlist.c:3800
static VOID UpdateHwDiskNumbers(IN PPARTLIST List)
Definition: partlist.c:1245
static BOOLEAN ReAllocateLayoutBuffer(IN PDISKENTRY DiskEntry)
Definition: partlist.c:2482
PPARTENTRY FindSupportedSystemPartition(IN PPARTLIST List, IN BOOLEAN ForceSelect, IN PDISKENTRY AlternativeDisk OPTIONAL, IN PPARTENTRY AlternativePart OPTIONAL)
Definition: partlist.c:3260
static BOOLEAN IsSupportedActivePartition(IN PPARTENTRY PartEntry)
Definition: partlist.c:3180
PDISKENTRY GetDiskBySignature(IN PPARTLIST List, IN ULONG Signature)
Definition: partlist.c:2070
NTSTATUS DismountVolume(IN PPARTENTRY PartEntry)
Definition: partlist.c:2940
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:3619
PDISKENTRY GetDiskBySCSI(IN PPARTLIST List, IN USHORT Port, IN USHORT Bus, IN USHORT Id)
Definition: partlist.c:2040
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:142
ULONG ControllerNumber
Definition: partlist.h:143
ULONG DiskNumber
Definition: partlist.h:144
ULONG Checksum
Definition: partlist.h:146
ULONG Signature
Definition: partlist.h:145
PDISKENTRY DiskEntry
Definition: partlist.h:147
CM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry
Definition: partlist.h:148
CM_PARTIAL_RESOURCE_LIST PartialResourceList
Definition: hwresource.cpp:160
struct _CM_PARTIAL_RESOURCE_DESCRIPTOR::@382::@391 DeviceSpecificData
union _CM_PARTIAL_RESOURCE_DESCRIPTOR::@382 u
CM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptors[1]
Definition: hwresource.cpp:119
ULONG HwAdapterNumber
Definition: partlist.h:103
ULONG SectorAlignment
Definition: partlist.h:98
ULARGE_INTEGER SectorCount
Definition: partlist.h:97
UNICODE_STRING DriverName
Definition: partlist.h:123
ULONG HwControllerNumber
Definition: partlist.h:104
ULONG HwDiskNumber
Definition: partlist.h:105
ULONG SectorsPerTrack
Definition: partlist.h:94
PPARTENTRY ExtendedPartition
Definition: partlist.h:135
LIST_ENTRY LogicalPartListHead
Definition: partlist.h:132
struct _PARTLIST * PartList
Definition: partlist.h:86
BOOLEAN NewDisk
Definition: partlist.h:120
ULONG DiskNumber
Definition: partlist.h:111
ULONG BytesPerSector
Definition: partlist.h:95
BOOLEAN BiosFound
Definition: partlist.h:102
ULONGLONG Cylinders
Definition: partlist.h:92
USHORT Bus
Definition: partlist.h:114
USHORT Id
Definition: partlist.h:115
LIST_ENTRY ListEntry
Definition: partlist.h:83
BOOLEAN Dirty
Definition: partlist.h:118
USHORT Port
Definition: partlist.h:113
PARTITION_STYLE DiskStyle
Definition: partlist.h:121
ULONG TracksPerCylinder
Definition: partlist.h:93
LIST_ENTRY PrimaryPartListHead
Definition: partlist.h:131
MEDIA_TYPE MediaType
Definition: partlist.h:88
ULONG HwFixedDiskNumber
Definition: partlist.h:106
ULONG CylinderAlignment
Definition: partlist.h:99
PDRIVE_LAYOUT_INFORMATION LayoutBuffer
Definition: partlist.h:125
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
ULONG Characteristics
Definition: