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/ntndk.h>
17 #include <fmifs/fmifs.h>
22 /* DEFINES ******************************************************************/
24 #define FS_ATTRIBUTE_BUFFER_SIZE (MAX_PATH * sizeof(WCHAR) + sizeof(FILE_FS_ATTRIBUTE_INFORMATION))
27 /* FUNCTIONS ****************************************************************/
33 PrintString(char* fmt
,...)
37 UNICODE_STRING UnicodeString
;
38 ANSI_STRING AnsiString
;
41 vsprintf(buffer
, fmt
, ap
);
44 RtlInitAnsiString(&AnsiString
, buffer
);
45 RtlAnsiStringToUnicodeString(&UnicodeString
,
48 NtDisplayString(&UnicodeString
);
49 RtlFreeUnicodeString(&UnicodeString
);
52 // this func is taken from kernel32/file/volume.c
58 UNICODE_STRING NtPathU
;
59 OBJECT_ATTRIBUTES ObjectAttributes
;
61 IO_STATUS_BLOCK IoStatusBlock
;
64 if (!RtlDosPathNameToNtPathName_U(DirName
,
69 DPRINT1("Invalid path!\n");
70 return INVALID_HANDLE_VALUE
;
73 InitializeObjectAttributes(
80 Status
= NtCreateFile(
82 Write
? FILE_GENERIC_WRITE
: FILE_GENERIC_READ
,
87 FILE_SHARE_READ
|FILE_SHARE_WRITE
,
93 RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathU
.Buffer
);
95 if (!NT_SUCCESS(Status
))
97 return INVALID_HANDLE_VALUE
;
106 IN OUT LPWSTR FileSystemName
,
107 IN SIZE_T FileSystemNameSize
)
111 IO_STATUS_BLOCK IoStatusBlock
;
112 PFILE_FS_ATTRIBUTE_INFORMATION FileFsAttribute
;
113 UCHAR Buffer
[FS_ATTRIBUTE_BUFFER_SIZE
];
115 FileFsAttribute
= (PFILE_FS_ATTRIBUTE_INFORMATION
)Buffer
;
117 FileHandle
= OpenDirectory(Drive
, FALSE
);
118 if (FileHandle
== INVALID_HANDLE_VALUE
)
119 return STATUS_INVALID_PARAMETER
;
121 Status
= NtQueryVolumeInformationFile(FileHandle
,
124 FS_ATTRIBUTE_BUFFER_SIZE
,
125 FileFsAttributeInformation
);
128 if (NT_SUCCESS(Status
))
130 if (FileSystemNameSize
* sizeof(WCHAR
) >= FileFsAttribute
->FileSystemNameLength
+ sizeof(WCHAR
))
132 CopyMemory(FileSystemName
,
133 FileFsAttribute
->FileSystemName
,
134 FileFsAttribute
->FileSystemNameLength
);
135 FileSystemName
[FileFsAttribute
->FileSystemNameLength
/ sizeof(WCHAR
)] = 0;
138 return STATUS_BUFFER_TOO_SMALL
;
143 return STATUS_SUCCESS
;
146 // This is based on SysInternal's ChkDsk app
149 IN CALLBACKCOMMAND Command
,
158 // We get other types of commands,
159 // but we don't have to pay attention to them
164 DPRINT("UNKNOWN2\r");
168 DPRINT("UNKNOWN3\r");
172 DPRINT("UNKNOWN4\r");
176 DPRINT("UNKNOWN5\r");
180 DPRINT("UNKNOWN9\r");
184 DPRINT("UNKNOWNA\r");
188 DPRINT("UNKNOWNC\r");
192 DPRINT("UNKNOWND\r");
195 case INSUFFICIENTRIGHTS
:
196 DPRINT("INSUFFICIENTRIGHTS\r");
200 DPRINT("FSNOTSUPPORTED\r");
204 DPRINT("VOLUMEINUSE\r");
207 case STRUCTUREPROGRESS
:
208 DPRINT("STRUCTUREPROGRESS\r");
211 case DONEWITHSTRUCTURE
:
212 DPRINT("DONEWITHSTRUCTURE\r");
215 case CLUSTERSIZETOOSMALL
:
216 DPRINT("CLUSTERSIZETOOSMALL\r");
220 Percent
= (PDWORD
) Argument
;
221 PrintString("%d percent completed.\r", *Percent
);
225 Output
= (PTEXTOUTPUT
) Argument
;
226 PrintString("%s", Output
->Output
);
230 Status
= (PBOOLEAN
)Argument
;
233 PrintString("Autochk was unable to complete successfully.\n\n");
241 /* Load the provider associated with this file system */
244 IN PWCHAR FileSystem
)
246 UNICODE_STRING ProviderDll
;
250 /* FIXME: add more providers here */
252 if (wcscmp(FileSystem
, L
"NTFS") == 0)
254 RtlInitUnicodeString(&ProviderDll
, L
"untfs.dll");
256 else if (wcscmp(FileSystem
, L
"FAT") == 0
257 || wcscmp(FileSystem
, L
"FAT32") == 0)
259 RtlInitUnicodeString(&ProviderDll
, L
"ufat.dll");
266 Status
= LdrLoadDll(NULL
, NULL
, &ProviderDll
, &BaseAddress
);
267 if (!NT_SUCCESS(Status
))
276 WCHAR FileSystem
[128];
277 ANSI_STRING ChkdskFunctionName
= RTL_CONSTANT_STRING("ChkdskEx");
280 WCHAR NtDrivePath
[64];
281 UNICODE_STRING DrivePathU
;
284 /* Get the file system */
285 Status
= GetFileSystem(DrivePath
,
287 sizeof(FileSystem
) / sizeof(FileSystem
[0]));
288 if (!NT_SUCCESS(Status
))
290 DPRINT1("GetFileSystem() failed with status 0x%08lx\n", Status
);
291 PrintString(" Unable to get file system of %S\n", DrivePath
);
295 /* Load the provider which will do the chkdsk */
296 Provider
= LoadProvider(FileSystem
);
297 if (Provider
== NULL
)
299 DPRINT1("LoadProvider() failed\n");
300 PrintString(" Unable to verify a %S volume\n", FileSystem
);
301 return STATUS_DLL_NOT_FOUND
;
304 /* Get the Chkdsk function address */
305 Status
= LdrGetProcedureAddress(Provider
,
308 (PVOID
*)&ChkdskFunc
);
309 if (!NT_SUCCESS(Status
))
311 DPRINT1("LdrGetProcedureAddress() failed with status 0x%08lx\n", Status
);
312 PrintString(" Unable to verify a %S volume\n", FileSystem
);
313 LdrUnloadDll(Provider
);
318 //PrintString(" Verifying volume %S\n", DrivePath);
319 swprintf(NtDrivePath
, L
"\\??\\");
320 wcscat(NtDrivePath
, DrivePath
);
321 NtDrivePath
[wcslen(NtDrivePath
)-1] = 0;
322 RtlInitUnicodeString(&DrivePathU
, NtDrivePath
);
324 Status
= ChkdskFunc(&DrivePathU
,
327 FALSE
, // CheckOnlyIfDirty
331 LdrUnloadDll(Provider
);
335 /* Native image's entry point */
343 PROCESS_DEVICEMAP_INFORMATION DeviceMap
;
346 WCHAR DrivePath
[128];
348 // Win2003 passes the only param - "*". Probably means to check all drives
350 DPRINT("Got %d params\n", argc);
351 for (i=0; i<argc; i++)
352 DPRINT("Param %d: %s\n", i, argv[i]);
355 /* FIXME: We should probably use here the mount manager to be
356 * able to check volumes which don't have a drive letter.
359 Status
= NtQueryInformationProcess(NtCurrentProcess(),
362 sizeof(DeviceMap
.Query
),
364 if (!NT_SUCCESS(Status
))
366 DPRINT1("NtQueryInformationProcess() failed with status 0x%08lx\n",
371 for (i
= 0; i
< 26; i
++)
373 if ((DeviceMap
.Query
.DriveMap
& (1 << i
))
374 && (DeviceMap
.Query
.DriveType
[i
] == DOSDEVICE_DRIVE_FIXED
))
376 swprintf(DrivePath
, L
"%c:\\", L
'A'+i
);
377 CheckVolume(DrivePath
);
380 //PrintString(" Done\n\n");