Reactos
1/*
2 * PROJECT: ReactOS DiskPart
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: base/system/diskpart/format.c
5 * PURPOSE: Manages all the partitions of the OS in an interactive way.
6 * PROGRAMMERS: Lee Schroeder
7 */
8
9#include "diskpart.h"
10
11#include <fmifs/fmifs.h>
12
13#define NDEBUG
14#include <debug.h>
15
16static
17BOOL
18GetFsModule(
19 _In_ PWSTR pszFileSystem,
20 _Out_ HMODULE *phModule)
21{
22 WCHAR szDllNameBuffer[32];
23 HKEY hKey;
24 DWORD dwLength, dwErr;
25
26 *phModule = NULL;
27
28 dwErr = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
29 L"SOFTWARE\\ReactOS\\ReactOS\\CurrentVersion\\IFS",
30 0,
31 KEY_READ,
32 &hKey);
33 if (dwErr != ERROR_SUCCESS)
34 {
35 DPRINT1("Failed to open!\n");
36 return FALSE;
37 }
38
39 dwLength = sizeof(szDllNameBuffer);
40 dwErr = RegQueryValueExW(hKey,
41 pszFileSystem,
42 NULL,
43 NULL,
44 (PBYTE)szDllNameBuffer,
45 &dwLength);
46
47 RegCloseKey(hKey);
48
49 if (dwErr != ERROR_SUCCESS)
50 {
51 DPRINT1("Failed to query!\n");
52 return FALSE;
53 }
54
55 *phModule = LoadLibraryW(szDllNameBuffer);
56 if (*phModule == NULL)
57 {
58 DPRINT1("Failed to load!\n");
59 return FALSE;
60 }
61
62 return TRUE;
63}
64
65
66BOOLEAN
67WINAPI
68FormatCallback(
69 CALLBACKCOMMAND Command,
70 ULONG Size,
71 PVOID Argument)
72{
73 PDWORD percent;
74
75 switch (Command)
76 {
77 case PROGRESS:
78 percent = (PDWORD)Argument;
79 ConResPrintf(StdOut, IDS_FORMAT_PROGRESS, *percent);
80 break;
81
82 case DONE:
83 break;
84
85 default:
86 DPRINT1("Callback (%u %lu %p)\n", Command, Size, Argument);
87 break;
88 }
89
90 return TRUE;
91}
92
93
94EXIT_CODE
95format_main(
96 _In_ INT argc,
97 _In_ PWSTR *argv)
98{
99 UNICODE_STRING usDriveRoot;
100 UNICODE_STRING LabelString;
101 PWSTR pszSuffix = NULL;
102 PWSTR pszFileSystem = NULL;
103 PWSTR pszLabel = NULL;
104 BOOLEAN bQuickFormat = FALSE;
105 ULONG ulClusterSize = 0;
106 HMODULE hModule = NULL;
107 PULIB_FORMAT pFormat = NULL;
108// FMIFS_MEDIA_FLAG MediaType = FMIFS_HARDDISK;
109 INT i;
110 BOOLEAN Success = FALSE;
111
112
113 if (CurrentVolume == NULL)
114 {
115 ConResPuts(StdOut, IDS_SELECT_NO_VOLUME);
116 return EXIT_SUCCESS;
117 }
118
119 for (i = 1; i < argc; i++)
120 {
121 if (_wcsicmp(argv[i], L"noerr") == 0)
122 {
123 /* noerr */
124 DPRINT("NoErr\n", pszSuffix);
125 ConPuts(StdOut, L"The NOERR option is not supported yet!\n");
126#if 0
127 bNoErr = TRUE;
128#endif
129 }
130 }
131
132 for (i = 1; i < argc; i++)
133 {
134 ConPrintf(StdOut, L"%s\n", argv[i]);
135
136 if (HasPrefix(argv[i], L"fs=", &pszSuffix))
137 {
138 /* fs=<fs> */
139 pszFileSystem = pszSuffix;
140 }
141 else if (HasPrefix(argv[i], L"revision=", &pszSuffix))
142 {
143 /* revision=<X.XX> */
144 ConPuts(StdOut, L"The REVISION option is not supported yet!\n");
145 }
146 else if (HasPrefix(argv[i], L"label=", &pszSuffix))
147 {
148 /* label=<"label"> */
149 pszLabel = pszSuffix;
150 }
151 else if (HasPrefix(argv[i], L"unit=", &pszSuffix))
152 {
153 /* unit=<N> */
154 ulClusterSize = wcstoul(pszSuffix, NULL, 0);
155 if ((ulClusterSize == 0) && (errno == ERANGE))
156 {
157 ConResPuts(StdErr, IDS_ERROR_INVALID_ARGS);
158 goto done;
159 }
160 }
161 else if (_wcsicmp(argv[i], L"recommended") == 0)
162 {
163 /* recommended */
164 ConPuts(StdOut, L"The RECOMMENDED option is not supported yet!\n");
165 }
166 else if (_wcsicmp(argv[i], L"quick") == 0)
167 {
168 /* quick */
169 bQuickFormat = TRUE;
170 }
171 else if (_wcsicmp(argv[i], L"compress") == 0)
172 {
173 /* compress */
174 ConPuts(StdOut, L"The COMPRESS option is not supported yet!\n");
175 }
176 else if (_wcsicmp(argv[i], L"override") == 0)
177 {
178 /* override */
179 ConPuts(StdOut, L"The OVERRIDE option is not supported yet!\n");
180 }
181 else if (_wcsicmp(argv[i], L"duplicate") == 0)
182 {
183 /* duplicate */
184 ConPuts(StdOut, L"The DUPLICATE option is not supported yet!\n");
185 }
186 else if (_wcsicmp(argv[i], L"nowait") == 0)
187 {
188 /* nowait */
189 ConPuts(StdOut, L"The NOWAIT option is not supported yet!\n");
190 }
191 else if (_wcsicmp(argv[i], L"noerr") == 0)
192 {
193 /* noerr - Already handled above */
194 }
195 else
196 {
197 ConResPuts(StdErr, IDS_ERROR_INVALID_ARGS);
198 return EXIT_SUCCESS;
199 }
200 }
201
202 DPRINT("VolumeName : %S\n", CurrentVolume->VolumeName);
203 DPRINT("DeviceName : %S\n", CurrentVolume->DeviceName);
204 DPRINT("DriveLetter : %C\n", CurrentVolume->DriveLetter);
205#if 0
206 switch (CurrentVolume->VolumeType)
207 {
208 case VOLUME_TYPE_CDROM:
209 MediaType = FMIFS_REMOVABLE; // ???
210 break;
211
212 case VOLUME_TYPE_PARTITION:
213 MediaType = FMIFS_HARDDISK;
214 break;
215
216 case VOLUME_TYPE_REMOVABLE:
217 MediaType = FMIFS_REMOVABLE; // ???
218 break;
219
220 case VOLUME_TYPE_UNKNOWN:
221 default:
222 MediaType = FMIFS_REMOVABLE; // ???
223 break;
224 }
225#endif
226
227 DPRINT("FileSystem: %S\n", pszFileSystem);
228 DPRINT("Label: %S\n", pszLabel);
229 DPRINT("Quick: %d\n", bQuickFormat);
230 DPRINT("ClusterSize: %lu\n", ulClusterSize);
231
232 RtlDosPathNameToNtPathName_U(CurrentVolume->VolumeName, &usDriveRoot, NULL, NULL);
233
234 /* Remove trailing backslash */
235 if (usDriveRoot.Buffer[(usDriveRoot.Length / sizeof(WCHAR)) - 1] == L'\\')
236 {
237 usDriveRoot.Buffer[(usDriveRoot.Length / sizeof(WCHAR)) - 1] = UNICODE_NULL;
238 usDriveRoot.Length -= sizeof(WCHAR);
239 }
240
241 DPRINT("DriveRoot: %wZ\n", &usDriveRoot);
242
243 /* Use the FAT filesystem as default */
244 if (pszFileSystem == NULL)
245 pszFileSystem = L"FAT";
246
247 BOOLEAN bBackwardCompatible = FALSE; // Default to latest FS versions.
248 if (_wcsicmp(pszFileSystem, L"FAT") == 0)
249 bBackwardCompatible = TRUE;
250 // else if (wcsicmp(pszFileSystem, L"FAT32") == 0)
251 // bBackwardCompatible = FALSE;
252
253 if (pszLabel == NULL)
254 pszLabel = L"";
255
256 RtlInitUnicodeString(&LabelString, pszLabel);
257
258 if (!GetFsModule(pszFileSystem, &hModule))
259 {
260 DPRINT1("GetFsModule() failed\n");
261 goto done;
262 }
263
264 pFormat = (PULIB_FORMAT)GetProcAddress(hModule, "Format");
265 if (pFormat)
266 {
267 Success = (pFormat)(&usDriveRoot,
268 FormatCallback,
269 bQuickFormat,
270 bBackwardCompatible,
271 FMIFS_HARDDISK, //MediaType,
272 &LabelString,
273 ulClusterSize);
274 }
275
276done:
277 ConPuts(StdOut, L"\n");
278 if (Success)
279 ConResPrintf(StdOut, IDS_FORMAT_SUCCESS);
280 else
281 ConResPrintf(StdOut, IDS_FORMAT_FAIL);
282
283 if (hModule)
284 FreeLibrary(hModule);
285
286 RtlFreeUnicodeString(&usDriveRoot);
287
288 return EXIT_SUCCESS;
289}