ReactOS  0.4.15-dev-2972-gda2a567
fsrec.c File Reference
#include "precomp.h"
#include "fsrec.h"
#include <debug.h>
Include dependency graph for fsrec.c:

Go to the source code of this file.

Macros

#define NDEBUG
 

Functions

static NTSTATUS GetFileSystemNameWorker (IN HANDLE PartitionHandle, OUT PIO_STATUS_BLOCK IoStatusBlock, IN OUT PWSTR FileSystemName, IN SIZE_T FileSystemNameSize)
 
NTSTATUS GetFileSystemName_UStr (IN PUNICODE_STRING PartitionPath OPTIONAL, IN HANDLE PartitionHandle OPTIONAL, IN OUT PWSTR FileSystemName, IN SIZE_T FileSystemNameSize)
 
NTSTATUS GetFileSystemName (IN PCWSTR PartitionPath OPTIONAL, IN HANDLE PartitionHandle OPTIONAL, IN OUT PWSTR FileSystemName, IN SIZE_T FileSystemNameSize)
 
static NTSTATUS InferFileSystemWorker (IN HANDLE PartitionHandle, OUT PIO_STATUS_BLOCK IoStatusBlock, IN OUT PWSTR FileSystemName, IN SIZE_T FileSystemNameSize)
 
NTSTATUS InferFileSystem (IN PCWSTR PartitionPath OPTIONAL, IN HANDLE PartitionHandle OPTIONAL, IN OUT PWSTR FileSystemName, IN SIZE_T FileSystemNameSize)
 
UCHAR FileSystemToMBRPartitionType (IN PCWSTR FileSystem, IN ULONGLONG StartSector, IN ULONGLONG SectorCount)
 

Macro Definition Documentation

◆ NDEBUG

#define NDEBUG

Definition at line 15 of file fsrec.c.

Function Documentation

◆ FileSystemToMBRPartitionType()

UCHAR FileSystemToMBRPartitionType ( IN PCWSTR  FileSystem,
IN ULONGLONG  StartSector,
IN ULONGLONG  SectorCount 
)

Definition at line 333 of file fsrec.c.

337 {
339 
340  if (SectorCount == 0)
341  return PARTITION_ENTRY_UNUSED;
342 
343  if (wcsicmp(FileSystem, L"FAT") == 0 ||
344  wcsicmp(FileSystem, L"FAT32") == 0 ||
345  wcsicmp(FileSystem, L"RAW") == 0)
346  {
347  if (SectorCount < 8192ULL)
348  {
349  /* FAT12 CHS partition (disk is smaller than 4.1MB) */
350  return PARTITION_FAT_12;
351  }
352  else if (StartSector < 1450560ULL)
353  {
354  /* Partition starts below the 8.4GB boundary ==> CHS partition */
355 
356  if (SectorCount < 65536ULL)
357  {
358  /* FAT16 CHS partition (partition size < 32MB) */
359  return PARTITION_FAT_16;
360  }
361  else if (SectorCount < 1048576ULL)
362  {
363  /* FAT16 CHS partition (partition size < 512MB) */
364  return PARTITION_HUGE;
365  }
366  else
367  {
368  /* FAT32 CHS partition (partition size >= 512MB) */
369  return PARTITION_FAT32;
370  }
371  }
372  else
373  {
374  /* Partition starts above the 8.4GB boundary ==> LBA partition */
375 
376  if (SectorCount < 1048576ULL)
377  {
378  /* FAT16 LBA partition (partition size < 512MB) */
379  return PARTITION_XINT13;
380  }
381  else
382  {
383  /* FAT32 LBA partition (partition size >= 512MB) */
384  return PARTITION_FAT32_XINT13;
385  }
386  }
387  }
388  else if (wcsicmp(FileSystem, L"NTFS") == 0)
389  {
390  return PARTITION_IFS;
391  }
392  else if (wcsicmp(FileSystem, L"BTRFS") == 0 ||
393  wcsicmp(FileSystem, L"EXT2") == 0 ||
394  wcsicmp(FileSystem, L"EXT3") == 0 ||
395  wcsicmp(FileSystem, L"EXT4") == 0 ||
396  wcsicmp(FileSystem, L"FFS") == 0 ||
397  wcsicmp(FileSystem, L"REISERFS") == 0)
398  {
399  return PARTITION_LINUX;
400  }
401  else
402  {
403  /* Unknown file system */
404  DPRINT1("Unknown file system '%S'\n", FileSystem);
405  return PARTITION_ENTRY_UNUSED;
406  }
407 }
#define PARTITION_FAT32
Definition: disk.h:95
PWCHAR FileSystem
Definition: format.c:72
#define PARTITION_XINT13
Definition: disk.h:97
#define PARTITION_ENTRY_UNUSED
Definition: disk.h:86
#define PARTITION_HUGE
Definition: disk.h:92
#define PARTITION_IFS
Definition: disk.h:93
#define ULL(a, b)
Definition: format_msg.c:27
#define ASSERT(a)
Definition: mode.c:44
#define PARTITION_FAT_16
Definition: disk.h:90
#define wcsicmp
Definition: compat.h:15
static const WCHAR L[]
Definition: oid.c:1250
ULONG SectorCount
Definition: part_xbox.c:31
#define PARTITION_LINUX
Definition: partlist.c:36
#define DPRINT1
Definition: precomp.h:8
#define PARTITION_FAT_12
Definition: disk.h:87
#define PARTITION_FAT32_XINT13
Definition: disk.h:96

