3 * Copyright (C) 2002 ReactOS Team
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.
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.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 /* $Id: partlist.c,v 1.11 2003/08/02 16:49:36 ekohl Exp $
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS text-mode setup
22 * FILE: subsys/system/usetup/partlist.c
23 * PURPOSE: Partition list functions
24 * PROGRAMMER: Eric Kohl
25 * Casper S. Hornstrup (chorns@users.sourceforge.net)
28 #include <ddk/ntddk.h>
29 #include <ddk/ntddscsi.h>
31 #include <ntdll/rtl.h>
33 #include <ntos/minmax.h>
41 /* FUNCTIONS ****************************************************************/
44 GetDriverName(PDISKENTRY DiskEntry
)
46 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
50 RtlInitUnicodeString(&DiskEntry
->DriverName
,
54 L
"\\Scsi\\Scsi Port %lu",
57 RtlZeroMemory(&QueryTable
,
60 QueryTable
[0].Name
= L
"Driver";
61 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
;
62 QueryTable
[0].EntryContext
= &DiskEntry
->DriverName
;
64 Status
= RtlQueryRegistryValues(RTL_REGISTRY_DEVICEMAP
,
69 if (!NT_SUCCESS(Status
))
71 DPRINT1("RtlQueryRegistryValues() failed (Status %lx)\n", Status
);
77 AddPartitionToList (ULONG DiskNumber
,
79 DRIVE_LAYOUT_INFORMATION
*LayoutBuffer
)
84 BOOLEAN LastEntryWasUnused
;
85 ULONGLONG LastStartingOffset
;
86 ULONGLONG LastPartitionSize
;
87 ULONGLONG LastUnusedPartitionSize
;
88 ULONG LastUnusedEntry
;
92 * Determine required number of partiton entries.
93 * This must include entries for unused disk space.
96 /* Check for unpartitioned disk */
97 if (LayoutBuffer
->PartitionCount
== 0)
103 EntryCount
= LayoutBuffer
->PartitionCount
;
107 DiskEntry
->PartArray
= (PPARTENTRY
)RtlAllocateHeap(ProcessHeap
,
109 EntryCount
* sizeof(PARTENTRY
));
110 DiskEntry
->PartCount
= EntryCount
;
112 RtlZeroMemory(DiskEntry
->PartArray
,
113 EntryCount
* sizeof(PARTENTRY
));
115 if (LayoutBuffer
->PartitionCount
== 0)
117 /* Initialize an 'Unpartitioned space' entry */
118 PartEntry
= &DiskEntry
->PartArray
[0];
120 PartEntry
->Unpartitioned
= TRUE
;
121 // Start partition at head 1, cylinder 0
122 PartEntry
->StartingOffset
= DiskEntry
->SectorsPerTrack
* DiskEntry
->BytesPerSector
;
123 PartEntry
->PartSize
= DiskEntry
->DiskSize
- PartEntry
->StartingOffset
;
124 PartEntry
->Used
= FALSE
;
125 PartEntry
->HidePartEntry
= FALSE
;
126 PartEntry
->PartNumber
= 1;
130 LastEntryWasUnused
= FALSE
;
131 // Start partition at head 1, cylinder 0
132 LastStartingOffset
= DiskEntry
->SectorsPerTrack
* DiskEntry
->BytesPerSector
;
133 LastPartitionSize
= 0;
134 LastUnusedEntry
= -1;
135 LastUnusedPartitionSize
= 0;
136 for (i
= 0; i
< LayoutBuffer
->PartitionCount
; i
++)
138 PartEntry
= &DiskEntry
->PartArray
[i
];
140 if ((LayoutBuffer
->PartitionEntry
[i
].PartitionType
!= PARTITION_ENTRY_UNUSED
) &&
141 (!IsContainerPartition(LayoutBuffer
->PartitionEntry
[i
].PartitionType
)))
143 LastUnusedPartitionSize
= LayoutBuffer
->PartitionEntry
[i
].StartingOffset
.QuadPart
144 - (LastStartingOffset
+ LastPartitionSize
);
145 if (LastUnusedEntry
!= -1)
147 DiskEntry
->PartArray
[LastUnusedEntry
].StartingOffset
= LastStartingOffset
+ LastPartitionSize
;
148 DiskEntry
->PartArray
[LastUnusedEntry
].PartSize
= LastUnusedPartitionSize
;
149 DiskEntry
->PartArray
[LastUnusedEntry
].PartNumber
= LastUnusedEntry
+ 1; /* FIXME: Is this always correct? */
151 LastStartingOffset
= LayoutBuffer
->PartitionEntry
[i
].StartingOffset
.QuadPart
;
152 LastPartitionSize
= LayoutBuffer
->PartitionEntry
[i
].PartitionLength
.QuadPart
;
154 PartEntry
->StartingOffset
= LayoutBuffer
->PartitionEntry
[i
].StartingOffset
.QuadPart
;
155 PartEntry
->PartSize
= LayoutBuffer
->PartitionEntry
[i
].PartitionLength
.QuadPart
;
156 PartEntry
->PartNumber
= LayoutBuffer
->PartitionEntry
[i
].PartitionNumber
,
157 PartEntry
->PartType
= LayoutBuffer
->PartitionEntry
[i
].PartitionType
;
158 PartEntry
->Active
= LayoutBuffer
->PartitionEntry
[i
].BootIndicator
;
160 PartEntry
->DriveLetter
= GetDriveLetter(DiskNumber
,
161 LayoutBuffer
->PartitionEntry
[i
].PartitionNumber
);
163 PartEntry
->Unpartitioned
= FALSE
;
165 PartEntry
->Used
= TRUE
;
166 PartEntry
->HidePartEntry
= FALSE
;
167 LastEntryWasUnused
= FALSE
;
168 LastUnusedEntry
= -1;
172 if (LastEntryWasUnused
)
174 /* Group unused entries into one unpartitioned disk space area */
175 PartEntry
->HidePartEntry
= TRUE
;
176 PartEntry
->PartSize
= 0;
183 PartEntry
->Unpartitioned
= TRUE
;
185 PartEntry
->Used
= FALSE
;
186 LastEntryWasUnused
= TRUE
;
189 LastUnusedPartitionSize
= DiskEntry
->DiskSize
190 - (LastStartingOffset
+ LastPartitionSize
);
191 if (LastUnusedEntry
!= -1)
193 DiskEntry
->PartArray
[LastUnusedEntry
].StartingOffset
= LastStartingOffset
+ LastPartitionSize
;
194 DiskEntry
->PartArray
[LastUnusedEntry
].PartSize
= LastUnusedPartitionSize
;
195 DiskEntry
->PartArray
[LastUnusedEntry
].PartNumber
= LastUnusedEntry
+ 1; /* FIXME: Is this always correct? */
202 AddDiskToList (HANDLE FileHandle
,
206 DRIVE_LAYOUT_INFORMATION
*LayoutBuffer
;
207 DISK_GEOMETRY DiskGeometry
;
208 SCSI_ADDRESS ScsiAddress
;
209 PDISKENTRY DiskEntry
;
210 IO_STATUS_BLOCK Iosb
;
213 Status
= NtDeviceIoControlFile (FileHandle
,
218 IOCTL_DISK_GET_DRIVE_GEOMETRY
,
222 sizeof(DISK_GEOMETRY
));
223 if (!NT_SUCCESS(Status
))
228 if (DiskGeometry
.MediaType
!= FixedMedia
)
233 Status
= NtDeviceIoControlFile (FileHandle
,
238 IOCTL_SCSI_GET_ADDRESS
,
242 sizeof(SCSI_ADDRESS
));
243 if (!NT_SUCCESS(Status
))
248 DiskEntry
= (PDISKENTRY
)RtlAllocateHeap (ProcessHeap
,
251 if (DiskEntry
== NULL
)
256 DiskEntry
->Cylinders
= DiskGeometry
.Cylinders
.QuadPart
;
257 DiskEntry
->TracksPerCylinder
= DiskGeometry
.TracksPerCylinder
;
258 DiskEntry
->SectorsPerTrack
= DiskGeometry
.SectorsPerTrack
;
259 DiskEntry
->BytesPerSector
= DiskGeometry
.BytesPerSector
;
261 DPRINT("Cylinders %d\n", DiskEntry
->Cylinders
);
262 DPRINT("TracksPerCylinder %d\n", DiskEntry
->TracksPerCylinder
);
263 DPRINT("SectorsPerTrack %d\n", DiskEntry
->SectorsPerTrack
);
264 DPRINT("BytesPerSector %d\n", DiskEntry
->BytesPerSector
);
266 DiskEntry
->DiskSize
=
267 DiskGeometry
.Cylinders
.QuadPart
*
268 (ULONGLONG
)DiskGeometry
.TracksPerCylinder
*
269 (ULONGLONG
)DiskGeometry
.SectorsPerTrack
*
270 (ULONGLONG
)DiskGeometry
.BytesPerSector
;
271 DiskEntry
->DiskNumber
= DiskNumber
;
272 DiskEntry
->Port
= ScsiAddress
.PortNumber
;
273 DiskEntry
->Bus
= ScsiAddress
.PathId
;
274 DiskEntry
->Id
= ScsiAddress
.TargetId
;
276 GetDriverName (DiskEntry
);
278 InsertTailList (&List
->DiskList
, &DiskEntry
->ListEntry
);
280 LayoutBuffer
= (DRIVE_LAYOUT_INFORMATION
*)RtlAllocateHeap (ProcessHeap
,
283 if (LayoutBuffer
== NULL
)
288 Status
= NtDeviceIoControlFile (FileHandle
,
293 IOCTL_DISK_GET_DRIVE_LAYOUT
,
298 if (NT_SUCCESS (Status
))
300 AddPartitionToList (DiskNumber
,
305 RtlFreeHeap (ProcessHeap
,
312 InitializePartitionList(VOID
)
315 OBJECT_ATTRIBUTES ObjectAttributes
;
316 SYSTEM_DEVICE_INFORMATION Sdi
;
317 DISK_GEOMETRY DiskGeometry
;
318 IO_STATUS_BLOCK Iosb
;
322 WCHAR Buffer
[MAX_PATH
];
326 List
= (PPARTLIST
)RtlAllocateHeap(ProcessHeap
, 0, sizeof(PARTLIST
));
337 List
->TopDisk
= (ULONG
)-1;
338 List
->TopPartition
= (ULONG
)-1;
340 List
->CurrentDisk
= NULL
;
341 List
->CurrentPartition
= (ULONG
)-1;
343 InitializeListHead (&List
->DiskList
);
345 Status
= NtQuerySystemInformation(SystemDeviceInformation
,
347 sizeof(SYSTEM_DEVICE_INFORMATION
),
349 if (!NT_SUCCESS(Status
))
351 RtlFreeHeap(ProcessHeap
, 0, List
);
355 for (DiskNumber
= 0; DiskNumber
< Sdi
.NumberOfDisks
; DiskNumber
++)
358 L
"\\Device\\Harddisk%d\\Partition0",
360 RtlInitUnicodeString(&Name
,
363 InitializeObjectAttributes(&ObjectAttributes
,
369 Status
= NtOpenFile(&FileHandle
,
374 FILE_SYNCHRONOUS_IO_NONALERT
);
375 if (NT_SUCCESS(Status
))
377 AddDiskToList (FileHandle
,
386 List
->TopPartition
= 0;
388 /* Search for first usable disk and partition */
389 if (IsListEmpty (&List
->DiskList
))
391 List
->CurrentDisk
= NULL
;
392 List
->CurrentPartition
= (ULONG
)-1;
396 List
->CurrentDisk
= CONTAINING_RECORD(List
->DiskList
.Flink
, DISKENTRY
, ListEntry
);
397 List
->CurrentPartition
= 0;
405 CreatePartitionList(SHORT Left
,
412 List
= InitializePartitionList();
419 List
->Bottom
= Bottom
;
421 DrawPartitionList(List
);
428 GetPartitionInformation(PPARTLIST List
,
430 ULONG PartitionNumber
,
431 PULONG PartEntryNumber
)
433 PPARTENTRY PartEntry
;
436 if (IsListEmpty(&List
->DiskList
))
442 if (DiskNumber
>= List
->DiskCount
)
447 if (PartitionNumber
>= List
->DiskArray
[DiskNumber
].PartCount
)
452 if (List
->DiskArray
[DiskNumber
].FixedDisk
!= TRUE
)
457 for (i
= 0; i
< List
->DiskArray
[DiskNumber
].PartCount
; i
++)
459 PartEntry
= &List
->DiskArray
[DiskNumber
].PartArray
[i
];
460 if (PartEntry
->PartNumber
== PartitionNumber
)
462 *PartEntryNumber
= i
;
472 DestroyPartitionList(PPARTLIST List
)
475 PDISKENTRY DiskEntry
;
480 /* clear occupied screen area */
481 coPos
.X
= List
->Left
;
482 Width
= List
->Right
- List
->Left
+ 1;
483 for (coPos
.Y
= List
->Top
; coPos
.Y
<= List
->Bottom
; coPos
.Y
++)
485 FillConsoleOutputAttribute(0x17,
490 FillConsoleOutputCharacter(' ',
497 /* Release disk and partition info */
498 while (!IsListEmpty (&List
->DiskList
))
500 Entry
= RemoveHeadList (&List
->DiskList
);
501 DiskEntry
= CONTAINING_RECORD (Entry
, DISKENTRY
, ListEntry
);
503 /* Release driver name */
504 RtlFreeUnicodeString(&DiskEntry
->DriverName
);
506 /* Release partition array */
507 if (DiskEntry
->PartArray
!= NULL
)
509 RtlFreeHeap(ProcessHeap
, 0, DiskEntry
->PartArray
);
512 /* Release disk entry */
513 RtlFreeHeap (ProcessHeap
, 0, DiskEntry
);
516 /* Release list head */
517 RtlFreeHeap (ProcessHeap
, 0, List
);
522 PrintEmptyLine(PPARTLIST List
)
529 Width
= List
->Right
- List
->Left
- 1;
530 Height
= List
->Bottom
- List
->Top
- 1;
532 if (List
->Line
< 0 || List
->Line
> Height
)
535 coPos
.X
= List
->Left
+ 1;
536 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
538 FillConsoleOutputAttribute(0x17,
543 FillConsoleOutputCharacter(' ',
553 PrintPartitionData(PPARTLIST List
,
554 PDISKENTRY DiskEntry
,
557 PPARTENTRY PartEntry
;
558 CHAR LineBuffer
[128];
569 Width
= List
->Right
- List
->Left
- 1;
570 Height
= List
->Bottom
- List
->Top
- 1;
572 if (List
->Line
< 0 || List
->Line
> Height
)
575 coPos
.X
= List
->Left
+ 1;
576 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
578 PartEntry
= &DiskEntry
->PartArray
[PartIndex
];
580 /* Determine partition type */
582 if (PartEntry
->Unpartitioned
== FALSE
)
584 if ((PartEntry
->PartType
== PARTITION_FAT_12
) ||
585 (PartEntry
->PartType
== PARTITION_FAT_16
) ||
586 (PartEntry
->PartType
== PARTITION_HUGE
) ||
587 (PartEntry
->PartType
== PARTITION_XINT13
))
591 else if ((PartEntry
->PartType
== PARTITION_FAT32
) ||
592 (PartEntry
->PartType
== PARTITION_FAT32_XINT13
))
596 else if (PartEntry
->PartType
== PARTITION_IFS
)
598 PartType
= "NTFS"; /* FIXME: Not quite correct! */
604 if (PartEntry
->PartSize
>= 0x280000000ULL
) /* 10 GB */
606 PartSize
= (PartEntry
->PartSize
+ (1 << 29)) >> 30;
611 if (PartEntry
->PartSize
>= 0xA00000ULL
) /* 10 MB */
613 PartSize
= (PartEntry
->PartSize
+ (1 << 19)) >> 20;
618 PartSize
= (PartEntry
->PartSize
+ (1 << 9)) >> 10;
623 if (PartEntry
->Unpartitioned
== TRUE
)
626 " Unpartitioned space %I64u %s",
630 else if (PartEntry
->DriveLetter
!= (CHAR
)0)
632 if (PartType
== NULL
)
635 "%c: Type %-3lu %I64u %s",
636 PartEntry
->DriveLetter
,
645 PartEntry
->DriveLetter
,
654 "-- %s Type -3lu %I64u %s",
655 PartEntry
->FileSystemName
,
661 Attribute
= (List
->CurrentDisk
== DiskEntry
&&
662 List
->CurrentPartition
== PartIndex
) ? 0x71 : 0x17;
664 FillConsoleOutputCharacter(' ',
671 FillConsoleOutputAttribute(Attribute
,
678 WriteConsoleOutputCharacters(LineBuffer
,
679 min(strlen(LineBuffer
), Width
),
687 PrintDiskData(PPARTLIST List
,
688 PDISKENTRY DiskEntry
)
690 CHAR LineBuffer
[128];
699 Width
= List
->Right
- List
->Left
- 1;
700 Height
= List
->Bottom
- List
->Top
- 1;
702 if (List
->Line
< 0 || List
->Line
> Height
)
705 coPos
.X
= List
->Left
+ 1;
706 coPos
.Y
= List
->Top
+ 1 + List
->Line
;
709 if (DiskEntry
->DiskSize
>= 0x280000000ULL
) /* 10 GB */
711 DiskSize
= (DiskEntry
->DiskSize
+ (1 << 29)) >> 30;
717 DiskSize
= (DiskEntry
->DiskSize
+ (1 << 19)) >> 20;
723 if (DiskEntry
->DriverName
.Length
> 0)
726 "%I64u %s Harddisk %lu (Port=%hu, Bus=%hu, Id=%hu) on %wZ",
729 DiskEntry
->DiskNumber
,
733 &DiskEntry
->DriverName
);
738 "%I64u %s Harddisk %lu (Port=%hu, Bus=%hu, Id=%hu)",
741 DiskEntry
->DiskNumber
,
747 FillConsoleOutputAttribute(0x17,
752 FillConsoleOutputCharacter(' ',
758 WriteConsoleOutputCharacters(LineBuffer
,
759 min(strlen(LineBuffer
), Width
- 2),
764 /* Print separator line */
765 PrintEmptyLine(List
);
767 /* Print partition lines*/
768 for (PartIndex
= 0; PartIndex
< DiskEntry
->PartCount
; PartIndex
++)
770 if (!DiskEntry
->PartArray
[PartIndex
].HidePartEntry
)
772 PrintPartitionData(List
,
778 /* Print separator line */
779 PrintEmptyLine(List
);
784 DrawPartitionList(PPARTLIST List
)
787 PDISKENTRY DiskEntry
;
788 CHAR LineBuffer
[128];
794 /* draw upper left corner */
795 coPos
.X
= List
->Left
;
797 FillConsoleOutputCharacter(0xDA, // '+',
802 /* draw upper edge */
803 coPos
.X
= List
->Left
+ 1;
805 FillConsoleOutputCharacter(0xC4, // '-',
806 List
->Right
- List
->Left
- 1,
810 /* draw upper right corner */
811 coPos
.X
= List
->Right
;
813 FillConsoleOutputCharacter(0xBF, // '+',
818 /* draw left and right edge */
819 for (i
= List
->Top
+ 1; i
< List
->Bottom
; i
++)
821 coPos
.X
= List
->Left
;
823 FillConsoleOutputCharacter(0xB3, // '|',
828 coPos
.X
= List
->Right
;
829 FillConsoleOutputCharacter(0xB3, //'|',
835 /* draw lower left corner */
836 coPos
.X
= List
->Left
;
837 coPos
.Y
= List
->Bottom
;
838 FillConsoleOutputCharacter(0xC0, // '+',
843 /* draw lower edge */
844 coPos
.X
= List
->Left
+ 1;
845 coPos
.Y
= List
->Bottom
;
846 FillConsoleOutputCharacter(0xC4, // '-',
847 List
->Right
- List
->Left
- 1,
851 /* draw lower right corner */
852 coPos
.X
= List
->Right
;
853 coPos
.Y
= List
->Bottom
;
854 FillConsoleOutputCharacter(0xD9, // '+',
859 /* print list entries */
862 Entry
= List
->DiskList
.Flink
;
863 while (Entry
!= &List
->DiskList
)
865 DiskEntry
= CONTAINING_RECORD (Entry
, DISKENTRY
, ListEntry
);
867 /* Print disk entry */
871 Entry
= Entry
->Flink
;
877 ScrollDownPartitionList(PPARTLIST List
)
880 PDISKENTRY DiskEntry
;
883 /* Check for empty disks */
884 if (IsListEmpty (&List
->DiskList
))
887 /* check for next usable entry on current disk */
888 for (i
= List
->CurrentPartition
+ 1; i
< List
->CurrentDisk
->PartCount
; i
++)
890 if (List
->CurrentDisk
->PartArray
[i
].HidePartEntry
== FALSE
)
892 List
->CurrentPartition
= i
;
893 DrawPartitionList(List
);
898 /* check for first usable entry on next disk */
899 Entry
= List
->CurrentDisk
->ListEntry
.Flink
;
900 while (Entry
!= &List
->DiskList
)
902 DiskEntry
= CONTAINING_RECORD (Entry
, DISKENTRY
, ListEntry
);
903 for (i
= 0; i
< DiskEntry
->PartCount
; i
++)
905 if (DiskEntry
->PartArray
[i
].HidePartEntry
== FALSE
)
907 List
->CurrentDisk
= DiskEntry
;
908 List
->CurrentPartition
= i
;
909 DrawPartitionList(List
);
913 Entry
= Entry
->Flink
;
919 ScrollUpPartitionList(PPARTLIST List
)
922 PDISKENTRY DiskEntry
;
925 /* Check for empty disks */
926 if (IsListEmpty (&List
->DiskList
))
929 /* check for previous usable entry on current disk */
930 for (i
= List
->CurrentPartition
- 1; i
!= (ULONG
)-1; i
--)
932 if (List
->CurrentDisk
->PartArray
[i
].HidePartEntry
== FALSE
)
934 List
->CurrentPartition
= i
;
935 DrawPartitionList(List
);
940 /* check for last usable entry on previous disk */
941 Entry
= List
->CurrentDisk
->ListEntry
.Blink
;
942 while (Entry
!= &List
->DiskList
)
944 DiskEntry
= CONTAINING_RECORD (Entry
, DISKENTRY
, ListEntry
);
945 for (i
= DiskEntry
->PartCount
- 1; i
!= (ULONG
)-1; i
--)
947 if (DiskEntry
->PartArray
[i
].HidePartEntry
== FALSE
)
949 List
->CurrentDisk
= DiskEntry
;
950 List
->CurrentPartition
= i
;
951 DrawPartitionList(List
);
955 Entry
= Entry
->Blink
;
961 GetSelectedPartition(PPARTLIST List
,
964 PDISKENTRY DiskEntry
;
965 PPARTENTRY PartEntry
;
967 if (List
->CurrentDisk
== NULL
)
970 DiskEntry
= List
->CurrentDisk
;
972 if (List
->CurrentPartition
>= DiskEntry
->PartCount
)
975 PartEntry
= &DiskEntry
->PartArray
[List
->CurrentPartition
];
977 if (PartEntry
->Used
== FALSE
)
982 /* Copy disk-specific data */
983 Data
->DiskSize
= DiskEntry
->DiskSize
;
984 Data
->DiskNumber
= DiskEntry
->DiskNumber
;
985 Data
->Port
= DiskEntry
->Port
;
986 Data
->Bus
= DiskEntry
->Bus
;
987 Data
->Id
= DiskEntry
->Id
;
989 /* Copy driver name */
990 RtlInitUnicodeString(&Data
->DriverName
,
992 if (DiskEntry
->DriverName
.Length
!= 0)
994 Data
->DriverName
.Buffer
= RtlAllocateHeap(ProcessHeap
,
996 DiskEntry
->DriverName
.MaximumLength
);
997 if (Data
->DriverName
.Buffer
!= NULL
)
999 Data
->DriverName
.MaximumLength
= DiskEntry
->DriverName
.MaximumLength
;
1000 Data
->DriverName
.Length
= DiskEntry
->DriverName
.Length
;
1001 RtlCopyMemory(Data
->DriverName
.Buffer
,
1002 DiskEntry
->DriverName
.Buffer
,
1003 DiskEntry
->DriverName
.MaximumLength
);
1007 /* Copy partition-specific data */
1008 Data
->CreatePartition
= FALSE
;
1009 Data
->NewPartSize
= 0;
1010 Data
->PartSize
= PartEntry
->PartSize
;
1011 Data
->PartNumber
= PartEntry
->PartNumber
;
1012 Data
->PartType
= PartEntry
->PartType
;
1013 Data
->DriveLetter
= PartEntry
->DriveLetter
;
1020 GetActiveBootPartition(PPARTLIST List
,
1023 PDISKENTRY DiskEntry
;
1024 PPARTENTRY PartEntry
;
1027 if (List
->CurrentDisk
== NULL
)
1030 DiskEntry
= List
->CurrentDisk
;
1032 for (i
= 0; i
< DiskEntry
->PartCount
; i
++)
1034 if (DiskEntry
->PartArray
[i
].Active
)
1036 PartEntry
= &DiskEntry
->PartArray
[i
];
1038 if (PartEntry
->Used
== FALSE
)
1043 /* Copy disk-specific data */
1044 Data
->DiskSize
= DiskEntry
->DiskSize
;
1045 Data
->DiskNumber
= DiskEntry
->DiskNumber
;
1046 Data
->Port
= DiskEntry
->Port
;
1047 Data
->Bus
= DiskEntry
->Bus
;
1048 Data
->Id
= DiskEntry
->Id
;
1050 /* Copy driver name */
1051 RtlInitUnicodeString(&Data
->DriverName
,
1053 if (DiskEntry
->DriverName
.Length
!= 0)
1055 Data
->DriverName
.Buffer
= RtlAllocateHeap(ProcessHeap
,
1057 DiskEntry
->DriverName
.MaximumLength
);
1058 if (Data
->DriverName
.Buffer
!= NULL
)
1060 Data
->DriverName
.MaximumLength
= DiskEntry
->DriverName
.MaximumLength
;
1061 Data
->DriverName
.Length
= DiskEntry
->DriverName
.Length
;
1062 RtlCopyMemory(Data
->DriverName
.Buffer
,
1063 DiskEntry
->DriverName
.Buffer
,
1064 DiskEntry
->DriverName
.MaximumLength
);
1068 /* Copy partition-specific data */
1069 Data
->PartSize
= PartEntry
->PartSize
;
1070 Data
->PartNumber
= PartEntry
->PartNumber
;
1071 Data
->PartType
= PartEntry
->PartType
;
1072 Data
->DriveLetter
= PartEntry
->DriveLetter
;
1083 CreateSelectedPartition(PPARTLIST List
,
1085 ULONGLONG NewPartSize
)
1087 PDISKENTRY DiskEntry
;
1088 PPARTENTRY PartEntry
;
1089 ULONG PartEntryNumber
;
1090 OBJECT_ATTRIBUTES ObjectAttributes
;
1091 DRIVE_LAYOUT_INFORMATION
*LayoutBuffer
;
1092 IO_STATUS_BLOCK Iosb
;
1094 WCHAR Buffer
[MAX_PATH
];
1095 UNICODE_STRING Name
;
1099 DiskEntry
= List
->CurrentDisk
;
1100 PartEntry
= &DiskEntry
->PartArray
[List
->CurrentPartition
];
1101 PartEntry
->PartType
= PartType
;
1102 PartEntryNumber
= List
->CurrentPartition
;
1104 DPRINT("NewPartSize %d (%d MB)\n", NewPartSize
, NewPartSize
/ (1024 * 1024));
1105 DPRINT("PartEntry->StartingOffset %d\n", PartEntry
->StartingOffset
);
1106 DPRINT("PartEntry->PartSize %d\n", PartEntry
->PartSize
);
1107 DPRINT("PartEntry->PartNumber %d\n", PartEntry
->PartNumber
);
1108 DPRINT("PartEntry->PartType 0x%x\n", PartEntry
->PartType
);
1109 DPRINT("PartEntry->FileSystemName %s\n", PartEntry
->FileSystemName
);
1112 L
"\\Device\\Harddisk%d\\Partition0",
1113 DiskEntry
->DiskNumber
);
1114 RtlInitUnicodeString(&Name
, Buffer
);
1116 InitializeObjectAttributes(&ObjectAttributes
,
1122 Status
= NtOpenFile(&FileHandle
,
1127 FILE_SYNCHRONOUS_IO_NONALERT
);
1128 if (NT_SUCCESS(Status
))
1130 LayoutBuffer
= (DRIVE_LAYOUT_INFORMATION
*)RtlAllocateHeap(ProcessHeap
, 0, 8192);
1132 Status
= NtDeviceIoControlFile(FileHandle
,
1137 IOCTL_DISK_GET_DRIVE_LAYOUT
,
1142 if (!NT_SUCCESS(Status
))
1144 DPRINT("IOCTL_DISK_GET_DRIVE_LAYOUT failed() 0x%.08x\n", Status
);
1145 NtClose(FileHandle
);
1146 RtlFreeHeap(ProcessHeap
, 0, LayoutBuffer
);
1150 li
.QuadPart
= PartEntry
->StartingOffset
;
1151 LayoutBuffer
->PartitionEntry
[PartEntryNumber
].StartingOffset
= li
;
1152 /* FIXME: Adjust PartitionLength so the partition will end on the last sector of a track */
1153 li
.QuadPart
= NewPartSize
;
1154 LayoutBuffer
->PartitionEntry
[PartEntryNumber
].PartitionLength
= li
;
1155 LayoutBuffer
->PartitionEntry
[PartEntryNumber
].HiddenSectors
=
1156 PartEntry
->StartingOffset
/ DiskEntry
->BytesPerSector
;
1157 LayoutBuffer
->PartitionEntry
[PartEntryNumber
].PartitionType
= PartType
;
1158 LayoutBuffer
->PartitionEntry
[PartEntryNumber
].RecognizedPartition
= TRUE
;
1159 LayoutBuffer
->PartitionEntry
[PartEntryNumber
].RewritePartition
= TRUE
;
1161 Status
= NtDeviceIoControlFile(FileHandle
,
1166 IOCTL_DISK_SET_DRIVE_LAYOUT
,
1171 if (!NT_SUCCESS(Status
))
1173 DPRINT("IOCTL_DISK_SET_DRIVE_LAYOUT failed() 0x%.08x\n", Status
);
1174 NtClose(FileHandle
);
1175 RtlFreeHeap(ProcessHeap
, 0, LayoutBuffer
);
1181 DPRINT("NtOpenFile failed() 0x%.08x\n", Status
);
1182 NtClose(FileHandle
);
1183 RtlFreeHeap(ProcessHeap
, 0, LayoutBuffer
);
1187 NtClose(FileHandle
);
1188 RtlFreeHeap(ProcessHeap
, 0, LayoutBuffer
);
1195 DeleteSelectedPartition(PPARTLIST List
)
1197 PDISKENTRY DiskEntry
;
1198 PPARTENTRY PartEntry
;
1199 ULONG PartEntryNumber
;
1200 OBJECT_ATTRIBUTES ObjectAttributes
;
1201 DRIVE_LAYOUT_INFORMATION
*LayoutBuffer
;
1202 IO_STATUS_BLOCK Iosb
;
1204 WCHAR Buffer
[MAX_PATH
];
1205 UNICODE_STRING Name
;
1209 DiskEntry
= List
->CurrentDisk
;
1210 PartEntry
= &DiskEntry
->PartArray
[List
->CurrentPartition
];
1211 PartEntry
->PartType
= PARTITION_ENTRY_UNUSED
;
1212 PartEntryNumber
= List
->CurrentPartition
;
1214 DPRINT1("DeleteSelectedPartition(PartEntryNumber = %d)\n", PartEntryNumber
);
1215 DPRINT1("PartEntry->StartingOffset %d\n", PartEntry
->StartingOffset
);
1216 DPRINT1("PartEntry->PartSize %d\n", PartEntry
->PartSize
);
1217 DPRINT1("PartEntry->PartNumber %d\n", PartEntry
->PartNumber
);
1218 DPRINT1("PartEntry->PartType 0x%x\n", PartEntry
->PartType
);
1219 DPRINT1("PartEntry->FileSystemName %s\n", PartEntry
->FileSystemName
);
1222 L
"\\Device\\Harddisk%d\\Partition0",
1223 DiskEntry
->DiskNumber
);
1224 RtlInitUnicodeString(&Name
, Buffer
);
1226 InitializeObjectAttributes(&ObjectAttributes
,
1232 Status
= NtOpenFile(&FileHandle
,
1237 FILE_SYNCHRONOUS_IO_NONALERT
);
1238 if (NT_SUCCESS(Status
))
1240 LayoutBuffer
= (DRIVE_LAYOUT_INFORMATION
*)RtlAllocateHeap(ProcessHeap
, 0, 8192);
1242 Status
= NtDeviceIoControlFile(FileHandle
,
1247 IOCTL_DISK_GET_DRIVE_LAYOUT
,
1252 if (!NT_SUCCESS(Status
))
1254 DPRINT("IOCTL_DISK_GET_DRIVE_LAYOUT failed() 0x%.08x\n", Status
);
1255 NtClose(FileHandle
);
1256 RtlFreeHeap(ProcessHeap
, 0, LayoutBuffer
);
1261 LayoutBuffer
->PartitionEntry
[PartEntryNumber
].StartingOffset
= li
;
1263 LayoutBuffer
->PartitionEntry
[PartEntryNumber
].PartitionLength
= li
;
1264 LayoutBuffer
->PartitionEntry
[PartEntryNumber
].HiddenSectors
= 0;
1265 LayoutBuffer
->PartitionEntry
[PartEntryNumber
].PartitionType
= 0;
1266 LayoutBuffer
->PartitionEntry
[PartEntryNumber
].RecognizedPartition
= FALSE
;
1267 LayoutBuffer
->PartitionEntry
[PartEntryNumber
].RewritePartition
= TRUE
;
1269 Status
= NtDeviceIoControlFile(FileHandle
,
1274 IOCTL_DISK_SET_DRIVE_LAYOUT
,
1279 if (!NT_SUCCESS(Status
))
1281 DPRINT("IOCTL_DISK_SET_DRIVE_LAYOUT failed() 0x%.08x\n", Status
);
1282 NtClose(FileHandle
);
1283 RtlFreeHeap(ProcessHeap
, 0, LayoutBuffer
);
1289 DPRINT("NtOpenFile failed() 0x%.08x\n", Status
);
1290 NtClose(FileHandle
);
1291 RtlFreeHeap(ProcessHeap
, 0, LayoutBuffer
);
1295 NtClose(FileHandle
);
1296 RtlFreeHeap(ProcessHeap
, 0, LayoutBuffer
);
1303 MarkPartitionActive (ULONG DiskNumber
,
1304 ULONG PartitionNumber
,
1305 PPARTDATA ActivePartition
)
1308 PPARTENTRY PartEntry
;
1309 ULONG PartEntryNumber
;
1310 OBJECT_ATTRIBUTES ObjectAttributes
;
1311 DRIVE_LAYOUT_INFORMATION
*LayoutBuffer
;
1312 IO_STATUS_BLOCK Iosb
;
1314 WCHAR Buffer
[MAX_PATH
];
1315 UNICODE_STRING Name
;
1318 List
= InitializePartitionList ();
1324 PartEntry
= GetPartitionInformation(List
,
1330 DestroyPartitionList(List
);
1336 L
"\\Device\\Harddisk%d\\Partition0",
1338 RtlInitUnicodeString(&Name
, Buffer
);
1340 InitializeObjectAttributes(&ObjectAttributes
,
1346 Status
= NtOpenFile(&FileHandle
,
1351 FILE_SYNCHRONOUS_IO_NONALERT
);
1352 if (NT_SUCCESS(Status
))
1354 LayoutBuffer
= (DRIVE_LAYOUT_INFORMATION
*)RtlAllocateHeap(ProcessHeap
, 0, 8192);
1356 Status
= NtDeviceIoControlFile(FileHandle
,
1361 IOCTL_DISK_GET_DRIVE_LAYOUT
,
1366 if (!NT_SUCCESS(Status
))
1368 NtClose(FileHandle
);
1369 RtlFreeHeap(ProcessHeap
, 0, LayoutBuffer
);
1370 DestroyPartitionList(List
);
1375 LayoutBuffer
->PartitionEntry
[PartEntryNumber
].BootIndicator
= TRUE
;
1377 Status
= NtDeviceIoControlFile(FileHandle
,
1382 IOCTL_DISK_SET_DRIVE_LAYOUT
,
1387 if (!NT_SUCCESS(Status
))
1389 NtClose(FileHandle
);
1390 RtlFreeHeap(ProcessHeap
, 0, LayoutBuffer
);
1391 DestroyPartitionList(List
);
1397 NtClose(FileHandle
);
1398 RtlFreeHeap(ProcessHeap
, 0, LayoutBuffer
);
1399 DestroyPartitionList(List
);
1403 NtClose(FileHandle
);
1404 RtlFreeHeap(ProcessHeap
, 0, LayoutBuffer
);
1406 PartEntry
->Active
= TRUE
;
1407 if (!GetActiveBootPartition(List
, ActivePartition
))
1409 DestroyPartitionList(List
);
1410 DPRINT("GetActiveBootPartition() failed\n");
1414 DestroyPartitionList(List
);