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