Referenced by FormatPartition(), and InitializePartitionEntry().

◆ GetFileSystemName()

NTSTATUS GetFileSystemName ( IN PCWSTR PartitionPath  OPTIONAL,
IN HANDLE PartitionHandle  OPTIONAL,
IN OUT PWSTR  FileSystemName,
IN SIZE_T  FileSystemNameSize 
)

Definition at line 112 of file fsrec.c.

117 {
118  UNICODE_STRING PartitionPathU;
119 
120  if (PartitionPath && PartitionHandle)
122 
123  if (PartitionPath)
124  RtlInitUnicodeString(&PartitionPathU, PartitionPath);
125 
126  return GetFileSystemName_UStr(PartitionPath ? &PartitionPathU : NULL,
127  PartitionPath ? NULL : PartitionHandle,
128  FileSystemName,
129  FileSystemNameSize);
130 }
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
NTSTATUS GetFileSystemName_UStr(IN PUNICODE_STRING PartitionPath OPTIONAL, IN HANDLE PartitionHandle OPTIONAL, IN OUT PWSTR FileSystemName, IN SIZE_T FileSystemNameSize)
Definition: fsrec.c:55
#define NULL
Definition: types.h:112
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)

◆ GetFileSystemName_UStr()

NTSTATUS GetFileSystemName_UStr ( IN PUNICODE_STRING PartitionPath  OPTIONAL,
IN HANDLE PartitionHandle  OPTIONAL,
IN OUT PWSTR  FileSystemName,
IN SIZE_T  FileSystemNameSize 
)

Definition at line 55 of file fsrec.c.

60 {
64 
65  if (PartitionPath && PartitionHandle)
67 
68  /* Open the partition if a path has been given;
69  * otherwise just use the provided handle. */
70  if (PartitionPath)
71  {
73  PartitionPath,
75  NULL,
76  NULL);
77  Status = NtOpenFile(&PartitionHandle,
78  FILE_GENERIC_READ /* | SYNCHRONIZE */,
82  0 /* FILE_SYNCHRONOUS_IO_NONALERT */);
83  if (!NT_SUCCESS(Status))
84  {
85  DPRINT1("Failed to open partition '%wZ', Status 0x%08lx\n",
86  PartitionPath, Status);
87  return Status;
88  }
89  }
90 
91  /* Retrieve the FS attributes */
92  Status = GetFileSystemNameWorker(PartitionHandle,
94  FileSystemName,
95  FileSystemNameSize);
96  if (!NT_SUCCESS(Status))
97  {
98  DPRINT1("GetFileSystemName() failed for partition '%wZ' (0x%p), Status 0x%08lx\n",
99  PartitionPath, PartitionHandle, Status);
100  }
101 
102  if (PartitionPath)
103  {
104  /* Close the partition */
105  NtClose(PartitionHandle);
106  }
107 
108  return Status;
109 }
#define FILE_GENERIC_READ
Definition: nt_native.h:653
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
static NTSTATUS GetFileSystemNameWorker(IN HANDLE PartitionHandle, OUT PIO_STATUS_BLOCK IoStatusBlock, IN OUT PWSTR FileSystemName, IN SIZE_T FileSystemNameSize)
Definition: fsrec.c:24
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
LONG NTSTATUS
Definition: precomp.h:26
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define FILE_SHARE_READ
Definition: compat.h:136
Status
Definition: gdiplustypes.h:24
NTSYSAPI NTSTATUS NTAPI NtOpenFile(OUT PHANDLE phFile, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN ULONG ShareMode, IN ULONG OpenMode)
Definition: file.c:3951
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3398
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define NULL
Definition: types.h:112
#define DPRINT1
Definition: precomp.h:8
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106

