fix UNICODE redefined warning
[reactos.git] / rosapps / applications / sysutils / chkdsk / chkdsk.c
1 //======================================================================
2 //
3 // $Id$
4 //
5 // Chkdskx
6 //
7 // Copyright (c) 1998 Mark Russinovich
8 // Systems Internals
9 // http://www.sysinternals.com/
10 //
11 // --------------------------------------------------------------------
12 //
13 // This software is free software; you can redistribute it and/or
14 // modify it under the terms of the GNU Library General Public License as
15 // published by the Free Software Foundation; either version 2 of the
16 // License, or (at your option) any later version.
17 //
18 // This software is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 // Library General Public License for more details.
22 //
23 // You should have received a copy of the GNU Library General Public
24 // License along with this software; see the file COPYING.LIB. If
25 // not, write to the Free Software Foundation, Inc., 675 Mass Ave,
26 // Cambridge, MA 02139, USA.
27 //
28 // --------------------------------------------------------------------
29 //
30 // Chkdsk clone that demonstrates the use of the FMIFS file system
31 // utility library.
32 //
33 // 1999 February (Emanuele Aliberti)
34 // Adapted for ReactOS and lcc-win32.
35 //
36 // 1999 April (Emanuele Aliberti)
37 // Adapted for ReactOS and egcs.
38 //
39 // 2008 July (Aleksey Bragin)
40 // Cleanup, use ReactOS's fmifs.h
41 //
42 //======================================================================
43 #define WIN32_NO_STATUS
44 #define NTOS_MODE_USER
45 #include <windows.h>
46 #include <stdio.h>
47 #include <ndk/ntndk.h>
48 #include <fmifs/fmifs.h>
49 #define _UNICODE 1
50 #include <tchar.h>
51 #include "config.h"
52 #include "win32err.h"
53
54 //
55 // Globals
56 //
57 BOOL Error = FALSE;
58
59 // switches
60 BOOL FixErrors = FALSE;
61 BOOL SkipClean = FALSE;
62 BOOL ScanSectors = FALSE;
63 BOOL Verbose = FALSE;
64 PWCHAR Drive = NULL;
65 WCHAR CurrentDirectory[1024];
66
67 #ifndef FMIFS_IMPORT_DLL
68 //
69 // FMIFS function
70 //
71 //PCHKDSK Chkdsk;
72 #endif /* ndef FMIFS_IMPORT_DLL */
73
74
75 //--------------------------------------------------------------------
76 //
77 // CtrlCIntercept
78 //
79 // Intercepts Ctrl-C's so that the program can't be quit with the
80 // disk in an inconsistent state.
81 //
82 //--------------------------------------------------------------------
83 BOOL
84 WINAPI
85 CtrlCIntercept( DWORD dwCtrlType )
86 {
87 //
88 // Handle the event so that the default handler doesn't
89 //
90 return TRUE;
91 }
92
93
94 //----------------------------------------------------------------------
95 //
96 // Usage
97 //
98 // Tell the user how to use the program
99 //
100 // 19990216 EA Missing printf %s argument
101 //----------------------------------------------------------------------
102 VOID
103 Usage( PWCHAR ProgramName )
104 {
105 _tprintf(
106 L"\
107 Usage: %s [drive:] [-F] [-V] [-R] [-C]\n\n\
108 [drive:] Specifies the drive to check.\n\
109 -F Fixes errors on the disk.\n\
110 -V Displays the full path of every file on the disk.\n\
111 -R Locates bad sectors and recovers readable information.\n\
112 -C Checks the drive only if it is dirty.\n\n",
113 ProgramName
114 );
115 }
116
117
118 //----------------------------------------------------------------------
119 //
120 // ParseCommandLine
121 //
122 // Get the switches.
123 //
124 //----------------------------------------------------------------------
125 int
126 ParseCommandLine(
127 int argc,
128 WCHAR *argv []
129 )
130 {
131 int i;
132 BOOLEAN gotFix = FALSE;
133 BOOLEAN gotVerbose = FALSE;
134 BOOLEAN gotClean = FALSE;
135 /*BOOLEAN gotScan = FALSE;*/
136
137
138 for ( i = 1;
139 (i < argc);
140 i++
141 ) {
142 switch( argv[i][0] )
143 {
144 case L'-':
145 case L'/':
146
147 switch( argv[i][1] )
148 {
149 case L'F':
150 case L'f':
151
152 if( gotFix ) return i;
153 FixErrors = TRUE;
154 gotFix = TRUE;
155 break;
156
157 case L'V':
158 case L'v':
159
160 if( gotVerbose) return i;
161 Verbose = TRUE;
162 gotVerbose = TRUE;
163 break;
164
165 case L'R':
166 case L'r':
167
168 if( gotFix ) return i;
169 ScanSectors = TRUE;
170 gotFix = TRUE;
171 break;
172
173 case L'C':
174 case L'c':
175
176 if( gotClean ) return i;
177 SkipClean = TRUE;
178 gotClean = TRUE;
179 break;
180
181 default:
182 return i;
183 }
184 break;
185
186 default:
187
188 if( Drive ) return i;
189 if( argv[i][1] != L':' ) return i;
190
191 Drive = argv[i];
192 break;
193 }
194 }
195 return 0;
196 }
197
198
199 //----------------------------------------------------------------------
200 //
201 // ChkdskCallback
202 //
203 // The file system library will call us back with commands that we
204 // can interpret. If we wanted to halt the chkdsk we could return FALSE.
205 //
206 //----------------------------------------------------------------------
207 BOOLEAN
208 STDCALL
209 ChkdskCallback(
210 CALLBACKCOMMAND Command,
211 DWORD Modifier,
212 PVOID Argument
213 )
214 {
215 PDWORD percent;
216 PBOOLEAN status;
217 PTEXTOUTPUT output;
218
219 //
220 // We get other types of commands,
221 // but we don't have to pay attention to them
222 //
223 switch( Command )
224 {
225 case UNKNOWN2:
226 wprintf(L"UNKNOWN2\r");
227 break;
228
229 case UNKNOWN3:
230 wprintf(L"UNKNOWN3\r");
231 break;
232
233 case UNKNOWN4:
234 wprintf(L"UNKNOWN4\r");
235 break;
236
237 case UNKNOWN5:
238 wprintf(L"UNKNOWN5\r");
239 break;
240
241 case FSNOTSUPPORTED:
242 wprintf(L"FSNOTSUPPORTED\r");
243 break;
244
245 case VOLUMEINUSE:
246 wprintf(L"VOLUMEINUSE\r");
247 break;
248
249 case UNKNOWN9:
250 wprintf(L"UNKNOWN9\r");
251 break;
252
253 case UNKNOWNA:
254 wprintf(L"UNKNOWNA\r");
255 break;
256
257 case UNKNOWNC:
258 wprintf(L"UNKNOWNC\r");
259 break;
260
261 case UNKNOWND:
262 wprintf(L"UNKNOWND\r");
263 break;
264
265 case INSUFFICIENTRIGHTS:
266 wprintf(L"INSUFFICIENTRIGHTS\r");
267 break;
268
269 case STRUCTUREPROGRESS:
270 wprintf(L"STRUCTUREPROGRESS\r");
271 break;
272
273 case DONEWITHSTRUCTURE:
274 wprintf(L"DONEWITHSTRUCTURE\r");
275 break;
276
277 case CLUSTERSIZETOOSMALL:
278 wprintf(L"CLUSTERSIZETOOSMALL\r");
279 break;
280
281 case PROGRESS:
282 percent = (PDWORD) Argument;
283 wprintf(L"%d percent completed.\r", *percent);
284 break;
285
286 case OUTPUT:
287 output = (PTEXTOUTPUT) Argument;
288 fwprintf(stdout, L"%s", output->Output);
289 break;
290
291 case DONE:
292 status = (PBOOLEAN) Argument;
293 if ( *status == TRUE )
294 {
295 wprintf(L"Chkdsk was unable to complete successfully.\n\n");
296 Error = TRUE;
297 }
298 break;
299 }
300 return TRUE;
301 }
302
303 #ifndef FMIFS_IMPORT_DLL
304 //----------------------------------------------------------------------
305 //
306 // LoadFMIFSEntryPoints
307 //
308 // Loads FMIFS.DLL and locates the entry point(s) we are going to use
309 //
310 // 19990216 EA Used wide functions
311 //
312 //----------------------------------------------------------------------
313 BOOLEAN
314 LoadFMIFSEntryPoints(VOID)
315 {
316 LoadLibraryW( L"fmifs.dll" );
317
318 if( !(Chkdsk =
319 (void *) GetProcAddress(
320 GetModuleHandleW(L"fmifs.dll"),
321 "Chkdsk" ))
322 )
323 {
324 return FALSE;
325 }
326 return TRUE;
327 }
328 #endif /* ndef FMIFS_IMPORT_DLL */
329
330
331 //----------------------------------------------------------------------
332 //
333 // WMain
334 //
335 // Engine. Just get command line switches and fire off a chkdsk. This
336 // could also be done in a GUI like Explorer does when you select a
337 // drive and run a check on it.
338 //
339 // We do this in UNICODE because the chkdsk command expects PWCHAR
340 // arguments.
341 //
342 //----------------------------------------------------------------------
343 int
344 wmain( int argc, WCHAR *argv[] )
345 {
346 int badArg;
347 HANDLE volumeHandle;
348 WCHAR fileSystem [1024];
349 WCHAR volumeName [1024];
350 DWORD serialNumber;
351 DWORD flags,
352 maxComponent;
353
354 wprintf(
355 L"\n\
356 Chkdskx v1.0.1 by Mark Russinovich\n\
357 Systems Internals - http://www.sysinternals.com/\n\
358 ReactOS adaptation 1999 by Emanuele Aliberti\n\n"
359 );
360 #ifndef FMIFS_IMPORT_DLL
361 //
362 // Get function pointers
363 //
364 if( !LoadFMIFSEntryPoints())
365 {
366 wprintf(L"Could not located FMIFS entry points.\n\n");
367 return -1;
368 }
369 #endif /* ndef FMIFS_IMPORT_DLL */
370 //
371 // Parse command line
372 //
373 if( (badArg = ParseCommandLine( argc, argv )))
374 {
375 wprintf(
376 L"Unknown argument: %s\n",
377 argv[badArg]
378 );
379
380 Usage(argv[0]);
381 return -1;
382 }
383
384 //
385 // Get the drive's format
386 //
387 if( !Drive )
388 {
389 if( !GetCurrentDirectoryW(
390 sizeof(CurrentDirectory),
391 CurrentDirectory
392 )
393 ) {
394
395 PrintWin32Error(
396 L"Could not get current directory",
397 GetLastError()
398 );
399 return -1;
400 }
401
402 } else {
403
404 wcscpy( CurrentDirectory, Drive );
405 }
406 CurrentDirectory[2] = L'\\';
407 CurrentDirectory[3] = L'\0';
408 Drive = CurrentDirectory;
409
410 //
411 // Determine the drive's file system format, which we need to
412 // tell chkdsk
413 //
414 if( !GetVolumeInformationW(
415 Drive,
416 volumeName,
417 sizeof volumeName,
418 & serialNumber,
419 & maxComponent,
420 & flags,
421 fileSystem,
422 sizeof fileSystem
423 )
424 ) {
425 PrintWin32Error(
426 L"Could not query volume",
427 GetLastError()
428 );
429 return -1;
430 }
431
432 //
433 // If they want to fix, we need to have access to the drive
434 //
435 if ( FixErrors )
436 {
437 swprintf(
438 volumeName,
439 L"\\\\.\\%C:",
440 Drive[0]
441 );
442 volumeHandle = CreateFileW(
443 volumeName,
444 GENERIC_WRITE,
445 0,
446 NULL,
447 OPEN_EXISTING,
448 0,
449 0
450 );
451 if( volumeHandle == INVALID_HANDLE_VALUE )
452 {
453 wprintf(L"Chdskx cannot run because the volume is in use by another process.\n\n");
454 return -1;
455 }
456 CloseHandle( volumeHandle );
457
458 //
459 // Can't let the user break out of a chkdsk that can modify the drive
460 //
461 SetConsoleCtrlHandler( CtrlCIntercept, TRUE );
462 }
463
464 //
465 // Just do it
466 //
467 wprintf(
468 L"The type of file system is %s.\n",
469 fileSystem
470 );
471 Chkdsk(
472 Drive,
473 fileSystem,
474 FixErrors,
475 Verbose,
476 SkipClean,
477 ScanSectors,
478 NULL,
479 NULL,
480 ChkdskCallback
481 );
482
483 if ( Error ) return -1;
484 return 0;
485 }
486
487 /* EOF */