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