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