2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: base/system/autochk/autochk.c
5 * PURPOSE: Filesystem checker
6 * PROGRAMMERS: Aleksey Bragin
12 /* INCLUDES *****************************************************************/
15 #define WIN32_NO_STATUS
18 #define NTOS_MODE_USER
19 #include <ndk/exfuncs.h>
20 #include <ndk/iofuncs.h>
21 #include <ndk/obfuncs.h>
22 #include <ndk/psfuncs.h>
23 #include <ndk/rtlfuncs.h>
24 #include <ndk/umfuncs.h>
25 #include <fmifs/fmifs.h>
27 #include <fslib/vfatlib.h>
28 #include <fslib/ext2lib.h>
29 #include <fslib/ntfslib.h>
30 #include <fslib/cdfslib.h>
31 #include <fslib/btrfslib.h>
32 #include <fslib/ffslib.h>
33 #include <fslib/reiserfslib.h>
38 /* DEFINES ******************************************************************/
40 #define FS_ATTRIBUTE_BUFFER_SIZE (MAX_PATH * sizeof(WCHAR) + sizeof(FILE_FS_ATTRIBUTE_INFORMATION))
42 typedef struct _FILESYSTEM_CHKDSK
46 } FILESYSTEM_CHKDSK
, *PFILESYSTEM_CHKDSK
;
48 FILESYSTEM_CHKDSK FileSystems
[10] =
50 { L
"FAT", VfatChkdsk
},
51 { L
"FAT32", VfatChkdsk
},
52 { L
"NTFS", NtfsChkdsk
},
53 { L
"EXT2", Ext2Chkdsk
},
54 { L
"EXT3", Ext2Chkdsk
},
55 { L
"EXT4", Ext2Chkdsk
},
56 { L
"Btrfs", BtrfsChkdskEx
},
57 { L
"RFSD", ReiserfsChkdsk
},
58 { L
"FFS", FfsChkdsk
},
59 { L
"CDFS", CdfsChkdsk
},
62 /* FUNCTIONS ****************************************************************/
68 PrintString(char* fmt
,...)
72 UNICODE_STRING UnicodeString
;
73 ANSI_STRING AnsiString
;
76 vsprintf(buffer
, fmt
, ap
);
79 RtlInitAnsiString(&AnsiString
, buffer
);
80 RtlAnsiStringToUnicodeString(&UnicodeString
,
83 NtDisplayString(&UnicodeString
);
84 RtlFreeUnicodeString(&UnicodeString
);
87 // this func is taken from kernel32/file/volume.c
93 UNICODE_STRING NtPathU
;
94 OBJECT_ATTRIBUTES ObjectAttributes
;
96 IO_STATUS_BLOCK IoStatusBlock
;
99 if (!RtlDosPathNameToNtPathName_U(DirName
,
104 DPRINT1("Invalid path!\n");
105 return INVALID_HANDLE_VALUE
;
108 InitializeObjectAttributes(
111 OBJ_CASE_INSENSITIVE
,
115 Status
= NtCreateFile(
117 Write
? FILE_GENERIC_WRITE
: FILE_GENERIC_READ
,
122 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
128 RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathU
.Buffer
);
130 if (!NT_SUCCESS(Status
))
132 return INVALID_HANDLE_VALUE
;
141 IN OUT LPWSTR FileSystemName
,
142 IN SIZE_T FileSystemNameSize
)
146 IO_STATUS_BLOCK IoStatusBlock
;
147 PFILE_FS_ATTRIBUTE_INFORMATION FileFsAttribute
;
148 UCHAR Buffer
[FS_ATTRIBUTE_BUFFER_SIZE
];
150 FileFsAttribute
= (PFILE_FS_ATTRIBUTE_INFORMATION
)Buffer
;
152 FileHandle
= OpenDirectory(Drive
, FALSE
);
153 if (FileHandle
== INVALID_HANDLE_VALUE
)
154 return STATUS_INVALID_PARAMETER
;
156 Status
= NtQueryVolumeInformationFile(FileHandle
,
159 FS_ATTRIBUTE_BUFFER_SIZE
,
160 FileFsAttributeInformation
);
163 if (NT_SUCCESS(Status
))
165 if (FileSystemNameSize
* sizeof(WCHAR
) >= FileFsAttribute
->FileSystemNameLength
+ sizeof(WCHAR
))
167 CopyMemory(FileSystemName
,
168 FileFsAttribute
->FileSystemName
,
169 FileFsAttribute
->FileSystemNameLength
);
170 FileSystemName
[FileFsAttribute
->FileSystemNameLength
/ sizeof(WCHAR
)] = 0;
173 return STATUS_BUFFER_TOO_SMALL
;
178 return STATUS_SUCCESS
;
181 // This is based on SysInternal's ChkDsk app
184 IN CALLBACKCOMMAND Command
,
193 // We get other types of commands,
194 // but we don't have to pay attention to them
199 DPRINT("UNKNOWN2\n");
203 DPRINT("UNKNOWN3\n");
207 DPRINT("UNKNOWN4\n");
211 DPRINT("UNKNOWN5\n");
215 DPRINT("UNKNOWN9\n");
219 DPRINT("UNKNOWNA\n");
223 DPRINT("UNKNOWNC\n");
227 DPRINT("UNKNOWND\n");
230 case INSUFFICIENTRIGHTS
:
231 DPRINT("INSUFFICIENTRIGHTS\n");
235 DPRINT("FSNOTSUPPORTED\n");
239 DPRINT("VOLUMEINUSE\n");
242 case STRUCTUREPROGRESS
:
243 DPRINT("STRUCTUREPROGRESS\n");
246 case DONEWITHSTRUCTURE
:
247 DPRINT("DONEWITHSTRUCTURE\n");
250 case CLUSTERSIZETOOSMALL
:
251 DPRINT("CLUSTERSIZETOOSMALL\n");
255 Percent
= (PDWORD
) Argument
;
256 PrintString("%d percent completed.\r", *Percent
);
260 Output
= (PTEXTOUTPUT
) Argument
;
261 PrintString("%s", Output
->Output
);
265 Status
= (PBOOLEAN
)Argument
;
266 if (*Status
!= FALSE
)
268 PrintString("Autochk was unable to complete successfully.\r\n\r\n");
280 WCHAR FileSystem
[128];
281 WCHAR NtDrivePath
[64];
282 UNICODE_STRING DrivePathU
;
286 /* Get the file system */
287 Status
= GetFileSystem(DrivePath
,
289 ARRAYSIZE(FileSystem
));
290 if (!NT_SUCCESS(Status
))
292 DPRINT1("GetFileSystem() failed with status 0x%08lx\n", Status
);
293 PrintString(" Unable to get file system of %S\r\n", DrivePath
);
298 for (Count
= 0; Count
< sizeof(FileSystems
) / sizeof(FileSystems
[0]); ++Count
)
300 if (wcscmp(FileSystem
, FileSystems
[Count
].Name
) != 0)
305 // PrintString(" Verifying volume %S\r\n", DrivePath);
306 swprintf(NtDrivePath
, L
"\\??\\");
307 wcscat(NtDrivePath
, DrivePath
);
308 NtDrivePath
[wcslen(NtDrivePath
)-1] = 0;
309 RtlInitUnicodeString(&DrivePathU
, NtDrivePath
);
311 DPRINT1("AUTOCHK: Checking %wZ\n", &DrivePathU
);
312 Status
= FileSystems
[Count
].ChkdskFunc(&DrivePathU
,
315 TRUE
, // CheckOnlyIfDirty
321 if (Count
== sizeof(FileSystems
) / sizeof(FileSystems
[0]))
323 DPRINT1("File system not supported\n");
324 PrintString(" Unable to verify a %S volume\r\n", FileSystem
);
325 return STATUS_DLL_NOT_FOUND
;
331 /* Native image's entry point */
339 PROCESS_DEVICEMAP_INFORMATION DeviceMap
;
342 WCHAR DrivePath
[128];
344 // Win2003 passes the only param - "*". Probably means to check all drives
346 DPRINT("Got %d params\n", argc);
347 for (i=0; i<argc; i++)
348 DPRINT("Param %d: %s\n", i, argv[i]);
351 /* FIXME: We should probably use here the mount manager to be
352 * able to check volumes which don't have a drive letter.
355 Status
= NtQueryInformationProcess(NtCurrentProcess(),
358 sizeof(DeviceMap
.Query
),
360 if (!NT_SUCCESS(Status
))
362 DPRINT1("NtQueryInformationProcess() failed with status 0x%08lx\n",
367 for (i
= 0; i
< 26; i
++)
369 if ((DeviceMap
.Query
.DriveMap
& (1 << i
))
370 && (DeviceMap
.Query
.DriveType
[i
] == DOSDEVICE_DRIVE_FIXED
))
372 swprintf(DrivePath
, L
"%c:\\", L
'A'+i
);
373 CheckVolume(DrivePath
);
376 // PrintString(" Done\r\n\r\n");