Referenced by GetFileSystemName(), and InferFileSystemWorker().

◆ GetFileSystemNameWorker()

static NTSTATUS GetFileSystemNameWorker ( IN HANDLE  PartitionHandle,
OUT PIO_STATUS_BLOCK  IoStatusBlock,
IN OUT PWSTR  FileSystemName,
IN SIZE_T  FileSystemNameSize 
)
inlinestatic

Definition at line 24 of file fsrec.c.

29 {
33 
34  /* Retrieve the FS attributes */
35  Status = NtQueryVolumeInformationFile(PartitionHandle,
37  FileFsAttribute,
38  sizeof(Buffer),
40  if (!NT_SUCCESS(Status))
41  {
42  DPRINT1("NtQueryVolumeInformationFile() failed, Status 0x%08lx\n", Status);
43  return Status;
44  }
45 
46  if (FileSystemNameSize < FileFsAttribute->FileSystemNameLength + sizeof(WCHAR))
48 
49  return RtlStringCbCopyNW(FileSystemName, FileSystemNameSize,
50  FileFsAttribute->FileSystemName,
51  FileFsAttribute->FileSystemNameLength);
52 }
LONG NTSTATUS
Definition: precomp.h:26
struct _FILE_FS_ATTRIBUTE_INFORMATION FILE_FS_ATTRIBUTE_INFORMATION
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
NTSTRSAFEAPI RtlStringCbCopyNW(_Out_writes_bytes_(cbDest) NTSTRSAFE_PWSTR pszDest, _In_ size_t cbDest, _In_reads_bytes_(cbToCopy) STRSAFE_LPCWSTR pszSrc, _In_ size_t cbToCopy)
Definition: ntstrsafe.h:416
Definition: bufpool.h:45
Status
Definition: gdiplustypes.h:24
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define MAX_PATH
Definition: compat.h:34
struct _FILE_FS_ATTRIBUTE_INFORMATION * PFILE_FS_ATTRIBUTE_INFORMATION
unsigned char UCHAR
Definition: xmlstorage.h:181
NTSTATUS NTAPI NtQueryVolumeInformationFile(HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock, PVOID FsInformation, ULONG Length, FS_INFORMATION_CLASS FsInformationClass)
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define DPRINT1
Definition: precomp.h:8

Referenced by GetFileSystemName_UStr().

◆ InferFileSystem()

NTSTATUS InferFileSystem ( IN PCWSTR PartitionPath  OPTIONAL,
IN HANDLE PartitionHandle  OPTIONAL,
IN OUT PWSTR  FileSystemName,
IN SIZE_T  FileSystemNameSize 
)

Definition at line 269 of file fsrec.c.

274 {
276  UNICODE_STRING PartitionPathU;
279 
280  if (PartitionPath && PartitionHandle)
282 
283  /* Open the partition if a path has been given;
284  * otherwise just use the provided handle. */
285  if (PartitionPath)
286  {
287  RtlInitUnicodeString(&PartitionPathU, PartitionPath);
289  &PartitionPathU,
291  NULL,
292  NULL);
293  Status = NtOpenFile(&PartitionHandle,
294  FILE_GENERIC_READ /* | SYNCHRONIZE */,
296  &IoStatusBlock,
298  0 /* FILE_SYNCHRONOUS_IO_NONALERT */);
299  if (!NT_SUCCESS(Status))
300  {
301  DPRINT1("Failed to open partition '%S', Status 0x%08lx\n",
302  PartitionPath, Status);
303  return Status;
304  }
305  }
306 
307  /* Retrieve the FS */
308  Status = InferFileSystemWorker(PartitionHandle,
309  &IoStatusBlock,
310  FileSystemName,
311  FileSystemNameSize);
312  if (!NT_SUCCESS(Status))
313  {
314  DPRINT1("InferFileSystem() failed for partition '%S' (0x%p), Status 0x%08lx\n",
315  PartitionPath, PartitionHandle, Status);
316  }
317  else
318  {
319  DPRINT1("InferFileSystem(): FileSystem (guessed): %S\n",
320  *FileSystemName ? FileSystemName : L"None");
321  }
322 
323  if (PartitionPath)
324  {
325  /* Close the partition */
326  NtClose(PartitionHandle);
327  }
328 
329  return Status;
330 }
#define FILE_GENERIC_READ
Definition: nt_native.h:653
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:35
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
LONG NTSTATUS
Definition: precomp.h:26
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define FILE_SHARE_READ
Definition: compat.h:136
Status
Definition: gdiplustypes.h:24
NTSYSAPI NTSTATUS NTAPI NtOpenFile(OUT PHANDLE phFile, IN ACCESS_MASK DesiredAccess, IN POBJECT_ATTRIBUTES ObjectAttributes, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN ULONG ShareMode, IN ULONG OpenMode)
Definition: file.c:3951
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3398
static const WCHAR L[]
Definition: oid.c:1250
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
static NTSTATUS InferFileSystemWorker(IN HANDLE PartitionHandle, OUT PIO_STATUS_BLOCK IoStatusBlock, IN OUT PWSTR FileSystemName, IN SIZE_T FileSystemNameSize)
Definition: fsrec.c:134
#define NULL
Definition: types.h:112
#define DPRINT1
Definition: precomp.h:8
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106

