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