1 /* PROJECT: ReactOS Kernel
2 * LICENSE: GPL - See COPYING in the top level directory
3 * FILE: base/system/autochk/autochk.c
4 * PURPOSE: Filesystem checker
5 * PROGRAMMERS: Aleksey Bragin
10 /* INCLUDES *****************************************************************/
13 #define WIN32_NO_STATUS
15 #define NTOS_MODE_USER
16 #include <ndk/exfuncs.h>
17 #include <ndk/iofuncs.h>
18 #include <ndk/obfuncs.h>
19 #include <ndk/psfuncs.h>
20 #include <ndk/rtlfuncs.h>
21 #include <ndk/umfuncs.h>
22 #include <fmifs/fmifs.h>
27 /* DEFINES ******************************************************************/
29 #define FS_ATTRIBUTE_BUFFER_SIZE (MAX_PATH * sizeof(WCHAR) + sizeof(FILE_FS_ATTRIBUTE_INFORMATION))
32 /* FUNCTIONS ****************************************************************/
38 PrintString(char* fmt
,...)
42 UNICODE_STRING UnicodeString
;
43 ANSI_STRING AnsiString
;
46 vsprintf(buffer
, fmt
, ap
);
49 RtlInitAnsiString(&AnsiString
, buffer
);
50 RtlAnsiStringToUnicodeString(&UnicodeString
,
53 NtDisplayString(&UnicodeString
);
54 RtlFreeUnicodeString(&UnicodeString
);
57 // this func is taken from kernel32/file/volume.c
63 UNICODE_STRING NtPathU
;
64 OBJECT_ATTRIBUTES ObjectAttributes
;
66 IO_STATUS_BLOCK IoStatusBlock
;
69 if (!RtlDosPathNameToNtPathName_U(DirName
,
74 DPRINT1("Invalid path!\n");
75 return INVALID_HANDLE_VALUE
;
78 InitializeObjectAttributes(
85 Status
= NtCreateFile(
87 Write
? FILE_GENERIC_WRITE
: FILE_GENERIC_READ
,
92 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
98 RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathU
.Buffer
);
100 if (!NT_SUCCESS(Status
))
102 return INVALID_HANDLE_VALUE
;
111 IN OUT LPWSTR FileSystemName
,
112 IN SIZE_T FileSystemNameSize
)
116 IO_STATUS_BLOCK IoStatusBlock
;
117 PFILE_FS_ATTRIBUTE_INFORMATION FileFsAttribute
;
118 UCHAR Buffer
[FS_ATTRIBUTE_BUFFER_SIZE
];
120 FileFsAttribute
= (PFILE_FS_ATTRIBUTE_INFORMATION
)Buffer
;
122 FileHandle
= OpenDirectory(Drive
, FALSE
);
123 if (FileHandle
== INVALID_HANDLE_VALUE
)
124 return STATUS_INVALID_PARAMETER
;
126 Status
= NtQueryVolumeInformationFile(FileHandle
,
129 FS_ATTRIBUTE_BUFFER_SIZE
,
130 FileFsAttributeInformation
);
133 if (NT_SUCCESS(Status
))
135 if (FileSystemNameSize
* sizeof(WCHAR
) >= FileFsAttribute
->FileSystemNameLength
+ sizeof(WCHAR
))
137 CopyMemory(FileSystemName
,
138 FileFsAttribute
->FileSystemName
,
139 FileFsAttribute
->FileSystemNameLength
);
140 FileSystemName
[FileFsAttribute
->FileSystemNameLength
/ sizeof(WCHAR
)] = 0;
143 return STATUS_BUFFER_TOO_SMALL
;
148 return STATUS_SUCCESS
;
151 // This is based on SysInternal's ChkDsk app
154 IN CALLBACKCOMMAND Command
,
163 // We get other types of commands,
164 // but we don't have to pay attention to them
169 DPRINT("UNKNOWN2\r");
173 DPRINT("UNKNOWN3\r");
177 DPRINT("UNKNOWN4\r");
181 DPRINT("UNKNOWN5\r");
185 DPRINT("UNKNOWN9\r");
189 DPRINT("UNKNOWNA\r");
193 DPRINT("UNKNOWNC\r");
197 DPRINT("UNKNOWND\r");
200 case INSUFFICIENTRIGHTS
:
201 DPRINT("INSUFFICIENTRIGHTS\r");
205 DPRINT("FSNOTSUPPORTED\r");
209 DPRINT("VOLUMEINUSE\r");
212 case STRUCTUREPROGRESS
:
213 DPRINT("STRUCTUREPROGRESS\r");
216 case DONEWITHSTRUCTURE
:
217 DPRINT("DONEWITHSTRUCTURE\r");
220 case CLUSTERSIZETOOSMALL
:
221 DPRINT("CLUSTERSIZETOOSMALL\r");
225 Percent
= (PDWORD
) Argument
;
226 PrintString("%d percent completed.\r", *Percent
);
230 Output
= (PTEXTOUTPUT
) Argument
;
231 PrintString("%s", Output
->Output
);
235 Status
= (PBOOLEAN
)Argument
;
238 PrintString("Autochk was unable to complete successfully.\n\n");
246 /* Load the provider associated with this file system */
249 IN PWCHAR FileSystem
)
251 UNICODE_STRING ProviderDll
;
255 /* FIXME: add more providers here */
257 if (wcscmp(FileSystem
, L
"NTFS") == 0)
259 RtlInitUnicodeString(&ProviderDll
, L
"untfs.dll");
261 else if (wcscmp(FileSystem
, L
"FAT") == 0
262 || wcscmp(FileSystem
, L
"FAT32") == 0)
264 RtlInitUnicodeString(&ProviderDll
, L
"ufat.dll");
271 Status
= LdrLoadDll(NULL
, NULL
, &ProviderDll
, &BaseAddress
);
272 if (!NT_SUCCESS(Status
))
281 WCHAR FileSystem
[128];
282 ANSI_STRING ChkdskFunctionName
= RTL_CONSTANT_STRING("ChkdskEx");
285 WCHAR NtDrivePath
[64];
286 UNICODE_STRING DrivePathU
;
289 /* Get the file system */
290 Status
= GetFileSystem(DrivePath
,
292 sizeof(FileSystem
) / sizeof(FileSystem
[0]));
293 if (!NT_SUCCESS(Status
))
295 DPRINT1("GetFileSystem() failed with status 0x%08lx\n", Status
);
296 PrintString(" Unable to get file system of %S\n", DrivePath
);
300 /* Load the provider which will do the chkdsk */
301 Provider
= LoadProvider(FileSystem
);
302 if (Provider
== NULL
)
304 DPRINT1("LoadProvider() failed\n");
305 PrintString(" Unable to verify a %S volume\n", FileSystem
);
306 return STATUS_DLL_NOT_FOUND
;
309 /* Get the Chkdsk function address */
310 Status
= LdrGetProcedureAddress(Provider
,
313 (PVOID
*)&ChkdskFunc
);
314 if (!NT_SUCCESS(Status
))
316 DPRINT1("LdrGetProcedureAddress() failed with status 0x%08lx\n", Status
);
317 PrintString(" Unable to verify a %S volume\n", FileSystem
);
318 LdrUnloadDll(Provider
);
323 //PrintString(" Verifying volume %S\n", DrivePath);
324 swprintf(NtDrivePath
, L
"\\??\\");
325 wcscat(NtDrivePath
, DrivePath
);
326 NtDrivePath
[wcslen(NtDrivePath
)-1] = 0;
327 RtlInitUnicodeString(&DrivePathU
, NtDrivePath
);
329 Status
= ChkdskFunc(&DrivePathU
,
332 TRUE
, // CheckOnlyIfDirty
336 LdrUnloadDll(Provider
);
340 /* Native image's entry point */
348 PROCESS_DEVICEMAP_INFORMATION DeviceMap
;
351 WCHAR DrivePath
[128];
353 // Win2003 passes the only param - "*". Probably means to check all drives
355 DPRINT("Got %d params\n", argc);
356 for (i=0; i<argc; i++)
357 DPRINT("Param %d: %s\n", i, argv[i]);
360 /* FIXME: We should probably use here the mount manager to be
361 * able to check volumes which don't have a drive letter.
364 Status
= NtQueryInformationProcess(NtCurrentProcess(),
367 sizeof(DeviceMap
.Query
),
369 if (!NT_SUCCESS(Status
))
371 DPRINT1("NtQueryInformationProcess() failed with status 0x%08lx\n",
376 for (i
= 0; i
< 26; i
++)
378 if ((DeviceMap
.Query
.DriveMap
& (1 << i
))
379 && (DeviceMap
.Query
.DriveType
[i
] == DOSDEVICE_DRIVE_FIXED
))
381 swprintf(DrivePath
, L
"%c:\\", L
'A'+i
);
382 CheckVolume(DrivePath
);
385 //PrintString(" Done\n\n");