2 * PROJECT: ReactOS Setup Library
3 * LICENSE: GPL-2.0+ (https://spdx.org/licenses/GPL-2.0+)
4 * PURPOSE: Filesystem support functions
5 * COPYRIGHT: Copyright 2002-2018 Eric Kohl
6 * Copyright 2003-2018 Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * Copyright 2017-2018 Hermes Belusca-Maito
11 // This is basically the code for listing available FileSystem providers
12 // (currently hardcoded in a list), and for performing a basic FileSystem
13 // recognition for a given disk partition.
15 // See also: https://git.reactos.org/?p=reactos.git;a=blob;f=reactos/dll/win32/fmifs/init.c;h=e895f5ef9cae4806123f6bbdd3dfed37ec1c8d33;hb=b9db9a4e377a2055f635b2fb69fef4e1750d219c
16 // for how to get FS providers in a dynamic way. In the (near) future we may
17 // consider merging some of this code with us into a fmifs / fsutil / fslib library...
20 /* INCLUDES *****************************************************************/
27 /** For FileSystems **/
28 #include <fslib/vfatlib.h>
29 #include <fslib/ext2lib.h>
30 // #include <fslib/ntfslib.h>
37 FILE_SYSTEM RegisteredFileSystems
[] =
39 { L
"FAT" , VfatFormat
, VfatChkdsk
},
40 // { L"FAT32", VfatFormat, VfatChkdsk },
42 { L
"EXT2" , Ext2Format
, Ext2Chkdsk
},
43 { L
"NTFS" , NtfsFormat
, NtfsChkdsk
}
48 /* FUNCTIONS ****************************************************************/
51 GetRegisteredFileSystems(OUT PULONG Count
)
53 *Count
= ARRAYSIZE(RegisteredFileSystems
);
54 return RegisteredFileSystems
;
59 // IN PFILE_SYSTEM_LIST List,
60 IN PCWSTR FileSystemName
)
62 #if 0 // Reenable when the list of registered FSes will again be dynamic
64 PLIST_ENTRY ListEntry
;
65 PFILE_SYSTEM_ITEM Item
;
67 ListEntry
= List
->ListHead
.Flink
;
68 while (ListEntry
!= &List
->ListHead
)
70 Item
= CONTAINING_RECORD(ListEntry
, FILE_SYSTEM_ITEM
, ListEntry
);
71 if (Item
->FileSystemName
&& wcsicmp(FileSystemName
, Item
->FileSystemName
) == 0)
74 ListEntry
= ListEntry
->Flink
;
80 PFILE_SYSTEM FileSystems
;
82 FileSystems
= GetRegisteredFileSystems(&Count
);
83 if (!FileSystems
|| Count
== 0)
88 if (FileSystems
->FileSystemName
&& wcsicmp(FileSystemName
, FileSystems
->FileSystemName
) == 0)
101 // FileSystem recognition (using NT OS functionality)
104 #if 0 // FIXME: To be fully enabled when our storage stack & al. will work better!
106 /* NOTE: Ripped & adapted from base/system/autochk/autochk.c */
109 IN
struct _PARTENTRY
* PartEntry
,
110 IN OUT PWSTR FileSystemName
,
111 IN SIZE_T FileSystemNameSize
)
115 IO_STATUS_BLOCK IoStatusBlock
;
116 PFILE_FS_ATTRIBUTE_INFORMATION FileFsAttribute
;
117 UCHAR Buffer
[sizeof(FILE_FS_ATTRIBUTE_INFORMATION
) + MAX_PATH
* sizeof(WCHAR
)];
119 OBJECT_ATTRIBUTES ObjectAttributes
;
120 UNICODE_STRING PartitionRootPath
;
121 WCHAR PathBuffer
[MAX_PATH
];
123 FileFsAttribute
= (PFILE_FS_ATTRIBUTE_INFORMATION
)Buffer
;
125 /* Set PartitionRootPath */
127 // L"\\Device\\Harddisk%lu\\Partition%lu", // Should work! But because ReactOS sucks atm. it actually doesn't work!!
128 L
"\\Device\\Harddisk%lu\\Partition%lu\\", // HACK: Use this as a temporary hack!
129 PartEntry
->DiskEntry
->DiskNumber
,
130 PartEntry
->PartitionNumber
);
131 RtlInitUnicodeString(&PartitionRootPath
, PathBuffer
);
132 DPRINT("PartitionRootPath: %wZ\n", &PartitionRootPath
);
134 /* Open the partition */
135 InitializeObjectAttributes(&ObjectAttributes
,
137 OBJ_CASE_INSENSITIVE
,
140 Status
= NtOpenFile(&FileHandle
, // PartitionHandle,
141 FILE_GENERIC_READ
/* | SYNCHRONIZE */,
145 0 /* FILE_SYNCHRONOUS_IO_NONALERT */);
146 if (!NT_SUCCESS(Status
))
148 DPRINT1("Failed to open partition %wZ, Status 0x%08lx\n", &PartitionRootPath
, Status
);
152 /* Retrieve the FS attributes */
153 Status
= NtQueryVolumeInformationFile(FileHandle
,
157 FileFsAttributeInformation
);
160 if (!NT_SUCCESS(Status
))
162 DPRINT1("NtQueryVolumeInformationFile failed for partition %wZ, Status 0x%08lx\n", &PartitionRootPath
, Status
);
166 if (FileSystemNameSize
* sizeof(WCHAR
) < FileFsAttribute
->FileSystemNameLength
+ sizeof(WCHAR
))
167 return STATUS_BUFFER_TOO_SMALL
;
169 RtlCopyMemory(FileSystemName
,
170 FileFsAttribute
->FileSystemName
,
171 FileFsAttribute
->FileSystemNameLength
);
172 FileSystemName
[FileFsAttribute
->FileSystemNameLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
174 return STATUS_SUCCESS
;
181 // IN PFILE_SYSTEM_LIST FileSystemList,
182 IN
struct _PARTENTRY
* PartEntry
)
184 PFILE_SYSTEM CurrentFileSystem
;
185 PWSTR FileSystemName
= NULL
;
186 #if 0 // For code temporarily disabled below
188 WCHAR FsRecFileSystemName
[MAX_PATH
];
191 CurrentFileSystem
= PartEntry
->FileSystem
;
193 /* We have a file system, return it */
194 if (CurrentFileSystem
!= NULL
&& CurrentFileSystem
->FileSystemName
!= NULL
)
195 return CurrentFileSystem
;
197 DPRINT1("File system not found, try to guess one...\n");
199 CurrentFileSystem
= NULL
;
201 #if 0 // FIXME: To be fully enabled when our storage stack & al. will work better!
204 * We don't have one...
206 * Try to infer one using NT file system recognition.
208 Status
= _MyGetFileSystem(PartEntry
, FsRecFileSystemName
, ARRAYSIZE(FsRecFileSystemName
));
209 if (NT_SUCCESS(Status
) && *FsRecFileSystemName
)
211 /* Temporary HACK: map FAT32 back to FAT */
212 if (wcscmp(FsRecFileSystemName
, L
"FAT32") == 0)
213 wcscpy(FsRecFileSystemName
, L
"FAT");
215 FileSystemName
= FsRecFileSystemName
;
222 * We don't have one...
224 * Try to infer a preferred file system for this partition, given its ID.
226 * WARNING: This is partly a hack, since partitions with the same ID can
227 * be formatted with different file systems: for example, usual Linux
228 * partitions that are formatted in EXT2/3/4, ReiserFS, etc... have the
229 * same partition ID 0x83.
231 * The proper fix is to make a function that detects the existing FS
232 * from a given partition (not based on the partition ID).
233 * On the contrary, for unformatted partitions with a given ID, the
234 * following code is OK.
236 if ((PartEntry
->PartitionType
== PARTITION_FAT_12
) ||
237 (PartEntry
->PartitionType
== PARTITION_FAT_16
) ||
238 (PartEntry
->PartitionType
== PARTITION_HUGE
) ||
239 (PartEntry
->PartitionType
== PARTITION_XINT13
) ||
240 (PartEntry
->PartitionType
== PARTITION_FAT32
) ||
241 (PartEntry
->PartitionType
== PARTITION_FAT32_XINT13
))
243 FileSystemName
= L
"FAT";
245 else if (PartEntry
->PartitionType
== PARTITION_EXT2
)
247 // WARNING: See the warning above.
248 FileSystemName
= L
"EXT2";
250 else if (PartEntry
->PartitionType
== PARTITION_IFS
)
252 // WARNING: See the warning above.
253 FileSystemName
= L
"NTFS"; /* FIXME: Not quite correct! */
257 Quit
: // For code temporarily disabled above
260 // HACK: WARNING: We cannot write on this FS yet!
263 if (PartEntry
->PartitionType
== PARTITION_EXT2
|| PartEntry
->PartitionType
== PARTITION_IFS
)
264 DPRINT1("Recognized file system %S that doesn't support write support yet!\n", FileSystemName
);
267 DPRINT1("GetFileSystem -- PartitionType: 0x%02X ; FileSystemName (guessed): %S\n",
268 PartEntry
->PartitionType
, FileSystemName
? FileSystemName
: L
"None");
270 if (FileSystemName
!= NULL
)
271 CurrentFileSystem
= GetFileSystemByName(/*FileSystemList,*/ FileSystemName
);
273 return CurrentFileSystem
;