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