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