Referenced by AddPartitionToDisk().

◆ InferFileSystemWorker()

static NTSTATUS InferFileSystemWorker ( IN HANDLE  PartitionHandle,
OUT PIO_STATUS_BLOCK  IoStatusBlock,
IN OUT PWSTR  FileSystemName,
IN SIZE_T  FileSystemNameSize 
)
inlinestatic

Definition at line 134 of file fsrec.c.

139 {
140  NTSTATUS Status, Status2;
141  union
142  {
145  } PartInfo;
147 
148  if (FileSystemNameSize < sizeof(WCHAR))
150 
151  *FileSystemName = L'\0';
152 
153  /* Try to infer a file system using NT file system recognition */
154  Status = GetFileSystemName_UStr(NULL, PartitionHandle,
155  FileSystemName,
156  FileSystemNameSize);
157  if (NT_SUCCESS(Status) && *FileSystemName)
158  goto Quit;
159 
160  /*
161  * Check whether the partition is MBR, and if so, retrieve its MBR
162  * partition type and try to infer a preferred file system for it.
163  */
164 
165  // NOTE: Use Status2 in order not to clobber the original Status.
166  Status2 = NtDeviceIoControlFile(PartitionHandle,
167  NULL,
168  NULL,
169  NULL,
172  NULL,
173  0,
174  &PartInfo.InfoEx,
175  sizeof(PartInfo.InfoEx));
176  if (!NT_SUCCESS(Status2))
177  {
178  DPRINT1("IOCTL_DISK_GET_PARTITION_INFO_EX failed (Status %lx)\n", Status2);
179 
180  if (Status2 != STATUS_INVALID_DEVICE_REQUEST)
181  goto Quit;
182 
183  /*
184  * We could have failed because the partition is on a dynamic
185  * MBR or GPT data disk, so retry with the non-EX IOCTL.
186  */
187  Status2 = NtDeviceIoControlFile(PartitionHandle,
188  NULL,
189  NULL,
190  NULL,
193  NULL,
194  0,
195  &PartInfo.Info,
196  sizeof(PartInfo.Info));
197  if (!NT_SUCCESS(Status2))
198  {
199  /* We failed again, bail out */
200  DPRINT1("IOCTL_DISK_GET_PARTITION_INFO failed (Status %lx)\n", Status2);
201  goto Quit;
202  }
203 
204  /* The partition is supposed to be on an MBR disk; retrieve its type */
205  PartitionType = PartInfo.Info.PartitionType;
206  }
207  else
208  {
209  /* We succeeded; retrieve the partition type only if it is on an MBR disk */
210  if (PartInfo.InfoEx.PartitionStyle != PARTITION_STYLE_MBR)
211  {
212  /* Disk is not MBR, bail out */
213  goto Quit;
214  }
215  PartitionType = PartInfo.InfoEx.Mbr.PartitionType;
216  }
217 
218  /*
219  * Given an MBR partition type, try to infer a preferred file system.
220  *
221  * WARNING: This is partly a hack, since partitions with the same type
222  * can be formatted with different file systems: for example, usual Linux
223  * partitions that are formatted in EXT2/3/4, ReiserFS, etc... have the
224  * same partition type 0x83.
225  *
226  * The proper fix is to make a function that detects the existing FS
227  * from a given partition (not based on the partition type).
228  * On the contrary, for unformatted partitions with a given type, the
229  * following code is OK.
230  */
231  if ((PartitionType == PARTITION_FAT_12) ||
235  {
236  /* FAT12 or FAT16 */
237  Status = RtlStringCbCopyW(FileSystemName, FileSystemNameSize, L"FAT");
238  }
239  else if ((PartitionType == PARTITION_FAT32) ||
241  {
242  Status = RtlStringCbCopyW(FileSystemName, FileSystemNameSize, L"FAT32");
243  }
244  else if (PartitionType == PARTITION_LINUX)
245  {
246  // WARNING: See the warning above.
247  /* Could also be EXT2/3/4, ReiserFS, ... */
248  Status = RtlStringCbCopyW(FileSystemName, FileSystemNameSize, L"BTRFS");
249  }
250  else if (PartitionType == PARTITION_IFS)
251  {
252  // WARNING: See the warning above.
253  /* Could also be HPFS */
254  Status = RtlStringCbCopyW(FileSystemName, FileSystemNameSize, L"NTFS");
255  }
256 
257 Quit:
258  if (*FileSystemName && wcsicmp(FileSystemName, L"NTFS") == 0)
259  {
260  // WARNING: We cannot write on this FS yet!
261  DPRINT1("Recognized file system '%S' that doesn't have write support yet!\n",
262  FileSystemName);
263  }
264 
265  return Status;
266 }
#define PARTITION_FAT32
Definition: disk.h:95
NTSTRSAFEAPI RtlStringCbCopyW(_Out_writes_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest, _In_ size_t cbDest, _In_ NTSTRSAFE_PCWSTR pszSrc)
Definition: ntstrsafe.h:174
LONG NTSTATUS
Definition: precomp.h:26
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
NTSYSAPI NTSTATUS NTAPI NtDeviceIoControlFile(IN HANDLE hFile, IN HANDLE hEvent OPTIONAL, IN PIO_APC_ROUTINE IoApcRoutine OPTIONAL, IN PVOID IoApcContext OPTIONAL, OUT PIO_STATUS_BLOCK pIoStatusBlock, IN ULONG DeviceIoControlCode, IN PVOID InBuffer OPTIONAL, IN ULONG InBufferLength, OUT PVOID OutBuffer OPTIONAL, IN ULONG OutBufferLength)
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define PARTITION_XINT13
Definition: disk.h:97
_Must_inspect_result_ _In_ WDFCHILDLIST _In_ PWDF_CHILD_LIST_ITERATOR _Out_ WDFDEVICE _Inout_opt_ PWDF_CHILD_RETRIEVE_INFO Info
Definition: wdfchildlist.h:683
#define PARTITION_HUGE
Definition: disk.h:92
#define PARTITION_IFS
Definition: disk.h:93
Status
Definition: gdiplustypes.h:24
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
NTSTATUS GetFileSystemName_UStr(IN PUNICODE_STRING PartitionPath OPTIONAL, IN HANDLE PartitionHandle OPTIONAL, IN OUT PWSTR FileSystemName, IN SIZE_T FileSystemNameSize)
Definition: fsrec.c:55
#define PARTITION_FAT_16
Definition: disk.h:90
#define wcsicmp
Definition: compat.h:15
unsigned char UCHAR
Definition: xmlstorage.h:181
#define IOCTL_DISK_GET_PARTITION_INFO
Definition: ntdddisk.h:106
static const WCHAR L[]
Definition: oid.c:1250
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define NULL
Definition: types.h:112
#define PARTITION_LINUX
Definition: partlist.c:36
#define DPRINT1
Definition: precomp.h:8
CHAR PartitionType
Definition: part_xbox.c:32
#define PARTITION_FAT_12
Definition: disk.h:87
#define PARTITION_FAT32_XINT13
Definition: disk.h:96
#define IOCTL_DISK_GET_PARTITION_INFO_EX
Definition: ntddk_ex.h:206

Referenced by InferFileSystem().