Correctly implement autochk, which now calls the ChkdskEx function in u{FS}.dll.

svn path=/trunk/; revision=23962
This commit is contained in:
Hervé Poussineau 2006-09-07 17:54:23 +00:00
parent 611b577fd6
commit 0d173915ac

View file

@ -1,10 +1,10 @@
/* $Id$ /* PROJECT: ReactOS Kernel
* PROJECT: ReactOS Kernel
* LICENSE: GPL - See COPYING in the top level directory * LICENSE: GPL - See COPYING in the top level directory
* FILE: base/system/autochk/autochk.c * FILE: base/system/autochk/autochk.c
* PURPOSE: Filesystem checker * PURPOSE: Filesystem checker
* PROGRAMMERS: Aleksey Bragin * PROGRAMMERS: Aleksey Bragin
* Eric Kohl * Eric Kohl
* Hervé Poussineau
*/ */
/* INCLUDES *****************************************************************/ /* INCLUDES *****************************************************************/
@ -28,30 +28,8 @@
// //
// FMIFS function // FMIFS function
// //
typedef
VOID
(STDCALL *PCHKDSK)(PWCHAR DriveRoot,
PWCHAR Format,
BOOLEAN CorrectErrors,
BOOLEAN Verbose,
BOOLEAN CheckOnlyIfDirty,
BOOLEAN ScanDrive,
PVOID Unused2,
PVOID Unused3,
PFMIFSCALLBACK Callback);
PCHKDSK ChkdskFunc = NULL; static VOID
void
DisplayString(LPCWSTR lpwString)
{
UNICODE_STRING us;
RtlInitUnicodeString(&us, lpwString);
NtDisplayString(&us);
}
void
PrintString(char* fmt,...) PrintString(char* fmt,...)
{ {
char buffer[512]; char buffer[512];
@ -72,9 +50,10 @@ PrintString(char* fmt,...)
} }
// this func is taken from kernel32/file/volume.c // this func is taken from kernel32/file/volume.c
HANDLE static HANDLE
OpenDirectory(LPCWSTR DirName, OpenDirectory(
BOOLEAN Write) IN LPCWSTR DirName,
IN BOOLEAN Write)
{ {
UNICODE_STRING NtPathU; UNICODE_STRING NtPathU;
OBJECT_ATTRIBUTES ObjectAttributes; OBJECT_ATTRIBUTES ObjectAttributes;
@ -121,10 +100,11 @@ OpenDirectory(LPCWSTR DirName,
return hFile; return hFile;
} }
NTSTATUS static NTSTATUS
GetFileSystem(LPCWSTR Drive, GetFileSystem(
LPWSTR FileSystemName, IN LPCWSTR Drive,
ULONG FileSystemNameSize) IN OUT LPWSTR FileSystemName,
IN SIZE_T FileSystemNameSize)
{ {
HANDLE FileHandle; HANDLE FileHandle;
NTSTATUS Status; NTSTATUS Status;
@ -149,7 +129,7 @@ GetFileSystem(LPCWSTR Drive,
{ {
if (FileSystemNameSize * sizeof(WCHAR) >= FileFsAttribute->FileSystemNameLength + sizeof(WCHAR)) if (FileSystemNameSize * sizeof(WCHAR) >= FileFsAttribute->FileSystemNameLength + sizeof(WCHAR))
{ {
memcpy(FileSystemName, CopyMemory(FileSystemName,
FileFsAttribute->FileSystemName, FileFsAttribute->FileSystemName,
FileFsAttribute->FileSystemNameLength); FileFsAttribute->FileSystemNameLength);
FileSystemName[FileFsAttribute->FileSystemNameLength / sizeof(WCHAR)] = 0; FileSystemName[FileFsAttribute->FileSystemNameLength / sizeof(WCHAR)] = 0;
@ -164,11 +144,11 @@ GetFileSystem(LPCWSTR Drive,
} }
// This is based on SysInternal's ChkDsk app // This is based on SysInternal's ChkDsk app
BOOLEAN static BOOLEAN CALLBACK
STDCALL ChkdskCallback(
ChkdskCallback(CALLBACKCOMMAND Command, IN CALLBACKCOMMAND Command,
DWORD Modifier, IN DWORD Modifier,
PVOID Argument) IN PVOID Argument)
{ {
PDWORD Percent; PDWORD Percent;
PBOOLEAN Status; PBOOLEAN Status;
@ -254,6 +234,86 @@ ChkdskCallback(CALLBACKCOMMAND Command,
return TRUE; return TRUE;
} }
/* Load the provider associated with this file system */
static PVOID
LoadProvider(
IN PWCHAR FileSystem)
{
UNICODE_STRING ProviderDll = RTL_CONSTANT_STRING(L"ufat.dll");
PVOID BaseAddress;
NTSTATUS Status;
/* FIXME: add more providers here */
if (wcscmp(FileSystem, L"FAT") != 0
&& wcscmp(FileSystem, L"FAT32") != 0)
{
return NULL;
}
Status = LdrLoadDll(NULL, NULL, &ProviderDll, &BaseAddress);
if (!NT_SUCCESS(Status))
return NULL;
return BaseAddress;
}
static NTSTATUS
CheckVolume(
IN PWCHAR DrivePath)
{
WCHAR FileSystem[128];
ANSI_STRING ChkdskFunctionName = RTL_CONSTANT_STRING("ChkdskEx");
PVOID Provider;
CHKDSKEX ChkdskFunc;
UNICODE_STRING DrivePathU;
NTSTATUS Status;
/* Get the file system */
Status = GetFileSystem(DrivePath,
FileSystem,
sizeof(FileSystem) / sizeof(FileSystem[0]));
if (!NT_SUCCESS(Status))
{
DPRINT1("GetFileSystem() failed with status 0x%08lx\n", Status);
PrintString(" Unable to get file system of %S\n", DrivePath);
return Status;
}
/* Load the provider which will do the chkdsk */
Provider = LoadProvider(FileSystem);
if (!NT_SUCCESS(Status))
{
DPRINT1("LoadProvider() failed\n");
PrintString(" Unable to verify a %S volume\n", FileSystem);
return STATUS_DLL_NOT_FOUND;
}
/* Get the Chkdsk function address */
Status = LdrGetProcedureAddress(Provider,
&ChkdskFunctionName,
0,
(PVOID*)&ChkdskFunc);
if (!NT_SUCCESS(Status))
{
DPRINT1("LdrGetProcedureAddress() failed with status 0x%08lx\n", Status);
PrintString(" Unable to verify a %S volume\n", FileSystem);
LdrUnloadDll(Provider);
return Status;
}
/* Call provider */
PrintString(" Verifying volume %S\n", DrivePath);
RtlInitUnicodeString(&DrivePathU, DrivePath);
Status = ChkdskFunc(&DrivePathU,
TRUE, // FixErrors
TRUE, // Verbose
FALSE, // CheckOnlyIfDirty
FALSE,// ScanDrive
ChkdskCallback);
LdrUnloadDll(Provider);
return Status;
}
/* Native image's entry point */ /* Native image's entry point */
int int
@ -266,11 +326,8 @@ _main(int argc,
PROCESS_DEVICEMAP_INFORMATION DeviceMap; PROCESS_DEVICEMAP_INFORMATION DeviceMap;
ULONG i; ULONG i;
NTSTATUS Status; NTSTATUS Status;
WCHAR FileSystem[128];
WCHAR DrivePath[128]; WCHAR DrivePath[128];
PrintString("Autochk 0.0.2\n");
// Win2003 passes the only param - "*". Probably means to check all drives // Win2003 passes the only param - "*". Probably means to check all drives
/* /*
DPRINT("Got %d params\n", argc); DPRINT("Got %d params\n", argc);
@ -278,61 +335,33 @@ _main(int argc,
DPRINT("Param %d: %s\n", i, argv[i]); DPRINT("Param %d: %s\n", i, argv[i]);
*/ */
/* FIXME: We should probably use here the mount manager to be
* able to check volumes which don't have a drive letter.
*/
Status = NtQueryInformationProcess(NtCurrentProcess(), Status = NtQueryInformationProcess(NtCurrentProcess(),
ProcessDeviceMap, ProcessDeviceMap,
&DeviceMap.Query, &DeviceMap.Query,
sizeof(DeviceMap.Query), sizeof(DeviceMap.Query),
NULL); NULL);
if(NT_SUCCESS(Status))
{
for (i = 0; i < 26; i++)
{
if ((DeviceMap.Query.DriveMap & (1 << i)) &&
(DeviceMap.Query.DriveType[i] == DOSDEVICE_DRIVE_FIXED))
{
swprintf(DrivePath, L"%c:\\", 'A'+i);
Status = GetFileSystem(DrivePath,
FileSystem,
sizeof(FileSystem));
PrintString(" Checking drive %c: \n", 'A'+i);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT1("Error getting FS information, Status=0x%08X\n", DPRINT1("NtQueryInformationProcess() failed with status 0x%08lx\n",
Status); Status);
// skip to the next volume
continue;
}
// FS type known, show it to user and then call chkdsk routine
PrintString(" Filesystem type ");
DisplayString(FileSystem);
PrintString("\n");
/*ChkdskFunc(DrivePath,
FileSystem,
TRUE, // FixErrors
TRUE, // Verbose
FALSE, // SkipClean
FALSE,// ScanSectors
NULL,
NULL,
ChkdskCallback);*/
PrintString(" OK\n");
}
}
PrintString("\n");
return 0;
}
else
{
DPRINT1("NtQueryInformationProcess() failed with status=0x%08X\n",
Status);
}
return 1; return 1;
}
for (i = 0; i < 26; i++)
{
if ((DeviceMap.Query.DriveMap & (1 << i))
&& (DeviceMap.Query.DriveType[i] == DOSDEVICE_DRIVE_FIXED))
{
swprintf(DrivePath, L"%c:\\", 'A'+i);
CheckVolume(DrivePath);
}
}
PrintString(" Done\n\n");
return 0;
} }
/* EOF */ /* EOF */