ReactOS 0.4.16-dev-178-g8ba6102
volutil.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS Setup Library
3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: Volume utility functions
5 * COPYRIGHT: Copyright 2024 Hermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
6 */
7
8/* INCLUDES ******************************************************************/
9
10#include "precomp.h"
11
12#include "volutil.h"
13#include "fsrec.h"
14#include "devutils.h"
15
16#define NDEBUG
17#include <debug.h>
18
19
20/* FUNCTIONS *****************************************************************/
21
25 _In_opt_ UCHAR MbrPartitionType)
26{
29
30 /* If the volume is already mounted, just return success */
31 if (*Volume->FileSystem)
32 return STATUS_SUCCESS;
33
34 /* Try to open the volume so as to mount it */
36 Status = pOpenDevice(Volume->DeviceName, &VolumeHandle);
37 if (!NT_SUCCESS(Status))
38 {
39 DPRINT1("pOpenDevice() failed, Status 0x%08lx\n", Status);
40
41 /* We failed, reset some data and bail out */
42 Volume->DriveLetter = UNICODE_NULL;
43 Volume->VolumeLabel[0] = UNICODE_NULL;
44 Volume->FileSystem[0] = UNICODE_NULL;
45
46 return Status;
47 }
49
50 /* We don't have a FS, try to guess one */
52 Volume->FileSystem,
53 sizeof(Volume->FileSystem));
54 if (!NT_SUCCESS(Status))
55 DPRINT1("InferFileSystem() failed, Status 0x%08lx\n", Status);
56
57 if (*Volume->FileSystem)
58 {
59 /*
60 * Handle volume mounted with RawFS: it is
61 * either unformatted or has an unknown format.
62 */
63 if (IsUnformatted(Volume)) // FileSystem is "RAW"
64 {
65 /*
66 * True unformatted partitions on NT are created with their
67 * partition type set to either one of the following values,
68 * and are mounted with RawFS. This is done this way since we
69 * are assured to have FAT support, which is the only FS that
70 * uses these partition types. Therefore, having a partition
71 * mounted with RawFS and with these partition types means that
72 * the FAT FS was unable to mount it beforehand and thus the
73 * partition is unformatted.
74 * However, any partition mounted by RawFS that does NOT have
75 * any of these partition types must be considered as having
76 * an unknown format.
77 */
78 if (MbrPartitionType == PARTITION_FAT_12 ||
79 MbrPartitionType == PARTITION_FAT_16 ||
80 MbrPartitionType == PARTITION_HUGE ||
81 MbrPartitionType == PARTITION_XINT13 ||
82 MbrPartitionType == PARTITION_FAT32 ||
83 MbrPartitionType == PARTITION_FAT32_XINT13)
84 {
85 /* The volume is unformatted */
86 }
87 else
88 {
89 /* Close the volume before dismounting */
92 /*
93 * Dismount the volume since RawFS owns it, and reset its
94 * format (it is unknown, may or may not be actually formatted).
95 */
97 Volume->FileSystem[0] = UNICODE_NULL;
98 }
99 }
100 /* Else, the volume is formatted */
101 }
102 /* Else, the volume has an unknown format */
103
104 /* Retrieve the volume label */
105 if (VolumeHandle)
106 {
108 struct
109 {
111 WCHAR Data[255];
112 } LabelInfo;
113
116 &LabelInfo,
117 sizeof(LabelInfo),
119 if (NT_SUCCESS(Status))
120 {
121 /* Copy the (possibly truncated) volume label and NULL-terminate it */
122 RtlStringCbCopyNW(Volume->VolumeLabel, sizeof(Volume->VolumeLabel),
123 LabelInfo.VolumeLabel, LabelInfo.VolumeLabelLength);
124 }
125 else
126 {
127 DPRINT1("NtQueryVolumeInformationFile() failed, Status 0x%08lx\n", Status);
128 }
129 }
130
131 /* Close the volume */
132 if (VolumeHandle)
134
135 return STATUS_SUCCESS;
136}
137
155{
156 NTSTATUS Status, LockStatus;
159
160 /* If the volume is not mounted, just return success */
161 if (!*Volume->FileSystem)
162 return STATUS_SUCCESS;
163
164 /* Open the volume */
165 Status = pOpenDeviceEx(Volume->DeviceName, &VolumeHandle,
168 if (!NT_SUCCESS(Status))
169 {
170 DPRINT1("ERROR: Cannot open volume %S for dismounting! (Status 0x%lx)\n",
171 Volume->DeviceName, Status);
172 return Status;
173 }
174
175 /* Lock the volume (succeeds only if there are no open handles to files) */
176 LockStatus = NtFsControlFile(VolumeHandle,
177 NULL, NULL, NULL,
180 NULL, 0,
181 NULL, 0);
182 if (!NT_SUCCESS(LockStatus))
183 DPRINT1("WARNING: Failed to lock volume (Status 0x%lx)\n", LockStatus);
184
185 /* Dismount the volume (succeeds even when lock fails and there are open handles) */
186 Status = STATUS_ACCESS_DENIED; // Suppose dismount failure.
187 if (NT_SUCCESS(LockStatus) || Force)
188 {
190 NULL, NULL, NULL,
193 NULL, 0,
194 NULL, 0);
195 if (!NT_SUCCESS(Status))
196 DPRINT1("Failed to unmount volume (Status 0x%lx)\n", Status);
197 }
198
199 /* Unlock the volume */
200 if (NT_SUCCESS(LockStatus))
201 {
202 LockStatus = NtFsControlFile(VolumeHandle,
203 NULL, NULL, NULL,
206 NULL, 0,
207 NULL, 0);
208 if (!NT_SUCCESS(LockStatus))
209 DPRINT1("Failed to unlock volume (Status 0x%lx)\n", LockStatus);
210 }
211
212 /* Close the volume */
214
215 /* Reset some data only if dismount succeeded */
216 if (NT_SUCCESS(Status))
217 {
218 Volume->DriveLetter = UNICODE_NULL;
219 Volume->VolumeLabel[0] = UNICODE_NULL;
220 Volume->FileSystem[0] = UNICODE_NULL;
221 }
222
223 return Status;
224}
225
226/* EOF */
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
#define PARTITION_XINT13
Definition: disk.h:98
#define PARTITION_FAT32
Definition: disk.h:96
#define PARTITION_FAT_12
Definition: disk.h:88
#define PARTITION_HUGE
Definition: disk.h:93
#define PARTITION_FAT_16
Definition: disk.h:91
#define PARTITION_FAT32_XINT13
Definition: disk.h:97
_Inout_ PVCB _In_ BOOLEAN Force
Definition: cdprocs.h:1417
NTSTATUS pOpenDevice(_In_ PCWSTR DevicePath, _Out_ PHANDLE DeviceHandle)
Open an existing device given by its NT-style path, which is assumed to be for a disk device or a par...
Definition: devutils.c:128
NTSTATUS pOpenDeviceEx(_In_ PCWSTR DevicePath, _Out_ PHANDLE DeviceHandle, _In_ ACCESS_MASK DesiredAccess, _In_ ULONG ShareAccess)
Open an existing device given by its NT-style path, which is assumed to be for a disk device or a par...
Definition: devutils.c:102
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define GENERIC_READ
Definition: compat.h:135
#define FILE_SHARE_READ
Definition: compat.h:136
_Must_inspect_result_ _Out_ PHANDLE VolumeHandle
Definition: fltkernel.h:2283
@ FileFsVolumeInformation
Definition: from_kernel.h:219
NTSTATUS InferFileSystem(IN PCWSTR PartitionPath OPTIONAL, IN HANDLE PartitionHandle OPTIONAL, IN OUT PWSTR FileSystemName, IN SIZE_T FileSystemNameSize)
Definition: fsrec.c:269
Status
Definition: gdiplustypes.h:25
UNICODE_STRING Volume
Definition: fltkernel.h:1172
#define ASSERT(a)
Definition: mode.c:44
static OUT PIO_STATUS_BLOCK IoStatusBlock
Definition: pipe.c:75
#define _Inout_
Definition: ms_sal.h:378
#define _In_
Definition: ms_sal.h:308
#define _In_opt_
Definition: ms_sal.h:309
#define FILE_SHARE_WRITE
Definition: nt_native.h:681
#define FSCTL_LOCK_VOLUME
Definition: nt_native.h:832
#define FSCTL_UNLOCK_VOLUME
Definition: nt_native.h:833
NTSTATUS NTAPI NtClose(IN HANDLE Handle)
Definition: obhandle.c:3402
#define FSCTL_DISMOUNT_VOLUME
Definition: nt_native.h:834
#define GENERIC_WRITE
Definition: nt_native.h:90
NTSYSAPI NTSTATUS NTAPI NtFsControlFile(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 UNICODE_NULL
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
struct _FILE_FS_VOLUME_INFORMATION FILE_FS_VOLUME_INFORMATION
NTSTATUS NTAPI NtQueryVolumeInformationFile(HANDLE FileHandle, PIO_STATUS_BLOCK IoStatusBlock, PVOID FsInformation, ULONG Length, FS_INFORMATION_CLASS FsInformationClass)
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_ACCESS_DENIED
Definition: udferr_usr.h:145
NTSTATUS DismountVolume(_Inout_ PVOLINFO Volume, _In_ BOOLEAN Force)
Attempts to dismount the designated volume.
Definition: volutil.c:152
NTSTATUS MountVolume(_Inout_ PVOLINFO Volume, _In_opt_ UCHAR MbrPartitionType)
Definition: volutil.c:23
#define IsUnformatted(VolInfo)
Definition: volutil.h:31
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180