706 lines
20 KiB
C++
706 lines
20 KiB
C++
|
/*++
|
||
|
|
||
|
Copyright (c) 1996 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
chkntfs.cxx
|
||
|
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
This utility allows the users to find the state of the dirty bit
|
||
|
on NTFS volumes, to schedule autochk for specific drives, and to
|
||
|
mofidy the default autochk action for a drive.
|
||
|
|
||
|
|
||
|
SYNTAX:
|
||
|
|
||
|
chkntfs drive: [...] -- tells if a drive is dirty or chkdsk has been scheduled
|
||
|
chkntfs /d -- restore default autochk behavior
|
||
|
chkntfs /x drive: [...] -- exclude drives from default autochk
|
||
|
chkntfs /c drive: [...] -- schedule autochk to run on drives
|
||
|
chkntfs /e drive: [...] -- enable automatic volume upgrades on drives
|
||
|
chkntfs /t[:countdowntime] -- display or set autochk countdown time
|
||
|
|
||
|
|
||
|
EXIT:
|
||
|
|
||
|
0 -- OK, dirty bit not set on drive or bit not checked
|
||
|
1 -- OK, and dirty bit set on at least one drive
|
||
|
2 -- Error
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Matthew Bradburn (MattBr) 19-Aug-1996
|
||
|
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "ulib.hxx"
|
||
|
#include "arg.hxx"
|
||
|
#include "array.hxx"
|
||
|
#include "path.hxx"
|
||
|
#include "wstring.hxx"
|
||
|
#include "ifssys.hxx"
|
||
|
#include "system.hxx"
|
||
|
#include "arrayit.hxx"
|
||
|
#include "autoreg.hxx"
|
||
|
#include "chkntfs.hxx"
|
||
|
#include "mpmap.hxx"
|
||
|
#include "volume.hxx"
|
||
|
|
||
|
DEFINE_CONSTRUCTOR(CHKNTFS, PROGRAM);
|
||
|
|
||
|
BOOLEAN
|
||
|
CHKNTFS::Initialize(
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Initializes an object of class CHKNTFS. Called once when the program
|
||
|
starts.
|
||
|
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
None.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
BOOLEAN - Indicates whether the initialization succeeded.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
ARGUMENT_LEXEMIZER arg_lex;
|
||
|
ARRAY lex_array;
|
||
|
ARRAY argument_array;
|
||
|
STRING_ARGUMENT program_name_argument;
|
||
|
|
||
|
FLAG_ARGUMENT flag_restore_default;
|
||
|
FLAG_ARGUMENT flag_exclude;
|
||
|
FLAG_ARGUMENT flag_schedule_check;
|
||
|
FLAG_ARGUMENT flag_invalid;
|
||
|
FLAG_ARGUMENT flag_display_help;
|
||
|
FLAG_ARGUMENT flag_count_down_time;
|
||
|
LONG_ARGUMENT arg_count_down_time;
|
||
|
|
||
|
ExitStatus = 0;
|
||
|
|
||
|
PROGRAM::Initialize();
|
||
|
|
||
|
if (!argument_array.Initialize()) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (!program_name_argument.Initialize("*") ||
|
||
|
!flag_restore_default.Initialize("/D") ||
|
||
|
!flag_exclude.Initialize("/X") ||
|
||
|
!flag_schedule_check.Initialize("/C") ||
|
||
|
!flag_count_down_time.Initialize("/T") ||
|
||
|
!arg_count_down_time.Initialize("/T:*") ||
|
||
|
!flag_display_help.Initialize("/?") ||
|
||
|
!flag_invalid.Initialize("/*") || // close comment */
|
||
|
!_drive_arguments.Initialize("*", FALSE, TRUE)) {
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (!argument_array.Put(&program_name_argument) ||
|
||
|
!argument_array.Put(&flag_display_help) ||
|
||
|
!argument_array.Put(&flag_restore_default) ||
|
||
|
!argument_array.Put(&flag_exclude) ||
|
||
|
!argument_array.Put(&flag_schedule_check) ||
|
||
|
!argument_array.Put(&flag_count_down_time) ||
|
||
|
!argument_array.Put(&arg_count_down_time) ||
|
||
|
!argument_array.Put(&flag_invalid) ||
|
||
|
!argument_array.Put(&_drive_arguments)) {
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (!lex_array.Initialize() ||
|
||
|
!arg_lex.Initialize(&lex_array)) {
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
arg_lex.PutSwitches("/");
|
||
|
arg_lex.PutStartQuotes("\"");
|
||
|
arg_lex.PutEndQuotes("\"");
|
||
|
arg_lex.PutSeparators(" \"\t");
|
||
|
arg_lex.SetCaseSensitive(FALSE);
|
||
|
|
||
|
if (!arg_lex.PrepareToParse()) {
|
||
|
|
||
|
DisplayMessage(MSG_CHKNTFS_INVALID_FORMAT);
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (!arg_lex.DoParsing(&argument_array)) {
|
||
|
|
||
|
if (flag_invalid.QueryFlag()) {
|
||
|
|
||
|
DisplayMessage(MSG_CHKNTFS_INVALID_SWITCH, NORMAL_MESSAGE,
|
||
|
"%W", flag_invalid.GetLexeme());
|
||
|
|
||
|
} else {
|
||
|
|
||
|
DisplayMessage(MSG_CHKNTFS_INVALID_FORMAT);
|
||
|
}
|
||
|
|
||
|
return FALSE;
|
||
|
|
||
|
} else if (_drive_arguments.WildCardExpansionFailed()) {
|
||
|
|
||
|
DisplayMessage(MSG_CHKNTFS_NO_WILDCARDS);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (flag_invalid.QueryFlag()) {
|
||
|
|
||
|
DisplayMessage(MSG_CHKNTFS_INVALID_SWITCH);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (flag_display_help.QueryFlag()) {
|
||
|
|
||
|
DisplayMessage(MSG_CHKNTFS_USAGE);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
_restore_default = flag_restore_default.QueryFlag();
|
||
|
_exclude = flag_exclude.QueryFlag();
|
||
|
_schedule_check = flag_schedule_check.QueryFlag();
|
||
|
_display_count_down_time = flag_count_down_time.IsValueSet();
|
||
|
_set_count_down_time = arg_count_down_time.IsValueSet() ?
|
||
|
arg_count_down_time.QueryLong() : -1;
|
||
|
_count_down_time = _display_count_down_time || arg_count_down_time.IsValueSet();
|
||
|
|
||
|
if (_restore_default + _exclude + _schedule_check + _count_down_time > 1) {
|
||
|
|
||
|
DisplayMessage(MSG_CHKNTFS_ARGS_CONFLICT);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (0 == _drive_arguments.QueryPathCount() &&
|
||
|
!(_restore_default || _count_down_time)) {
|
||
|
|
||
|
DisplayMessage(MSG_CHKNTFS_REQUIRES_DRIVE);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if ((_restore_default || _count_down_time)
|
||
|
&& _drive_arguments.QueryPathCount() > 0) {
|
||
|
|
||
|
DisplayMessage(MSG_CHKNTFS_INVALID_FORMAT);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (_count_down_time && arg_count_down_time.IsValueSet() &&
|
||
|
(arg_count_down_time.QueryLong() > MAX_AUTOCHK_TIMEOUT_VALUE ||
|
||
|
arg_count_down_time.QueryLong() < 0)) {
|
||
|
|
||
|
DisplayMessage(MSG_CHKNTFS_INVALID_AUTOCHK_COUNT_DOWN_TIME,
|
||
|
NORMAL_MESSAGE, "%d%d",
|
||
|
MAX_AUTOCHK_TIMEOUT_VALUE, AUTOCHK_TIMEOUT);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
BOOLEAN
|
||
|
CHKNTFS::CheckNtfs(
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Look at the arguments specified by the user and do what
|
||
|
he wants.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
None.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
BOOLEAN -- success or failure.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
DSTRING volume_name;
|
||
|
PATH fullpath;
|
||
|
DSTRING drive_path_string;
|
||
|
PATH_ANALYZE_CODE rst;
|
||
|
|
||
|
MOUNT_POINT_MAP drive_array_map;
|
||
|
PMOUNT_POINT_TUPLE mptuple;
|
||
|
|
||
|
PARRAY drive_array;
|
||
|
PARRAY_ITERATOR iterator;
|
||
|
PPATH current_drive;
|
||
|
PCWSTRING display_drive_string;
|
||
|
PCWSTRING dos_volume_name;
|
||
|
PCWSTRING dos_drive_name;
|
||
|
DSTRING nt_drive_name;
|
||
|
DSTRING ntfs_str;
|
||
|
DSTRING fat_str;
|
||
|
DSTRING fat32_str;
|
||
|
DSTRING fs_name;
|
||
|
DSTRING fs_name_and_version;
|
||
|
BOOLEAN is_dirty = 0;
|
||
|
DSTRING cmd_line;
|
||
|
ULONG old_error_mode;
|
||
|
DRIVE_TYPE drive_type;
|
||
|
DP_DRIVE dpdrive;
|
||
|
|
||
|
if (_restore_default) {
|
||
|
|
||
|
// Remove all autochk commands and insert the
|
||
|
// default entry into the registry.
|
||
|
|
||
|
if (!cmd_line.Initialize("autocheck autochk") ||
|
||
|
!AUTOREG::DeleteEntry(&cmd_line, TRUE)) {
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
if (!cmd_line.Initialize("autocheck autochk *") ||
|
||
|
!AUTOREG::AddEntry(&cmd_line)) {
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
if (_count_down_time) {
|
||
|
|
||
|
ULONG timeout;
|
||
|
|
||
|
if (_display_count_down_time) {
|
||
|
if (!VOL_LIODPDRV::QueryAutochkTimeOut(&timeout)) {
|
||
|
timeout = AUTOCHK_TIMEOUT;
|
||
|
}
|
||
|
DisplayMessage(MSG_CHKNTFS_AUTOCHK_COUNT_DOWN_TIME,
|
||
|
NORMAL_MESSAGE, "%d", timeout);
|
||
|
return TRUE;
|
||
|
|
||
|
} else if (_set_count_down_time >= 0) {
|
||
|
|
||
|
if (!VOL_LIODPDRV::SetAutochkTimeOut(_set_count_down_time)) {
|
||
|
DisplayMessage(MSG_CHKNTFS_AUTOCHK_SET_COUNT_DOWN_TIME_FAILED,
|
||
|
NORMAL_MESSAGE, "%d", _set_count_down_time);
|
||
|
}
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
DebugAssert(FALSE);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (!ntfs_str.Initialize("NTFS") ||
|
||
|
!fat_str.Initialize("FAT") ||
|
||
|
!fat32_str.Initialize("FAT32"))
|
||
|
return FALSE;
|
||
|
|
||
|
if (!drive_array_map.Initialize()) {
|
||
|
DebugPrint("Unable to initialize drive_array_map.\n");
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
drive_array = _drive_arguments.GetPathArray();
|
||
|
iterator = (PARRAY_ITERATOR)drive_array->QueryIterator();
|
||
|
iterator->Reset();
|
||
|
|
||
|
//
|
||
|
// Run through the arguments here and translate each of
|
||
|
// them into their ultimate volume names, and mount points.
|
||
|
// Build an array of tuple consists of the mount point,
|
||
|
// volume name, and original drive specification tuple.
|
||
|
|
||
|
while (NULL != (current_drive = (PPATH)iterator->GetNext())) {
|
||
|
|
||
|
display_drive_string = current_drive->GetPathString();
|
||
|
|
||
|
rst = current_drive->AnalyzePath(&volume_name,
|
||
|
&fullpath,
|
||
|
&drive_path_string);
|
||
|
|
||
|
switch (rst) {
|
||
|
case PATH_OK:
|
||
|
case PATH_COULD_BE_FLOPPY:
|
||
|
if (drive_path_string.QueryChCount() != 0) {
|
||
|
DisplayMessage(MSG_CHKNTFS_BAD_ARG, NORMAL_MESSAGE,
|
||
|
"%W", display_drive_string);
|
||
|
DELETE(iterator);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
mptuple = (PMOUNT_POINT_TUPLE)NEW MOUNT_POINT_TUPLE;
|
||
|
if (mptuple == NULL ||
|
||
|
!mptuple->_DeviceName.Initialize(display_drive_string) ||
|
||
|
!mptuple->_VolumeName.Initialize(&volume_name) ||
|
||
|
!mptuple->_DriveName.Initialize(fullpath.GetPathString())) {
|
||
|
DebugPrint("Out of memory.\n");
|
||
|
DELETE(mptuple);
|
||
|
DELETE(iterator);
|
||
|
return FALSE;
|
||
|
}
|
||
|
if (!drive_array_map.Put(mptuple)) {
|
||
|
DebugPrint("Unable to put away an object.\n");
|
||
|
DELETE(mptuple);
|
||
|
DELETE(iterator);
|
||
|
return FALSE;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case PATH_OUT_OF_MEMORY:
|
||
|
DebugPrint("Out of memory.\n");
|
||
|
DELETE(iterator);
|
||
|
return FALSE;
|
||
|
|
||
|
case PATH_NO_MOUNT_POINT_FOR_VOLUME_NAME_PATH:
|
||
|
DisplayMessage(MSG_CHKNTFS_NO_MOUNT_POINT_FOR_GUID_VOLNAME_PATH,
|
||
|
NORMAL_MESSAGE, "%W", display_drive_string);
|
||
|
DELETE(iterator);
|
||
|
return FALSE;
|
||
|
|
||
|
default:
|
||
|
DisplayMessage(MSG_CHKNTFS_BAD_ARG, NORMAL_MESSAGE,
|
||
|
"%W", display_drive_string);
|
||
|
DELETE(iterator);
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
DELETE(iterator);
|
||
|
|
||
|
iterator = (PARRAY_ITERATOR)drive_array_map.QueryIterator();
|
||
|
iterator->Reset();
|
||
|
|
||
|
//
|
||
|
// Run through the tuples here and make sure they're all
|
||
|
// valid drive names.
|
||
|
//
|
||
|
|
||
|
while (NULL != (mptuple = (PMOUNT_POINT_TUPLE)iterator->GetNext())) {
|
||
|
|
||
|
display_drive_string = &(mptuple->_DeviceName);
|
||
|
dos_volume_name = &(mptuple->_VolumeName);
|
||
|
|
||
|
old_error_mode = SetErrorMode(SEM_FAILCRITICALERRORS);
|
||
|
|
||
|
drive_type = SYSTEM::QueryDriveType(dos_volume_name);
|
||
|
|
||
|
SetErrorMode(old_error_mode);
|
||
|
|
||
|
switch (drive_type) {
|
||
|
case UnknownDrive:
|
||
|
DisplayMessage(MSG_CHKNTFS_NONEXISTENT_DRIVE, NORMAL_MESSAGE,
|
||
|
"%W", display_drive_string);
|
||
|
DELETE(iterator);
|
||
|
return FALSE;
|
||
|
|
||
|
case RemoteDrive:
|
||
|
DisplayMessage(MSG_CHKNTFS_NO_NETWORK, NORMAL_MESSAGE,
|
||
|
"%W", display_drive_string);
|
||
|
DELETE(iterator);
|
||
|
return FALSE;
|
||
|
|
||
|
case RamDiskDrive:
|
||
|
DisplayMessage(MSG_CHKNTFS_NO_RAMDISK, NORMAL_MESSAGE,
|
||
|
"%W", display_drive_string);
|
||
|
DELETE(iterator);
|
||
|
return FALSE;
|
||
|
|
||
|
case RemovableDrive:
|
||
|
|
||
|
if (!IFS_SYSTEM::DosDriveNameToNtDriveName(dos_volume_name,
|
||
|
&nt_drive_name)) {
|
||
|
DELETE(iterator);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
old_error_mode = SetErrorMode(SEM_FAILCRITICALERRORS);
|
||
|
|
||
|
if (!dpdrive.Initialize(&nt_drive_name)) {
|
||
|
|
||
|
SetErrorMode(old_error_mode);
|
||
|
|
||
|
DisplayMessage(MSG_CHKNTFS_CANNOT_CHECK, NORMAL_MESSAGE,
|
||
|
"%W", display_drive_string);
|
||
|
DELETE(iterator);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
SetErrorMode(old_error_mode);
|
||
|
|
||
|
if (dpdrive.IsFloppy()) {
|
||
|
DisplayMessage(MSG_CHKNTFS_FLOPPY_DRIVE, NORMAL_MESSAGE, "%W",
|
||
|
display_drive_string);
|
||
|
DELETE(iterator);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
iterator->Reset();
|
||
|
|
||
|
if (_exclude) {
|
||
|
|
||
|
DSTRING cmd_line2;
|
||
|
DSTRING option;
|
||
|
|
||
|
// Remove all previous autochk commands, if any.
|
||
|
|
||
|
if (!cmd_line.Initialize("autocheck autochk *") ||
|
||
|
!AUTOREG::DeleteEntry(&cmd_line, TRUE)) {
|
||
|
DELETE(iterator);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (!cmd_line.Initialize("autocheck autochk /k:") ||
|
||
|
!AUTOREG::DeleteEntry(&cmd_line, TRUE)) {
|
||
|
DELETE(iterator);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (!cmd_line.Initialize("autocheck autochk") ||
|
||
|
!option.Initialize(" /k:") ||
|
||
|
!cmd_line2.Initialize("autocheck autochk")) {
|
||
|
DELETE(iterator);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Collect a list of drives to be excluded and add them to the
|
||
|
// command line
|
||
|
//
|
||
|
|
||
|
while (NULL != (mptuple = (PMOUNT_POINT_TUPLE)iterator->GetNext())) {
|
||
|
|
||
|
display_drive_string = &(mptuple->_DeviceName);
|
||
|
dos_volume_name = &(mptuple->_VolumeName);
|
||
|
dos_drive_name = &(mptuple->_DriveName);
|
||
|
|
||
|
// Warn the user if the filesystem is not NTFS.
|
||
|
|
||
|
if (!IFS_SYSTEM::DosDriveNameToNtDriveName(dos_volume_name,
|
||
|
&nt_drive_name)) {
|
||
|
DELETE(iterator);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (IFS_SYSTEM::QueryFileSystemName(&nt_drive_name, &fs_name,
|
||
|
NULL, &fs_name_and_version)) {
|
||
|
|
||
|
DisplayMessage(MSG_FILE_SYSTEM_TYPE, NORMAL_MESSAGE,
|
||
|
"%W", &fs_name);
|
||
|
}
|
||
|
|
||
|
if (!AUTOREG::DeleteEntry(&cmd_line2, &nt_drive_name)) {
|
||
|
DELETE(iterator);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (dos_drive_name->QueryChCount() == 2) {
|
||
|
if (!IFS_SYSTEM::DosDriveNameToNtDriveName(dos_drive_name,
|
||
|
&nt_drive_name)) {
|
||
|
DELETE(iterator);
|
||
|
return FALSE;
|
||
|
}
|
||
|
if (!AUTOREG::DeleteEntry(&cmd_line2, &nt_drive_name)) {
|
||
|
DELETE(iterator);
|
||
|
return FALSE;
|
||
|
}
|
||
|
if (!cmd_line.Strcat(&option) ||
|
||
|
!cmd_line.Strcat(dos_drive_name->QueryString(0, 1))) {
|
||
|
DELETE(iterator);
|
||
|
return FALSE;
|
||
|
}
|
||
|
} else {
|
||
|
if (!cmd_line.Strcat(&option) ||
|
||
|
!cmd_line.Strcat(dos_volume_name)) {
|
||
|
DELETE(iterator);
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
DELETE(iterator);
|
||
|
|
||
|
DSTRING star;
|
||
|
|
||
|
if (!star.Initialize(" *") ||
|
||
|
!cmd_line.Strcat(&star)) {
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
// Add the new command line.
|
||
|
|
||
|
return AUTOREG::AddEntry(&cmd_line);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// This loop handles the "schedule check" and default actions.
|
||
|
//
|
||
|
|
||
|
|
||
|
while (NULL != (mptuple = (PMOUNT_POINT_TUPLE)iterator->GetNext())) {
|
||
|
|
||
|
display_drive_string = &(mptuple->_DeviceName);
|
||
|
dos_volume_name = &(mptuple->_VolumeName);
|
||
|
dos_drive_name = &(mptuple->_DriveName);
|
||
|
|
||
|
if (!IFS_SYSTEM::DosDriveNameToNtDriveName(dos_volume_name,
|
||
|
&nt_drive_name)) {
|
||
|
DELETE(iterator);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Schedule check: Put a line in the registry like
|
||
|
// "autocheck autochk \??\X:" for each command-line argument.
|
||
|
//
|
||
|
|
||
|
if (_schedule_check) {
|
||
|
|
||
|
if (!IFS_SYSTEM::QueryFileSystemName(&nt_drive_name, &fs_name, NULL)) {
|
||
|
|
||
|
DisplayMessage(MSG_CHKNTFS_CANNOT_CHECK, NORMAL_MESSAGE,
|
||
|
"%W", display_drive_string);
|
||
|
DELETE(iterator);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (fs_name == ntfs_str ||
|
||
|
fs_name == fat_str ||
|
||
|
fs_name == fat32_str) {
|
||
|
|
||
|
if (!cmd_line.Initialize("autocheck autochk") ||
|
||
|
!AUTOREG::DeleteEntry(&cmd_line, &nt_drive_name)) {
|
||
|
DELETE(iterator);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (dos_drive_name->QueryChCount() == 2) {
|
||
|
if (!IFS_SYSTEM::DosDriveNameToNtDriveName(dos_drive_name,
|
||
|
&nt_drive_name)) {
|
||
|
DELETE(iterator);
|
||
|
return FALSE;
|
||
|
}
|
||
|
if (!cmd_line.Initialize("autocheck autochk") ||
|
||
|
!AUTOREG::DeleteEntry(&cmd_line, &nt_drive_name)) {
|
||
|
DELETE(iterator);
|
||
|
return FALSE;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!cmd_line.Initialize("autocheck autochk /m ") ||
|
||
|
!cmd_line.Strcat(&nt_drive_name) ||
|
||
|
!AUTOREG::PushEntry(&cmd_line)) {
|
||
|
DELETE(iterator);
|
||
|
return FALSE;
|
||
|
}
|
||
|
} else {
|
||
|
DisplayMessage(MSG_CHKNTFS_SKIP_DRIVE_RAW, NORMAL_MESSAGE,
|
||
|
"%W", display_drive_string);
|
||
|
}
|
||
|
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Default: check to see if the volume is dirty.
|
||
|
//
|
||
|
|
||
|
if (IFS_SYSTEM::QueryFileSystemName(&nt_drive_name, &fs_name,
|
||
|
NULL, &fs_name_and_version)) {
|
||
|
|
||
|
DisplayMessage(MSG_FILE_SYSTEM_TYPE, NORMAL_MESSAGE,
|
||
|
"%W", &fs_name);
|
||
|
|
||
|
}
|
||
|
|
||
|
if (!IFS_SYSTEM::IsVolumeDirty(&nt_drive_name, &is_dirty)) {
|
||
|
|
||
|
DisplayMessage(MSG_CHKNTFS_CANNOT_CHECK, NORMAL_MESSAGE,
|
||
|
"%W", display_drive_string);
|
||
|
DELETE(iterator);
|
||
|
return FALSE;
|
||
|
|
||
|
}
|
||
|
|
||
|
if (is_dirty) {
|
||
|
|
||
|
DisplayMessage(MSG_CHKNTFS_DIRTY, NORMAL_MESSAGE,
|
||
|
"%W", display_drive_string);
|
||
|
|
||
|
ExitStatus = 1;
|
||
|
|
||
|
} else {
|
||
|
|
||
|
DSTRING cmd_line2;
|
||
|
|
||
|
if (!cmd_line.Initialize("autocheck autochk") ||
|
||
|
!cmd_line2.Initialize(" ") ||
|
||
|
!cmd_line2.Strcat(&nt_drive_name)) {
|
||
|
DELETE(iterator);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
if (AUTOREG::IsFrontEndPresent(&cmd_line, &nt_drive_name)) {
|
||
|
DisplayMessage(MSG_CHKNTFS_CHKDSK_WILL_RUN,
|
||
|
NORMAL_MESSAGE,
|
||
|
"%W", display_drive_string);
|
||
|
continue;
|
||
|
} else if (dos_drive_name->QueryChCount() == 2) {
|
||
|
if (!IFS_SYSTEM::DosDriveNameToNtDriveName(dos_drive_name,
|
||
|
&nt_drive_name)) {
|
||
|
DELETE(iterator);
|
||
|
return FALSE;
|
||
|
}
|
||
|
if (AUTOREG::IsFrontEndPresent(&cmd_line, &nt_drive_name)) {
|
||
|
DisplayMessage(MSG_CHKNTFS_CHKDSK_WILL_RUN,
|
||
|
NORMAL_MESSAGE,
|
||
|
"%W", display_drive_string);
|
||
|
continue;
|
||
|
}
|
||
|
}
|
||
|
DisplayMessage(MSG_CHKNTFS_CLEAN, NORMAL_MESSAGE,
|
||
|
"%W", display_drive_string);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
DELETE(iterator);
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
VOID __cdecl
|
||
|
main()
|
||
|
{
|
||
|
DEFINE_CLASS_DESCRIPTOR(CHKNTFS);
|
||
|
|
||
|
{
|
||
|
CHKNTFS ChkNtfs;
|
||
|
|
||
|
if (!ChkNtfs.Initialize() ||
|
||
|
!ChkNtfs.CheckNtfs()) {
|
||
|
|
||
|
exit(2);
|
||
|
}
|
||
|
|
||
|
exit(ChkNtfs.ExitStatus);
|
||
|
|
||
|
}
|
||
|
}
|