[USETUP]
[reactos.git] / reactos / base / setup / usetup / partlist.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 2002, 2003, 2004, 2005 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 /* COPYRIGHT: See COPYING in the top level directory
20 * PROJECT: ReactOS text-mode setup
21 * FILE: base/setup/usetup/partlist.c
22 * PURPOSE: Partition list functions
23 * PROGRAMMER: Eric Kohl
24 * Casper S. Hornstrup (chorns@users.sourceforge.net)
25 */
26
27 #include "usetup.h"
28
29 #include <ntddscsi.h>
30
31 #define NDEBUG
32 #include <debug.h>
33
34 //#define DUMP_PARTITION_TABLE
35
36 /* HELPERS FOR PARTITION TYPES **********************************************/
37
38 typedef struct _PARTITION_TYPE
39 {
40 UCHAR Type;
41 PCHAR Description;
42 } PARTITION_TYPE, *PPARTITION_TYPE;
43
44 /*
45 * This partition type list was ripped off the kernelDisk.c module from:
46 *
47 * Visopsys Operating System
48 * Copyright (C) 1998-2015 J. Andrew McLaughlin
49 *
50 * This program is free software; you can redistribute it and/or modify it
51 * under the terms of the GNU General Public License as published by the Free
52 * Software Foundation; either version 2 of the License, or (at your option)
53 * any later version.
54 *
55 * This program is distributed in the hope that it will be useful, but
56 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
57 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
58 * for more details.
59 *
60 * You should have received a copy of the GNU General Public License along
61 * with this program; if not, write to the Free Software Foundation, Inc.,
62 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
63 *
64 *
65 * See also https://en.wikipedia.org/wiki/Partition_type#List_of_partition_IDs
66 * and http://www.win.tue.nl/~aeb/partitions/partition_types-1.html
67 * for a complete list.
68 */
69
70 /* This is a table for keeping known partition type codes and descriptions */
71 static PARTITION_TYPE PartitionTypes[] =
72 {
73 { 0x00, "(Empty)" },
74 { 0x01, "FAT12" },
75 { 0x02, "XENIX root" },
76 { 0x03, "XENIX /usr" },
77 { 0x04, "FAT16 (small)" },
78 { 0x05, "Extended" },
79 { 0x06, "FAT16" },
80 { 0x07, "NTFS/HPFS/exFAT" },
81 { 0x08, "OS/2 or AIX boot" },
82 { 0x09, "AIX data" },
83 { 0x0A, "OS/2 Boot Manager" },
84 { 0x0B, "FAT32" },
85 { 0x0C, "FAT32 (LBA)" },
86 { 0x0E, "FAT16 (LBA)" },
87 { 0x0F, "Extended (LBA)" },
88 { 0x11, "Hidden FAT12" },
89 { 0x12, "FAT diagnostic" },
90 { 0x14, "Hidden FAT16 (small)" },
91 { 0x16, "Hidden FAT16" },
92 { 0x17, "Hidden HPFS or NTFS" },
93 { 0x1B, "Hidden FAT32" },
94 { 0x1C, "Hidden FAT32 (LBA)" },
95 { 0x1E, "Hidden FAT16 (LBA)" },
96 { 0x35, "JFS" },
97 { 0x39, "Plan 9" },
98 { 0x3C, "PartitionMagic" },
99 { 0x3D, "Hidden Netware" },
100 { 0x41, "PowerPC PReP" },
101 { 0x42, "Win2K dynamic extended" },
102 { 0x43, "Old Linux" },
103 { 0x44, "GoBack" },
104 { 0x4D, "QNX4.x" },
105 { 0x4D, "QNX4.x 2nd" },
106 { 0x4D, "QNX4.x 3rd" },
107 { 0x50, "Ontrack R/O" },
108 { 0x51, "Ontrack R/W or Novell" },
109 { 0x52, "CP/M" },
110 { 0x63, "GNU HURD or UNIX SysV" },
111 { 0x64, "Netware 2" },
112 { 0x65, "Netware 3/4" },
113 { 0x66, "Netware SMS" },
114 { 0x67, "Novell" },
115 { 0x68, "Novell" },
116 { 0x69, "Netware 5+" },
117 { 0x7E, "Veritas VxVM public" },
118 { 0x7F, "Veritas VxVM private" },
119 { 0x80, "Minix" },
120 { 0x81, "Linux or Minix" },
121 { 0x82, "Linux swap or Solaris" },
122 { 0x83, "Linux" },
123 { 0x84, "Hibernation" },
124 { 0x85, "Linux extended" },
125 { 0x86, "HPFS or NTFS mirrored" },
126 { 0x87, "HPFS or NTFS mirrored" },
127 { 0x8E, "Linux LVM" },
128 { 0x93, "Hidden Linux" },
129 { 0x9F, "BSD/OS" },
130 { 0xA0, "Laptop hibernation" },
131 { 0xA1, "Laptop hibernation" },
132 { 0xA5, "BSD, NetBSD, FreeBSD" },
133 { 0xA6, "OpenBSD" },
134 { 0xA7, "NeXTSTEP" },
135 { 0xA8, "OS-X UFS" },
136 { 0xA9, "NetBSD" },
137 { 0xAB, "OS-X boot" },
138 { 0xAF, "OS-X HFS" },
139 { 0xB6, "NT corrupt mirror" },
140 { 0xB7, "BSDI" },
141 { 0xB8, "BSDI swap" },
142 { 0xBE, "Solaris 8 boot" },
143 { 0xBF, "Solaris x86" },
144 { 0xC0, "NTFT" },
145 { 0xC1, "DR-DOS FAT12" },
146 { 0xC2, "Hidden Linux" },
147 { 0xC3, "Hidden Linux swap" },
148 { 0xC4, "DR-DOS FAT16 (small)" },
149 { 0xC5, "DR-DOS Extended" },
150 { 0xC6, "DR-DOS FAT16" },
151 { 0xC7, "HPFS mirrored" },
152 { 0xCB, "DR-DOS FAT32" },
153 { 0xCC, "DR-DOS FAT32 (LBA)" },
154 { 0xCE, "DR-DOS FAT16 (LBA)" },
155 { 0xD0, "MDOS" },
156 { 0xD1, "MDOS FAT12" },
157 { 0xD4, "MDOS FAT16 (small)" },
158 { 0xD5, "MDOS Extended" },
159 { 0xD6, "MDOS FAT16" },
160 { 0xD8, "CP/M-86" },
161 { 0xDF, "BootIt EMBRM(FAT16/32)" },
162 { 0xEB, "BeOS BFS" },
163 { 0xEE, "EFI GPT protective" },
164 { 0xEF, "EFI filesystem" },
165 { 0xF0, "Linux/PA-RISC boot" },
166 { 0xF2, "DOS 3.3+ second" },
167 { 0xFA, "Bochs" },
168 { 0xFB, "VmWare" },
169 { 0xFC, "VmWare swap" },
170 { 0xFD, "Linux RAID" },
171 { 0xFE, "NT hidden" },
172 };
173
174 VOID
175 GetPartTypeStringFromPartitionType(
176 UCHAR partitionType,
177 PCHAR strPartType,
178 DWORD cchPartType)
179 {
180 /* Determine partition type */
181
182 if (IsContainerPartition(partitionType))
183 {
184 StringCchCopy(strPartType, cchPartType, MUIGetString(STRING_EXTENDED_PARTITION));
185 }
186 else if (partitionType == PARTITION_ENTRY_UNUSED)
187 {
188 StringCchCopy(strPartType, cchPartType, MUIGetString(STRING_FORMATUNUSED));
189 }
190 else
191 {
192 UINT i;
193
194 /* Do the table lookup */
195 for (i = 0; i < ARRAYSIZE(PartitionTypes); i++)
196 {
197 if (partitionType == PartitionTypes[i].Type)
198 {
199 StringCchCopy(strPartType, cchPartType, PartitionTypes[i].Description);
200 return;
201 }
202 }
203
204 /* We are here because the partition type is unknown */
205 StringCchCopy(strPartType, cchPartType, MUIGetString(STRING_FORMATUNKNOWN));
206 }
207 }
208
209 /* FUNCTIONS ****************************************************************/
210
211 #ifdef DUMP_PARTITION_TABLE
212 static
213 VOID
214 DumpPartitionTable(
215 PDISKENTRY DiskEntry)
216 {
217 PPARTITION_INFORMATION PartitionInfo;
218 ULONG i;
219
220 DbgPrint("\n");
221 DbgPrint("Index Start Length Hidden Nr Type Boot RW\n");
222 DbgPrint("----- ------------ ------------ ---------- -- ---- ---- --\n");
223
224 for (i = 0; i < DiskEntry->LayoutBuffer->PartitionCount; i++)
225 {
226 PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[i];
227 DbgPrint(" %3lu %12I64u %12I64u %10lu %2lu %2x %c %c\n",
228 i,
229 PartitionInfo->StartingOffset.QuadPart / DiskEntry->BytesPerSector,
230 PartitionInfo->PartitionLength.QuadPart / DiskEntry->BytesPerSector,
231 PartitionInfo->HiddenSectors,
232 PartitionInfo->PartitionNumber,
233 PartitionInfo->PartitionType,
234 PartitionInfo->BootIndicator ? '*': ' ',
235 PartitionInfo->RewritePartition ? 'Y': 'N');
236 }
237
238 DbgPrint("\n");
239 }
240 #endif
241
242
243 ULONGLONG
244 AlignDown(
245 IN ULONGLONG Value,
246 IN ULONG Alignment)
247 {
248 ULONGLONG Temp;
249
250 Temp = Value / Alignment;
251
252 return Temp * Alignment;
253 }
254
255
256 ULONGLONG
257 AlignUp(
258 IN ULONGLONG Value,
259 IN ULONG Alignment)
260 {
261 ULONGLONG Temp, Result;
262
263 Temp = Value / Alignment;
264
265 Result = Temp * Alignment;
266 if (Value % Alignment)
267 Result += Alignment;
268
269 return Result;
270 }
271
272 ULONGLONG
273 RoundingDivide(
274 IN ULONGLONG Dividend,
275 IN ULONGLONG Divisor)
276 {
277 return (Dividend + Divisor / 2) / Divisor;
278 }
279
280
281 static
282 VOID
283 GetDriverName(
284 PDISKENTRY DiskEntry)
285 {
286 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
287 WCHAR KeyName[32];
288 NTSTATUS Status;
289
290 RtlInitUnicodeString(&DiskEntry->DriverName,
291 NULL);
292
293 swprintf(KeyName,
294 L"\\Scsi\\Scsi Port %lu",
295 DiskEntry->Port);
296
297 RtlZeroMemory(&QueryTable,
298 sizeof(QueryTable));
299
300 QueryTable[0].Name = L"Driver";
301 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
302 QueryTable[0].EntryContext = &DiskEntry->DriverName;
303
304 Status = RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP,
305 KeyName,
306 QueryTable,
307 NULL,
308 NULL);
309 if (!NT_SUCCESS(Status))
310 {
311 DPRINT1("RtlQueryRegistryValues() failed (Status %lx)\n", Status);
312 }
313 }
314
315
316 static
317 VOID
318 AssignDriveLetters(
319 PPARTLIST List)
320 {
321 PDISKENTRY DiskEntry;
322 PPARTENTRY PartEntry;
323 PLIST_ENTRY Entry1;
324 PLIST_ENTRY Entry2;
325 CHAR Letter;
326
327 Letter = 'C';
328
329 /* Assign drive letters to primary partitions */
330 Entry1 = List->DiskListHead.Flink;
331 while (Entry1 != &List->DiskListHead)
332 {
333 DiskEntry = CONTAINING_RECORD(Entry1, DISKENTRY, ListEntry);
334
335 Entry2 = DiskEntry->PrimaryPartListHead.Flink;
336 while (Entry2 != &DiskEntry->PrimaryPartListHead)
337 {
338 PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
339
340 PartEntry->DriveLetter = 0;
341
342 if (PartEntry->IsPartitioned &&
343 !IsContainerPartition(PartEntry->PartitionType))
344 {
345 if (IsRecognizedPartition(PartEntry->PartitionType) ||
346 (PartEntry->PartitionType == PARTITION_ENTRY_UNUSED &&
347 PartEntry->SectorCount.QuadPart != 0LL))
348 {
349 if (Letter <= 'Z')
350 {
351 PartEntry->DriveLetter = Letter;
352 Letter++;
353 }
354 }
355 }
356
357 Entry2 = Entry2->Flink;
358 }
359
360 Entry1 = Entry1->Flink;
361 }
362
363 /* Assign drive letters to logical drives */
364 Entry1 = List->DiskListHead.Flink;
365 while (Entry1 != &List->DiskListHead)
366 {
367 DiskEntry = CONTAINING_RECORD(Entry1, DISKENTRY, ListEntry);
368
369 Entry2 = DiskEntry->LogicalPartListHead.Flink;
370 while (Entry2 != &DiskEntry->LogicalPartListHead)
371 {
372 PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
373
374 PartEntry->DriveLetter = 0;
375
376 if (PartEntry->IsPartitioned)
377 {
378 if (IsRecognizedPartition(PartEntry->PartitionType) ||
379 (PartEntry->PartitionType == PARTITION_ENTRY_UNUSED &&
380 PartEntry->SectorCount.QuadPart != 0LL))
381 {
382 if (Letter <= 'Z')
383 {
384 PartEntry->DriveLetter = Letter;
385 Letter++;
386 }
387 }
388 }
389
390 Entry2 = Entry2->Flink;
391 }
392
393 Entry1 = Entry1->Flink;
394 }
395 }
396
397
398 NTSTATUS
399 NTAPI
400 DiskIdentifierQueryRoutine(
401 PWSTR ValueName,
402 ULONG ValueType,
403 PVOID ValueData,
404 ULONG ValueLength,
405 PVOID Context,
406 PVOID EntryContext)
407 {
408 PBIOSDISKENTRY BiosDiskEntry = (PBIOSDISKENTRY)Context;
409 UNICODE_STRING NameU;
410
411 if (ValueType == REG_SZ &&
412 ValueLength == 20 * sizeof(WCHAR))
413 {
414 NameU.Buffer = (PWCHAR)ValueData;
415 NameU.Length = NameU.MaximumLength = 8 * sizeof(WCHAR);
416 RtlUnicodeStringToInteger(&NameU, 16, &BiosDiskEntry->Checksum);
417
418 NameU.Buffer = (PWCHAR)ValueData + 9;
419 RtlUnicodeStringToInteger(&NameU, 16, &BiosDiskEntry->Signature);
420
421 return STATUS_SUCCESS;
422 }
423
424 return STATUS_UNSUCCESSFUL;
425 }
426
427
428 NTSTATUS
429 NTAPI
430 DiskConfigurationDataQueryRoutine(
431 PWSTR ValueName,
432 ULONG ValueType,
433 PVOID ValueData,
434 ULONG ValueLength,
435 PVOID Context,
436 PVOID EntryContext)
437 {
438 PBIOSDISKENTRY BiosDiskEntry = (PBIOSDISKENTRY)Context;
439 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
440 PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry;
441 ULONG i;
442
443 if (ValueType != REG_FULL_RESOURCE_DESCRIPTOR ||
444 ValueLength < sizeof(CM_FULL_RESOURCE_DESCRIPTOR))
445 return STATUS_UNSUCCESSFUL;
446
447 FullResourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)ValueData;
448
449 /* Hm. Version and Revision are not set on Microsoft Windows XP... */
450 #if 0
451 if (FullResourceDescriptor->PartialResourceList.Version != 1 ||
452 FullResourceDescriptor->PartialResourceList.Revision != 1)
453 return STATUS_UNSUCCESSFUL;
454 #endif
455
456 for (i = 0; i < FullResourceDescriptor->PartialResourceList.Count; i++)
457 {
458 if (FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].Type != CmResourceTypeDeviceSpecific ||
459 FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].u.DeviceSpecificData.DataSize != sizeof(CM_DISK_GEOMETRY_DEVICE_DATA))
460 continue;
461
462 DiskGeometry = (PCM_DISK_GEOMETRY_DEVICE_DATA)&FullResourceDescriptor->PartialResourceList.PartialDescriptors[i + 1];
463 BiosDiskEntry->DiskGeometry = *DiskGeometry;
464
465 return STATUS_SUCCESS;
466 }
467
468 return STATUS_UNSUCCESSFUL;
469 }
470
471
472 NTSTATUS
473 NTAPI
474 SystemConfigurationDataQueryRoutine(
475 PWSTR ValueName,
476 ULONG ValueType,
477 PVOID ValueData,
478 ULONG ValueLength,
479 PVOID Context,
480 PVOID EntryContext)
481 {
482 PCM_FULL_RESOURCE_DESCRIPTOR FullResourceDescriptor;
483 PCM_INT13_DRIVE_PARAMETER* Int13Drives = (PCM_INT13_DRIVE_PARAMETER*)Context;
484 ULONG i;
485
486 if (ValueType != REG_FULL_RESOURCE_DESCRIPTOR ||
487 ValueLength < sizeof(CM_FULL_RESOURCE_DESCRIPTOR))
488 return STATUS_UNSUCCESSFUL;
489
490 FullResourceDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)ValueData;
491
492 /* Hm. Version and Revision are not set on Microsoft Windows XP... */
493 #if 0
494 if (FullResourceDescriptor->PartialResourceList.Version != 1 ||
495 FullResourceDescriptor->PartialResourceList.Revision != 1)
496 return STATUS_UNSUCCESSFUL;
497 #endif
498
499 for (i = 0; i < FullResourceDescriptor->PartialResourceList.Count; i++)
500 {
501 if (FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].Type != CmResourceTypeDeviceSpecific ||
502 FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].u.DeviceSpecificData.DataSize % sizeof(CM_INT13_DRIVE_PARAMETER) != 0)
503 continue;
504
505 *Int13Drives = (CM_INT13_DRIVE_PARAMETER*)RtlAllocateHeap(ProcessHeap, 0,
506 FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].u.DeviceSpecificData.DataSize);
507 if (*Int13Drives == NULL)
508 return STATUS_NO_MEMORY;
509
510 memcpy(*Int13Drives,
511 &FullResourceDescriptor->PartialResourceList.PartialDescriptors[i + 1],
512 FullResourceDescriptor->PartialResourceList.PartialDescriptors[i].u.DeviceSpecificData.DataSize);
513 return STATUS_SUCCESS;
514 }
515
516 return STATUS_UNSUCCESSFUL;
517 }
518
519
520 #define ROOT_NAME L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter"
521
522 static VOID
523 EnumerateBiosDiskEntries(
524 PPARTLIST PartList)
525 {
526 RTL_QUERY_REGISTRY_TABLE QueryTable[3];
527 WCHAR Name[120];
528 ULONG AdapterCount;
529 ULONG DiskCount;
530 NTSTATUS Status;
531 PCM_INT13_DRIVE_PARAMETER Int13Drives;
532 PBIOSDISKENTRY BiosDiskEntry;
533
534 memset(QueryTable, 0, sizeof(QueryTable));
535
536 QueryTable[1].Name = L"Configuration Data";
537 QueryTable[1].QueryRoutine = SystemConfigurationDataQueryRoutine;
538 Int13Drives = NULL;
539 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
540 L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System",
541 &QueryTable[1],
542 (PVOID)&Int13Drives,
543 NULL);
544 if (!NT_SUCCESS(Status))
545 {
546 DPRINT1("Unable to query the 'Configuration Data' key in '\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System', status=%lx\n", Status);
547 return;
548 }
549
550 AdapterCount = 0;
551 while (1)
552 {
553 swprintf(Name, L"%s\\%lu", ROOT_NAME, AdapterCount);
554 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
555 Name,
556 &QueryTable[2],
557 NULL,
558 NULL);
559 if (!NT_SUCCESS(Status))
560 {
561 break;
562 }
563
564 swprintf(Name, L"%s\\%lu\\DiskController", ROOT_NAME, AdapterCount);
565 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
566 Name,
567 &QueryTable[2],
568 NULL,
569 NULL);
570 if (NT_SUCCESS(Status))
571 {
572 while (1)
573 {
574 swprintf(Name, L"%s\\%lu\\DiskController\\0", ROOT_NAME, AdapterCount);
575 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
576 Name,
577 &QueryTable[2],
578 NULL,
579 NULL);
580 if (!NT_SUCCESS(Status))
581 {
582 RtlFreeHeap(ProcessHeap, 0, Int13Drives);
583 return;
584 }
585
586 swprintf(Name, L"%s\\%lu\\DiskController\\0\\DiskPeripheral", ROOT_NAME, AdapterCount);
587 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
588 Name,
589 &QueryTable[2],
590 NULL,
591 NULL);
592 if (NT_SUCCESS(Status))
593 {
594 QueryTable[0].Name = L"Identifier";
595 QueryTable[0].QueryRoutine = DiskIdentifierQueryRoutine;
596 QueryTable[1].Name = L"Configuration Data";
597 QueryTable[1].QueryRoutine = DiskConfigurationDataQueryRoutine;
598
599 DiskCount = 0;
600 while (1)
601 {
602 BiosDiskEntry = (BIOSDISKENTRY*)RtlAllocateHeap(ProcessHeap, HEAP_ZERO_MEMORY, sizeof(BIOSDISKENTRY));
603 if (BiosDiskEntry == NULL)
604 {
605 break;
606 }
607
608 swprintf(Name, L"%s\\%lu\\DiskController\\0\\DiskPeripheral\\%lu", ROOT_NAME, AdapterCount, DiskCount);
609 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
610 Name,
611 QueryTable,
612 (PVOID)BiosDiskEntry,
613 NULL);
614 if (!NT_SUCCESS(Status))
615 {
616 RtlFreeHeap(ProcessHeap, 0, BiosDiskEntry);
617 break;
618 }
619
620 BiosDiskEntry->DiskNumber = DiskCount;
621 BiosDiskEntry->Recognized = FALSE;
622
623 if (DiskCount < Int13Drives[0].NumberDrives)
624 {
625 BiosDiskEntry->Int13DiskData = Int13Drives[DiskCount];
626 }
627 else
628 {
629 DPRINT1("Didn't find int13 drive datas for disk %u\n", DiskCount);
630 }
631
632 InsertTailList(&PartList->BiosDiskListHead, &BiosDiskEntry->ListEntry);
633
634 DPRINT("DiskNumber: %lu\n", BiosDiskEntry->DiskNumber);
635 DPRINT("Signature: %08lx\n", BiosDiskEntry->Signature);
636 DPRINT("Checksum: %08lx\n", BiosDiskEntry->Checksum);
637 DPRINT("BytesPerSector: %lu\n", BiosDiskEntry->DiskGeometry.BytesPerSector);
638 DPRINT("NumberOfCylinders: %lu\n", BiosDiskEntry->DiskGeometry.NumberOfCylinders);
639 DPRINT("NumberOfHeads: %lu\n", BiosDiskEntry->DiskGeometry.NumberOfHeads);
640 DPRINT("DriveSelect: %02x\n", BiosDiskEntry->Int13DiskData.DriveSelect);
641 DPRINT("MaxCylinders: %lu\n", BiosDiskEntry->Int13DiskData.MaxCylinders);
642 DPRINT("SectorsPerTrack: %d\n", BiosDiskEntry->Int13DiskData.SectorsPerTrack);
643 DPRINT("MaxHeads: %d\n", BiosDiskEntry->Int13DiskData.MaxHeads);
644 DPRINT("NumberDrives: %d\n", BiosDiskEntry->Int13DiskData.NumberDrives);
645
646 DiskCount++;
647 }
648 }
649
650 RtlFreeHeap(ProcessHeap, 0, Int13Drives);
651 return;
652 }
653 }
654
655 AdapterCount++;
656 }
657
658 RtlFreeHeap(ProcessHeap, 0, Int13Drives);
659 }
660
661
662 static
663 VOID
664 AddPartitionToDisk(
665 ULONG DiskNumber,
666 PDISKENTRY DiskEntry,
667 ULONG PartitionIndex,
668 BOOLEAN LogicalPartition)
669 {
670 PPARTITION_INFORMATION PartitionInfo;
671 PPARTENTRY PartEntry;
672
673 PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[PartitionIndex];
674 if (PartitionInfo->PartitionType == 0 ||
675 (LogicalPartition == TRUE && IsContainerPartition(PartitionInfo->PartitionType)))
676 return;
677
678 PartEntry = RtlAllocateHeap(ProcessHeap,
679 HEAP_ZERO_MEMORY,
680 sizeof(PARTENTRY));
681 if (PartEntry == NULL)
682 {
683 return;
684 }
685
686 PartEntry->DiskEntry = DiskEntry;
687
688 PartEntry->StartSector.QuadPart = (ULONGLONG)PartitionInfo->StartingOffset.QuadPart / DiskEntry->BytesPerSector;
689 PartEntry->SectorCount.QuadPart = (ULONGLONG)PartitionInfo->PartitionLength.QuadPart / DiskEntry->BytesPerSector;
690
691 PartEntry->BootIndicator = PartitionInfo->BootIndicator;
692 PartEntry->PartitionType = PartitionInfo->PartitionType;
693 PartEntry->HiddenSectors = PartitionInfo->HiddenSectors;
694
695 PartEntry->LogicalPartition = LogicalPartition;
696 PartEntry->IsPartitioned = TRUE;
697 PartEntry->PartitionNumber = PartitionInfo->PartitionNumber;
698 PartEntry->PartitionIndex = PartitionIndex;
699
700 if (IsContainerPartition(PartEntry->PartitionType))
701 {
702 PartEntry->FormatState = Unformatted;
703
704 if (LogicalPartition == FALSE && DiskEntry->ExtendedPartition == NULL)
705 DiskEntry->ExtendedPartition = PartEntry;
706 }
707 else if ((PartEntry->PartitionType == PARTITION_FAT_12) ||
708 (PartEntry->PartitionType == PARTITION_FAT_16) ||
709 (PartEntry->PartitionType == PARTITION_HUGE) ||
710 (PartEntry->PartitionType == PARTITION_XINT13) ||
711 (PartEntry->PartitionType == PARTITION_FAT32) ||
712 (PartEntry->PartitionType == PARTITION_FAT32_XINT13))
713 {
714 #if 0
715 if (CheckFatFormat())
716 {
717 PartEntry->FormatState = Preformatted;
718 }
719 else
720 {
721 PartEntry->FormatState = Unformatted;
722 }
723 #endif
724 PartEntry->FormatState = Preformatted;
725 }
726 else if (PartEntry->PartitionType == PARTITION_EXT2)
727 {
728 #if 0
729 if (CheckExt2Format())
730 {
731 PartEntry->FormatState = Preformatted;
732 }
733 else
734 {
735 PartEntry->FormatState = Unformatted;
736 }
737 #endif
738 PartEntry->FormatState = Preformatted;
739 }
740 else if (PartEntry->PartitionType == PARTITION_IFS)
741 {
742 #if 0
743 if (CheckNtfsFormat())
744 {
745 PartEntry->FormatState = Preformatted;
746 }
747 else if (CheckHpfsFormat())
748 {
749 PartEntry->FormatState = Preformatted;
750 }
751 else
752 {
753 PartEntry->FormatState = Unformatted;
754 }
755 #endif
756 PartEntry->FormatState = Preformatted;
757 }
758 else
759 {
760 PartEntry->FormatState = UnknownFormat;
761 }
762
763 if (LogicalPartition)
764 InsertTailList(&DiskEntry->LogicalPartListHead,
765 &PartEntry->ListEntry);
766 else
767 InsertTailList(&DiskEntry->PrimaryPartListHead,
768 &PartEntry->ListEntry);
769 }
770
771
772 static
773 VOID
774 ScanForUnpartitionedDiskSpace(
775 PDISKENTRY DiskEntry)
776 {
777 ULONGLONG LastStartSector;
778 ULONGLONG LastSectorCount;
779 ULONGLONG LastUnusedSectorCount;
780 PPARTENTRY PartEntry;
781 PPARTENTRY NewPartEntry;
782 PLIST_ENTRY Entry;
783
784 DPRINT("ScanForUnpartitionedDiskSpace()\n");
785
786 if (IsListEmpty(&DiskEntry->PrimaryPartListHead))
787 {
788 DPRINT1("No primary partition!\n");
789
790 /* Create a partition table that represents the empty disk */
791 NewPartEntry = RtlAllocateHeap(ProcessHeap,
792 HEAP_ZERO_MEMORY,
793 sizeof(PARTENTRY));
794 if (NewPartEntry == NULL)
795 return;
796
797 NewPartEntry->DiskEntry = DiskEntry;
798
799 NewPartEntry->IsPartitioned = FALSE;
800 NewPartEntry->StartSector.QuadPart = (ULONGLONG)DiskEntry->SectorAlignment;
801 NewPartEntry->SectorCount.QuadPart = AlignDown(DiskEntry->SectorCount.QuadPart, DiskEntry->SectorAlignment) -
802 NewPartEntry->StartSector.QuadPart;
803
804 DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
805 DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
806 DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
807
808 NewPartEntry->FormatState = Unformatted;
809
810 InsertTailList(&DiskEntry->PrimaryPartListHead,
811 &NewPartEntry->ListEntry);
812
813 return;
814 }
815
816 /* Start partition at head 1, cylinder 0 */
817 LastStartSector = DiskEntry->SectorAlignment;
818 LastSectorCount = 0ULL;
819 LastUnusedSectorCount = 0ULL;
820
821 Entry = DiskEntry->PrimaryPartListHead.Flink;
822 while (Entry != &DiskEntry->PrimaryPartListHead)
823 {
824 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
825
826 if (PartEntry->PartitionType != PARTITION_ENTRY_UNUSED ||
827 PartEntry->SectorCount.QuadPart != 0ULL)
828 {
829 LastUnusedSectorCount =
830 PartEntry->StartSector.QuadPart - (LastStartSector + LastSectorCount);
831
832 if (PartEntry->StartSector.QuadPart > (LastStartSector + LastSectorCount) &&
833 LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment)
834 {
835 DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount);
836
837 NewPartEntry = RtlAllocateHeap(ProcessHeap,
838 HEAP_ZERO_MEMORY,
839 sizeof(PARTENTRY));
840 if (NewPartEntry == NULL)
841 return;
842
843 NewPartEntry->DiskEntry = DiskEntry;
844
845 NewPartEntry->IsPartitioned = FALSE;
846 NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount;
847 NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + LastUnusedSectorCount, DiskEntry->SectorAlignment) -
848 NewPartEntry->StartSector.QuadPart;
849
850 DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
851 DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
852 DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
853
854 NewPartEntry->FormatState = Unformatted;
855
856 /* Insert the table into the list */
857 InsertTailList(&PartEntry->ListEntry,
858 &NewPartEntry->ListEntry);
859 }
860
861 LastStartSector = PartEntry->StartSector.QuadPart;
862 LastSectorCount = PartEntry->SectorCount.QuadPart;
863 }
864
865 Entry = Entry->Flink;
866 }
867
868 /* Check for trailing unpartitioned disk space */
869 if ((LastStartSector + LastSectorCount) < DiskEntry->SectorCount.QuadPart)
870 {
871 LastUnusedSectorCount = AlignDown(DiskEntry->SectorCount.QuadPart - (LastStartSector + LastSectorCount), DiskEntry->SectorAlignment);
872
873 if (LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment)
874 {
875 DPRINT("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount);
876
877 NewPartEntry = RtlAllocateHeap(ProcessHeap,
878 HEAP_ZERO_MEMORY,
879 sizeof(PARTENTRY));
880 if (NewPartEntry == NULL)
881 return;
882
883 NewPartEntry->DiskEntry = DiskEntry;
884
885 NewPartEntry->IsPartitioned = FALSE;
886 NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount;
887 NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + LastUnusedSectorCount, DiskEntry->SectorAlignment) -
888 NewPartEntry->StartSector.QuadPart;
889
890 DPRINT("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
891 DPRINT("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
892 DPRINT("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
893
894 NewPartEntry->FormatState = Unformatted;
895
896 /* Append the table to the list */
897 InsertTailList(&DiskEntry->PrimaryPartListHead,
898 &NewPartEntry->ListEntry);
899 }
900 }
901
902 if (DiskEntry->ExtendedPartition != NULL)
903 {
904 if (IsListEmpty(&DiskEntry->LogicalPartListHead))
905 {
906 DPRINT1("No logical partition!\n");
907
908 /* Create a partition table entry that represents the empty extended partition */
909 NewPartEntry = RtlAllocateHeap(ProcessHeap,
910 HEAP_ZERO_MEMORY,
911 sizeof(PARTENTRY));
912 if (NewPartEntry == NULL)
913 return;
914
915 NewPartEntry->DiskEntry = DiskEntry;
916 NewPartEntry->LogicalPartition = TRUE;
917
918 NewPartEntry->IsPartitioned = FALSE;
919 NewPartEntry->StartSector.QuadPart = DiskEntry->ExtendedPartition->StartSector.QuadPart + (ULONGLONG)DiskEntry->SectorAlignment;
920 NewPartEntry->SectorCount.QuadPart = DiskEntry->ExtendedPartition->SectorCount.QuadPart - (ULONGLONG)DiskEntry->SectorAlignment;
921
922 DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
923 DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
924 DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
925
926 NewPartEntry->FormatState = Unformatted;
927
928 InsertTailList(&DiskEntry->LogicalPartListHead,
929 &NewPartEntry->ListEntry);
930
931 return;
932 }
933
934 /* Start partition at head 1, cylinder 0 */
935 LastStartSector = DiskEntry->ExtendedPartition->StartSector.QuadPart + (ULONGLONG)DiskEntry->SectorAlignment;
936 LastSectorCount = 0ULL;
937 LastUnusedSectorCount = 0ULL;
938
939 Entry = DiskEntry->LogicalPartListHead.Flink;
940 while (Entry != &DiskEntry->LogicalPartListHead)
941 {
942 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
943
944 if (PartEntry->PartitionType != PARTITION_ENTRY_UNUSED ||
945 PartEntry->SectorCount.QuadPart != 0ULL)
946 {
947 LastUnusedSectorCount =
948 PartEntry->StartSector.QuadPart - (ULONGLONG)DiskEntry->SectorAlignment - (LastStartSector + LastSectorCount);
949
950 if ((PartEntry->StartSector.QuadPart - (ULONGLONG)DiskEntry->SectorAlignment) > (LastStartSector + LastSectorCount) &&
951 LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment)
952 {
953 DPRINT("Unpartitioned disk space %I64u sectors\n", LastUnusedSectorCount);
954
955 NewPartEntry = RtlAllocateHeap(ProcessHeap,
956 HEAP_ZERO_MEMORY,
957 sizeof(PARTENTRY));
958 if (NewPartEntry == NULL)
959 return;
960
961 NewPartEntry->DiskEntry = DiskEntry;
962 NewPartEntry->LogicalPartition = TRUE;
963
964 NewPartEntry->IsPartitioned = FALSE;
965 NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount;
966 NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + LastUnusedSectorCount, DiskEntry->SectorAlignment) -
967 NewPartEntry->StartSector.QuadPart;
968
969 DPRINT("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
970 DPRINT("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
971 DPRINT("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
972
973 NewPartEntry->FormatState = Unformatted;
974
975 /* Insert the table into the list */
976 InsertTailList(&PartEntry->ListEntry,
977 &NewPartEntry->ListEntry);
978 }
979
980 LastStartSector = PartEntry->StartSector.QuadPart;
981 LastSectorCount = PartEntry->SectorCount.QuadPart;
982 }
983
984 Entry = Entry->Flink;
985 }
986
987 /* Check for trailing unpartitioned disk space */
988 if ((LastStartSector + LastSectorCount) < DiskEntry->ExtendedPartition->StartSector.QuadPart + DiskEntry->ExtendedPartition->SectorCount.QuadPart)
989 {
990 LastUnusedSectorCount = AlignDown(DiskEntry->ExtendedPartition->StartSector.QuadPart + DiskEntry->ExtendedPartition->SectorCount.QuadPart - (LastStartSector + LastSectorCount), DiskEntry->SectorAlignment);
991
992 if (LastUnusedSectorCount >= (ULONGLONG)DiskEntry->SectorAlignment)
993 {
994 DPRINT("Unpartitioned disk space: %I64u sectors\n", LastUnusedSectorCount);
995
996 NewPartEntry = RtlAllocateHeap(ProcessHeap,
997 HEAP_ZERO_MEMORY,
998 sizeof(PARTENTRY));
999 if (NewPartEntry == NULL)
1000 return;
1001
1002 NewPartEntry->DiskEntry = DiskEntry;
1003 NewPartEntry->LogicalPartition = TRUE;
1004
1005 NewPartEntry->IsPartitioned = FALSE;
1006 NewPartEntry->StartSector.QuadPart = LastStartSector + LastSectorCount;
1007 NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + LastUnusedSectorCount, DiskEntry->SectorAlignment) -
1008 NewPartEntry->StartSector.QuadPart;
1009
1010 DPRINT("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
1011 DPRINT("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
1012 DPRINT("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
1013
1014 NewPartEntry->FormatState = Unformatted;
1015
1016 /* Append the table to the list */
1017 InsertTailList(&DiskEntry->LogicalPartListHead,
1018 &NewPartEntry->ListEntry);
1019 }
1020 }
1021 }
1022
1023 DPRINT("ScanForUnpartitionedDiskSpace() done\n");
1024 }
1025
1026
1027 static
1028 VOID
1029 SetDiskSignature(
1030 IN PPARTLIST List,
1031 IN PDISKENTRY DiskEntry)
1032 {
1033 LARGE_INTEGER SystemTime;
1034 TIME_FIELDS TimeFields;
1035 PLIST_ENTRY Entry2;
1036 PDISKENTRY DiskEntry2;
1037 PUCHAR Buffer;
1038
1039 Buffer = (PUCHAR)&DiskEntry->LayoutBuffer->Signature;
1040
1041 while (1)
1042 {
1043 NtQuerySystemTime(&SystemTime);
1044 RtlTimeToTimeFields(&SystemTime, &TimeFields);
1045
1046 Buffer[0] = (UCHAR)(TimeFields.Year & 0xFF) + (UCHAR)(TimeFields.Hour & 0xFF);
1047 Buffer[1] = (UCHAR)(TimeFields.Year >> 8) + (UCHAR)(TimeFields.Minute & 0xFF);
1048 Buffer[2] = (UCHAR)(TimeFields.Month & 0xFF) + (UCHAR)(TimeFields.Second & 0xFF);
1049 Buffer[3] = (UCHAR)(TimeFields.Day & 0xFF) + (UCHAR)(TimeFields.Milliseconds & 0xFF);
1050
1051 if (DiskEntry->LayoutBuffer->Signature == 0)
1052 {
1053 continue;
1054 }
1055
1056 /* check if the signature already exist */
1057 /* FIXME:
1058 * Check also signatures from disks, which are
1059 * not visible (bootable) by the bios.
1060 */
1061 Entry2 = List->DiskListHead.Flink;
1062 while (Entry2 != &List->DiskListHead)
1063 {
1064 DiskEntry2 = CONTAINING_RECORD(Entry2, DISKENTRY, ListEntry);
1065
1066 if (DiskEntry != DiskEntry2 &&
1067 DiskEntry->LayoutBuffer->Signature == DiskEntry2->LayoutBuffer->Signature)
1068 break;
1069
1070 Entry2 = Entry2->Flink;
1071 }
1072
1073 if (Entry2 == &List->DiskListHead)
1074 break;
1075 }
1076 }
1077
1078
1079 static
1080 VOID
1081 UpdateDiskSignatures(
1082 PPARTLIST List)
1083 {
1084 PLIST_ENTRY Entry;
1085 PDISKENTRY DiskEntry;
1086
1087 /* Print partition lines*/
1088 Entry = List->DiskListHead.Flink;
1089 while (Entry != &List->DiskListHead)
1090 {
1091 DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
1092
1093 if (DiskEntry->LayoutBuffer &&
1094 DiskEntry->LayoutBuffer->Signature == 0)
1095 {
1096 SetDiskSignature(List, DiskEntry);
1097 DiskEntry->LayoutBuffer->PartitionEntry[0].RewritePartition = TRUE;
1098 }
1099
1100 Entry = Entry->Flink;
1101 }
1102 }
1103
1104
1105 static
1106 VOID
1107 AddDiskToList(
1108 HANDLE FileHandle,
1109 ULONG DiskNumber,
1110 PPARTLIST List)
1111 {
1112 DISK_GEOMETRY DiskGeometry;
1113 SCSI_ADDRESS ScsiAddress;
1114 PDISKENTRY DiskEntry;
1115 IO_STATUS_BLOCK Iosb;
1116 NTSTATUS Status;
1117 PPARTITION_SECTOR Mbr;
1118 PULONG Buffer;
1119 LARGE_INTEGER FileOffset;
1120 WCHAR Identifier[20];
1121 ULONG Checksum;
1122 ULONG Signature;
1123 ULONG i;
1124 PLIST_ENTRY ListEntry;
1125 PBIOSDISKENTRY BiosDiskEntry;
1126 ULONG LayoutBufferSize;
1127 PDRIVE_LAYOUT_INFORMATION NewLayoutBuffer;
1128
1129 Status = NtDeviceIoControlFile(FileHandle,
1130 NULL,
1131 NULL,
1132 NULL,
1133 &Iosb,
1134 IOCTL_DISK_GET_DRIVE_GEOMETRY,
1135 NULL,
1136 0,
1137 &DiskGeometry,
1138 sizeof(DISK_GEOMETRY));
1139 if (!NT_SUCCESS(Status))
1140 {
1141 return;
1142 }
1143
1144 if (DiskGeometry.MediaType != FixedMedia &&
1145 DiskGeometry.MediaType != RemovableMedia)
1146 {
1147 return;
1148 }
1149
1150 Status = NtDeviceIoControlFile(FileHandle,
1151 NULL,
1152 NULL,
1153 NULL,
1154 &Iosb,
1155 IOCTL_SCSI_GET_ADDRESS,
1156 NULL,
1157 0,
1158 &ScsiAddress,
1159 sizeof(SCSI_ADDRESS));
1160 if (!NT_SUCCESS(Status))
1161 {
1162 return;
1163 }
1164
1165 Mbr = (PARTITION_SECTOR*)RtlAllocateHeap(ProcessHeap,
1166 0,
1167 DiskGeometry.BytesPerSector);
1168 if (Mbr == NULL)
1169 {
1170 return;
1171 }
1172
1173 FileOffset.QuadPart = 0;
1174 Status = NtReadFile(FileHandle,
1175 NULL,
1176 NULL,
1177 NULL,
1178 &Iosb,
1179 (PVOID)Mbr,
1180 DiskGeometry.BytesPerSector,
1181 &FileOffset,
1182 NULL);
1183 if (!NT_SUCCESS(Status))
1184 {
1185 RtlFreeHeap(ProcessHeap, 0, Mbr);
1186 DPRINT1("NtReadFile failed, status=%x\n", Status);
1187 return;
1188 }
1189 Signature = Mbr->Signature;
1190
1191 /* Calculate the MBR checksum */
1192 Checksum = 0;
1193 Buffer = (PULONG)Mbr;
1194 for (i = 0; i < 128; i++)
1195 {
1196 Checksum += Buffer[i];
1197 }
1198 Checksum = ~Checksum + 1;
1199
1200 swprintf(Identifier, L"%08x-%08x-A", Checksum, Signature);
1201 DPRINT("Identifier: %S\n", Identifier);
1202
1203 DiskEntry = RtlAllocateHeap(ProcessHeap,
1204 HEAP_ZERO_MEMORY,
1205 sizeof(DISKENTRY));
1206 if (DiskEntry == NULL)
1207 {
1208 return;
1209 }
1210
1211 // DiskEntry->Checksum = Checksum;
1212 // DiskEntry->Signature = Signature;
1213 DiskEntry->BiosFound = FALSE;
1214
1215 /* Check if this disk has a valid MBR */
1216 if (Mbr->BootCode[0] == 0 && Mbr->BootCode[1] == 0)
1217 DiskEntry->NoMbr = TRUE;
1218 else
1219 DiskEntry->NoMbr = FALSE;
1220
1221 /* Free Mbr sector buffer */
1222 RtlFreeHeap(ProcessHeap, 0, Mbr);
1223
1224 ListEntry = List->BiosDiskListHead.Flink;
1225 while (ListEntry != &List->BiosDiskListHead)
1226 {
1227 BiosDiskEntry = CONTAINING_RECORD(ListEntry, BIOSDISKENTRY, ListEntry);
1228 /* FIXME:
1229 * Compare the size from bios and the reported size from driver.
1230 * If we have more than one disk with a zero or with the same signatur
1231 * we must create new signatures and reboot. After the reboot,
1232 * it is possible to identify the disks.
1233 */
1234 if (BiosDiskEntry->Signature == Signature &&
1235 BiosDiskEntry->Checksum == Checksum &&
1236 !BiosDiskEntry->Recognized)
1237 {
1238 if (!DiskEntry->BiosFound)
1239 {
1240 DiskEntry->BiosDiskNumber = BiosDiskEntry->DiskNumber;
1241 DiskEntry->BiosFound = TRUE;
1242 BiosDiskEntry->Recognized = TRUE;
1243 }
1244 else
1245 {
1246 }
1247 }
1248 ListEntry = ListEntry->Flink;
1249 }
1250
1251 if (!DiskEntry->BiosFound)
1252 {
1253 #if 0
1254 RtlFreeHeap(ProcessHeap, 0, DiskEntry);
1255 return;
1256 #else
1257 DPRINT1("WARNING: Setup could not find a matching BIOS disk entry. Disk %d is not be bootable by the BIOS!\n", DiskNumber);
1258 #endif
1259 }
1260
1261 InitializeListHead(&DiskEntry->PrimaryPartListHead);
1262 InitializeListHead(&DiskEntry->LogicalPartListHead);
1263
1264 DiskEntry->Cylinders = DiskGeometry.Cylinders.QuadPart;
1265 DiskEntry->TracksPerCylinder = DiskGeometry.TracksPerCylinder;
1266 DiskEntry->SectorsPerTrack = DiskGeometry.SectorsPerTrack;
1267 DiskEntry->BytesPerSector = DiskGeometry.BytesPerSector;
1268
1269 DPRINT("Cylinders %I64u\n", DiskEntry->Cylinders);
1270 DPRINT("TracksPerCylinder %I64u\n", DiskEntry->TracksPerCylinder);
1271 DPRINT("SectorsPerTrack %I64u\n", DiskEntry->SectorsPerTrack);
1272 DPRINT("BytesPerSector %I64u\n", DiskEntry->BytesPerSector);
1273
1274 DiskEntry->SectorCount.QuadPart = DiskGeometry.Cylinders.QuadPart *
1275 (ULONGLONG)DiskGeometry.TracksPerCylinder *
1276 (ULONGLONG)DiskGeometry.SectorsPerTrack;
1277
1278 DiskEntry->SectorAlignment = DiskGeometry.SectorsPerTrack;
1279 DiskEntry->CylinderAlignment = DiskGeometry.TracksPerCylinder *
1280 DiskGeometry.SectorsPerTrack;
1281
1282 DPRINT("SectorCount %I64u\n", DiskEntry->SectorCount);
1283 DPRINT("SectorAlignment %lu\n", DiskEntry->SectorAlignment);
1284
1285 DiskEntry->DiskNumber = DiskNumber;
1286 DiskEntry->Port = ScsiAddress.PortNumber;
1287 DiskEntry->Bus = ScsiAddress.PathId;
1288 DiskEntry->Id = ScsiAddress.TargetId;
1289
1290 GetDriverName(DiskEntry);
1291
1292 InsertAscendingList(&List->DiskListHead, DiskEntry, DISKENTRY, ListEntry, DiskNumber);
1293
1294 /* Allocate a layout buffer with 4 partition entries first */
1295 LayoutBufferSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
1296 ((4 - ANYSIZE_ARRAY) * sizeof(PARTITION_INFORMATION));
1297 DiskEntry->LayoutBuffer = RtlAllocateHeap(ProcessHeap,
1298 HEAP_ZERO_MEMORY,
1299 LayoutBufferSize);
1300 if (DiskEntry->LayoutBuffer == NULL)
1301 {
1302 DPRINT1("Failed to allocate the disk layout buffer!\n");
1303 return;
1304 }
1305
1306 for (;;)
1307 {
1308 DPRINT1("Buffer size: %lu\n", LayoutBufferSize);
1309 Status = NtDeviceIoControlFile(FileHandle,
1310 NULL,
1311 NULL,
1312 NULL,
1313 &Iosb,
1314 IOCTL_DISK_GET_DRIVE_LAYOUT,
1315 NULL,
1316 0,
1317 DiskEntry->LayoutBuffer,
1318 LayoutBufferSize);
1319 if (NT_SUCCESS(Status))
1320 break;
1321
1322 if (Status != STATUS_BUFFER_TOO_SMALL)
1323 {
1324 DPRINT1("NtDeviceIoControlFile() failed (Status: 0x%08lx)\n", Status);
1325 return;
1326 }
1327
1328 LayoutBufferSize += 4 * sizeof(PARTITION_INFORMATION);
1329 NewLayoutBuffer = RtlReAllocateHeap(ProcessHeap,
1330 HEAP_ZERO_MEMORY,
1331 DiskEntry->LayoutBuffer,
1332 LayoutBufferSize);
1333 if (NewLayoutBuffer == NULL)
1334 {
1335 DPRINT1("Failed to reallocate the disk layout buffer!\n");
1336 return;
1337 }
1338
1339 DiskEntry->LayoutBuffer = NewLayoutBuffer;
1340 }
1341
1342 DPRINT1("PartitionCount: %lu\n", DiskEntry->LayoutBuffer->PartitionCount);
1343
1344 #ifdef DUMP_PARTITION_TABLE
1345 DumpPartitionTable(DiskEntry);
1346 #endif
1347
1348 if (DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart != 0 &&
1349 DiskEntry->LayoutBuffer->PartitionEntry[0].PartitionLength.QuadPart != 0 &&
1350 DiskEntry->LayoutBuffer->PartitionEntry[0].PartitionType != 0)
1351 {
1352 if ((DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart / DiskEntry->BytesPerSector) % DiskEntry->SectorsPerTrack == 0)
1353 {
1354 DPRINT("Use %lu Sector alignment!\n", DiskEntry->SectorsPerTrack);
1355 }
1356 else if (DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart % (1024 * 1024) == 0)
1357 {
1358 DPRINT1("Use megabyte (%lu Sectors) alignment!\n", (1024 * 1024) / DiskEntry->BytesPerSector);
1359 }
1360 else
1361 {
1362 DPRINT1("No matching aligment found! Partition 1 starts at %I64u\n", DiskEntry->LayoutBuffer->PartitionEntry[0].StartingOffset.QuadPart);
1363 }
1364 }
1365 else
1366 {
1367 DPRINT1("No valid partition table found! Use megabyte (%lu Sectors) alignment!\n", (1024 * 1024) / DiskEntry->BytesPerSector);
1368 }
1369
1370
1371 if (DiskEntry->LayoutBuffer->PartitionCount == 0)
1372 {
1373 DiskEntry->NewDisk = TRUE;
1374 DiskEntry->LayoutBuffer->PartitionCount = 4;
1375
1376 for (i = 0; i < 4; i++)
1377 DiskEntry->LayoutBuffer->PartitionEntry[i].RewritePartition = TRUE;
1378 }
1379 else
1380 {
1381 for (i = 0; i < 4; i++)
1382 {
1383 AddPartitionToDisk(DiskNumber, DiskEntry, i, FALSE);
1384 }
1385
1386 for (i = 4; i < DiskEntry->LayoutBuffer->PartitionCount; i += 4)
1387 {
1388 AddPartitionToDisk(DiskNumber, DiskEntry, i, TRUE);
1389 }
1390 }
1391
1392 ScanForUnpartitionedDiskSpace(DiskEntry);
1393 }
1394
1395
1396 PPARTLIST
1397 CreatePartitionList(
1398 SHORT Left,
1399 SHORT Top,
1400 SHORT Right,
1401 SHORT Bottom)
1402 {
1403 PPARTLIST List;
1404 OBJECT_ATTRIBUTES ObjectAttributes;
1405 SYSTEM_DEVICE_INFORMATION Sdi;
1406 IO_STATUS_BLOCK Iosb;
1407 ULONG ReturnSize;
1408 NTSTATUS Status;
1409 ULONG DiskNumber;
1410 WCHAR Buffer[MAX_PATH];
1411 UNICODE_STRING Name;
1412 HANDLE FileHandle;
1413
1414 List = (PPARTLIST)RtlAllocateHeap(ProcessHeap,
1415 0,
1416 sizeof (PARTLIST));
1417 if (List == NULL)
1418 return NULL;
1419
1420 List->Left = Left;
1421 List->Top = Top;
1422 List->Right = Right;
1423 List->Bottom = Bottom;
1424
1425 List->Line = 0;
1426 List->Offset = 0;
1427
1428 List->CurrentDisk = NULL;
1429 List->CurrentPartition = NULL;
1430
1431 List->SystemDisk = NULL;
1432 List->SystemPartition = NULL;
1433
1434 List->TempDisk = NULL;
1435 List->TempPartition = NULL;
1436 List->FormatState = Start;
1437
1438 InitializeListHead(&List->DiskListHead);
1439 InitializeListHead(&List->BiosDiskListHead);
1440
1441 EnumerateBiosDiskEntries(List);
1442
1443 Status = NtQuerySystemInformation(SystemDeviceInformation,
1444 &Sdi,
1445 sizeof(SYSTEM_DEVICE_INFORMATION),
1446 &ReturnSize);
1447 if (!NT_SUCCESS(Status))
1448 {
1449 RtlFreeHeap(ProcessHeap, 0, List);
1450 return NULL;
1451 }
1452
1453 for (DiskNumber = 0; DiskNumber < Sdi.NumberOfDisks; DiskNumber++)
1454 {
1455 swprintf(Buffer,
1456 L"\\Device\\Harddisk%d\\Partition0",
1457 DiskNumber);
1458 RtlInitUnicodeString(&Name,
1459 Buffer);
1460
1461 InitializeObjectAttributes(&ObjectAttributes,
1462 &Name,
1463 0,
1464 NULL,
1465 NULL);
1466
1467 Status = NtOpenFile(&FileHandle,
1468 FILE_READ_DATA | FILE_READ_ATTRIBUTES | SYNCHRONIZE,
1469 &ObjectAttributes,
1470 &Iosb,
1471 FILE_SHARE_READ,
1472 FILE_SYNCHRONOUS_IO_NONALERT);
1473 if (NT_SUCCESS(Status))
1474 {
1475 AddDiskToList(FileHandle, DiskNumber, List);
1476
1477 NtClose(FileHandle);
1478 }
1479 }
1480
1481 UpdateDiskSignatures(List);
1482
1483 AssignDriveLetters(List);
1484
1485 /* Search for first usable disk and partition */
1486 if (IsListEmpty(&List->DiskListHead))
1487 {
1488 List->CurrentDisk = NULL;
1489 List->CurrentPartition = NULL;
1490 }
1491 else
1492 {
1493 List->CurrentDisk = CONTAINING_RECORD(List->DiskListHead.Flink,
1494 DISKENTRY,
1495 ListEntry);
1496
1497 if (IsListEmpty(&List->CurrentDisk->PrimaryPartListHead))
1498 {
1499 List->CurrentPartition = 0;
1500 }
1501 else
1502 {
1503 List->CurrentPartition = CONTAINING_RECORD(List->CurrentDisk->PrimaryPartListHead.Flink,
1504 PARTENTRY,
1505 ListEntry);
1506 }
1507 }
1508
1509 return List;
1510 }
1511
1512
1513 VOID
1514 DestroyPartitionList(
1515 PPARTLIST List)
1516 {
1517 PDISKENTRY DiskEntry;
1518 PBIOSDISKENTRY BiosDiskEntry;
1519 PPARTENTRY PartEntry;
1520 PLIST_ENTRY Entry;
1521
1522 /* Release disk and partition info */
1523 while (!IsListEmpty(&List->DiskListHead))
1524 {
1525 Entry = RemoveHeadList(&List->DiskListHead);
1526 DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
1527
1528 /* Release driver name */
1529 RtlFreeUnicodeString(&DiskEntry->DriverName);
1530
1531 /* Release primary partition list */
1532 while (!IsListEmpty(&DiskEntry->PrimaryPartListHead))
1533 {
1534 Entry = RemoveHeadList(&DiskEntry->PrimaryPartListHead);
1535 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
1536
1537 RtlFreeHeap(ProcessHeap, 0, PartEntry);
1538 }
1539
1540 /* Release logical partition list */
1541 while (!IsListEmpty(&DiskEntry->LogicalPartListHead))
1542 {
1543 Entry = RemoveHeadList(&DiskEntry->LogicalPartListHead);
1544 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
1545
1546 RtlFreeHeap(ProcessHeap, 0, PartEntry);
1547 }
1548
1549 /* Release layout buffer */
1550 if (DiskEntry->LayoutBuffer != NULL)
1551 RtlFreeHeap(ProcessHeap, 0, DiskEntry->LayoutBuffer);
1552
1553
1554 /* Release disk entry */
1555 RtlFreeHeap(ProcessHeap, 0, DiskEntry);
1556 }
1557
1558 /* Release the bios disk info */
1559 while (!IsListEmpty(&List->BiosDiskListHead))
1560 {
1561 Entry = RemoveHeadList(&List->BiosDiskListHead);
1562 BiosDiskEntry = CONTAINING_RECORD(Entry, BIOSDISKENTRY, ListEntry);
1563
1564 RtlFreeHeap(ProcessHeap, 0, BiosDiskEntry);
1565 }
1566
1567 /* Release list head */
1568 RtlFreeHeap(ProcessHeap, 0, List);
1569 }
1570
1571
1572 static
1573 VOID
1574 PrintEmptyLine(
1575 PPARTLIST List)
1576 {
1577 COORD coPos;
1578 DWORD Written;
1579 USHORT Width;
1580 USHORT Height;
1581
1582 Width = List->Right - List->Left - 1;
1583 Height = List->Bottom - List->Top - 2;
1584
1585 coPos.X = List->Left + 1;
1586 coPos.Y = List->Top + 1 + List->Line;
1587
1588 if (List->Line >= 0 && List->Line <= Height)
1589 {
1590 FillConsoleOutputAttribute(StdOutput,
1591 FOREGROUND_WHITE | BACKGROUND_BLUE,
1592 Width,
1593 coPos,
1594 &Written);
1595
1596 FillConsoleOutputCharacterA(StdOutput,
1597 ' ',
1598 Width,
1599 coPos,
1600 &Written);
1601 }
1602
1603 List->Line++;
1604 }
1605
1606
1607 static
1608 VOID
1609 PrintPartitionData(
1610 PPARTLIST List,
1611 PDISKENTRY DiskEntry,
1612 PPARTENTRY PartEntry)
1613 {
1614 CHAR LineBuffer[128];
1615 COORD coPos;
1616 DWORD Written;
1617 USHORT Width;
1618 USHORT Height;
1619 LARGE_INTEGER PartSize;
1620 PCHAR Unit;
1621 UCHAR Attribute;
1622 CHAR PartTypeString[32];
1623 PCHAR PartType;
1624 PartType = PartTypeString;
1625
1626 Width = List->Right - List->Left - 1;
1627 Height = List->Bottom - List->Top - 2;
1628
1629 coPos.X = List->Left + 1;
1630 coPos.Y = List->Top + 1 + List->Line;
1631
1632 if (PartEntry->IsPartitioned == FALSE)
1633 {
1634 PartSize.QuadPart = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
1635 #if 0
1636 if (PartSize.QuadPart >= 10737418240) /* 10 GB */
1637 {
1638 PartSize.QuadPart = RoundingDivide(PartSize.QuadPart, 1073741824);
1639 Unit = MUIGetString(STRING_GB);
1640 }
1641 else
1642 #endif
1643 if (PartSize.QuadPart >= 10485760) /* 10 MB */
1644 {
1645 PartSize.QuadPart = RoundingDivide(PartSize.QuadPart, 1048576);
1646 Unit = MUIGetString(STRING_MB);
1647 }
1648 else
1649 {
1650 PartSize.QuadPart = RoundingDivide(PartSize.QuadPart, 1024);
1651 Unit = MUIGetString(STRING_KB);
1652 }
1653
1654 sprintf(LineBuffer,
1655 MUIGetString(STRING_UNPSPACE),
1656 PartEntry->LogicalPartition ? " " : "",
1657 PartEntry->LogicalPartition ? "" : " ",
1658 PartSize.u.LowPart,
1659 Unit);
1660 }
1661 else
1662 {
1663 /* Determine partition type */
1664 PartTypeString[0] = '\0';
1665 if (PartEntry->New == TRUE)
1666 {
1667 PartType = MUIGetString(STRING_UNFORMATTED);
1668 }
1669 else if (PartEntry->IsPartitioned == TRUE)
1670 {
1671 GetPartTypeStringFromPartitionType(PartEntry->PartitionType,
1672 PartTypeString,
1673 30);
1674 PartType = PartTypeString;
1675 }
1676
1677 PartSize.QuadPart = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
1678 #if 0
1679 if (PartSize.QuadPart >= 10737418240) /* 10 GB */
1680 {
1681 PartSize.QuadPart = RoundingDivide(PartSize.QuadPart, 1073741824);
1682 Unit = MUIGetString(STRING_GB);
1683 }
1684 else
1685 #endif
1686 if (PartSize.QuadPart >= 10485760) /* 10 MB */
1687 {
1688 PartSize.QuadPart = RoundingDivide(PartSize.QuadPart, 1048576);
1689 Unit = MUIGetString(STRING_MB);
1690 }
1691 else
1692 {
1693 PartSize.QuadPart = RoundingDivide(PartSize.QuadPart, 1024);
1694 Unit = MUIGetString(STRING_KB);
1695 }
1696
1697 if (strcmp(PartType, MUIGetString(STRING_FORMATUNKNOWN)) == 0)
1698 {
1699 sprintf(LineBuffer,
1700 MUIGetString(STRING_HDDINFOUNK5),
1701 (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
1702 (PartEntry->DriveLetter == 0) ? '-' : ':',
1703 PartEntry->BootIndicator ? '*' : ' ',
1704 PartEntry->LogicalPartition ? " " : "",
1705 PartEntry->PartitionType,
1706 PartEntry->LogicalPartition ? "" : " ",
1707 PartSize.u.LowPart,
1708 Unit);
1709 }
1710 else
1711 {
1712 sprintf(LineBuffer,
1713 "%c%c %c %s%-24s%s %6lu %s",
1714 (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
1715 (PartEntry->DriveLetter == 0) ? '-' : ':',
1716 PartEntry->BootIndicator ? '*' : ' ',
1717 PartEntry->LogicalPartition ? " " : "",
1718 PartType,
1719 PartEntry->LogicalPartition ? "" : " ",
1720 PartSize.u.LowPart,
1721 Unit);
1722 }
1723 }
1724
1725 Attribute = (List->CurrentDisk == DiskEntry &&
1726 List->CurrentPartition == PartEntry) ?
1727 FOREGROUND_BLUE | BACKGROUND_WHITE :
1728 FOREGROUND_WHITE | BACKGROUND_BLUE;
1729
1730 if (List->Line >= 0 && List->Line <= Height)
1731 {
1732 FillConsoleOutputCharacterA(StdOutput,
1733 ' ',
1734 Width,
1735 coPos,
1736 &Written);
1737 }
1738 coPos.X += 4;
1739 Width -= 8;
1740 if (List->Line >= 0 && List->Line <= Height)
1741 {
1742 FillConsoleOutputAttribute(StdOutput,
1743 Attribute,
1744 Width,
1745 coPos,
1746 &Written);
1747 }
1748 coPos.X++;
1749 Width -= 2;
1750 if (List->Line >= 0 && List->Line <= Height)
1751 {
1752 WriteConsoleOutputCharacterA(StdOutput,
1753 LineBuffer,
1754 min(strlen(LineBuffer), Width),
1755 coPos,
1756 &Written);
1757 }
1758
1759 List->Line++;
1760 }
1761
1762
1763 static
1764 VOID
1765 PrintDiskData(
1766 PPARTLIST List,
1767 PDISKENTRY DiskEntry)
1768 {
1769 PPARTENTRY PrimaryPartEntry, LogicalPartEntry;
1770 PLIST_ENTRY PrimaryEntry, LogicalEntry;
1771 CHAR LineBuffer[128];
1772 COORD coPos;
1773 DWORD Written;
1774 USHORT Width;
1775 USHORT Height;
1776 ULARGE_INTEGER DiskSize;
1777 PCHAR Unit;
1778
1779 Width = List->Right - List->Left - 1;
1780 Height = List->Bottom - List->Top - 2;
1781
1782 coPos.X = List->Left + 1;
1783 coPos.Y = List->Top + 1 + List->Line;
1784
1785 DiskSize.QuadPart = DiskEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
1786 if (DiskSize.QuadPart >= 10737418240) /* 10 GB */
1787 {
1788 DiskSize.QuadPart = RoundingDivide(DiskSize.QuadPart, 1073741824);
1789 Unit = MUIGetString(STRING_GB);
1790 }
1791 else
1792 {
1793 DiskSize.QuadPart = RoundingDivide(DiskSize.QuadPart, 1048576);
1794 if (DiskSize.QuadPart == 0)
1795 DiskSize.QuadPart = 1;
1796 Unit = MUIGetString(STRING_MB);
1797 }
1798
1799 if (DiskEntry->DriverName.Length > 0)
1800 {
1801 sprintf(LineBuffer,
1802 MUIGetString(STRING_HDINFOPARTSELECT),
1803 DiskSize.u.LowPart,
1804 Unit,
1805 DiskEntry->DiskNumber,
1806 DiskEntry->Port,
1807 DiskEntry->Bus,
1808 DiskEntry->Id,
1809 DiskEntry->DriverName.Buffer);
1810 }
1811 else
1812 {
1813 sprintf(LineBuffer,
1814 MUIGetString(STRING_HDDINFOUNK6),
1815 DiskSize.u.LowPart,
1816 Unit,
1817 DiskEntry->DiskNumber,
1818 DiskEntry->Port,
1819 DiskEntry->Bus,
1820 DiskEntry->Id);
1821 }
1822
1823 if (List->Line >= 0 && List->Line <= Height)
1824 {
1825 FillConsoleOutputAttribute(StdOutput,
1826 FOREGROUND_WHITE | BACKGROUND_BLUE,
1827 Width,
1828 coPos,
1829 &Written);
1830
1831 FillConsoleOutputCharacterA(StdOutput,
1832 ' ',
1833 Width,
1834 coPos,
1835 &Written);
1836 }
1837
1838 coPos.X++;
1839 if (List->Line >= 0 && List->Line <= Height)
1840 {
1841 WriteConsoleOutputCharacterA(StdOutput,
1842 LineBuffer,
1843 min((USHORT)strlen(LineBuffer), Width - 2),
1844 coPos,
1845 &Written);
1846 }
1847
1848 List->Line++;
1849
1850 /* Print separator line */
1851 PrintEmptyLine(List);
1852
1853 /* Print partition lines */
1854 PrimaryEntry = DiskEntry->PrimaryPartListHead.Flink;
1855 while (PrimaryEntry != &DiskEntry->PrimaryPartListHead)
1856 {
1857 PrimaryPartEntry = CONTAINING_RECORD(PrimaryEntry, PARTENTRY, ListEntry);
1858
1859 PrintPartitionData(List,
1860 DiskEntry,
1861 PrimaryPartEntry);
1862
1863 if (IsContainerPartition(PrimaryPartEntry->PartitionType))
1864 {
1865 LogicalEntry = DiskEntry->LogicalPartListHead.Flink;
1866 while (LogicalEntry != &DiskEntry->LogicalPartListHead)
1867 {
1868 LogicalPartEntry = CONTAINING_RECORD(LogicalEntry, PARTENTRY, ListEntry);
1869
1870 PrintPartitionData(List,
1871 DiskEntry,
1872 LogicalPartEntry);
1873
1874 LogicalEntry = LogicalEntry->Flink;
1875 }
1876 }
1877
1878 PrimaryEntry = PrimaryEntry->Flink;
1879 }
1880
1881 /* Print separator line */
1882 PrintEmptyLine(List);
1883 }
1884
1885
1886 VOID
1887 DrawPartitionList(
1888 PPARTLIST List)
1889 {
1890 PLIST_ENTRY Entry, Entry2;
1891 PDISKENTRY DiskEntry;
1892 PPARTENTRY PartEntry = NULL;
1893 COORD coPos;
1894 DWORD Written;
1895 SHORT i;
1896 SHORT CurrentDiskLine;
1897 SHORT CurrentPartLine;
1898 SHORT LastLine;
1899 BOOL CurrentPartLineFound = FALSE;
1900 BOOL CurrentDiskLineFound = FALSE;
1901
1902 /* Calculate the line of the current disk and partition */
1903 CurrentDiskLine = 0;
1904 CurrentPartLine = 0;
1905 LastLine = 0;
1906
1907 Entry = List->DiskListHead.Flink;
1908 while (Entry != &List->DiskListHead)
1909 {
1910 DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
1911
1912 LastLine += 2;
1913 if (CurrentPartLineFound == FALSE)
1914 {
1915 CurrentPartLine += 2;
1916 }
1917
1918 Entry2 = DiskEntry->PrimaryPartListHead.Flink;
1919 while (Entry2 != &DiskEntry->PrimaryPartListHead)
1920 {
1921 PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
1922 if (PartEntry == List->CurrentPartition)
1923 {
1924 CurrentPartLineFound = TRUE;
1925 }
1926
1927 Entry2 = Entry2->Flink;
1928 if (CurrentPartLineFound == FALSE)
1929 {
1930 CurrentPartLine++;
1931 }
1932
1933 LastLine++;
1934 }
1935
1936 if (DiskEntry == List->CurrentDisk)
1937 {
1938 CurrentDiskLineFound = TRUE;
1939 }
1940
1941 Entry = Entry->Flink;
1942 if (Entry != &List->DiskListHead)
1943 {
1944 if (CurrentDiskLineFound == FALSE)
1945 {
1946 CurrentPartLine ++;
1947 CurrentDiskLine = CurrentPartLine;
1948 }
1949
1950 LastLine++;
1951 }
1952 else
1953 {
1954 LastLine--;
1955 }
1956 }
1957
1958 /* If it possible, make the disk name visible */
1959 if (CurrentPartLine < List->Offset)
1960 {
1961 List->Offset = CurrentPartLine;
1962 }
1963 else if (CurrentPartLine - List->Offset > List->Bottom - List->Top - 2)
1964 {
1965 List->Offset = CurrentPartLine - (List->Bottom - List->Top - 2);
1966 }
1967
1968 if (CurrentDiskLine < List->Offset && CurrentPartLine - CurrentDiskLine < List->Bottom - List->Top - 2)
1969 {
1970 List->Offset = CurrentDiskLine;
1971 }
1972
1973 /* draw upper left corner */
1974 coPos.X = List->Left;
1975 coPos.Y = List->Top;
1976 FillConsoleOutputCharacterA(StdOutput,
1977 0xDA, // '+',
1978 1,
1979 coPos,
1980 &Written);
1981
1982 /* draw upper edge */
1983 coPos.X = List->Left + 1;
1984 coPos.Y = List->Top;
1985 if (List->Offset == 0)
1986 {
1987 FillConsoleOutputCharacterA(StdOutput,
1988 0xC4, // '-',
1989 List->Right - List->Left - 1,
1990 coPos,
1991 &Written);
1992 }
1993 else
1994 {
1995 FillConsoleOutputCharacterA(StdOutput,
1996 0xC4, // '-',
1997 List->Right - List->Left - 5,
1998 coPos,
1999 &Written);
2000 coPos.X = List->Right - 5;
2001 WriteConsoleOutputCharacterA(StdOutput,
2002 "(\x18)", // "(up)"
2003 3,
2004 coPos,
2005 &Written);
2006 coPos.X = List->Right - 2;
2007 FillConsoleOutputCharacterA(StdOutput,
2008 0xC4, // '-',
2009 2,
2010 coPos,
2011 &Written);
2012 }
2013
2014 /* draw upper right corner */
2015 coPos.X = List->Right;
2016 coPos.Y = List->Top;
2017 FillConsoleOutputCharacterA(StdOutput,
2018 0xBF, // '+',
2019 1,
2020 coPos,
2021 &Written);
2022
2023 /* draw left and right edge */
2024 for (i = List->Top + 1; i < List->Bottom; i++)
2025 {
2026 coPos.X = List->Left;
2027 coPos.Y = i;
2028 FillConsoleOutputCharacterA(StdOutput,
2029 0xB3, // '|',
2030 1,
2031 coPos,
2032 &Written);
2033
2034 coPos.X = List->Right;
2035 FillConsoleOutputCharacterA(StdOutput,
2036 0xB3, //'|',
2037 1,
2038 coPos,
2039 &Written);
2040 }
2041
2042 /* draw lower left corner */
2043 coPos.X = List->Left;
2044 coPos.Y = List->Bottom;
2045 FillConsoleOutputCharacterA(StdOutput,
2046 0xC0, // '+',
2047 1,
2048 coPos,
2049 &Written);
2050
2051 /* draw lower edge */
2052 coPos.X = List->Left + 1;
2053 coPos.Y = List->Bottom;
2054 if (LastLine - List->Offset <= List->Bottom - List->Top - 2)
2055 {
2056 FillConsoleOutputCharacterA(StdOutput,
2057 0xC4, // '-',
2058 List->Right - List->Left - 1,
2059 coPos,
2060 &Written);
2061 }
2062 else
2063 {
2064 FillConsoleOutputCharacterA(StdOutput,
2065 0xC4, // '-',
2066 List->Right - List->Left - 5,
2067 coPos,
2068 &Written);
2069 coPos.X = List->Right - 5;
2070 WriteConsoleOutputCharacterA(StdOutput,
2071 "(\x19)", // "(down)"
2072 3,
2073 coPos,
2074 &Written);
2075 coPos.X = List->Right - 2;
2076 FillConsoleOutputCharacterA(StdOutput,
2077 0xC4, // '-',
2078 2,
2079 coPos,
2080 &Written);
2081 }
2082
2083 /* draw lower right corner */
2084 coPos.X = List->Right;
2085 coPos.Y = List->Bottom;
2086 FillConsoleOutputCharacterA(StdOutput,
2087 0xD9, // '+',
2088 1,
2089 coPos,
2090 &Written);
2091
2092 /* print list entries */
2093 List->Line = - List->Offset;
2094
2095 Entry = List->DiskListHead.Flink;
2096 while (Entry != &List->DiskListHead)
2097 {
2098 DiskEntry = CONTAINING_RECORD(Entry, DISKENTRY, ListEntry);
2099
2100 /* Print disk entry */
2101 PrintDiskData(List,
2102 DiskEntry);
2103
2104 Entry = Entry->Flink;
2105 }
2106 }
2107
2108
2109 DWORD
2110 SelectPartition(
2111 PPARTLIST List,
2112 ULONG DiskNumber,
2113 ULONG PartitionNumber)
2114 {
2115 PDISKENTRY DiskEntry;
2116 PPARTENTRY PartEntry;
2117 PLIST_ENTRY Entry1;
2118 PLIST_ENTRY Entry2;
2119
2120 /* Check for empty disks */
2121 if (IsListEmpty(&List->DiskListHead))
2122 return FALSE;
2123
2124 /* Check for first usable entry on next disk */
2125 Entry1 = List->CurrentDisk->ListEntry.Flink;
2126 while (Entry1 != &List->DiskListHead)
2127 {
2128 DiskEntry = CONTAINING_RECORD(Entry1, DISKENTRY, ListEntry);
2129
2130 if (DiskEntry->DiskNumber == DiskNumber)
2131 {
2132 Entry2 = DiskEntry->PrimaryPartListHead.Flink;
2133 while (Entry2 != &DiskEntry->PrimaryPartListHead)
2134 {
2135 PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
2136
2137 if (PartEntry->PartitionNumber == PartitionNumber)
2138 {
2139 List->CurrentDisk = DiskEntry;
2140 List->CurrentPartition = PartEntry;
2141 DrawPartitionList(List);
2142 return TRUE;
2143 }
2144
2145 Entry2 = Entry2->Flink;
2146 }
2147
2148 return FALSE;
2149 }
2150
2151 Entry1 = Entry1->Flink;
2152 }
2153
2154 return FALSE;
2155 }
2156
2157
2158 BOOL
2159 ScrollDownPartitionList(
2160 PPARTLIST List)
2161 {
2162 PLIST_ENTRY DiskListEntry;
2163 PLIST_ENTRY PartListEntry;
2164 PDISKENTRY DiskEntry;
2165 PPARTENTRY PartEntry;
2166
2167 /* Fail, if no disks are available */
2168 if (IsListEmpty(&List->DiskListHead))
2169 return FALSE;
2170
2171 /* Check for next usable entry on current disk */
2172 if (List->CurrentPartition != NULL)
2173 {
2174 if (List->CurrentPartition->LogicalPartition)
2175 {
2176 /* Logical partition */
2177
2178 PartListEntry = List->CurrentPartition->ListEntry.Flink;
2179 if (PartListEntry != &List->CurrentDisk->LogicalPartListHead)
2180 {
2181 /* Next logical partition */
2182 PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
2183
2184 List->CurrentPartition = PartEntry;
2185 return TRUE;
2186 }
2187 else
2188 {
2189 PartListEntry = List->CurrentDisk->ExtendedPartition->ListEntry.Flink;
2190 if (PartListEntry != &List->CurrentDisk->PrimaryPartListHead)
2191 {
2192 PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
2193
2194 List->CurrentPartition = PartEntry;
2195 return TRUE;
2196 }
2197 }
2198 }
2199 else
2200 {
2201 /* Primary or extended partition */
2202
2203 if (List->CurrentPartition->IsPartitioned == TRUE &&
2204 IsContainerPartition(List->CurrentPartition->PartitionType))
2205 {
2206 /* First logical partition */
2207 PartListEntry = List->CurrentDisk->LogicalPartListHead.Flink;
2208 if (PartListEntry != &List->CurrentDisk->LogicalPartListHead)
2209 {
2210 PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
2211
2212 List->CurrentPartition = PartEntry;
2213 return TRUE;
2214 }
2215 }
2216 else
2217 {
2218 /* Next primary partition */
2219 PartListEntry = List->CurrentPartition->ListEntry.Flink;
2220 if (PartListEntry != &List->CurrentDisk->PrimaryPartListHead)
2221 {
2222 PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
2223
2224 List->CurrentPartition = PartEntry;
2225 return TRUE;
2226 }
2227 }
2228 }
2229 }
2230
2231 /* Search for the first partition entry on the next disk */
2232 DiskListEntry = List->CurrentDisk->ListEntry.Flink;
2233 while (DiskListEntry != &List->DiskListHead)
2234 {
2235 DiskEntry = CONTAINING_RECORD(DiskListEntry, DISKENTRY, ListEntry);
2236
2237 PartListEntry = DiskEntry->PrimaryPartListHead.Flink;
2238 if (PartListEntry != &DiskEntry->PrimaryPartListHead)
2239 {
2240 PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
2241
2242 List->CurrentDisk = DiskEntry;
2243 List->CurrentPartition = PartEntry;
2244 return TRUE;
2245 }
2246
2247 DiskListEntry = DiskListEntry->Flink;
2248 }
2249
2250 return FALSE;
2251 }
2252
2253
2254 BOOL
2255 ScrollUpPartitionList(
2256 PPARTLIST List)
2257 {
2258 PLIST_ENTRY DiskListEntry;
2259 PLIST_ENTRY PartListEntry;
2260 PDISKENTRY DiskEntry;
2261 PPARTENTRY PartEntry;
2262
2263 /* Fail, if no disks are available */
2264 if (IsListEmpty(&List->DiskListHead))
2265 return FALSE;
2266
2267 /* Check for previous usable entry on current disk */
2268 if (List->CurrentPartition != NULL)
2269 {
2270 if (List->CurrentPartition->LogicalPartition)
2271 {
2272 /* Logical partition */
2273 PartListEntry = List->CurrentPartition->ListEntry.Blink;
2274 if (PartListEntry != &List->CurrentDisk->LogicalPartListHead)
2275 {
2276 /* Previous logical partition */
2277 PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
2278 }
2279 else
2280 {
2281 /* Extended partition*/
2282 PartEntry = List->CurrentDisk->ExtendedPartition;
2283 }
2284
2285 List->CurrentPartition = PartEntry;
2286 return TRUE;
2287 }
2288 else
2289 {
2290 /* Primary or extended partition */
2291
2292 PartListEntry = List->CurrentPartition->ListEntry.Blink;
2293 if (PartListEntry != &List->CurrentDisk->PrimaryPartListHead)
2294 {
2295 PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
2296
2297 if (PartEntry->IsPartitioned == TRUE &&
2298 IsContainerPartition(PartEntry->PartitionType))
2299 {
2300 PartListEntry = List->CurrentDisk->LogicalPartListHead.Blink;
2301 PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
2302 }
2303
2304 List->CurrentPartition = PartEntry;
2305 return TRUE;
2306 }
2307
2308 }
2309 }
2310
2311 /* Search for the last partition entry on the previous disk */
2312 DiskListEntry = List->CurrentDisk->ListEntry.Blink;
2313 while (DiskListEntry != &List->DiskListHead)
2314 {
2315 DiskEntry = CONTAINING_RECORD(DiskListEntry, DISKENTRY, ListEntry);
2316
2317 PartListEntry = DiskEntry->PrimaryPartListHead.Blink;
2318 if (PartListEntry != &DiskEntry->PrimaryPartListHead)
2319 {
2320 PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
2321
2322 if (PartEntry->IsPartitioned == TRUE &&
2323 IsContainerPartition(PartEntry->PartitionType))
2324 {
2325 PartListEntry = DiskEntry->LogicalPartListHead.Blink;
2326 if (PartListEntry != &DiskEntry->LogicalPartListHead)
2327 {
2328 PartEntry = CONTAINING_RECORD(PartListEntry, PARTENTRY, ListEntry);
2329
2330 List->CurrentDisk = DiskEntry;
2331 List->CurrentPartition = PartEntry;
2332 return TRUE;
2333 }
2334 }
2335 else
2336 {
2337 List->CurrentDisk = DiskEntry;
2338 List->CurrentPartition = PartEntry;
2339 return TRUE;
2340 }
2341 }
2342
2343 DiskListEntry = DiskListEntry->Blink;
2344 }
2345
2346 return FALSE;
2347 }
2348
2349
2350 static
2351 BOOLEAN
2352 IsEmptyLayoutEntry(
2353 PPARTITION_INFORMATION PartitionInfo)
2354 {
2355 if (PartitionInfo->StartingOffset.QuadPart == 0 &&
2356 PartitionInfo->PartitionLength.QuadPart == 0)
2357 return TRUE;
2358
2359 return FALSE;
2360 }
2361
2362
2363 static
2364 BOOLEAN
2365 IsSamePrimaryLayoutEntry(
2366 IN PPARTITION_INFORMATION PartitionInfo,
2367 IN PDISKENTRY DiskEntry,
2368 IN PPARTENTRY PartEntry)
2369 {
2370 if (PartitionInfo->StartingOffset.QuadPart == PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector &&
2371 PartitionInfo->PartitionLength.QuadPart == PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector)
2372 // PartitionInfo->PartitionNumber = PartEntry->PartitionNumber &&
2373 // PartitionInfo->PartitionType == PartEntry->PartitionType
2374 return TRUE;
2375
2376 return FALSE;
2377 }
2378
2379
2380 static
2381 ULONG
2382 GetPrimaryPartitionCount(
2383 IN PDISKENTRY DiskEntry)
2384 {
2385 PLIST_ENTRY Entry;
2386 PPARTENTRY PartEntry;
2387 ULONG Count = 0;
2388
2389 Entry = DiskEntry->PrimaryPartListHead.Flink;
2390 while (Entry != &DiskEntry->PrimaryPartListHead)
2391 {
2392 PartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
2393 if (PartEntry->IsPartitioned == TRUE)
2394 Count++;
2395
2396 Entry = Entry->Flink;
2397 }
2398
2399 return Count;
2400 }
2401
2402
2403 static
2404 ULONG
2405 GetLogicalPartitionCount(
2406 PDISKENTRY DiskEntry)
2407 {
2408 PLIST_ENTRY ListEntry;
2409 PPARTENTRY PartEntry;
2410 ULONG Count = 0;
2411
2412 ListEntry = DiskEntry->LogicalPartListHead.Flink;
2413 while (ListEntry != &DiskEntry->LogicalPartListHead)
2414 {
2415 PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
2416 if (PartEntry->IsPartitioned)
2417 Count++;
2418
2419 ListEntry = ListEntry->Flink;
2420 }
2421
2422 return Count;
2423 }
2424
2425
2426 static
2427 BOOL
2428 ReAllocateLayoutBuffer(
2429 PDISKENTRY DiskEntry)
2430 {
2431 PDRIVE_LAYOUT_INFORMATION NewLayoutBuffer;
2432 ULONG NewPartitionCount;
2433 ULONG CurrentPartitionCount = 0;
2434 ULONG LayoutBufferSize;
2435 ULONG i;
2436
2437 DPRINT1("ReAllocateLayoutBuffer()\n");
2438
2439 NewPartitionCount = 4 + GetLogicalPartitionCount(DiskEntry) * 4;
2440
2441 if (DiskEntry->LayoutBuffer)
2442 CurrentPartitionCount = DiskEntry->LayoutBuffer->PartitionCount;
2443
2444 DPRINT1("CurrentPartitionCount: %lu NewPartitionCount: %lu\n",
2445 CurrentPartitionCount, NewPartitionCount);
2446
2447 if (CurrentPartitionCount == NewPartitionCount)
2448 return TRUE;
2449
2450 LayoutBufferSize = sizeof(DRIVE_LAYOUT_INFORMATION) +
2451 ((NewPartitionCount - ANYSIZE_ARRAY) * sizeof(PARTITION_INFORMATION));
2452 NewLayoutBuffer = RtlReAllocateHeap(ProcessHeap,
2453 HEAP_ZERO_MEMORY,
2454 DiskEntry->LayoutBuffer,
2455 LayoutBufferSize);
2456 if (NewLayoutBuffer == NULL)
2457 {
2458 DPRINT1("Failed to allocate the new layout buffer (size: %lu)\n", LayoutBufferSize);
2459 return FALSE;
2460 }
2461
2462 /* If the layout buffer grows, make sure the new (empty) entries are written to the disk */
2463 if (NewPartitionCount > CurrentPartitionCount)
2464 {
2465 for (i = CurrentPartitionCount; i < NewPartitionCount; i++)
2466 NewLayoutBuffer->PartitionEntry[i].RewritePartition = TRUE;
2467 }
2468
2469 DiskEntry->LayoutBuffer = NewLayoutBuffer;
2470 DiskEntry->LayoutBuffer->PartitionCount = NewPartitionCount;
2471
2472 return TRUE;
2473 }
2474
2475
2476 static
2477 VOID
2478 UpdateDiskLayout(
2479 IN PDISKENTRY DiskEntry)
2480 {
2481 PPARTITION_INFORMATION PartitionInfo;
2482 PPARTITION_INFORMATION LinkInfo = NULL;
2483 PLIST_ENTRY ListEntry;
2484 PPARTENTRY PartEntry;
2485 LARGE_INTEGER HiddenSectors64;
2486 ULONG Index;
2487 ULONG PartitionNumber = 1;
2488
2489 DPRINT1("UpdateDiskLayout()\n");
2490
2491 /* Resize the layout buffer if necessary */
2492 if (ReAllocateLayoutBuffer(DiskEntry) == FALSE)
2493 {
2494 DPRINT("ReAllocateLayoutBuffer() failed.\n");
2495 return;
2496 }
2497
2498 /* Update the primary partition table */
2499 Index = 0;
2500 ListEntry = DiskEntry->PrimaryPartListHead.Flink;
2501 while (ListEntry != &DiskEntry->PrimaryPartListHead)
2502 {
2503 PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
2504
2505 if (PartEntry->IsPartitioned == TRUE)
2506 {
2507 PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
2508
2509 if (!IsSamePrimaryLayoutEntry(PartitionInfo, DiskEntry, PartEntry))
2510 {
2511 DPRINT1("Updating primary partition entry %lu\n", Index);
2512
2513 PartitionInfo->StartingOffset.QuadPart = PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector;
2514 PartitionInfo->PartitionLength.QuadPart = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
2515 PartitionInfo->HiddenSectors = PartEntry->StartSector.LowPart;
2516 PartitionInfo->PartitionNumber = (!IsContainerPartition(PartEntry->PartitionType)) ? PartitionNumber : 0;
2517 PartitionInfo->PartitionType = PartEntry->PartitionType;
2518 PartitionInfo->BootIndicator = PartEntry->BootIndicator;
2519 PartitionInfo->RecognizedPartition = FALSE;
2520 PartitionInfo->RewritePartition = TRUE;
2521 }
2522
2523 PartEntry->PartitionNumber = (!IsContainerPartition(PartEntry->PartitionType)) ? PartitionNumber : 0;
2524 PartEntry->PartitionIndex = Index;
2525
2526 if (!IsContainerPartition(PartEntry->PartitionType))
2527 PartitionNumber++;
2528
2529 Index++;
2530 }
2531
2532 ListEntry = ListEntry->Flink;
2533 }
2534
2535 /* Update the logical partition tables */
2536 Index = 4;
2537 ListEntry = DiskEntry->LogicalPartListHead.Flink;
2538 while (ListEntry != &DiskEntry->LogicalPartListHead)
2539 {
2540 PartEntry = CONTAINING_RECORD(ListEntry, PARTENTRY, ListEntry);
2541
2542 if (PartEntry->IsPartitioned)
2543 {
2544 PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
2545
2546 DPRINT1("Updating logical partition entry %lu\n", Index);
2547
2548 PartitionInfo->StartingOffset.QuadPart = PartEntry->StartSector.QuadPart * DiskEntry->BytesPerSector;
2549 PartitionInfo->PartitionLength.QuadPart = PartEntry->SectorCount.QuadPart * DiskEntry->BytesPerSector;
2550 PartitionInfo->HiddenSectors = DiskEntry->SectorAlignment;
2551 PartitionInfo->PartitionNumber = PartitionNumber;
2552 PartitionInfo->PartitionType = PartEntry->PartitionType;
2553 PartitionInfo->BootIndicator = FALSE;
2554 PartitionInfo->RecognizedPartition = FALSE;
2555 PartitionInfo->RewritePartition = TRUE;
2556
2557 PartEntry->PartitionNumber = PartitionNumber;
2558 PartEntry->PartitionIndex = Index;
2559
2560 /* Fill the link entry of the previous partition table */
2561 if (LinkInfo != NULL)
2562 {
2563 LinkInfo->StartingOffset.QuadPart = (PartEntry->StartSector.QuadPart - DiskEntry->SectorAlignment) * DiskEntry->BytesPerSector;
2564 LinkInfo->PartitionLength.QuadPart = (PartEntry->StartSector.QuadPart + DiskEntry->SectorAlignment) * DiskEntry->BytesPerSector;
2565 HiddenSectors64.QuadPart = PartEntry->StartSector.QuadPart - DiskEntry->SectorAlignment - DiskEntry->ExtendedPartition->StartSector.QuadPart;
2566 LinkInfo->HiddenSectors = HiddenSectors64.LowPart;
2567 LinkInfo->PartitionNumber = 0;
2568 LinkInfo->PartitionType = PARTITION_EXTENDED;
2569 LinkInfo->BootIndicator = FALSE;
2570 LinkInfo->RecognizedPartition = FALSE;
2571 LinkInfo->RewritePartition = TRUE;
2572 }
2573
2574 /* Save a pointer to the link entry of the current partition table */
2575 LinkInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index + 1];
2576
2577 PartitionNumber++;
2578 Index += 4;
2579 }
2580
2581 ListEntry = ListEntry->Flink;
2582 }
2583
2584 /* Wipe unused primary partition table entries */
2585 for (Index = GetPrimaryPartitionCount(DiskEntry); Index < 4; Index++)
2586 {
2587 DPRINT1("Primary partition entry %lu\n", Index);
2588
2589 PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
2590
2591 if (!IsEmptyLayoutEntry(PartitionInfo))
2592 {
2593 DPRINT1("Wiping primary partition entry %lu\n", Index);
2594
2595 PartitionInfo->StartingOffset.QuadPart = 0;
2596 PartitionInfo->PartitionLength.QuadPart = 0;
2597 PartitionInfo->HiddenSectors = 0;
2598 PartitionInfo->PartitionNumber = 0;
2599 PartitionInfo->PartitionType = PARTITION_ENTRY_UNUSED;
2600 PartitionInfo->BootIndicator = FALSE;
2601 PartitionInfo->RecognizedPartition = FALSE;
2602 PartitionInfo->RewritePartition = TRUE;
2603 }
2604 }
2605
2606 /* Wipe unused logical partition table entries */
2607 for (Index = 4; Index < DiskEntry->LayoutBuffer->PartitionCount; Index++)
2608 {
2609 if (Index % 4 >= 2)
2610 {
2611 DPRINT1("Logical partition entry %lu\n", Index);
2612
2613 PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[Index];
2614
2615 if (!IsEmptyLayoutEntry(PartitionInfo))
2616 {
2617 DPRINT1("Wiping partition entry %lu\n", Index);
2618
2619 PartitionInfo->StartingOffset.QuadPart = 0;
2620 PartitionInfo->PartitionLength.QuadPart = 0;
2621 PartitionInfo->HiddenSectors = 0;
2622 PartitionInfo->PartitionNumber = 0;
2623 PartitionInfo->PartitionType = PARTITION_ENTRY_UNUSED;
2624 PartitionInfo->BootIndicator = FALSE;
2625 PartitionInfo->RecognizedPartition = FALSE;
2626 PartitionInfo->RewritePartition = TRUE;
2627 }
2628 }
2629 }
2630
2631 #ifdef DUMP_PARTITION_TABLE
2632 DumpPartitionTable(DiskEntry);
2633 #endif
2634 }
2635
2636
2637 static
2638 PPARTENTRY
2639 GetPrevUnpartitionedEntry(
2640 PDISKENTRY DiskEntry,
2641 PPARTENTRY PartEntry)
2642 {
2643 PPARTENTRY PrevPartEntry;
2644 PLIST_ENTRY ListHead;
2645
2646 if (PartEntry->LogicalPartition)
2647 ListHead = &DiskEntry->LogicalPartListHead;
2648 else
2649 ListHead = &DiskEntry->PrimaryPartListHead;
2650
2651 if (PartEntry->ListEntry.Blink != ListHead)
2652 {
2653 PrevPartEntry = CONTAINING_RECORD(PartEntry->ListEntry.Blink,
2654 PARTENTRY,
2655 ListEntry);
2656 if (PrevPartEntry->IsPartitioned == FALSE)
2657 return PrevPartEntry;
2658 }
2659
2660 return NULL;
2661 }
2662
2663
2664 static
2665 PPARTENTRY
2666 GetNextUnpartitionedEntry(
2667 PDISKENTRY DiskEntry,
2668 PPARTENTRY PartEntry)
2669 {
2670 PPARTENTRY NextPartEntry;
2671 PLIST_ENTRY ListHead;
2672
2673 if (PartEntry->LogicalPartition)
2674 ListHead = &DiskEntry->LogicalPartListHead;
2675 else
2676 ListHead = &DiskEntry->PrimaryPartListHead;
2677
2678 if (PartEntry->ListEntry.Flink != ListHead)
2679 {
2680 NextPartEntry = CONTAINING_RECORD(PartEntry->ListEntry.Flink,
2681 PARTENTRY,
2682 ListEntry);
2683 if (NextPartEntry->IsPartitioned == FALSE)
2684 return NextPartEntry;
2685 }
2686
2687 return NULL;
2688 }
2689
2690
2691 VOID
2692 CreatePrimaryPartition(
2693 PPARTLIST List,
2694 ULONGLONG SectorCount,
2695 BOOLEAN AutoCreate)
2696 {
2697 PDISKENTRY DiskEntry;
2698 PPARTENTRY PartEntry;
2699 PPARTENTRY NewPartEntry;
2700
2701 DPRINT1("CreatePrimaryPartition(%I64u)\n", SectorCount);
2702
2703 if (List == NULL ||
2704 List->CurrentDisk == NULL ||
2705 List->CurrentPartition == NULL ||
2706 List->CurrentPartition->IsPartitioned == TRUE)
2707 {
2708 return;
2709 }
2710
2711 DiskEntry = List->CurrentDisk;
2712 PartEntry = List->CurrentPartition;
2713
2714 DPRINT1("Current partition sector count: %I64u\n", PartEntry->SectorCount.QuadPart);
2715
2716 if (AutoCreate == TRUE ||
2717 AlignDown(PartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) - PartEntry->StartSector.QuadPart == PartEntry->SectorCount.QuadPart)
2718 {
2719 DPRINT1("Convert existing partition entry\n");
2720
2721 /* Convert current entry to 'new (unformatted)' */
2722 PartEntry->IsPartitioned = TRUE;
2723 PartEntry->PartitionType = PARTITION_ENTRY_UNUSED;
2724 PartEntry->FormatState = Unformatted;
2725 PartEntry->AutoCreate = AutoCreate;
2726 PartEntry->New = TRUE;
2727 PartEntry->BootIndicator = FALSE;
2728
2729 DPRINT1("First Sector: %I64u\n", PartEntry->StartSector.QuadPart);
2730 DPRINT1("Last Sector: %I64u\n", PartEntry->StartSector.QuadPart + PartEntry->SectorCount.QuadPart - 1);
2731 DPRINT1("Total Sectors: %I64u\n", PartEntry->SectorCount.QuadPart);
2732 }
2733 else
2734 {
2735 DPRINT1("Add new partition entry\n");
2736
2737 /* Insert and initialize a new partition entry */
2738 NewPartEntry = RtlAllocateHeap(ProcessHeap,
2739 HEAP_ZERO_MEMORY,
2740 sizeof(PARTENTRY));
2741 if (NewPartEntry == NULL)
2742 return;
2743
2744 /* Insert the new entry into the list */
2745 InsertTailList(&PartEntry->ListEntry,
2746 &NewPartEntry->ListEntry);
2747
2748 NewPartEntry->DiskEntry = DiskEntry;
2749
2750 NewPartEntry->IsPartitioned = TRUE;
2751 NewPartEntry->StartSector.QuadPart = PartEntry->StartSector.QuadPart;
2752 NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) -
2753 NewPartEntry->StartSector.QuadPart;
2754 NewPartEntry->PartitionType = PARTITION_ENTRY_UNUSED;
2755
2756 DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
2757 DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
2758 DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
2759
2760 NewPartEntry->New = TRUE;
2761 NewPartEntry->FormatState = Unformatted;
2762 NewPartEntry->BootIndicator = FALSE;
2763
2764 PartEntry->StartSector.QuadPart = NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart;
2765 PartEntry->SectorCount.QuadPart -= (PartEntry->StartSector.QuadPart - NewPartEntry->StartSector.QuadPart);
2766 }
2767
2768 UpdateDiskLayout(DiskEntry);
2769
2770 DiskEntry->Dirty = TRUE;
2771
2772 AssignDriveLetters(List);
2773 }
2774
2775
2776 static
2777 VOID
2778 AddLogicalDiskSpace(
2779 PDISKENTRY DiskEntry)
2780 {
2781 PPARTENTRY NewPartEntry;
2782
2783 DPRINT1("AddLogicalDiskSpace()\n");
2784
2785 /* Create a partition table entry that represents the empty space in the container partition */
2786 NewPartEntry = RtlAllocateHeap(ProcessHeap,
2787 HEAP_ZERO_MEMORY,
2788 sizeof(PARTENTRY));
2789 if (NewPartEntry == NULL)
2790 return;
2791
2792 NewPartEntry->DiskEntry = DiskEntry;
2793 NewPartEntry->LogicalPartition = TRUE;
2794
2795 NewPartEntry->IsPartitioned = FALSE;
2796 NewPartEntry->StartSector.QuadPart = DiskEntry->ExtendedPartition->StartSector.QuadPart + (ULONGLONG)DiskEntry->SectorAlignment;
2797 NewPartEntry->SectorCount.QuadPart = DiskEntry->ExtendedPartition->SectorCount.QuadPart - (ULONGLONG)DiskEntry->SectorAlignment;
2798
2799 DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
2800 DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
2801 DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
2802
2803 NewPartEntry->FormatState = Unformatted;
2804
2805 InsertTailList(&DiskEntry->LogicalPartListHead,
2806 &NewPartEntry->ListEntry);
2807 }
2808
2809
2810 VOID
2811 CreateExtendedPartition(
2812 PPARTLIST List,
2813 ULONGLONG SectorCount)
2814 {
2815 PDISKENTRY DiskEntry;
2816 PPARTENTRY PartEntry;
2817 PPARTENTRY NewPartEntry;
2818
2819 DPRINT1("CreateExtendedPartition(%I64u)\n", SectorCount);
2820
2821 if (List == NULL ||
2822 List->CurrentDisk == NULL ||
2823 List->CurrentPartition == NULL ||
2824 List->CurrentPartition->IsPartitioned == TRUE)
2825 {
2826 return;
2827 }
2828
2829 DiskEntry = List->CurrentDisk;
2830 PartEntry = List->CurrentPartition;
2831
2832 DPRINT1("Current partition sector count: %I64u\n", PartEntry->SectorCount.QuadPart);
2833
2834 if (AlignDown(PartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) - PartEntry->StartSector.QuadPart == PartEntry->SectorCount.QuadPart)
2835 {
2836 DPRINT1("Convert existing partition entry\n");
2837
2838 /* Convert current entry to 'new (unformatted)' */
2839 PartEntry->IsPartitioned = TRUE;
2840 PartEntry->FormatState = Formatted;
2841 PartEntry->AutoCreate = FALSE;
2842 PartEntry->New = FALSE;
2843 PartEntry->BootIndicator = FALSE;
2844
2845 if (PartEntry->StartSector.QuadPart < 1450560)
2846 {
2847 /* Partition starts below the 8.4GB boundary ==> CHS partition */
2848 PartEntry->PartitionType = PARTITION_EXTENDED;
2849 }
2850 else
2851 {
2852 /* Partition starts above the 8.4GB boundary ==> LBA partition */
2853 PartEntry->PartitionType = PARTITION_XINT13_EXTENDED;
2854 }
2855
2856 DiskEntry->ExtendedPartition = PartEntry;
2857
2858 DPRINT1("First Sector: %I64u\n", PartEntry->StartSector.QuadPart);
2859 DPRINT1("Last Sector: %I64u\n", PartEntry->StartSector.QuadPart + PartEntry->SectorCount.QuadPart - 1);
2860 DPRINT1("Total Sectors: %I64u\n", PartEntry->SectorCount.QuadPart);
2861 }
2862 else
2863 {
2864 DPRINT1("Add new partition entry\n");
2865
2866 /* Insert and initialize a new partition entry */
2867 NewPartEntry = RtlAllocateHeap(ProcessHeap,
2868 HEAP_ZERO_MEMORY,
2869 sizeof(PARTENTRY));
2870 if (NewPartEntry == NULL)
2871 return;
2872
2873 /* Insert the new entry into the list */
2874 InsertTailList(&PartEntry->ListEntry,
2875 &NewPartEntry->ListEntry);
2876
2877 NewPartEntry->DiskEntry = DiskEntry;
2878
2879 NewPartEntry->IsPartitioned = TRUE;
2880 NewPartEntry->StartSector.QuadPart = PartEntry->StartSector.QuadPart;
2881 NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) -
2882 NewPartEntry->StartSector.QuadPart;
2883
2884 NewPartEntry->New = FALSE;
2885 NewPartEntry->FormatState = Formatted;
2886 NewPartEntry->BootIndicator = FALSE;
2887
2888 if (NewPartEntry->StartSector.QuadPart < 1450560)
2889 {
2890 /* Partition starts below the 8.4GB boundary ==> CHS partition */
2891 NewPartEntry->PartitionType = PARTITION_EXTENDED;
2892 }
2893 else
2894 {
2895 /* Partition starts above the 8.4GB boundary ==> LBA partition */
2896 NewPartEntry->PartitionType = PARTITION_XINT13_EXTENDED;
2897 }
2898
2899 DiskEntry->ExtendedPartition = NewPartEntry;
2900
2901 PartEntry->StartSector.QuadPart = NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart;
2902 PartEntry->SectorCount.QuadPart -= (PartEntry->StartSector.QuadPart - NewPartEntry->StartSector.QuadPart);
2903
2904 DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
2905 DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
2906 DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
2907 }
2908
2909 AddLogicalDiskSpace(DiskEntry);
2910
2911 UpdateDiskLayout(DiskEntry);
2912
2913 DiskEntry->Dirty = TRUE;
2914
2915 AssignDriveLetters(List);
2916 }
2917
2918
2919 VOID
2920 CreateLogicalPartition(
2921 PPARTLIST List,
2922 ULONGLONG SectorCount,
2923 BOOLEAN AutoCreate)
2924 {
2925 PDISKENTRY DiskEntry;
2926 PPARTENTRY PartEntry;
2927 PPARTENTRY NewPartEntry;
2928
2929 DPRINT1("CreateLogicalPartition(%I64u)\n", SectorCount);
2930
2931 if (List == NULL ||
2932 List->CurrentDisk == NULL ||
2933 List->CurrentPartition == NULL ||
2934 List->CurrentPartition->IsPartitioned == TRUE)
2935 {
2936 return;
2937 }
2938
2939 DiskEntry = List->CurrentDisk;
2940 PartEntry = List->CurrentPartition;
2941
2942 DPRINT1("Current partition sector count: %I64u\n", PartEntry->SectorCount.QuadPart);
2943
2944 if (AutoCreate == TRUE ||
2945 AlignDown(PartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) - PartEntry->StartSector.QuadPart == PartEntry->SectorCount.QuadPart)
2946 {
2947 DPRINT1("Convert existing partition entry\n");
2948
2949 /* Convert current entry to 'new (unformatted)' */
2950 PartEntry->IsPartitioned = TRUE;
2951 PartEntry->PartitionType = PARTITION_ENTRY_UNUSED;
2952 PartEntry->FormatState = Unformatted;
2953 PartEntry->AutoCreate = FALSE;
2954 PartEntry->New = TRUE;
2955 PartEntry->BootIndicator = FALSE;
2956 PartEntry->LogicalPartition = TRUE;
2957
2958 DPRINT1("First Sector: %I64u\n", PartEntry->StartSector.QuadPart);
2959 DPRINT1("Last Sector: %I64u\n", PartEntry->StartSector.QuadPart + PartEntry->SectorCount.QuadPart - 1);
2960 DPRINT1("Total Sectors: %I64u\n", PartEntry->SectorCount.QuadPart);
2961 }
2962 else
2963 {
2964 DPRINT1("Add new partition entry\n");
2965
2966 /* Insert and initialize a new partition entry */
2967 NewPartEntry = RtlAllocateHeap(ProcessHeap,
2968 HEAP_ZERO_MEMORY,
2969 sizeof(PARTENTRY));
2970 if (NewPartEntry == NULL)
2971 return;
2972
2973 /* Insert the new entry into the list */
2974 InsertTailList(&PartEntry->ListEntry,
2975 &NewPartEntry->ListEntry);
2976
2977 NewPartEntry->DiskEntry = DiskEntry;
2978
2979 NewPartEntry->IsPartitioned = TRUE;
2980 NewPartEntry->StartSector.QuadPart = PartEntry->StartSector.QuadPart;
2981 NewPartEntry->SectorCount.QuadPart = AlignDown(NewPartEntry->StartSector.QuadPart + SectorCount, DiskEntry->SectorAlignment) -
2982 NewPartEntry->StartSector.QuadPart;
2983 NewPartEntry->PartitionType = PARTITION_ENTRY_UNUSED;
2984
2985 DPRINT1("First Sector: %I64u\n", NewPartEntry->StartSector.QuadPart);
2986 DPRINT1("Last Sector: %I64u\n", NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart - 1);
2987 DPRINT1("Total Sectors: %I64u\n", NewPartEntry->SectorCount.QuadPart);
2988
2989 NewPartEntry->New = TRUE;
2990 NewPartEntry->FormatState = Unformatted;
2991 NewPartEntry->BootIndicator = FALSE;
2992 NewPartEntry->LogicalPartition = TRUE;
2993
2994 PartEntry->StartSector.QuadPart = NewPartEntry->StartSector.QuadPart + NewPartEntry->SectorCount.QuadPart;
2995 PartEntry->SectorCount.QuadPart -= (PartEntry->StartSector.QuadPart - NewPartEntry->StartSector.QuadPart);
2996 }
2997
2998 UpdateDiskLayout(DiskEntry);
2999
3000 DiskEntry->Dirty = TRUE;
3001
3002 AssignDriveLetters(List);
3003 }
3004
3005
3006 VOID
3007 DeleteCurrentPartition(
3008 PPARTLIST List)
3009 {
3010 PDISKENTRY DiskEntry;
3011 PPARTENTRY PartEntry;
3012 PPARTENTRY PrevPartEntry;
3013 PPARTENTRY NextPartEntry;
3014 PPARTENTRY LogicalPartEntry;
3015 PLIST_ENTRY Entry;
3016
3017 if (List == NULL ||
3018 List->CurrentDisk == NULL ||
3019 List->CurrentPartition == NULL ||
3020 List->CurrentPartition->IsPartitioned == FALSE)
3021 {
3022 return;
3023 }
3024
3025 DiskEntry = List->CurrentDisk;
3026 PartEntry = List->CurrentPartition;
3027
3028 /* Delete all logical partition entries if an extended partition will be deleted */
3029 if (DiskEntry->ExtendedPartition == PartEntry)
3030 {
3031 while (!IsListEmpty(&DiskEntry->LogicalPartListHead))
3032 {
3033 Entry = RemoveHeadList(&DiskEntry->LogicalPartListHead);
3034 LogicalPartEntry = CONTAINING_RECORD(Entry, PARTENTRY, ListEntry);
3035
3036 RtlFreeHeap(ProcessHeap, 0, LogicalPartEntry);
3037 }
3038
3039 DiskEntry->ExtendedPartition = NULL;
3040 }
3041
3042 /* Adjust unpartitioned disk space entries */
3043
3044 /* Get pointer to previous and next unpartitioned entries */
3045 PrevPartEntry = GetPrevUnpartitionedEntry(DiskEntry, PartEntry);
3046 NextPartEntry = GetNextUnpartitionedEntry(DiskEntry, PartEntry);
3047
3048 if (PrevPartEntry != NULL && NextPartEntry != NULL)
3049 {
3050 /* Merge previous, current and next unpartitioned entry */
3051
3052 /* Adjust the previous entries length */
3053 PrevPartEntry->SectorCount.QuadPart += (PartEntry->SectorCount.QuadPart + NextPartEntry->SectorCount.QuadPart);
3054
3055 /* Remove the current entry */
3056 RemoveEntryList(&PartEntry->ListEntry);
3057 RtlFreeHeap(ProcessHeap, 0, PartEntry);
3058
3059 /* Remove the next entry */
3060 RemoveEntryList (&NextPartEntry->ListEntry);
3061 RtlFreeHeap(ProcessHeap, 0, NextPartEntry);
3062
3063 /* Update current partition */
3064 List->CurrentPartition = PrevPartEntry;
3065 }
3066 else if (PrevPartEntry != NULL && NextPartEntry == NULL)
3067 {
3068 /* Merge current and previous unpartitioned entry */
3069
3070 /* Adjust the previous entries length */
3071 PrevPartEntry->SectorCount.QuadPart += PartEntry->SectorCount.QuadPart;
3072
3073 /* Remove the current entry */
3074 RemoveEntryList(&PartEntry->ListEntry);
3075 RtlFreeHeap(ProcessHeap, 0, PartEntry);
3076
3077 /* Update current partition */
3078 List->CurrentPartition = PrevPartEntry;
3079 }
3080 else if (PrevPartEntry == NULL && NextPartEntry != NULL)
3081 {
3082 /* Merge current and next unpartitioned entry */
3083
3084 /* Adjust the next entries offset and length */
3085 NextPartEntry->StartSector.QuadPart = PartEntry->StartSector.QuadPart;
3086 NextPartEntry->SectorCount.QuadPart += PartEntry->SectorCount.QuadPart;
3087
3088 /* Remove the current entry */
3089 RemoveEntryList(&PartEntry->ListEntry);
3090 RtlFreeHeap(ProcessHeap, 0, PartEntry);
3091
3092 /* Update current partition */
3093 List->CurrentPartition = NextPartEntry;
3094 }
3095 else
3096 {
3097 /* Nothing to merge but change current entry */
3098 PartEntry->IsPartitioned = FALSE;
3099 PartEntry->PartitionType = PARTITION_ENTRY_UNUSED;
3100 PartEntry->FormatState = Unformatted;
3101 PartEntry->DriveLetter = 0;
3102 }
3103
3104 UpdateDiskLayout(DiskEntry);
3105
3106 DiskEntry->Dirty = TRUE;
3107
3108 AssignDriveLetters(List);
3109 }
3110
3111
3112 VOID
3113 CheckActiveSystemPartition(
3114 PPARTLIST List)
3115 {
3116 PDISKENTRY DiskEntry;
3117 PPARTENTRY PartEntry;
3118 PLIST_ENTRY ListEntry;
3119
3120 /* Check for empty disk list */
3121 if (IsListEmpty(&List->DiskListHead))
3122 {
3123 List->SystemDisk = NULL;
3124 List->SystemPartition = NULL;
3125 return;
3126 }
3127
3128 #if 0
3129 if (List->SystemDisk != NULL &&
3130 List->SystemPartition != NULL)
3131 {
3132 /* We already have an active system partition */
3133 return;
3134 }
3135 #endif
3136
3137 /* Choose the currently selected disk */
3138 DiskEntry = List->CurrentDisk;
3139
3140 /* Check for empty partition list */
3141 if (IsListEmpty(&DiskEntry->PrimaryPartListHead))
3142 {
3143 List->SystemDisk = NULL;
3144 List->SystemPartition = NULL;
3145 return;
3146 }
3147
3148 /*
3149 * Check the first partition of the disk in case it is fresh new,
3150 * and if so, use it as the system partition.
3151 */
3152
3153 PartEntry = CONTAINING_RECORD(DiskEntry->PrimaryPartListHead.Flink,
3154 PARTENTRY,
3155 ListEntry);
3156
3157 /* Set active system partition */
3158 if ((DiskEntry->NewDisk == TRUE) ||
3159 (PartEntry->BootIndicator == FALSE))
3160 {
3161 PartEntry->BootIndicator = TRUE;
3162 DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].BootIndicator = TRUE;
3163 DiskEntry->LayoutBuffer->PartitionEntry[PartEntry->PartitionIndex].RewritePartition = TRUE;
3164 DiskEntry->Dirty = TRUE;
3165
3166 /* FIXME: Might be incorrect if partitions were created by Linux FDISK */
3167 List->SystemDisk = DiskEntry;
3168 List->SystemPartition = PartEntry;
3169
3170 return;
3171 }
3172
3173 /* Disk is not new, scan all partitions to find a bootable one */
3174 List->SystemDisk = NULL;
3175 List->SystemPartition = NULL;
3176
3177 ListEntry = DiskEntry->PrimaryPartListHead.Flink;
3178 while (ListEntry != &DiskEntry->PrimaryPartListHead)
3179 {
3180 PartEntry = CONTAINING_RECORD(ListEntry,
3181 PARTENTRY,
3182 ListEntry);<