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
16 #define NTOS_MODE_USER
17 #include <ndk/exfuncs.h>
18 #include <ndk/iofuncs.h>
19 #include <ndk/obfuncs.h>
20 #include <ndk/psfuncs.h>
21 #include <ndk/rtlfuncs.h>
22 #include <ndk/umfuncs.h>
23 #include <fmifs/fmifs.h>
28 /* DEFINES ******************************************************************/
30 #define FS_ATTRIBUTE_BUFFER_SIZE (MAX_PATH * sizeof(WCHAR) + sizeof(FILE_FS_ATTRIBUTE_INFORMATION))
33 /* FUNCTIONS ****************************************************************/
39 PrintString(char* fmt
,...)
43 UNICODE_STRING UnicodeString
;
44 ANSI_STRING AnsiString
;
47 vsprintf(buffer
, fmt
, ap
);
50 RtlInitAnsiString(&AnsiString
, buffer
);
51 RtlAnsiStringToUnicodeString(&UnicodeString
,
54 NtDisplayString(&UnicodeString
);
55 RtlFreeUnicodeString(&UnicodeString
);
58 // this func is taken from kernel32/file/volume.c
64 UNICODE_STRING NtPathU
;
65 OBJECT_ATTRIBUTES ObjectAttributes
;
67 IO_STATUS_BLOCK IoStatusBlock
;
70 if (!RtlDosPathNameToNtPathName_U(DirName
,
75 DPRINT1("Invalid path!\n");
76 return INVALID_HANDLE_VALUE
;
79 InitializeObjectAttributes(
86 Status
= NtCreateFile(
88 Write
? FILE_GENERIC_WRITE
: FILE_GENERIC_READ
,
93 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
99 RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathU
.Buffer
);
101 if (!NT_SUCCESS(Status
))
103 return INVALID_HANDLE_VALUE
;
112 IN OUT LPWSTR FileSystemName
,
113 IN SIZE_T FileSystemNameSize
)
117 IO_STATUS_BLOCK IoStatusBlock
;
118 PFILE_FS_ATTRIBUTE_INFORMATION FileFsAttribute
;
119 UCHAR Buffer
[FS_ATTRIBUTE_BUFFER_SIZE
];
121 FileFsAttribute
= (PFILE_FS_ATTRIBUTE_INFORMATION
)Buffer
;
123 FileHandle
= OpenDirectory(Drive
, FALSE
);
124 if (FileHandle
== INVALID_HANDLE_VALUE
)
125 return STATUS_INVALID_PARAMETER
;
127 Status
= NtQueryVolumeInformationFile(FileHandle
,
130 FS_ATTRIBUTE_BUFFER_SIZE
,
131 FileFsAttributeInformation
);
134 if (NT_SUCCESS(Status
))
136 if (FileSystemNameSize
* sizeof(WCHAR
) >= FileFsAttribute
->FileSystemNameLength
+ sizeof(WCHAR
))
138 CopyMemory(FileSystemName
,
139 FileFsAttribute
->FileSystemName
,
140 FileFsAttribute
->FileSystemNameLength
);
141 FileSystemName
[FileFsAttribute
->FileSystemNameLength
/ sizeof(WCHAR
)] = 0;
144 return STATUS_BUFFER_TOO_SMALL
;
149 return STATUS_SUCCESS
;
152 // This is based on SysInternal's ChkDsk app
155 IN CALLBACKCOMMAND Command
,
164 // We get other types of commands,
165 // but we don't have to pay attention to them
170 DPRINT("UNKNOWN2\n");
174 DPRINT("UNKNOWN3\n");
178 DPRINT("UNKNOWN4\n");
182 DPRINT("UNKNOWN5\n");
186 DPRINT("UNKNOWN9\n");
190 DPRINT("UNKNOWNA\n");
194 DPRINT("UNKNOWNC\n");
198 DPRINT("UNKNOWND\n");
201 case INSUFFICIENTRIGHTS
:
202 DPRINT("INSUFFICIENTRIGHTS\n");
206 DPRINT("FSNOTSUPPORTED\n");
210 DPRINT("VOLUMEINUSE\n");
213 case STRUCTUREPROGRESS
:
214 DPRINT("STRUCTUREPROGRESS\n");
217 case DONEWITHSTRUCTURE
:
218 DPRINT("DONEWITHSTRUCTURE\n");
221 case CLUSTERSIZETOOSMALL
:
222 DPRINT("CLUSTERSIZETOOSMALL\n");
226 Percent
= (PDWORD
) Argument
;
227 PrintString("%d percent completed.\r", *Percent
);
231 Output
= (PTEXTOUTPUT
) Argument
;
232 PrintString("%s", Output
->Output
);
236 Status
= (PBOOLEAN
)Argument
;
239 PrintString("Autochk was unable to complete successfully.\r\n\r\n");
247 /* Load the provider associated with this file system */
250 IN PWCHAR FileSystem
)
252 UNICODE_STRING ProviderDll
;
256 /* FIXME: add more providers here */
258 if (wcscmp(FileSystem
, L
"NTFS") == 0)
260 RtlInitUnicodeString(&ProviderDll
, L
"untfs.dll");
262 else if (wcscmp(FileSystem
, L
"FAT") == 0
263 || wcscmp(FileSystem
, L
"FAT32") == 0)
265 RtlInitUnicodeString(&ProviderDll
, L
"ufat.dll");
272 Status
= LdrLoadDll(NULL
, NULL
, &ProviderDll
, &BaseAddress
);
273 if (!NT_SUCCESS(Status
))
282 WCHAR FileSystem
[128];
283 ANSI_STRING ChkdskFunctionName
= RTL_CONSTANT_STRING("ChkdskEx");
286 WCHAR NtDrivePath
[64];
287 UNICODE_STRING DrivePathU
;
290 /* Get the file system */
291 Status
= GetFileSystem(DrivePath
,
293 sizeof(FileSystem
) / sizeof(FileSystem
[0]));
294 if (!NT_SUCCESS(Status
))
296 DPRINT1("GetFileSystem() failed with status 0x%08lx\n", Status
);
297 PrintString(" Unable to get file system of %S\r\n", DrivePath
);
301 /* Load the provider which will do the chkdsk */
302 Provider
= LoadProvider(FileSystem
);
303 if (Provider
== NULL
)
305 DPRINT1("LoadProvider() failed\n");
306 PrintString(" Unable to verify a %S volume\r\n", FileSystem
);
307 return STATUS_DLL_NOT_FOUND
;
310 /* Get the Chkdsk function address */
311 Status
= LdrGetProcedureAddress(Provider
,
314 (PVOID
*)&ChkdskFunc
);
315 if (!NT_SUCCESS(Status
))
317 DPRINT1("LdrGetProcedureAddress() failed with status 0x%08lx\n", Status
);
318 PrintString(" Unable to verify a %S volume\r\n", FileSystem
);
319 LdrUnloadDll(Provider
);
324 // PrintString(" Verifying volume %S\r\n", DrivePath);
325 swprintf(NtDrivePath
, L
"\\??\\");
326 wcscat(NtDrivePath
, DrivePath
);
327 NtDrivePath
[wcslen(NtDrivePath
)-1] = 0;
328 RtlInitUnicodeString(&DrivePathU
, NtDrivePath
);
330 DPRINT("AUTOCHK: Checking %wZ\n", &DrivePathU
);
331 Status
= ChkdskFunc(&DrivePathU
,
334 TRUE
, // CheckOnlyIfDirty
338 LdrUnloadDll(Provider
);
342 /* Native image's entry point */
350 PROCESS_DEVICEMAP_INFORMATION DeviceMap
;
353 WCHAR DrivePath
[128];
355 // Win2003 passes the only param - "*". Probably means to check all drives
357 DPRINT("Got %d params\n", argc);
358 for (i=0; i<argc; i++)
359 DPRINT("Param %d: %s\n", i, argv[i]);
362 /* FIXME: We should probably use here the mount manager to be
363 * able to check volumes which don't have a drive letter.
366 Status
= NtQueryInformationProcess(NtCurrentProcess(),
369 sizeof(DeviceMap
.Query
),
371 if (!NT_SUCCESS(Status
))
373 DPRINT1("NtQueryInformationProcess() failed with status 0x%08lx\n",
378 for (i
= 0; i
< 26; i
++)
380 if ((DeviceMap
.Query
.DriveMap
& (1 << i
))
381 && (DeviceMap
.Query
.DriveType
[i
] == DOSDEVICE_DRIVE_FIXED
))
383 swprintf(DrivePath
, L
"%c:\\", L
'A'+i
);
384 CheckVolume(DrivePath
);
387 // PrintString(" Done\r\n\r\n");