3de244885b0d29544f52464153fa3ecd556a46f8
[reactos.git] / reactos / subsys / system / 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
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id$
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS text-mode setup
22 * FILE: subsys/system/usetup/partlist.c
23 * PURPOSE: Partition list functions
24 * PROGRAMMER: Eric Kohl
25 * Casper S. Hornstrup (chorns@users.sourceforge.net)
26 * Hartmut Birr
27 */
28
29 #include <usetup.h>
30
31 #define NDEBUG
32 #include <debug.h>
33
34 /* FUNCTIONS ****************************************************************/
35
36 static VOID
37 GetDriverName (PDISKENTRY DiskEntry)
38 {
39 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
40 WCHAR KeyName[32];
41 NTSTATUS Status;
42
43 RtlInitUnicodeString (&DiskEntry->DriverName,
44 NULL);
45
46 swprintf (KeyName,
47 L"\\Scsi\\Scsi Port %lu",
48 DiskEntry->Port);
49
50 RtlZeroMemory (&QueryTable,
51 sizeof(QueryTable));
52
53 QueryTable[0].Name = L"Driver";
54 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
55 QueryTable[0].EntryContext = &DiskEntry->DriverName;
56
57 Status = RtlQueryRegistryValues (RTL_REGISTRY_DEVICEMAP,
58 KeyName,
59 QueryTable,
60 NULL,
61 NULL);
62 if (!NT_SUCCESS (Status))
63 {
64 DPRINT1 ("RtlQueryRegistryValues() failed (Status %lx)\n", Status);
65 }
66 }
67
68
69 static VOID
70 AssignDriverLetters (PPARTLIST List)
71 {
72 PDISKENTRY DiskEntry;
73 PPARTENTRY PartEntry;
74 PLIST_ENTRY Entry1;
75 PLIST_ENTRY Entry2;
76 CHAR Letter;
77
78 Letter = 'C';
79
80 /* Assign drive letters to primary partitions */
81 Entry1 = List->DiskListHead.Flink;
82 while (Entry1 != &List->DiskListHead)
83 {
84 DiskEntry = CONTAINING_RECORD (Entry1, DISKENTRY, ListEntry);
85
86 if (!IsListEmpty (&DiskEntry->PartListHead))
87 {
88 PartEntry = CONTAINING_RECORD (DiskEntry->PartListHead.Flink,
89 PARTENTRY,
90 ListEntry);
91
92 PartEntry->DriveLetter = 0;
93
94 if (PartEntry->Unpartitioned == FALSE &&
95 !IsContainerPartition (PartEntry->PartInfo[0].PartitionType))
96 {
97 if (IsRecognizedPartition (PartEntry->PartInfo[0].PartitionType) ||
98 (PartEntry->PartInfo[0].PartitionType == PARTITION_ENTRY_UNUSED &&
99 PartEntry->PartInfo[0].PartitionLength.QuadPart != 0LL))
100 {
101 if (Letter <= 'Z')
102 {
103 PartEntry->DriveLetter = Letter;
104 Letter++;
105 }
106 }
107 }
108 }
109
110 Entry1 = Entry1->Flink;
111 }
112
113
114 /* Assign drive letters to logical drives */
115 Entry1 = List->DiskListHead.Flink;
116 while (Entry1 != &List->DiskListHead)
117 {
118 DiskEntry = CONTAINING_RECORD (Entry1, DISKENTRY, ListEntry);
119
120 Entry2 = DiskEntry->PartListHead.Flink;
121 if (Entry2 != &DiskEntry->PartListHead)
122 {
123 Entry2 = Entry2->Flink;
124 while (Entry2 != &DiskEntry->PartListHead)
125 {
126 PartEntry = CONTAINING_RECORD (Entry2,
127 PARTENTRY,
128 ListEntry);
129
130 PartEntry->DriveLetter = 0;
131
132 if (PartEntry->Unpartitioned == FALSE &&
133 !IsContainerPartition (PartEntry->PartInfo[0].PartitionType))
134 {
135 if (IsRecognizedPartition (PartEntry->PartInfo[0].PartitionType) ||
136 (PartEntry->PartInfo[0].PartitionType == PARTITION_ENTRY_UNUSED &&
137 PartEntry->PartInfo[0].PartitionLength.QuadPart != 0LL))
138 {
139 if (Letter <= 'Z')
140 {
141 PartEntry->DriveLetter = Letter;
142 Letter++;
143 }
144 }
145 }
146
147 Entry2 = Entry2->Flink;
148 }
149 }
150
151 Entry1 = Entry1->Flink;
152 }
153 }
154
155
156 static VOID
157 UpdatePartitionNumbers (PDISKENTRY DiskEntry)
158 {
159 PPARTENTRY PartEntry;
160 PLIST_ENTRY Entry;
161 ULONG PartNumber;
162 ULONG i;
163
164 PartNumber = 1;
165 Entry = DiskEntry->PartListHead.Flink;
166 while (Entry != &DiskEntry->PartListHead)
167 {
168 PartEntry = CONTAINING_RECORD (Entry,
169 PARTENTRY,
170 ListEntry);
171
172 if (PartEntry->Unpartitioned == TRUE)
173 {
174 for (i = 0; i < 4; i++)
175 {
176 PartEntry->PartInfo[i].PartitionNumber = 0;
177 }
178 }
179 else
180 {
181 for (i = 0; i < 4; i++)
182 {
183 if (IsContainerPartition (PartEntry->PartInfo[i].PartitionType))
184 {
185 PartEntry->PartInfo[i].PartitionNumber = 0;
186 }
187 else if (PartEntry->PartInfo[i].PartitionType == PARTITION_ENTRY_UNUSED &&
188 PartEntry->PartInfo[i].PartitionLength.QuadPart == 0ULL)
189 {
190 PartEntry->PartInfo[i].PartitionNumber = 0;
191 }
192 else
193 {
194 PartEntry->PartInfo[i].PartitionNumber = PartNumber;
195 PartNumber++;
196 }
197 }
198 }
199
200 Entry = Entry->Flink;
201 }
202 }
203
204
205 static VOID
206 AddPartitionToList (ULONG DiskNumber,
207 PDISKENTRY DiskEntry,
208 DRIVE_LAYOUT_INFORMATION *LayoutBuffer)
209 {
210 PPARTENTRY PartEntry;
211 ULONG i;
212 ULONG j;
213
214 for (i = 0; i < LayoutBuffer->PartitionCount; i += 4)
215 {
216 for (j = 0; j < 4; j++)
217 {
218 if (LayoutBuffer->PartitionEntry[j].PartitionType != PARTITION_ENTRY_UNUSED ||
219 LayoutBuffer->PartitionEntry[j].PartitionLength.QuadPart != 0ULL)
220 {
221 break;
222 }
223 }
224 if (j >= 4)
225 {
226 continue;
227 }
228
229 PartEntry = (PPARTENTRY)RtlAllocateHeap (ProcessHeap,
230 0,
231 sizeof(PARTENTRY));
232 if (PartEntry == NULL)
233 {
234 return;
235 }
236
237 RtlZeroMemory (PartEntry,
238 sizeof(PARTENTRY));
239
240 PartEntry->Unpartitioned = FALSE;
241
242 for (j = 0; j < 4; j++)
243 {
244 RtlCopyMemory (&PartEntry->PartInfo[j],
245 &LayoutBuffer->PartitionEntry[i+j],
246 sizeof(PARTITION_INFORMATION));
247 }
248
249 if (IsContainerPartition(PartEntry->PartInfo[0].PartitionType))
250 {
251 PartEntry->FormatState = Unformatted;
252 }
253 else if ((PartEntry->PartInfo[0].PartitionType == PARTITION_FAT_12) ||
254 (PartEntry->PartInfo[0].PartitionType == PARTITION_FAT_16) ||
255 (PartEntry->PartInfo[0].PartitionType == PARTITION_HUGE) ||
256 (PartEntry->PartInfo[0].PartitionType == PARTITION_XINT13) ||
257 (PartEntry->PartInfo[0].PartitionType == PARTITION_FAT32) ||
258 (PartEntry->PartInfo[0].PartitionType == PARTITION_FAT32_XINT13))
259 {
260 #if 0
261 if (CheckFatFormat())
262 {
263 PartEntry->FormatState = Preformatted;
264 }
265 else
266 {
267 PartEntry->FormatState = Unformatted;
268 }
269 #endif
270 PartEntry->FormatState = Preformatted;
271 }
272 else if (PartEntry->PartInfo[0].PartitionType == PARTITION_IFS)
273 {
274 #if 0
275 if (CheckNtfsFormat())
276 {
277 PartEntry->FormatState = Preformatted;
278 }
279 else if (CheckHpfsFormat())
280 {
281 PartEntry->FormatState = Preformatted;
282 }
283 else
284 {
285 PartEntry->FormatState = Unformatted;
286 }
287 #endif
288 PartEntry->FormatState = Preformatted;
289 }
290 else
291 {
292 PartEntry->FormatState = Unknown;
293 }
294
295 InsertTailList (&DiskEntry->PartListHead,
296 &PartEntry->ListEntry);
297 }
298 }
299
300
301 static VOID
302 ScanForUnpartitionedDiskSpace (PDISKENTRY DiskEntry)
303 {
304 ULONGLONG LastStartingOffset;
305 ULONGLONG LastPartitionLength;
306 ULONGLONG LastUnusedPartitionLength;
307 PPARTENTRY PartEntry;
308 PPARTENTRY NewPartEntry;
309 PLIST_ENTRY Entry;
310 ULONG i;
311 ULONG j;
312
313 if (IsListEmpty (&DiskEntry->PartListHead))
314 {
315 /* Create a partition table that represents the empty disk */
316 PartEntry = (PPARTENTRY)RtlAllocateHeap (ProcessHeap,
317 0,
318 sizeof(PARTENTRY));
319 if (PartEntry == NULL)
320 return;
321
322 RtlZeroMemory (PartEntry,
323 sizeof(PARTENTRY));
324
325 PartEntry->Unpartitioned = TRUE;
326 PartEntry->UnpartitionedOffset = 0ULL;
327 PartEntry->UnpartitionedLength = DiskEntry->DiskSize;
328
329 PartEntry->FormatState = Unformatted;
330
331 InsertTailList (&DiskEntry->PartListHead,
332 &PartEntry->ListEntry);
333 }
334 else
335 {
336 /* Start partition at head 1, cylinder 0 */
337 LastStartingOffset = DiskEntry->TrackSize;
338 LastPartitionLength = 0ULL;
339 LastUnusedPartitionLength = 0ULL;
340
341 i = 0;
342 Entry = DiskEntry->PartListHead.Flink;
343 while (Entry != &DiskEntry->PartListHead)
344 {
345 PartEntry = CONTAINING_RECORD (Entry, PARTENTRY, ListEntry);
346
347 for (j = 0; j < 4; j++)
348 {
349 if ((!IsContainerPartition (PartEntry->PartInfo[j].PartitionType)) &&
350 (PartEntry->PartInfo[j].PartitionType != PARTITION_ENTRY_UNUSED ||
351 PartEntry->PartInfo[j].PartitionLength.QuadPart != 0LL))
352 {
353 LastUnusedPartitionLength =
354 PartEntry->PartInfo[j].StartingOffset.QuadPart -
355 (LastStartingOffset + LastPartitionLength);
356
357 if (LastUnusedPartitionLength >= DiskEntry->CylinderSize)
358 {
359 DPRINT ("Unpartitioned disk space %I64u\n", LastUnusedPartitionLength);
360
361 NewPartEntry = (PPARTENTRY)RtlAllocateHeap (ProcessHeap,
362 0,
363 sizeof(PARTENTRY));
364 if (NewPartEntry == NULL)
365 return;
366
367 RtlZeroMemory (NewPartEntry,
368 sizeof(PARTENTRY));
369
370 NewPartEntry->Unpartitioned = TRUE;
371 NewPartEntry->UnpartitionedOffset = LastStartingOffset + LastPartitionLength;
372 NewPartEntry->UnpartitionedLength = LastUnusedPartitionLength;
373 if (j == 0)
374 NewPartEntry->UnpartitionedLength -= DiskEntry->TrackSize;
375
376 NewPartEntry->FormatState = Unformatted;
377
378 /* Insert the table into the list */
379 InsertTailList (&PartEntry->ListEntry,
380 &NewPartEntry->ListEntry);
381 }
382
383 LastStartingOffset = PartEntry->PartInfo[j].StartingOffset.QuadPart;
384 LastPartitionLength = PartEntry->PartInfo[j].PartitionLength.QuadPart;
385 }
386 }
387
388 i += 4;
389 Entry = Entry->Flink;
390 }
391
392 /* Check for trailing unpartitioned disk space */
393 if (DiskEntry->DiskSize > (LastStartingOffset + LastPartitionLength))
394 {
395 /* Round-down to cylinder size */
396 LastUnusedPartitionLength =
397 ROUND_DOWN (DiskEntry->DiskSize - (LastStartingOffset + LastPartitionLength),
398 DiskEntry->CylinderSize);
399
400 if (LastUnusedPartitionLength >= DiskEntry->CylinderSize)
401 {
402 DPRINT ("Unpartitioned disk space %I64u\n", LastUnusedPartitionLength);
403
404 NewPartEntry = (PPARTENTRY)RtlAllocateHeap (ProcessHeap,
405 0,
406 sizeof(PARTENTRY));
407 if (NewPartEntry == NULL)
408 return;
409
410 RtlZeroMemory (NewPartEntry,
411 sizeof(PARTENTRY));
412
413 NewPartEntry->Unpartitioned = TRUE;
414 NewPartEntry->UnpartitionedOffset = LastStartingOffset + LastPartitionLength;
415 NewPartEntry->UnpartitionedLength = LastUnusedPartitionLength;
416
417 /* Append the table to the list */
418 InsertTailList (&DiskEntry->PartListHead,
419 &NewPartEntry->ListEntry);
420 }
421 }
422 }
423 }
424
425 NTSTATUS
426 STDCALL
427 DiskQueryRoutine(PWSTR ValueName,
428 ULONG ValueType,
429 PVOID ValueData,
430 ULONG ValueLength,
431 PVOID Context,
432 PVOID EntryContext)
433 {
434 PLIST_ENTRY ListHead = (PLIST_ENTRY)Context;
435 PULONG GlobalDiskCount = (PULONG)EntryContext;
436 PBIOSDISKENTRY BiosDiskEntry;
437 UNICODE_STRING NameU;
438
439 if (ValueType == REG_SZ &&
440 ValueLength == 20 * sizeof(WCHAR))
441 {
442 BiosDiskEntry = RtlAllocateHeap(ProcessHeap, 0, sizeof(BIOSDISKENTRY));
443 if (BiosDiskEntry == NULL)
444 {
445 return STATUS_NO_MEMORY;
446 }
447 BiosDiskEntry->DiskNumber = (*GlobalDiskCount)++;
448
449 NameU.Buffer = (PWCHAR)ValueData;
450 NameU.Length = NameU.MaximumLength = 8 * sizeof(WCHAR);
451 RtlUnicodeStringToInteger(&NameU, 16, &BiosDiskEntry->Checksum);
452
453 NameU.Buffer = (PWCHAR)ValueData + 9;
454 RtlUnicodeStringToInteger(&NameU, 16, &BiosDiskEntry->Signature);
455
456 InsertTailList(ListHead, &BiosDiskEntry->ListEntry);
457 }
458
459 return STATUS_SUCCESS;
460 }
461
462 #define ROOT_NAME L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter"
463
464 STATIC VOID
465 EnumerateBiosDiskEntries(PPARTLIST PartList)
466 {
467 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
468 WCHAR Name[100];
469 ULONG AdapterCount;
470 ULONG ControllerCount;
471 ULONG DiskCount;
472 NTSTATUS Status;
473 ULONG GlobalDiskCount=0;
474
475
476 memset(QueryTable, 0, sizeof(QueryTable));
477 QueryTable[0].Name = L"Identifier";
478 QueryTable[0].QueryRoutine = DiskQueryRoutine;
479 QueryTable[0].EntryContext = (PVOID)&GlobalDiskCount;
480
481 AdapterCount = 0;
482 while (1)
483 {
484 swprintf(Name, L"%s\\%lu", ROOT_NAME, AdapterCount);
485 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
486 Name,
487 &QueryTable[1],
488 NULL,
489 NULL);
490 if (!NT_SUCCESS(Status))
491 {
492 break;
493 }
494
495 swprintf(Name, L"%s\\%lu\\DiskController", ROOT_NAME, AdapterCount);
496 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
497 Name,
498 &QueryTable[1],
499 NULL,
500 NULL);
501 if (NT_SUCCESS(Status))
502 {
503 ControllerCount = 0;
504 while (1)
505 {
506 swprintf(Name, L"%s\\%lu\\DiskController\\%lu", ROOT_NAME, AdapterCount, ControllerCount);
507 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
508 Name,
509 &QueryTable[1],
510 NULL,
511 NULL);
512 if (!NT_SUCCESS(Status))
513 {
514 break;
515 }
516
517 swprintf(Name, L"%s\\%lu\\DiskController\\%lu\\DiskPeripheral", ROOT_NAME, AdapterCount, ControllerCount);
518 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
519 Name,
520 &QueryTable[1],
521 NULL,
522 NULL);
523 if (NT_SUCCESS(Status))
524 {
525 DiskCount = 0;
526 while (1)
527 {
528 swprintf(Name, L"%s\\%lu\\DiskController\\%lu\\DiskPeripheral\\%lu", ROOT_NAME, AdapterCount, ControllerCount, DiskCount);
529 Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
530 Name,
531 QueryTable,
532 (PVOID)&PartList->BiosDiskListHead,
533 NULL);
534 if (!NT_SUCCESS(Status))
535 {
536 break;
537 }
538 DiskCount++;
539 }
540 }
541 ControllerCount++;
542 }
543 }
544 AdapterCount++;
545 }
546 }
547
548 static VOID
549 AddDiskToList (HANDLE FileHandle,
550 ULONG DiskNumber,
551 PPARTLIST List)
552 {
553 DRIVE_LAYOUT_INFORMATION *LayoutBuffer;
554 DISK_GEOMETRY DiskGeometry;
555 SCSI_ADDRESS ScsiAddress;
556 PDISKENTRY DiskEntry;
557 IO_STATUS_BLOCK Iosb;
558 NTSTATUS Status;
559 PPARTITION_SECTOR Mbr;
560 PULONG Buffer;
561 LARGE_INTEGER FileOffset;
562 WCHAR Identifier[20];
563 ULONG Checksum;
564 ULONG Signature;
565 ULONG i;
566 PLIST_ENTRY ListEntry;
567 PBIOSDISKENTRY BiosDiskEntry;
568
569 Status = NtDeviceIoControlFile (FileHandle,
570 NULL,
571 NULL,
572 NULL,
573 &Iosb,
574 IOCTL_DISK_GET_DRIVE_GEOMETRY,
575 NULL,
576 0,
577 &DiskGeometry,
578 sizeof(DISK_GEOMETRY));
579 if (!NT_SUCCESS (Status))
580 {
581 return;
582 }
583
584 if (DiskGeometry.MediaType != FixedMedia)
585 {
586 return;
587 }
588
589 Status = NtDeviceIoControlFile (FileHandle,
590 NULL,
591 NULL,
592 NULL,
593 &Iosb,
594 IOCTL_SCSI_GET_ADDRESS,
595 NULL,
596 0,
597 &ScsiAddress,
598 sizeof(SCSI_ADDRESS));
599 if (!NT_SUCCESS(Status))
600 {
601 return;
602 }
603
604 Mbr = RtlAllocateHeap(ProcessHeap,
605 0,
606 DiskGeometry.BytesPerSector);
607
608 if (Mbr == NULL)
609 {
610 return;
611 }
612
613 FileOffset.QuadPart = 0;
614 Status = NtReadFile(FileHandle,
615 NULL,
616 NULL,
617 NULL,
618 &Iosb,
619 (PVOID)Mbr,
620 DiskGeometry.BytesPerSector,
621 &FileOffset,
622 NULL);
623 if (!NT_SUCCESS(Status))
624 {
625 RtlFreeHeap(ProcessHeap,
626 0,
627 Mbr);
628 DPRINT1("NtReadFile failed, status=%x\n", Status);
629 return;
630 }
631 Signature = Mbr->Signature;
632
633 /* Calculate the MBR checksum */
634 Checksum = 0;
635 Buffer = (PULONG)Mbr;
636 for (i = 0; i < 128; i++)
637 {
638 Checksum += Buffer[i];
639 }
640 Checksum = ~Checksum + 1;
641
642 RtlFreeHeap (ProcessHeap,
643 0,
644 Mbr);
645
646 swprintf(Identifier, L"%08x-%08x-A", Checksum, Signature);
647 DPRINT("Identifier: %S\n", Identifier);
648
649 DiskEntry = (PDISKENTRY)RtlAllocateHeap (ProcessHeap,
650 0,
651 sizeof(DISKENTRY));
652 if (DiskEntry == NULL)
653 {
654 return;
655 }
656
657 DiskEntry->Checksum = Checksum;
658 DiskEntry->Signature = Signature;
659 DiskEntry->BiosFound = FALSE;
660
661 ListEntry = List->BiosDiskListHead.Flink;
662 while(ListEntry != &List->BiosDiskListHead)
663 {
664 BiosDiskEntry = CONTAINING_RECORD(ListEntry, BIOSDISKENTRY, ListEntry);
665 if (BiosDiskEntry->Signature == Signature &&
666 BiosDiskEntry->Checksum == Checksum)
667 {
668 if (!DiskEntry->BiosFound)
669 {
670 DiskEntry->BiosDiskNumber = BiosDiskEntry->DiskNumber;
671 DiskEntry->BiosFound = TRUE;
672 }
673 else
674 {
675 }
676 }
677 ListEntry = ListEntry->Flink;
678 }
679
680 if (!DiskEntry->BiosFound)
681 {
682 RtlFreeHeap(ProcessHeap, 0, DiskEntry);
683 return;
684 }
685
686 InitializeListHead (&DiskEntry->PartListHead);
687
688 DiskEntry->Cylinders = DiskGeometry.Cylinders.QuadPart;
689 DiskEntry->TracksPerCylinder = DiskGeometry.TracksPerCylinder;
690 DiskEntry->SectorsPerTrack = DiskGeometry.SectorsPerTrack;
691 DiskEntry->BytesPerSector = DiskGeometry.BytesPerSector;
692
693 DPRINT ("Cylinders %d\n", DiskEntry->Cylinders);
694 DPRINT ("TracksPerCylinder %d\n", DiskEntry->TracksPerCylinder);
695 DPRINT ("SectorsPerTrack %d\n", DiskEntry->SectorsPerTrack);
696 DPRINT ("BytesPerSector %d\n", DiskEntry->BytesPerSector);
697
698 DiskEntry->DiskSize =
699 DiskGeometry.Cylinders.QuadPart *
700 (ULONGLONG)DiskGeometry.TracksPerCylinder *
701 (ULONGLONG)DiskGeometry.SectorsPerTrack *
702 (ULONGLONG)DiskGeometry.BytesPerSector;
703 DiskEntry->CylinderSize =
704 (ULONGLONG)DiskGeometry.TracksPerCylinder *
705 (ULONGLONG)DiskGeometry.SectorsPerTrack *
706 (ULONGLONG)DiskGeometry.BytesPerSector;
707 DiskEntry->TrackSize =
708 (ULONGLONG)DiskGeometry.SectorsPerTrack *
709 (ULONGLONG)DiskGeometry.BytesPerSector;
710
711 DiskEntry->DiskNumber = DiskNumber;
712 DiskEntry->Port = ScsiAddress.PortNumber;
713 DiskEntry->Bus = ScsiAddress.PathId;
714 DiskEntry->Id = ScsiAddress.TargetId;
715
716 GetDriverName (DiskEntry);
717
718 InsertAscendingList(&List->DiskListHead, DISKENTRY, ListEntry, DiskEntry, BiosDiskNumber);
719
720 LayoutBuffer = (DRIVE_LAYOUT_INFORMATION*)RtlAllocateHeap (ProcessHeap,
721 0,
722 8192);
723 if (LayoutBuffer == NULL)
724 {
725 return;
726 }
727
728 Status = NtDeviceIoControlFile (FileHandle,
729 NULL,
730 NULL,
731 NULL,
732 &Iosb,
733 IOCTL_DISK_GET_DRIVE_LAYOUT,
734 NULL,
735 0,
736 LayoutBuffer,
737 8192);
738 if (NT_SUCCESS (Status))
739 {
740 if (LayoutBuffer->PartitionCount == 0)
741 {
742 DiskEntry->NewDisk = TRUE;
743 }
744
745 AddPartitionToList (DiskNumber,
746 DiskEntry,
747 LayoutBuffer);
748
749 ScanForUnpartitionedDiskSpace (DiskEntry);
750 }
751
752 RtlFreeHeap (ProcessHeap,
753 0,
754 LayoutBuffer);
755 }
756
757
758 PPARTLIST
759 CreatePartitionList (SHORT Left,
760 SHORT Top,
761 SHORT Right,
762 SHORT Bottom)
763 {
764 PPARTLIST List;
765 OBJECT_ATTRIBUTES ObjectAttributes;
766 SYSTEM_DEVICE_INFORMATION Sdi;
767 IO_STATUS_BLOCK Iosb;
768 ULONG ReturnSize;
769 NTSTATUS Status;
770 ULONG DiskNumber;
771 WCHAR Buffer[MAX_PATH];
772 UNICODE_STRING Name;
773 HANDLE FileHandle;
774
775 List = (PPARTLIST)RtlAllocateHeap (ProcessHeap,
776 0,
777 sizeof (PARTLIST));
778 if (List == NULL)
779 return NULL;
780
781 List->Left = Left;
782 List->Top = Top;
783 List->Right = Right;
784 List->Bottom = Bottom;
785
786 List->Line = 0;
787
788 List->TopDisk = (ULONG)-1;
789 List->TopPartition = (ULONG)-1;
790
791 List->CurrentDisk = NULL;
792 List->CurrentPartition = NULL;
793
794 InitializeListHead (&List->DiskListHead);
795 InitializeListHead (&List->BiosDiskListHead);
796
797 EnumerateBiosDiskEntries(List);
798
799 Status = NtQuerySystemInformation (SystemDeviceInformation,
800 &Sdi,
801 sizeof(SYSTEM_DEVICE_INFORMATION),
802 &ReturnSize);
803 if (!NT_SUCCESS (Status))
804 {
805 RtlFreeHeap (ProcessHeap, 0, List);
806 return NULL;
807 }
808
809 for (DiskNumber = 0; DiskNumber < Sdi.NumberOfDisks; DiskNumber++)
810 {
811 swprintf (Buffer,
812 L"\\Device\\Harddisk%d\\Partition0",
813 DiskNumber);
814 RtlInitUnicodeString (&Name,
815 Buffer);
816
817 InitializeObjectAttributes (&ObjectAttributes,
818 &Name,
819 0,
820 NULL,
821 NULL);
822
823 Status = NtOpenFile (&FileHandle,
824 FILE_GENERIC_READ,
825 &ObjectAttributes,
826 &Iosb,
827 FILE_SHARE_READ,
828 FILE_SYNCHRONOUS_IO_NONALERT);
829 if (NT_SUCCESS(Status))
830 {
831 AddDiskToList (FileHandle,
832 DiskNumber,
833 List);
834
835 NtClose(FileHandle);
836 }
837 }
838
839 AssignDriverLetters (List);
840
841 List->TopDisk = 0;
842 List->TopPartition = 0;
843
844 /* Search for first usable disk and partition */
845 if (IsListEmpty (&List->DiskListHead))
846 {
847 List->CurrentDisk = NULL;
848 List->CurrentPartition = NULL;
849 }
850 else
851 {
852 List->CurrentDisk =
853 CONTAINING_RECORD (List->DiskListHead.Flink,
854 DISKENTRY,
855 ListEntry);
856
857 if (IsListEmpty (&List->CurrentDisk->PartListHead))
858 {
859 List->CurrentPartition = 0;
860 }
861 else
862 {
863 List->CurrentPartition =
864 CONTAINING_RECORD (List->CurrentDisk->PartListHead.Flink,
865 PARTENTRY,
866 ListEntry);
867 }
868 }
869
870 return List;
871 }
872
873
874 VOID
875 DestroyPartitionList (PPARTLIST List)
876 {
877 PDISKENTRY DiskEntry;
878 PBIOSDISKENTRY BiosDiskEntry;
879 PPARTENTRY PartEntry;
880 PLIST_ENTRY Entry;
881
882 /* Release disk and partition info */
883 while (!IsListEmpty (&List->DiskListHead))
884 {
885 Entry = RemoveHeadList (&List->DiskListHead);
886 DiskEntry = CONTAINING_RECORD (Entry, DISKENTRY, ListEntry);
887
888 /* Release driver name */
889 RtlFreeUnicodeString(&DiskEntry->DriverName);
890
891 /* Release partition array */
892 while (!IsListEmpty (&DiskEntry->PartListHead))
893 {
894 Entry = RemoveHeadList (&DiskEntry->PartListHead);
895 PartEntry = CONTAINING_RECORD (Entry, PARTENTRY, ListEntry);
896
897 RtlFreeHeap (ProcessHeap,
898 0,
899 PartEntry);
900 }
901
902 /* Release disk entry */
903 RtlFreeHeap (ProcessHeap, 0, DiskEntry);
904 }
905
906 /* release the bios disk info */
907 while(!IsListEmpty(&List->BiosDiskListHead))
908 {
909 Entry = RemoveHeadList(&List->BiosDiskListHead);
910 BiosDiskEntry = CONTAINING_RECORD(Entry, BIOSDISKENTRY, ListEntry);
911
912 RtlFreeHeap(ProcessHeap, 0, BiosDiskEntry);
913 }
914
915 /* Release list head */
916 RtlFreeHeap (ProcessHeap, 0, List);
917 }
918
919
920 static VOID
921 PrintEmptyLine (PPARTLIST List)
922 {
923 COORD coPos;
924 ULONG Written;
925 USHORT Width;
926 USHORT Height;
927
928 Width = List->Right - List->Left - 1;
929 Height = List->Bottom - List->Top - 2;
930
931
932 coPos.X = List->Left + 1;
933 coPos.Y = List->Top + 1 + List->Line;
934
935 if (List->Line >= 0 && List->Line <= Height)
936 {
937 FillConsoleOutputAttribute (0x17,
938 Width,
939 coPos,
940 &Written);
941
942 FillConsoleOutputCharacter (' ',
943 Width,
944 coPos,
945 &Written);
946 }
947 List->Line++;
948 }
949
950
951 static VOID
952 PrintPartitionData (PPARTLIST List,
953 PDISKENTRY DiskEntry,
954 PPARTENTRY PartEntry)
955 {
956 CHAR LineBuffer[128];
957 COORD coPos;
958 ULONG Written;
959 USHORT Width;
960 USHORT Height;
961
962 ULONGLONG PartSize;
963 PCHAR Unit;
964 UCHAR Attribute;
965 PCHAR PartType;
966
967 Width = List->Right - List->Left - 1;
968 Height = List->Bottom - List->Top - 2;
969
970
971 coPos.X = List->Left + 1;
972 coPos.Y = List->Top + 1 + List->Line;
973
974 if (PartEntry->Unpartitioned == TRUE)
975 {
976 #if 0
977 if (PartEntry->UnpartitionledLength >= 0x280000000ULL) /* 10 GB */
978 {
979 PartSize = (PartEntry->UnpartitionedLength + (1 << 29)) >> 30;
980 Unit = "GB";
981 }
982 else
983 #endif
984 if (PartEntry->UnpartitionedLength >= 0xA00000ULL) /* 10 MB */
985 {
986 PartSize = (PartEntry->UnpartitionedLength + (1 << 19)) >> 20;
987 Unit = "MB";
988 }
989 else
990 {
991 PartSize = (PartEntry->UnpartitionedLength + (1 << 9)) >> 10;
992 Unit = "KB";
993 }
994
995 sprintf (LineBuffer,
996 " Unpartitioned space %6I64u %s",
997 PartSize,
998 Unit);
999 }
1000 else
1001 {
1002 /* Determine partition type */
1003 PartType = NULL;
1004 if (PartEntry->New == TRUE)
1005 {
1006 PartType = "New (Unformatted)";
1007 }
1008 else if (PartEntry->Unpartitioned == FALSE)
1009 {
1010 if ((PartEntry->PartInfo[0].PartitionType == PARTITION_FAT_12) ||
1011 (PartEntry->PartInfo[0].PartitionType == PARTITION_FAT_16) ||
1012 (PartEntry->PartInfo[0].PartitionType == PARTITION_HUGE) ||
1013 (PartEntry->PartInfo[0].PartitionType == PARTITION_XINT13))
1014 {
1015 PartType = "FAT";
1016 }
1017 else if ((PartEntry->PartInfo[0].PartitionType == PARTITION_FAT32) ||
1018 (PartEntry->PartInfo[0].PartitionType == PARTITION_FAT32_XINT13))
1019 {
1020 PartType = "FAT32";
1021 }
1022 else if (PartEntry->PartInfo[0].PartitionType == PARTITION_IFS)
1023 {
1024 PartType = "NTFS"; /* FIXME: Not quite correct! */
1025 }
1026 }
1027
1028 #if 0
1029 if (PartEntry->PartInfo[0].PartitionLength.QuadPart >= 0x280000000LL) /* 10 GB */
1030 {
1031 PartSize = (PartEntry->PartInfo[0].PartitionLength.QuadPart + (1 << 29)) >> 30;
1032 Unit = "GB";
1033 }
1034 else
1035 #endif
1036 if (PartEntry->PartInfo[0].PartitionLength.QuadPart >= 0xA00000LL) /* 10 MB */
1037 {
1038 PartSize = (PartEntry->PartInfo[0].PartitionLength.QuadPart + (1 << 19)) >> 20;
1039 Unit = "MB";
1040 }
1041 else
1042 {
1043 PartSize = (PartEntry->PartInfo[0].PartitionLength.QuadPart + (1 << 9)) >> 10;
1044 Unit = "KB";
1045 }
1046
1047 if (PartType == NULL)
1048 {
1049 sprintf (LineBuffer,
1050 "%c%c Type %-3u %6I64u %s",
1051 (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
1052 (PartEntry->DriveLetter == 0) ? '-' : ':',
1053 PartEntry->PartInfo[0].PartitionType,
1054 PartSize,
1055 Unit);
1056 }
1057 else
1058 {
1059 sprintf (LineBuffer,
1060 "%c%c %-24s %6I64u %s",
1061 (PartEntry->DriveLetter == 0) ? '-' : PartEntry->DriveLetter,
1062 (PartEntry->DriveLetter == 0) ? '-' : ':',
1063 PartType,
1064 PartSize,
1065 Unit);
1066 }
1067 }
1068
1069 Attribute = (List->CurrentDisk == DiskEntry &&
1070 List->CurrentPartition == PartEntry) ? 0x71 : 0x17;
1071
1072 if (List->Line >= 0 && List->Line <= Height)
1073 {
1074 FillConsoleOutputCharacter (' ',
1075 Width,
1076 coPos,
1077 &Written);
1078 }
1079 coPos.X += 4;
1080 Width -= 8;
1081 if (List->Line >= 0 && List->Line <= Height)
1082 {
1083 FillConsoleOutputAttribute (Attribute,
1084 Width,
1085 coPos,
1086 &Written);
1087 }
1088 coPos.X++;
1089 Width -= 2;
1090 if (List->Line >= 0 && List->Line <= Height)
1091 {
1092 WriteConsoleOutputCharacters (LineBuffer,
1093 min (strlen (LineBuffer), Width),
1094 coPos);
1095 }
1096 List->Line++;
1097 }
1098
1099
1100 static VOID
1101 PrintDiskData (PPARTLIST List,
1102 PDISKENTRY DiskEntry)
1103 {
1104 PPARTENTRY PartEntry;
1105 PLIST_ENTRY Entry;
1106 CHAR LineBuffer[128];
1107 COORD coPos;
1108 ULONG Written;
1109 USHORT Width;
1110 USHORT Height;
1111 ULONGLONG DiskSize;
1112 PCHAR Unit;
1113
1114 Width = List->Right - List->Left - 1;
1115 Height = List->Bottom - List->Top - 2;
1116
1117
1118 coPos.X = List->Left + 1;
1119 coPos.Y = List->Top + 1 + List->Line;
1120
1121 #if 0
1122 if (DiskEntry->DiskSize >= 0x280000000ULL) /* 10 GB */
1123 {
1124 DiskSize = (DiskEntry->DiskSize + (1 << 29)) >> 30;
1125 Unit = "GB";
1126 }
1127 else
1128 #endif
1129 {
1130 DiskSize = (DiskEntry->DiskSize + (1 << 19)) >> 20;
1131 if (DiskSize == 0)
1132 DiskSize = 1;
1133 Unit = "MB";
1134 }
1135
1136 if (DiskEntry->DriverName.Length > 0)
1137 {
1138 sprintf (LineBuffer,
1139 "%6I64u %s Harddisk %lu (Port=%hu, Bus=%hu, Id=%hu) on %wZ",
1140 DiskSize,
1141 Unit,
1142 DiskEntry->DiskNumber,
1143 DiskEntry->Port,
1144 DiskEntry->Bus,
1145 DiskEntry->Id,
1146 &DiskEntry->DriverName);
1147 }
1148 else
1149 {
1150 sprintf (LineBuffer,
1151 "%6I64u %s Harddisk %lu (Port=%hu, Bus=%hu, Id=%hu)",
1152 DiskSize,
1153 Unit,
1154 DiskEntry->DiskNumber,
1155 DiskEntry->Port,
1156 DiskEntry->Bus,
1157 DiskEntry->Id);
1158 }
1159 if (List->Line >= 0 && List->Line <= Height)
1160 {
1161 FillConsoleOutputAttribute (0x17,
1162 Width,
1163 coPos,
1164 &Written);
1165
1166 FillConsoleOutputCharacter (' ',
1167 Width,
1168 coPos,
1169 &Written);
1170 }
1171
1172 coPos.X++;
1173 if (List->Line >= 0 && List->Line <= Height)
1174 {
1175 WriteConsoleOutputCharacters (LineBuffer,
1176 min (strlen (LineBuffer), Width - 2),
1177 coPos);
1178 }
1179 List->Line++;
1180
1181 /* Print separator line */
1182 PrintEmptyLine (List);
1183
1184 /* Print partition lines*/
1185 Entry = DiskEntry->PartListHead.Flink;
1186 while (Entry != &DiskEntry->PartListHead)
1187 {
1188 PartEntry = CONTAINING_RECORD (Entry, PARTENTRY, ListEntry);
1189
1190 /* Print disk entry */
1191 PrintPartitionData (List,
1192 DiskEntry,
1193 PartEntry);
1194
1195 Entry = Entry->Flink;
1196 }
1197
1198 /* Print separator line */
1199 PrintEmptyLine (List);
1200 }
1201
1202
1203 VOID
1204 DrawPartitionList (PPARTLIST List)
1205 {
1206 PLIST_ENTRY Entry, Entry2;
1207 PDISKENTRY DiskEntry;
1208 PPARTENTRY PartEntry = NULL;
1209 COORD coPos;
1210 ULONG Written;
1211 SHORT i;
1212 SHORT CurrentDiskLine;
1213 SHORT CurrentPartLine;
1214 SHORT LastLine;
1215 BOOL CurrentPartLineFound = FALSE;
1216 BOOL CurrentDiskLineFound = FALSE;
1217
1218 /* Calculate the line of the current disk and partition */
1219 CurrentDiskLine = 0;
1220 CurrentPartLine = 0;
1221 LastLine = 0;
1222 Entry = List->DiskListHead.Flink;
1223 while (Entry != &List->DiskListHead)
1224 {
1225 DiskEntry = CONTAINING_RECORD (Entry, DISKENTRY, ListEntry);
1226 LastLine += 2;
1227 if (CurrentPartLineFound == FALSE)
1228 {
1229 CurrentPartLine += 2;
1230 }
1231 Entry2 = DiskEntry->PartListHead.Flink;
1232 while (Entry2 != &DiskEntry->PartListHead)
1233 {
1234 PartEntry = CONTAINING_RECORD (Entry2, PARTENTRY, ListEntry);
1235 if (PartEntry == List->CurrentPartition)
1236 {
1237 CurrentPartLineFound = TRUE;
1238 }
1239 Entry2 = Entry2->Flink;
1240 if (CurrentPartLineFound == FALSE)
1241 {
1242 CurrentPartLine++;
1243 }
1244 LastLine++;
1245 }
1246 if (DiskEntry == List->CurrentDisk)
1247 {
1248 CurrentDiskLineFound = TRUE;
1249 }
1250 Entry = Entry->Flink;
1251 if (Entry != &List->DiskListHead)
1252 {
1253 if (CurrentDiskLineFound == FALSE)
1254 {
1255 CurrentPartLine ++;
1256 CurrentDiskLine = CurrentPartLine;
1257 }
1258 LastLine++;
1259 }
1260 else
1261 {
1262 LastLine--;
1263 }
1264 }
1265
1266 /* If it possible, make the disk name visible */
1267 if (CurrentPartLine < List->Offset)
1268 {
1269 List->Offset = CurrentPartLine;
1270 }
1271 else if (CurrentPartLine - List->Offset > List->Bottom - List->Top - 2)
1272 {
1273 List->Offset = CurrentPartLine - (List->Bottom - List->Top - 2);
1274 }
1275 if (CurrentDiskLine < List->Offset && CurrentPartLine - CurrentDiskLine < List->Bottom - List->Top - 2)
1276 {
1277 List->Offset = CurrentDiskLine;
1278 }
1279
1280
1281 /* draw upper left corner */
1282 coPos.X = List->Left;
1283 coPos.Y = List->Top;
1284 FillConsoleOutputCharacter (0xDA, // '+',
1285 1,
1286 coPos,
1287 &Written);
1288
1289 /* draw upper edge */
1290 coPos.X = List->Left + 1;
1291 coPos.Y = List->Top;
1292 if (List->Offset == 0)
1293 {
1294 FillConsoleOutputCharacter (0xC4, // '-',
1295 List->Right - List->Left - 1,
1296 coPos,
1297 &Written);
1298 }
1299 else
1300 {
1301 FillConsoleOutputCharacter (0xC4, // '-',
1302 List->Right - List->Left - 5,
1303 coPos,
1304 &Written);
1305 coPos.X = List->Right - 5;
1306 WriteConsoleOutputCharacters ("(\x18)", // "(up)"
1307 3,
1308 coPos);
1309 coPos.X = List->Right - 2;
1310 FillConsoleOutputCharacter (0xC4, // '-',
1311 2,
1312 coPos,
1313 &Written);
1314 }
1315
1316 /* draw upper right corner */
1317 coPos.X = List->Right;
1318 coPos.Y = List->Top;
1319 FillConsoleOutputCharacter (0xBF, // '+',
1320 1,
1321 coPos,
1322 &Written);
1323
1324 /* draw left and right edge */
1325 for (i = List->Top + 1; i < List->Bottom; i++)
1326 {
1327 coPos.X = List->Left;
1328 coPos.Y = i;
1329 FillConsoleOutputCharacter (0xB3, // '|',
1330 1,
1331 coPos,
1332 &Written);
1333
1334 coPos.X = List->Right;
1335 FillConsoleOutputCharacter (0xB3, //'|',
1336 1,
1337 coPos,
1338 &Written);
1339 }
1340
1341 /* draw lower left corner */
1342 coPos.X = List->Left;
1343 coPos.Y = List->Bottom;
1344 FillConsoleOutputCharacter (0xC0, // '+',
1345 1,
1346 coPos,
1347 &Written);
1348
1349 /* draw lower edge */
1350 coPos.X = List->Left + 1;
1351 coPos.Y = List->Bottom;
1352 if (LastLine - List->Offset <= List->Bottom - List->Top - 2)
1353 {
1354 FillConsoleOutputCharacter (0xC4, // '-',
1355 List->Right - List->Left - 1,
1356 coPos,
1357 &Written);
1358 }
1359 else
1360 {
1361 FillConsoleOutputCharacter (0xC4, // '-',
1362 List->Right - List->Left - 5,
1363 coPos,
1364 &Written);
1365 coPos.X = List->Right - 5;
1366 WriteConsoleOutputCharacters ("(\x19)", // "(down)"
1367 3,
1368 coPos);
1369 coPos.X = List->Right - 2;
1370 FillConsoleOutputCharacter (0xC4, // '-',
1371 2,
1372 coPos,
1373 &Written);
1374 }
1375
1376 /* draw lower right corner */
1377 coPos.X = List->Right;
1378 coPos.Y = List->Bottom;
1379 FillConsoleOutputCharacter (0xD9, // '+',
1380 1,
1381 coPos,
1382 &Written);
1383
1384 /* print list entries */
1385 List->Line = - List->Offset;
1386
1387 Entry = List->DiskListHead.Flink;
1388 while (Entry != &List->DiskListHead)
1389 {
1390 DiskEntry = CONTAINING_RECORD (Entry, DISKENTRY, ListEntry);
1391
1392 /* Print disk entry */
1393 PrintDiskData (List,
1394 DiskEntry);
1395
1396 Entry = Entry->Flink;
1397 }
1398 }
1399
1400
1401 VOID
1402 SelectPartition(PPARTLIST List, ULONG DiskNumber, ULONG PartitionNumber)
1403 {
1404 PDISKENTRY DiskEntry;
1405 PPARTENTRY PartEntry;
1406 PLIST_ENTRY Entry1;
1407 PLIST_ENTRY Entry2;
1408 ULONG i;
1409
1410 /* Check for empty disks */
1411 if (IsListEmpty (&List->DiskListHead))
1412 return;
1413
1414 /* Check for first usable entry on next disk */
1415 Entry1 = List->CurrentDisk->ListEntry.Flink;
1416 while (Entry1 != &List->DiskListHead)
1417 {
1418 DiskEntry = CONTAINING_RECORD (Entry1, DISKENTRY, ListEntry);
1419
1420 if (DiskEntry->DiskNumber == DiskNumber)
1421 {
1422 Entry2 = DiskEntry->PartListHead.Flink;
1423 while (Entry2 != &DiskEntry->PartListHead)
1424 {
1425 PartEntry = CONTAINING_RECORD (Entry2, PARTENTRY, ListEntry);
1426
1427 for (i = 0; i < 4; i++)
1428 {
1429 if (PartEntry->PartInfo[i].PartitionNumber == PartitionNumber)
1430 {
1431 List->CurrentDisk = DiskEntry;
1432 List->CurrentPartition = PartEntry;
1433 DrawPartitionList (List);
1434 return;
1435 }
1436 }
1437 Entry2 = Entry2->Flink;
1438 }
1439 return;
1440 }
1441 Entry1 = Entry1->Flink;
1442 }
1443 }
1444
1445
1446 VOID
1447 ScrollDownPartitionList (PPARTLIST List)
1448 {
1449 PDISKENTRY DiskEntry;
1450 PPARTENTRY PartEntry;
1451 PLIST_ENTRY Entry1;
1452 PLIST_ENTRY Entry2;
1453
1454 /* Check for empty disks */
1455 if (IsListEmpty (&List->DiskListHead))
1456 return;
1457
1458 /* Check for next usable entry on current disk */
1459 if (List->CurrentPartition != NULL)
1460 {
1461 Entry2 = List->CurrentPartition->ListEntry.Flink;
1462 while (Entry2 != &List->CurrentDisk->PartListHead)
1463 {
1464 PartEntry = CONTAINING_RECORD (Entry2, PARTENTRY, ListEntry);
1465
1466 // if (PartEntry->HidePartEntry == FALSE)
1467 {
1468 List->CurrentPartition = PartEntry;
1469 DrawPartitionList (List);
1470 return;
1471 }
1472 Entry2 = Entry2->Flink;
1473 }
1474 }
1475
1476 /* Check for first usable entry on next disk */
1477 if (List->CurrentDisk != NULL)
1478 {
1479 Entry1 = List->CurrentDisk->ListEntry.Flink;
1480 while (Entry1 != &List->DiskListHead)
1481 {
1482 DiskEntry = CONTAINING_RECORD (Entry1, DISKENTRY, ListEntry);
1483
1484 Entry2 = DiskEntry->PartListHead.Flink;
1485 while (Entry2 != &DiskEntry->PartListHead)
1486 {
1487 PartEntry = CONTAINING_RECORD (Entry2, PARTENTRY, ListEntry);
1488
1489 // if (PartEntry->HidePartEntry == FALSE)
1490 {
1491 List->CurrentDisk = DiskEntry;
1492 List->CurrentPartition = PartEntry;
1493 DrawPartitionList (List);
1494 return;
1495 }
1496
1497 Entry2 = Entry2->Flink;
1498 }
1499
1500 Entry1 = Entry1->Flink;
1501 }
1502 }
1503 }
1504
1505
1506 VOID
1507 ScrollUpPartitionList (PPARTLIST List)
1508 {
1509 PDISKENTRY DiskEntry;
1510 PPARTENTRY PartEntry;
1511 PLIST_ENTRY Entry1;
1512 PLIST_ENTRY Entry2;
1513
1514 /* Check for empty disks */
1515 if (IsListEmpty (&List->DiskListHead))
1516 return;
1517
1518 /* check for previous usable entry on current disk */
1519 if (List->CurrentPartition != NULL)
1520 {
1521 Entry2 = List->CurrentPartition->ListEntry.Blink;
1522 while (Entry2 != &List->CurrentDisk->PartListHead)
1523 {
1524 PartEntry = CONTAINING_RECORD (Entry2, PARTENTRY, ListEntry);
1525
1526 // if (PartEntry->HidePartEntry == FALSE)
1527 {
1528 List->CurrentPartition = PartEntry;
1529 DrawPartitionList (List);
1530 return;
1531 }
1532 Entry2 = Entry2->Blink;
1533 }
1534 }
1535
1536
1537 /* check for last usable entry on previous disk */
1538 if (List->CurrentDisk != NULL)
1539 {
1540 Entry1 = List->CurrentDisk->ListEntry.Blink;
1541 while (Entry1 != &List->DiskListHead)
1542 {
1543 DiskEntry = CONTAINING_RECORD (Entry1, DISKENTRY, ListEntry);
1544
1545 Entry2 = DiskEntry->PartListHead.Blink;
1546 while (Entry2 != &DiskEntry->PartListHead)
1547 {
1548 PartEntry = CONTAINING_RECORD (Entry2, PARTENTRY, ListEntry);
1549
1550 // if (PartEntry->HidePartEntry == FALSE)
1551 {
1552 List->CurrentDisk = DiskEntry;
1553 List->CurrentPartition = PartEntry;
1554 DrawPartitionList (List);
1555 return;
1556 }
1557
1558 Entry2 = Entry2->Blink;
1559 }
1560
1561 Entry1 = Entry1->Blink;
1562 }
1563 }
1564 }
1565
1566
1567 static PPARTENTRY
1568 GetPrevPartitionedEntry (PDISKENTRY DiskEntry,
1569 PPARTENTRY CurrentEntry)
1570 {
1571 PPARTENTRY PrevEntry;
1572 PLIST_ENTRY Entry;
1573
1574 if (CurrentEntry->ListEntry.Blink == &DiskEntry->PartListHead)
1575 return NULL;
1576
1577 Entry = CurrentEntry->ListEntry.Blink;
1578 while (Entry != &DiskEntry->PartListHead)
1579 {
1580 PrevEntry = CONTAINING_RECORD (Entry,
1581 PARTENTRY,
1582 ListEntry);
1583 if (PrevEntry->Unpartitioned == FALSE)
1584 return PrevEntry;
1585
1586 Entry = Entry->Blink;
1587 }
1588
1589 return NULL;
1590 }
1591
1592
1593 static PPARTENTRY
1594 GetNextPartitionedEntry (PDISKENTRY DiskEntry,
1595 PPARTENTRY CurrentEntry)
1596 {
1597 PPARTENTRY NextEntry;
1598 PLIST_ENTRY Entry;
1599
1600 if (CurrentEntry->ListEntry.Flink == &DiskEntry->PartListHead)
1601 return NULL;
1602
1603 Entry = CurrentEntry->ListEntry.Flink;
1604 while (Entry != &DiskEntry->PartListHead)
1605 {
1606 NextEntry = CONTAINING_RECORD (Entry,
1607 PARTENTRY,
1608 ListEntry);
1609 if (NextEntry->Unpartitioned == FALSE)
1610 return NextEntry;
1611
1612 Entry = Entry->Flink;
1613 }
1614
1615 return NULL;
1616 }
1617
1618
1619 static PPARTENTRY
1620 GetPrevUnpartitionedEntry (PDISKENTRY DiskEntry,
1621 PPARTENTRY PartEntry)
1622 {
1623 PPARTENTRY PrevPartEntry;
1624
1625 if (PartEntry->ListEntry.Blink != &DiskEntry->PartListHead)
1626 {
1627 PrevPartEntry = CONTAINING_RECORD (PartEntry->ListEntry.Blink,
1628 PARTENTRY,
1629 ListEntry);
1630 if (PrevPartEntry->Unpartitioned == TRUE)
1631 return PrevPartEntry;
1632 }
1633
1634 return NULL;
1635 }
1636
1637
1638 static PPARTENTRY
1639 GetNextUnpartitionedEntry (PDISKENTRY DiskEntry,
1640 PPARTENTRY PartEntry)
1641 {
1642 PPARTENTRY NextPartEntry;
1643
1644 if (PartEntry->ListEntry.Flink != &DiskEntry->PartListHead)
1645 {
1646 NextPartEntry = CONTAINING_RECORD (PartEntry->ListEntry.Flink,
1647 PARTENTRY,
1648 ListEntry);
1649 if (NextPartEntry->Unpartitioned == TRUE)
1650 return NextPartEntry;
1651 }
1652
1653 return NULL;
1654 }
1655
1656
1657 VOID
1658 CreateNewPartition (PPARTLIST List,
1659 ULONGLONG PartitionSize,
1660 BOOLEAN AutoCreate)
1661 {
1662 PDISKENTRY DiskEntry;
1663 PPARTENTRY PartEntry;
1664 PPARTENTRY PrevPartEntry;
1665 PPARTENTRY NextPartEntry;
1666 PPARTENTRY NewPartEntry;
1667
1668 if (List == NULL ||
1669 List->CurrentDisk == NULL ||
1670 List->CurrentPartition == NULL ||
1671 List->CurrentPartition->Unpartitioned == FALSE)
1672 {
1673 return;
1674 }
1675
1676 DiskEntry = List->CurrentDisk;
1677 PartEntry = List->CurrentPartition;
1678
1679 if (AutoCreate == TRUE ||
1680 PartitionSize == PartEntry->UnpartitionedLength)
1681 {
1682 /* Convert current entry to 'new (unformatted)' */
1683 PartEntry->FormatState = Unformatted;
1684 PartEntry->PartInfo[0].StartingOffset.QuadPart =
1685 PartEntry->UnpartitionedOffset + DiskEntry->TrackSize;
1686 PartEntry->PartInfo[0].PartitionLength.QuadPart =
1687 PartEntry->UnpartitionedLength - DiskEntry->TrackSize;
1688 PartEntry->PartInfo[0].PartitionType = PARTITION_ENTRY_UNUSED;
1689 PartEntry->PartInfo[0].BootIndicator = FALSE; /* FIXME */
1690 PartEntry->PartInfo[0].RewritePartition = TRUE;
1691 PartEntry->PartInfo[1].RewritePartition = TRUE;
1692 PartEntry->PartInfo[2].RewritePartition = TRUE;
1693 PartEntry->PartInfo[3].RewritePartition = TRUE;
1694
1695 /* Get previous and next partition entries */
1696 PrevPartEntry = GetPrevPartitionedEntry (DiskEntry,
1697 PartEntry);
1698 NextPartEntry = GetNextPartitionedEntry (DiskEntry,
1699 PartEntry);
1700
1701 if (PrevPartEntry != NULL && NextPartEntry != NULL)
1702 {
1703 /* Current entry is in the middle of the list */
1704
1705 /* Copy previous container partition data to current entry */
1706 RtlCopyMemory (&PartEntry->PartInfo[1],
1707 &PrevPartEntry->PartInfo[1],
1708 sizeof(PARTITION_INFORMATION));
1709 PartEntry->PartInfo[1].RewritePartition = TRUE;
1710
1711 /* Update previous container partition data */
1712
1713 PrevPartEntry->PartInfo[1].StartingOffset.QuadPart =
1714 PartEntry->PartInfo[0].StartingOffset.QuadPart - DiskEntry->TrackSize;
1715
1716 if (DiskEntry->PartListHead.Flink == &PrevPartEntry->ListEntry)
1717 {
1718 /* Special case - previous partition is first partition */
1719 PrevPartEntry->PartInfo[1].PartitionLength.QuadPart =
1720 DiskEntry->DiskSize - PrevPartEntry->PartInfo[1].StartingOffset.QuadPart;
1721 }
1722 else
1723 {
1724 PrevPartEntry->PartInfo[1].PartitionLength.QuadPart =
1725 PartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize;
1726 }
1727
1728 PrevPartEntry->PartInfo[1].RewritePartition = TRUE;
1729 }
1730 else if (PrevPartEntry == NULL && NextPartEntry != NULL)
1731 {
1732 /* Current entry is the first entry */
1733 return;
1734 }
1735 else if (PrevPartEntry != NULL && NextPartEntry == NULL)
1736 {
1737 /* Current entry is the last entry */
1738
1739 PrevPartEntry->PartInfo[1].StartingOffset.QuadPart =
1740 PartEntry->PartInfo[0].StartingOffset.QuadPart - DiskEntry->TrackSize;
1741
1742 if (DiskEntry->PartListHead.Flink == &PrevPartEntry->ListEntry)
1743 {
1744 /* Special case - previous partition is first partition */
1745 PrevPartEntry->PartInfo[1].PartitionLength.QuadPart =
1746 DiskEntry->DiskSize - PrevPartEntry->PartInfo[1].StartingOffset.QuadPart;
1747 }
1748 else
1749 {
1750 PrevPartEntry->PartInfo[1].PartitionLength.QuadPart =
1751 PartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize;
1752 }
1753
1754 if ((PartEntry->PartInfo[1].StartingOffset.QuadPart +
1755 PartEntry->PartInfo[1].PartitionLength.QuadPart) <
1756 (1024LL * 255LL * 63LL * 512LL))
1757 {
1758 PrevPartEntry->PartInfo[1].PartitionType = PARTITION_EXTENDED;
1759 }
1760 else
1761 {
1762 PrevPartEntry->PartInfo[1].PartitionType = PARTITION_XINT13_EXTENDED;
1763 }
1764
1765 PrevPartEntry->PartInfo[1].BootIndicator = FALSE;
1766 PrevPartEntry->PartInfo[1].RewritePartition = TRUE;
1767 }
1768
1769 PartEntry->AutoCreate = AutoCreate;
1770 PartEntry->New = TRUE;
1771 PartEntry->Unpartitioned = FALSE;
1772 PartEntry->UnpartitionedOffset = 0ULL;
1773 PartEntry->UnpartitionedLength = 0ULL;
1774 }
1775 else
1776 {
1777 /* Insert an initialize a new partition entry */
1778 NewPartEntry = (PPARTENTRY)RtlAllocateHeap (ProcessHeap,
1779 0,
1780 sizeof(PARTENTRY));
1781 if (NewPartEntry == NULL)
1782 return;
1783
1784 RtlZeroMemory (NewPartEntry,
1785 sizeof(PARTENTRY));
1786
1787 /* Insert the new entry into the list */
1788 InsertTailList (&PartEntry->ListEntry,
1789 &NewPartEntry->ListEntry);
1790
1791 NewPartEntry->New = TRUE;
1792
1793 NewPartEntry->FormatState = Unformatted;
1794 NewPartEntry->PartInfo[0].StartingOffset.QuadPart =
1795 PartEntry->UnpartitionedOffset + DiskEntry->TrackSize;
1796 NewPartEntry->PartInfo[0].PartitionLength.QuadPart =
1797 PartitionSize - DiskEntry->TrackSize;
1798 NewPartEntry->PartInfo[0].PartitionType = PARTITION_ENTRY_UNUSED;
1799 NewPartEntry->PartInfo[0].BootIndicator = FALSE; /* FIXME */
1800 NewPartEntry->PartInfo[0].RewritePartition = TRUE;
1801 NewPartEntry->PartInfo[1].RewritePartition = TRUE;
1802 NewPartEntry->PartInfo[2].RewritePartition = TRUE;
1803 NewPartEntry->PartInfo[3].RewritePartition = TRUE;
1804
1805 /* Get previous and next partition entries */
1806 PrevPartEntry = GetPrevPartitionedEntry (DiskEntry,
1807 NewPartEntry);
1808 NextPartEntry = GetNextPartitionedEntry (DiskEntry,
1809 NewPartEntry);
1810
1811 if (PrevPartEntry != NULL && NextPartEntry != NULL)
1812 {
1813 /* Current entry is in the middle of the list */
1814
1815 /* Copy previous container partition data to current entry */
1816 RtlCopyMemory (&NewPartEntry->PartInfo[1],
1817 &PrevPartEntry->PartInfo[1],
1818 sizeof(PARTITION_INFORMATION));
1819 NewPartEntry->PartInfo[1].RewritePartition = TRUE;
1820
1821 /* Update previous container partition data */
1822
1823 PrevPartEntry->PartInfo[1].StartingOffset.QuadPart =
1824 NewPartEntry->PartInfo[0].StartingOffset.QuadPart - DiskEntry->TrackSize;
1825
1826 if (DiskEntry->PartListHead.Flink == &PrevPartEntry->ListEntry)
1827 {
1828 /* Special case - previous partition is first partition */
1829 PrevPartEntry->PartInfo[1].PartitionLength.QuadPart =
1830 DiskEntry->DiskSize - PrevPartEntry->PartInfo[1].StartingOffset.QuadPart;
1831 }
1832 else
1833 {
1834 PrevPartEntry->PartInfo[1].PartitionLength.QuadPart =
1835 NewPartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize;
1836 }
1837
1838 PrevPartEntry->PartInfo[1].RewritePartition = TRUE;
1839 }
1840 else if (PrevPartEntry == NULL && NextPartEntry != NULL)
1841 {
1842 /* Current entry is the first entry */
1843 return;
1844 }
1845 else if (PrevPartEntry != NULL && NextPartEntry == NULL)
1846 {
1847 /* Current entry is the last entry */
1848
1849 PrevPartEntry->PartInfo[1].StartingOffset.QuadPart =
1850 NewPartEntry->PartInfo[0].StartingOffset.QuadPart - DiskEntry->TrackSize;
1851
1852 if (DiskEntry->PartListHead.Flink == &PrevPartEntry->ListEntry)
1853 {
1854 /* Special case - previous partition is first partition */
1855 PrevPartEntry->PartInfo[1].PartitionLength.QuadPart =
1856 DiskEntry->DiskSize - PrevPartEntry->PartInfo[1].StartingOffset.QuadPart;
1857 }
1858 else
1859 {
1860 PrevPartEntry->PartInfo[1].PartitionLength.QuadPart =
1861 NewPartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize;
1862 }
1863
1864 if ((PartEntry->PartInfo[1].StartingOffset.QuadPart +
1865 PartEntry->PartInfo[1].PartitionLength.QuadPart) <
1866 (1024LL * 255LL * 63LL * 512LL))
1867 {
1868 PrevPartEntry->PartInfo[1].PartitionType = PARTITION_EXTENDED;
1869 }
1870 else
1871 {
1872 PrevPartEntry->PartInfo[1].PartitionType = PARTITION_XINT13_EXTENDED;
1873 }
1874
1875 PrevPartEntry->PartInfo[1].BootIndicator = FALSE;
1876 PrevPartEntry->PartInfo[1].RewritePartition = TRUE;
1877 }
1878
1879 /* Update offset and size of the remaining unpartitioned disk space */
1880 PartEntry->UnpartitionedOffset += PartitionSize;
1881 PartEntry->UnpartitionedLength -= PartitionSize;
1882 }
1883
1884 DiskEntry->Modified = TRUE;
1885
1886 UpdatePartitionNumbers (DiskEntry);
1887
1888 AssignDriverLetters (List);
1889 }
1890
1891
1892 VOID
1893 DeleteCurrentPartition (PPARTLIST List)
1894 {
1895 PDISKENTRY DiskEntry;
1896 PPARTENTRY PartEntry;
1897 PPARTENTRY PrevPartEntry;
1898 PPARTENTRY NextPartEntry;
1899
1900 if (List == NULL ||
1901 List->CurrentDisk == NULL ||
1902 List->CurrentPartition == NULL ||
1903 List->CurrentPartition->Unpartitioned == TRUE)
1904 {
1905 return;
1906 }
1907
1908 DiskEntry = List->CurrentDisk;
1909 PartEntry = List->CurrentPartition;
1910
1911 /* Adjust container partition entries */
1912
1913 /* Get previous and next partition entries */
1914 PrevPartEntry = GetPrevPartitionedEntry (DiskEntry,
1915 PartEntry);
1916 NextPartEntry = GetNextPartitionedEntry (DiskEntry,
1917 PartEntry);
1918
1919 if (PrevPartEntry != NULL && NextPartEntry != NULL)
1920 {
1921 /* Current entry is in the middle of the list */
1922
1923 /*
1924 * The first extended partition can not be deleted
1925 * as long as other extended partitions are present.
1926 */
1927 if (PrevPartEntry->ListEntry.Blink == &DiskEntry->PartListHead)
1928 return;
1929
1930 /* Copy previous container partition data to current entry */
1931 RtlCopyMemory (&PrevPartEntry->PartInfo[1],
1932 &PartEntry->PartInfo[1],
1933 sizeof(PARTITION_INFORMATION));
1934 PrevPartEntry->PartInfo[1].RewritePartition = TRUE;
1935 }
1936 else if (PrevPartEntry == NULL && NextPartEntry != NULL)
1937 {
1938 /*
1939 * A primary partition can not be deleted as long as
1940 * extended partitions are present.
1941 */
1942 return;
1943 }
1944 else if (PrevPartEntry != NULL && NextPartEntry == NULL)
1945 {
1946 /* Current entry is the last entry */
1947 RtlZeroMemory (&PrevPartEntry->PartInfo[1],
1948 sizeof(PARTITION_INFORMATION));
1949 PrevPartEntry->PartInfo[1].RewritePartition = TRUE;
1950 }
1951
1952
1953 /* Adjust unpartitioned disk space entries */
1954
1955 /* Get pointer to previous and next unpartitioned entries */
1956 PrevPartEntry = GetPrevUnpartitionedEntry (DiskEntry,
1957 PartEntry);
1958
1959 NextPartEntry = GetNextUnpartitionedEntry (DiskEntry,
1960 PartEntry);
1961
1962 if (PrevPartEntry != NULL && NextPartEntry != NULL)
1963 {
1964 /* Merge previous, current and next unpartitioned entry */
1965
1966 /* Adjust the previous entries length */
1967 PrevPartEntry->UnpartitionedLength +=
1968 (PartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize +
1969 NextPartEntry->UnpartitionedLength);
1970
1971 /* Remove the current entry */
1972 RemoveEntryList (&PartEntry->ListEntry);
1973 RtlFreeHeap (ProcessHeap,
1974 0,
1975 PartEntry);
1976
1977 /* Remove the next entry */
1978 RemoveEntryList (&NextPartEntry->ListEntry);
1979 RtlFreeHeap (ProcessHeap,
1980 0,
1981 NextPartEntry);
1982
1983 /* Update current partition */
1984 List->CurrentPartition = PrevPartEntry;
1985 }
1986 else if (PrevPartEntry != NULL && NextPartEntry == NULL)
1987 {
1988 /* Merge current and previous unpartitioned entry */
1989
1990 /* Adjust the previous entries length */
1991 PrevPartEntry->UnpartitionedLength +=
1992 (PartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize);
1993
1994 /* Remove the current entry */
1995 RemoveEntryList (&PartEntry->ListEntry);
1996 RtlFreeHeap (ProcessHeap,
1997 0,
1998 PartEntry);
1999
2000 /* Update current partition */
2001 List->CurrentPartition = PrevPartEntry;
2002 }
2003 else if (PrevPartEntry == NULL && NextPartEntry != NULL)
2004 {
2005 /* Merge current and next unpartitioned entry */
2006
2007 /* Adjust the next entries offset and length */
2008 NextPartEntry->UnpartitionedOffset =
2009 PartEntry->PartInfo[0].StartingOffset.QuadPart - DiskEntry->TrackSize;
2010 NextPartEntry->UnpartitionedLength +=
2011 (PartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize);
2012
2013 /* Remove the current entry */
2014 RemoveEntryList (&PartEntry->ListEntry);
2015 RtlFreeHeap (ProcessHeap,
2016 0,
2017 PartEntry);
2018
2019 /* Update current partition */
2020 List->CurrentPartition = NextPartEntry;
2021 }
2022 else
2023 {
2024 /* Nothing to merge but change current entry */
2025 PartEntry->New = FALSE;
2026 PartEntry->Unpartitioned = TRUE;
2027 PartEntry->UnpartitionedOffset =
2028 PartEntry->PartInfo[0].StartingOffset.QuadPart - DiskEntry->TrackSize;
2029 PartEntry->UnpartitionedLength =
2030 PartEntry->PartInfo[0].PartitionLength.QuadPart + DiskEntry->TrackSize;
2031
2032 /* Wipe the partition table */
2033 RtlZeroMemory (&PartEntry->PartInfo,
2034 sizeof(PartEntry->PartInfo));
2035 }
2036
2037 DiskEntry->Modified = TRUE;
2038
2039 UpdatePartitionNumbers (DiskEntry);
2040
2041 AssignDriverLetters (List);
2042 }
2043
2044
2045 VOID
2046 CheckActiveBootPartition (PPARTLIST List)
2047 {
2048 PDISKENTRY DiskEntry;
2049 PPARTENTRY PartEntry;
2050
2051 /* Check for empty disk list */
2052 if (IsListEmpty (&List->DiskListHead))
2053 {
2054 List->ActiveBootDisk = NULL;
2055 List->ActiveBootPartition = NULL;
2056 return;
2057 }
2058
2059 #if 0
2060 if (List->ActiveBootDisk != NULL &&
2061 List->ActiveBootPartition != NULL)
2062 {
2063 /* We already have an active boot partition */
2064 return;
2065 }
2066 #endif
2067
2068 DiskEntry = CONTAINING_RECORD (List->DiskListHead.Flink,
2069 DISKENTRY,
2070 ListEntry);
2071
2072 /* Check for empty partition list */
2073 if (IsListEmpty (&DiskEntry->PartListHead))
2074 {
2075 List->ActiveBootDisk = NULL;
2076 List->ActiveBootPartition = NULL;
2077 return;
2078 }
2079
2080 PartEntry = CONTAINING_RECORD (DiskEntry->PartListHead.Flink,
2081 PARTENTRY,
2082 ListEntry);
2083
2084 /* Set active boot partition */
2085 if ((DiskEntry->NewDisk == TRUE) ||
2086 (PartEntry->PartInfo[0].BootIndicator == FALSE &&
2087 PartEntry->PartInfo[1].BootIndicator == FALSE &&
2088 PartEntry->PartInfo[2].BootIndicator == FALSE &&
2089 PartEntry->PartInfo[3].BootIndicator == FALSE))
2090 {
2091 PartEntry->PartInfo[0].BootIndicator = TRUE;
2092 PartEntry->PartInfo[0].RewritePartition = TRUE;
2093 DiskEntry->Modified = TRUE;
2094 }
2095
2096 /* FIXME: Might be incorrect if partitions were created by Linux FDISK */
2097 List->ActiveBootDisk = DiskEntry;
2098 List->ActiveBootPartition = PartEntry;
2099 }
2100
2101
2102 BOOLEAN
2103 CheckForLinuxFdiskPartitions (PPARTLIST List)
2104 {
2105 PDISKENTRY DiskEntry;
2106 PPARTENTRY PartEntry;
2107 PLIST_ENTRY Entry1;
2108 PLIST_ENTRY Entry2;
2109 ULONG PartitionCount;
2110 ULONG i;
2111
2112 Entry1 = List->DiskListHead.Flink;
2113 while (Entry1 != &List->DiskListHead)
2114 {
2115 DiskEntry = CONTAINING_RECORD (Entry1,
2116 DISKENTRY,
2117 ListEntry);
2118
2119 Entry2 = DiskEntry->PartListHead.Flink;
2120 while (Entry2 != &DiskEntry->PartListHead)
2121 {
2122 PartEntry = CONTAINING_RECORD (Entry2,
2123 PARTENTRY,
2124 ListEntry);
2125
2126 if (PartEntry->Unpartitioned == FALSE)
2127 {
2128 PartitionCount = 0;
2129
2130 for (i = 0; i < 4; i++)
2131 {
2132 if (!IsContainerPartition (PartEntry->PartInfo[i].PartitionType) &&
2133 PartEntry->PartInfo[i].PartitionLength.QuadPart != 0ULL)
2134 {
2135 PartitionCount++;
2136 }
2137 }
2138
2139 if (PartitionCount > 1)
2140 {
2141 return TRUE;
2142 }
2143 }
2144
2145 Entry2 = Entry2->Flink;
2146 }
2147
2148 Entry1 = Entry1->Flink;
2149 }
2150
2151 return FALSE;
2152 }
2153
2154
2155 BOOLEAN
2156 WritePartitionsToDisk (PPARTLIST List)
2157 {
2158 PDRIVE_LAYOUT_INFORMATION DriveLayout;
2159 OBJECT_ATTRIBUTES ObjectAttributes;
2160 IO_STATUS_BLOCK Iosb;
2161 WCHAR SrcPath[MAX_PATH];
2162 WCHAR DstPath[MAX_PATH];
2163 UNICODE_STRING Name;
2164 HANDLE FileHandle;
2165 PDISKENTRY DiskEntry;
2166 PPARTENTRY PartEntry;
2167 PLIST_ENTRY Entry1;
2168 PLIST_ENTRY Entry2;
2169 ULONG PartitionCount;
2170 ULONG DriveLayoutSize;
2171 ULONG Index;
2172 NTSTATUS Status;
2173
2174 if (List == NULL)
2175 {
2176 return TRUE;
2177 }
2178
2179 Entry1 = List->DiskListHead.Flink;
2180 while (Entry1 != &List->DiskListHead)
2181 {
2182 DiskEntry = CONTAINING_RECORD (Entry1,
2183 DISKENTRY,
2184 ListEntry);
2185
2186 if (DiskEntry->Modified == TRUE)
2187 {
2188 /* Count partitioned entries */
2189 PartitionCount = 0;
2190 Entry2 = DiskEntry->PartListHead.Flink;
2191 while (Entry2 != &DiskEntry->PartListHead)
2192 {
2193 PartEntry = CONTAINING_RECORD (Entry2,
2194 PARTENTRY,
2195 ListEntry);
2196 if (PartEntry->Unpartitioned == FALSE)
2197 {
2198 PartitionCount += 4;
2199 }
2200
2201 Entry2 = Entry2->Flink;
2202 }
2203
2204 if (PartitionCount > 0)
2205 {
2206 DriveLayoutSize = sizeof (DRIVE_LAYOUT_INFORMATION) +
2207 ((PartitionCount - 1) * sizeof (PARTITION_INFORMATION));
2208 DriveLayout = (PDRIVE_LAYOUT_INFORMATION)RtlAllocateHeap (ProcessHeap,
2209 0,
2210 DriveLayoutSize);
2211 if (DriveLayout == NULL)
2212 {
2213 DPRINT1 ("RtlAllocateHeap() failed\n");
2214 return FALSE;
2215 }
2216
2217 RtlZeroMemory (DriveLayout,
2218 DriveLayoutSize);
2219
2220 DriveLayout->PartitionCount = PartitionCount;
2221 if (DiskEntry->Signature == 0)
2222 {
2223 LARGE_INTEGER SystemTime;
2224 TIME_FIELDS TimeFields;
2225 PUCHAR Buffer;
2226
2227 NtQuerySystemTime (&SystemTime);
2228 RtlTimeToTimeFields (&SystemTime, &TimeFields);
2229
2230 Buffer = (PUCHAR)&DiskEntry->Signature;
2231 Buffer[0] = (UCHAR)(TimeFields.Year & 0xFF) + (UCHAR)(TimeFields.Hour & 0xFF);
2232 Buffer[1] = (UCHAR)(TimeFields.Year >> 8) + (UCHAR)(TimeFields.Minute & 0xFF);
2233 Buffer[2] = (UCHAR)(TimeFields.Month & 0xFF) + (UCHAR)(TimeFields.Second & 0xFF);
2234 Buffer[3] = (UCHAR)(TimeFields.Day & 0xFF) + (UCHAR)(TimeFields.Milliseconds & 0xFF);
2235
2236 /* FIXME:
2237 * check for an existing signature
2238 */
2239
2240 }
2241
2242 DriveLayout->Signature = DiskEntry->Signature;
2243
2244 Index = 0;
2245 Entry2 = DiskEntry->PartListHead.Flink;
2246 while (Entry2 != &DiskEntry->PartListHead)
2247 {
2248 PartEntry = CONTAINING_RECORD (Entry2,
2249 PARTENTRY,
2250 ListEntry);
2251 if (PartEntry->Unpartitioned == FALSE)
2252 {
2253 RtlCopyMemory (&DriveLayout->PartitionEntry[Index],
2254 &PartEntry->PartInfo[0],
2255 4 * sizeof (PARTITION_INFORMATION));
2256 Index += 4;
2257 }
2258
2259 Entry2 = Entry2->Flink;
2260 }
2261
2262 swprintf (DstPath,
2263 L"\\Device\\Harddisk%d\\Partition0",
2264 DiskEntry->DiskNumber);
2265 RtlInitUnicodeString (&Name,
2266 DstPath);
2267 InitializeObjectAttributes (&ObjectAttributes,
2268 &Name,
2269 0,
2270 NULL,
2271 NULL);
2272
2273 Status = NtOpenFile (&FileHandle,
2274 FILE_ALL_ACCESS,
2275 &ObjectAttributes,
2276 &Iosb,
2277 0,
2278 FILE_SYNCHRONOUS_IO_NONALERT);
2279 if (!NT_SUCCESS (Status))
2280 {
2281 DPRINT1 ("NtOpenFile() failed (Status %lx)\n", Status);
2282 return FALSE;
2283 }
2284
2285 Status = NtDeviceIoControlFile (FileHandle,
2286 NULL,
2287 NULL,
2288 NULL,
2289 &Iosb,
2290 IOCTL_DISK_SET_DRIVE_LAYOUT,
2291 DriveLayout,
2292 DriveLayoutSize,
2293 NULL,
2294 0);
2295 if (!NT_SUCCESS (Status))
2296 {
2297 DPRINT1 ("NtDeviceIoControlFile() failed (Status %lx)\n", Status);
2298 NtClose (FileHandle);
2299 return FALSE;
2300 }
2301
2302 RtlFreeHeap (ProcessHeap,
2303 0,
2304 DriveLayout);
2305
2306 NtClose (FileHandle);
2307
2308 /* Install MBR code if the disk is new */
2309 if (DiskEntry->NewDisk == TRUE)
2310 {
2311 wcscpy (SrcPath, SourceRootPath.Buffer);
2312 wcscat (SrcPath, L"\\loader\\dosmbr.bin");
2313
2314 DPRINT1 ("Install MBR bootcode: %S ==> %S\n",
2315 SrcPath, DstPath);
2316
2317 /* Install MBR bootcode */
2318 Status = InstallMbrBootCodeToDisk (SrcPath,
2319 DstPath);
2320 if (!NT_SUCCESS (Status))
2321 {
2322 DPRINT1 ("InstallMbrBootCodeToDisk() failed (Status %lx)\n",
2323 Status);
2324 return FALSE;
2325 }
2326
2327 DiskEntry->NewDisk = FALSE;
2328 }
2329 }
2330 }
2331
2332 Entry1 = Entry1->Flink;
2333 }
2334
2335 return TRUE;
2336 }
2337
2338 BOOL SetMountedDeviceValues(PPARTLIST List)
2339 {
2340 PLIST_ENTRY Entry1, Entry2;
2341 PDISKENTRY DiskEntry;
2342 PPARTENTRY PartEntry;
2343
2344 if (List == NULL)
2345 {
2346 return FALSE;
2347 }
2348
2349 Entry1 = List->DiskListHead.Flink;
2350 while (Entry1 != &List->DiskListHead)
2351 {
2352 DiskEntry = CONTAINING_RECORD (Entry1,
2353 DISKENTRY,
2354 ListEntry);
2355
2356 Entry2 = DiskEntry->PartListHead.Flink;
2357 while (Entry2 != &DiskEntry->PartListHead)
2358 {
2359 PartEntry = CONTAINING_RECORD(Entry2, PARTENTRY, ListEntry);
2360 if (!PartEntry->Unpartitioned && PartEntry->DriveLetter)
2361 {
2362 if (!SetMountedDeviceValue(PartEntry->DriveLetter, DiskEntry->Signature, PartEntry->PartInfo[0].StartingOffset))
2363 {
2364 return FALSE;
2365 }
2366 }
2367 Entry2 = Entry2->Flink;
2368 }
2369 Entry1 = Entry1->Flink;
2370 }
2371 return TRUE;
2372 }
2373
2374
2375
2376 /* EOF */