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