3 * Copyright (C) 2003 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 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.
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS text-mode setup
22 * FILE: base/setup/usetup/fslist.c
23 * PURPOSE: Filesystem list functions
24 * PROGRAMMER: Eric Kohl
25 * Casper S. Hornstrup (chorns@users.sourceforge.net)
33 /* FUNCTIONS ****************************************************************/
37 IN OUT PFILE_SYSTEM_LIST List
,
38 IN PCWSTR FileSystemName
,
39 IN FORMATEX FormatFunc
,
40 IN CHKDSKEX ChkdskFunc
)
42 PFILE_SYSTEM_ITEM Item
;
44 Item
= (PFILE_SYSTEM_ITEM
)RtlAllocateHeap(ProcessHeap
, 0, sizeof(FILE_SYSTEM_ITEM
));
48 Item
->FileSystemName
= FileSystemName
;
49 Item
->FormatFunc
= FormatFunc
;
50 Item
->ChkdskFunc
= ChkdskFunc
;
51 Item
->QuickFormat
= TRUE
;
52 InsertTailList(&List
->ListHead
, &Item
->ListEntry
);
57 Item
= (PFILE_SYSTEM_ITEM
)RtlAllocateHeap(ProcessHeap
, 0, sizeof(FILE_SYSTEM_ITEM
));
61 Item
->FileSystemName
= FileSystemName
;
62 Item
->FormatFunc
= FormatFunc
;
63 Item
->ChkdskFunc
= ChkdskFunc
;
64 Item
->QuickFormat
= FALSE
;
65 InsertTailList(&List
->ListHead
, &Item
->ListEntry
);
71 IN PFILE_SYSTEM_LIST List
,
72 IN PWSTR FileSystemName
)
74 PLIST_ENTRY ListEntry
;
75 PFILE_SYSTEM_ITEM Item
;
77 ListEntry
= List
->ListHead
.Flink
;
78 while (ListEntry
!= &List
->ListHead
)
80 Item
= CONTAINING_RECORD(ListEntry
, FILE_SYSTEM_ITEM
, ListEntry
);
81 if (Item
->FileSystemName
&& wcsicmp(FileSystemName
, Item
->FileSystemName
) == 0)
84 ListEntry
= ListEntry
->Flink
;
90 #if 0 // FIXME: To be fully enabled when our storage stack & al. will work better!
92 /* NOTE: Ripped & adapted from base/system/autochk/autochk.c */
95 IN
struct _PARTENTRY
* PartEntry
,
96 IN OUT PWSTR FileSystemName
,
97 IN SIZE_T FileSystemNameSize
)
101 IO_STATUS_BLOCK IoStatusBlock
;
102 PFILE_FS_ATTRIBUTE_INFORMATION FileFsAttribute
;
103 UCHAR Buffer
[sizeof(FILE_FS_ATTRIBUTE_INFORMATION
) + MAX_PATH
* sizeof(WCHAR
)];
105 OBJECT_ATTRIBUTES ObjectAttributes
;
106 UNICODE_STRING PartitionRootPath
;
107 WCHAR PathBuffer
[MAX_PATH
];
109 FileFsAttribute
= (PFILE_FS_ATTRIBUTE_INFORMATION
)Buffer
;
111 /* Set PartitionRootPath */
113 // L"\\Device\\Harddisk%lu\\Partition%lu", // Should work! But because ReactOS sucks atm. it actually doesn't work!!
114 L
"\\Device\\Harddisk%lu\\Partition%lu\\", // HACK: Use this as a temporary hack!
115 PartEntry
->DiskEntry
->DiskNumber
,
116 PartEntry
->PartitionNumber
);
117 RtlInitUnicodeString(&PartitionRootPath
, PathBuffer
);
118 DPRINT("PartitionRootPath: %wZ\n", &PartitionRootPath
);
120 /* Open the partition */
121 InitializeObjectAttributes(&ObjectAttributes
,
123 OBJ_CASE_INSENSITIVE
,
126 Status
= NtOpenFile(&FileHandle
, // PartitionHandle,
127 FILE_GENERIC_READ
/* | SYNCHRONIZE */,
131 0 /* FILE_SYNCHRONOUS_IO_NONALERT */);
132 if (!NT_SUCCESS(Status
))
134 DPRINT1("Failed to open partition %wZ, Status 0x%08lx\n", &PartitionRootPath
, Status
);
138 /* Retrieve the FS attributes */
139 Status
= NtQueryVolumeInformationFile(FileHandle
,
143 FileFsAttributeInformation
);
146 if (!NT_SUCCESS(Status
))
148 DPRINT1("NtQueryVolumeInformationFile failed for partition %wZ, Status 0x%08lx\n", &PartitionRootPath
, Status
);
152 if (FileSystemNameSize
* sizeof(WCHAR
) < FileFsAttribute
->FileSystemNameLength
+ sizeof(WCHAR
))
153 return STATUS_BUFFER_TOO_SMALL
;
155 RtlCopyMemory(FileSystemName
,
156 FileFsAttribute
->FileSystemName
,
157 FileFsAttribute
->FileSystemNameLength
);
158 FileSystemName
[FileFsAttribute
->FileSystemNameLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
160 return STATUS_SUCCESS
;
167 IN PFILE_SYSTEM_LIST FileSystemList
,
168 IN
struct _PARTENTRY
* PartEntry
)
170 PFILE_SYSTEM_ITEM CurrentFileSystem
;
171 PWSTR FileSystemName
= NULL
;
172 #if 0 // For code temporarily disabled below
174 WCHAR FsRecFileSystemName
[MAX_PATH
];
177 CurrentFileSystem
= PartEntry
->FileSystem
;
179 /* We have a file system, return it */
180 if (CurrentFileSystem
!= NULL
&& CurrentFileSystem
->FileSystemName
!= NULL
)
181 return CurrentFileSystem
;
183 DPRINT1("File system not found, try to guess one...\n");
185 CurrentFileSystem
= NULL
;
187 #if 0 // FIXME: To be fully enabled when our storage stack & al. will work better!
190 * We don't have one...
192 * Try to infer one using NT file system recognition.
194 Status
= _MyGetFileSystem(PartEntry
, FsRecFileSystemName
, ARRAYSIZE(FsRecFileSystemName
));
195 if (NT_SUCCESS(Status
) && *FsRecFileSystemName
)
197 /* Temporary HACK: map FAT32 back to FAT */
198 if (wcscmp(FsRecFileSystemName
, L
"FAT32") == 0)
199 wcscpy(FsRecFileSystemName
, L
"FAT");
201 FileSystemName
= FsRecFileSystemName
;
208 * We don't have one...
210 * Try to infer a preferred file system for this partition, given its ID.
212 * WARNING: This is partly a hack, since partitions with the same ID can
213 * be formatted with different file systems: for example, usual Linux
214 * partitions that are formatted in EXT2/3/4, ReiserFS, etc... have the
215 * same partition ID 0x83.
217 * The proper fix is to make a function that detects the existing FS
218 * from a given partition (not based on the partition ID).
219 * On the contrary, for unformatted partitions with a given ID, the
220 * following code is OK.
222 if ((PartEntry
->PartitionType
== PARTITION_FAT_12
) ||
223 (PartEntry
->PartitionType
== PARTITION_FAT_16
) ||
224 (PartEntry
->PartitionType
== PARTITION_HUGE
) ||
225 (PartEntry
->PartitionType
== PARTITION_XINT13
) ||
226 (PartEntry
->PartitionType
== PARTITION_FAT32
) ||
227 (PartEntry
->PartitionType
== PARTITION_FAT32_XINT13
))
229 FileSystemName
= L
"FAT";
231 else if (PartEntry
->PartitionType
== PARTITION_EXT2
)
233 // WARNING: See the warning above.
234 FileSystemName
= L
"EXT2";
236 else if (PartEntry
->PartitionType
== PARTITION_IFS
)
238 // WARNING: See the warning above.
239 FileSystemName
= L
"NTFS"; /* FIXME: Not quite correct! */
243 Quit
: // For code temporarily disabled above
246 // HACK: WARNING: We cannot write on this FS yet!
249 if (PartEntry
->PartitionType
== PARTITION_EXT2
|| PartEntry
->PartitionType
== PARTITION_IFS
)
250 DPRINT1("Recognized file system %S that doesn't support write support yet!\n", FileSystemName
);
253 DPRINT1("GetFileSystem -- PartitionType: 0x%02X ; FileSystemName (guessed): %S\n",
254 PartEntry
->PartitionType
, FileSystemName
? FileSystemName
: L
"None");
256 if (FileSystemName
!= NULL
)
257 CurrentFileSystem
= GetFileSystemByName(FileSystemList
, FileSystemName
);
259 return CurrentFileSystem
;
264 CreateFileSystemList(
267 IN BOOLEAN ForceFormat
,
268 IN PCWSTR SelectFileSystem
)
270 PFILE_SYSTEM_LIST List
;
271 PFILE_SYSTEM_ITEM Item
;
272 PLIST_ENTRY ListEntry
;
274 List
= (PFILE_SYSTEM_LIST
)RtlAllocateHeap(ProcessHeap
, 0, sizeof(FILE_SYSTEM_LIST
));
280 List
->Selected
= NULL
;
281 InitializeListHead(&List
->ListHead
);
283 AddProvider(List
, L
"FAT", VfatFormat
, VfatChkdsk
);
285 AddProvider(List
, L
"EXT2", Ext2Format
, Ext2Chkdsk
);
286 AddProvider(List
, L
"NTFS", NtfsFormat
, NtfsChkdsk
);
291 /* Add the 'Keep existing filesystem' dummy provider */
292 AddProvider(List
, NULL
, NULL
, NULL
);
295 /* Search for SelectFileSystem in list */
296 ListEntry
= List
->ListHead
.Flink
;
297 while (ListEntry
!= &List
->ListHead
)
299 Item
= CONTAINING_RECORD(ListEntry
, FILE_SYSTEM_ITEM
, ListEntry
);
300 if (Item
->FileSystemName
&& wcscmp(SelectFileSystem
, Item
->FileSystemName
) == 0)
302 List
->Selected
= Item
;
305 ListEntry
= ListEntry
->Flink
;
308 List
->Selected
= CONTAINING_RECORD(List
->ListHead
.Flink
, FILE_SYSTEM_ITEM
, ListEntry
);
314 DestroyFileSystemList(
315 IN PFILE_SYSTEM_LIST List
)
317 PLIST_ENTRY ListEntry
= List
->ListHead
.Flink
;
318 PFILE_SYSTEM_ITEM Item
;
321 while (ListEntry
!= &List
->ListHead
)
323 Item
= CONTAINING_RECORD(ListEntry
, FILE_SYSTEM_ITEM
, ListEntry
);
324 Next
= ListEntry
->Flink
;
326 RtlFreeHeap(ProcessHeap
, 0, Item
);
330 RtlFreeHeap(ProcessHeap
, 0, List
);
335 IN PFILE_SYSTEM_LIST List
)
337 PLIST_ENTRY ListEntry
;
338 PFILE_SYSTEM_ITEM Item
;
344 ListEntry
= List
->ListHead
.Flink
;
345 while (ListEntry
!= &List
->ListHead
)
347 Item
= CONTAINING_RECORD(ListEntry
, FILE_SYSTEM_ITEM
, ListEntry
);
349 coPos
.X
= List
->Left
;
350 coPos
.Y
= List
->Top
+ (SHORT
)Index
;
351 FillConsoleOutputAttribute(StdOutput
,
352 FOREGROUND_WHITE
| BACKGROUND_BLUE
,
356 FillConsoleOutputCharacterA(StdOutput
,
362 if (Item
->FileSystemName
)
364 if (Item
->QuickFormat
)
365 snprintf(Buffer
, sizeof(Buffer
), MUIGetString(STRING_FORMATDISK1
), Item
->FileSystemName
);
367 snprintf(Buffer
, sizeof(Buffer
), MUIGetString(STRING_FORMATDISK2
), Item
->FileSystemName
);
371 snprintf(Buffer
, sizeof(Buffer
), MUIGetString(STRING_KEEPFORMAT
));
374 if (ListEntry
== &List
->Selected
->ListEntry
)
375 CONSOLE_SetInvertedTextXY(List
->Left
,
376 List
->Top
+ (SHORT
)Index
,
379 CONSOLE_SetTextXY(List
->Left
,
380 List
->Top
+ (SHORT
)Index
,
383 ListEntry
= ListEntry
->Flink
;
388 ScrollDownFileSystemList(
389 IN PFILE_SYSTEM_LIST List
)
391 if (List
->Selected
->ListEntry
.Flink
!= &List
->ListHead
)
393 List
->Selected
= CONTAINING_RECORD(List
->Selected
->ListEntry
.Flink
, FILE_SYSTEM_ITEM
, ListEntry
);
394 DrawFileSystemList(List
);
399 ScrollUpFileSystemList(
400 IN PFILE_SYSTEM_LIST List
)
402 if (List
->Selected
->ListEntry
.Blink
!= &List
->ListHead
)
404 List
->Selected
= CONTAINING_RECORD(List
->Selected
->ListEntry
.Blink
, FILE_SYSTEM_ITEM
, ListEntry
);
405 DrawFileSystemList(List
);