Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

439 lines
9.9 KiB

/*++
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: [...] -- just display dirty bit state
chkntfs /d -- restore default autochk behavior
chkntfs /x drive: [...] -- exclude drives from default autochk
chkntfs /c drive: [...] -- schedule autochk to run on drives
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"
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;
PROGRAM::Initialize();
ExitStatus = 2;
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_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_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;
}
ExitStatus = 0;
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();
if (_restore_default + _exclude + _schedule_check > 1) {
DisplayMessage(MSG_CHKNTFS_ARGS_CONFLICT);
ExitStatus = 2;
return FALSE;
}
if (0 == _drive_arguments.QueryPathCount() && !_restore_default) {
DisplayMessage(MSG_CHKNTFS_REQUIRES_DRIVE);
ExitStatus = 2;
return FALSE;
}
if (_restore_default && _drive_arguments.QueryPathCount() > 0) {
DisplayMessage(MSG_CHKNTFS_INVALID_FORMAT);
ExitStatus = 2;
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.
--*/
{
PARRAY drive_array;
PARRAY_ITERATOR iterator;
PPATH current_drive;
PCWSTRING drive_string;
DSTRING nt_drive_name;
DSTRING fs_name;
BOOLEAN is_dirty = 0;
DSTRING cmd_line;
ULONG old_error_mode;
DRIVE_TYPE drive_type;
nt_drive_name.Initialize();
if (_restore_default) {
// Remove previous commands.
if (!cmd_line.Initialize("autocheck autochk /k:") ||
!AUTOREG::DeleteEntry(&cmd_line, TRUE) ||
!cmd_line.Initialize("autocheck autochk *") ||
!AUTOREG::DeleteEntry(&cmd_line)) {
return FALSE;
}
if (!cmd_line.Initialize("autocheck autochk *") ||
!AUTOREG::AddEntry(&cmd_line)) {
return FALSE;
}
return TRUE;
}
drive_array = _drive_arguments.GetPathArray();
iterator = (PARRAY_ITERATOR)drive_array->QueryIterator();
//
// Run through the arguments here and make sure they're all
// valid drive names.
//
while (NULL != (current_drive = (PPATH)iterator->GetNext())) {
drive_string = current_drive->GetPathString();
if (!current_drive->IsDrive()) {
DisplayMessage(MSG_CHKNTFS_BAD_ARG, NORMAL_MESSAGE,
"%W", drive_string);
return FALSE;
}
old_error_mode = SetErrorMode(SEM_FAILCRITICALERRORS);
drive_type = SYSTEM::QueryDriveType(drive_string);
SetErrorMode(old_error_mode);
switch (drive_type) {
case UnknownDrive:
DisplayMessage(MSG_CHKNTFS_NONEXISTENT_DRIVE, NORMAL_MESSAGE,
"%W", drive_string);
return FALSE;
case RemoteDrive:
DisplayMessage(MSG_CHKNTFS_NO_NETWORK, NORMAL_MESSAGE,
"%W", drive_string);
return FALSE;
case CdRomDrive:
DisplayMessage(MSG_CHKNTFS_NO_CDROM, NORMAL_MESSAGE,
"%W", drive_string);
return FALSE;
case RamDiskDrive:
DisplayMessage(MSG_CHKNTFS_NO_RAMDISK, NORMAL_MESSAGE,
"%W", drive_string);
return FALSE;
default:
break;
}
}
iterator->Reset();
if (_exclude) {
// Remove the previous registry commands, if any.
if (!cmd_line.Initialize("autocheck autochk *") ||
!AUTOREG::DeleteEntry(&cmd_line, TRUE)) {
return FALSE;
}
if (!cmd_line.Initialize("autocheck autochk /k:") ||
!AUTOREG::DeleteEntry(&cmd_line, TRUE)) {
return FALSE;
}
//
// Collect a list of drives to be excluded and add them to the
// command line
//
while (NULL != (current_drive = (PPATH)iterator->GetNext())) {
drive_string = current_drive->GetPathString();
if (!cmd_line.Strcat(drive_string->QueryString(0, 1))) {
return FALSE;
}
}
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 != (current_drive = (PPATH)iterator->GetNext())) {
drive_string = current_drive->GetPathString();
if (!IFS_SYSTEM::DosDriveNameToNtDriveName(drive_string,
&nt_drive_name)) {
return FALSE;
}
//
// Schedule check: Put a line in the registry like
// "autocheck autochck \??\X:" for each command-line argument.
//
if (_schedule_check) {
DSTRING cmd_line;
if (!cmd_line.Initialize("autocheck autochk /m ") ||
!cmd_line.Strcat(&nt_drive_name) ||
!AUTOREG::AddEntry(&cmd_line)) {
return FALSE;
}
ExitStatus = 0;
continue;
}
//
// Default: check to see if the volume is dirty.
//
if (IFS_SYSTEM::QueryFileSystemName(&nt_drive_name, &fs_name, NULL)) {
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", drive_string);
return FALSE;
}
if (is_dirty) {
DisplayMessage(MSG_CHKNTFS_DIRTY, NORMAL_MESSAGE,
"%W", drive_string);
ExitStatus = 1;
} else {
DisplayMessage(MSG_CHKNTFS_CLEAN, NORMAL_MESSAGE,
"%W", drive_string);
ExitStatus = ExitStatus > 0 ? ExitStatus : 0;
}
}
return TRUE;
}
VOID _CRTAPI1
main()
{
DEFINE_CLASS_DESCRIPTOR(CHKNTFS);
int r;
{
CHKNTFS ChkNtfs;
if (!ChkNtfs.Initialize() ||
!ChkNtfs.CheckNtfs()) {
exit(2);
}
r = ChkNtfs.ExitStatus;
}
_exit(r);
}