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