|
|
/*++
Copyright (c) 1991-2001 Microsoft Corporation
Module Name:
autofmt.cxx
Abstract:
This is the main program for the autofmt version of format.
Author:
Matthew Bradburn (mattbr) 13-Dec-94
--*/
#include "ulib.hxx"
#include "wstring.hxx"
#include "achkmsg.hxx"
#include "spackmsg.hxx"
#include "tmackmsg.hxx"
#include "ifssys.hxx"
#include "rtmsg.h"
#include "ifsentry.hxx"
#include "fatvol.hxx"
#include "ntfsvol.hxx"
#include "autoreg.hxx"
#include "autoentr.hxx"
#include "arg.hxx"
extern "C" BOOLEAN InitializeUfat( PVOID DllHandle, ULONG Reason, PCONTEXT Context );
extern "C" BOOLEAN InitializeUhpfs( PVOID DllHandle, ULONG Reason, PCONTEXT Context );
extern "C" BOOLEAN InitializeUntfs( PVOID DllHandle, ULONG Reason, PCONTEXT Context );
extern "C" BOOLEAN InitializeIfsUtil( PVOID DllHandle, ULONG Reason, PCONTEXT Context );
BOOLEAN DeRegister( int argc, char** argv );
BOOLEAN SavemessageLog( IN OUT PMESSAGE message, IN PCWSTRING drive_name );
int __cdecl main( int argc, char** argv, char** envp, ULONG DebugParameter ) /*++
Routine Description:
This routine is the main program for AutoFmt
Arguments:
argc, argv - Supplies the fully qualified NT path name of the the drive to check. The syntax of the autofmt command line is:
AUTOFMT drive-name /FS:target-file-system [/V:label] [/Q] [/A:size] [/C] [/S]
Return Value:
0 - Success. 1 - Failure.
--*/ { if (!InitializeUlib( NULL, ! DLL_PROCESS_DETACH, NULL ) || !InitializeIfsUtil(NULL, ! DLL_PROCESS_DETACH, NULL) || !InitializeUfat(NULL, ! DLL_PROCESS_DETACH, NULL) || !InitializeUntfs(NULL, ! DLL_PROCESS_DETACH, NULL) ) { return 1; }
PFAT_VOL fat_volume; PNTFS_VOL ntfs_volume; PDP_DRIVE dp_drive;
PAUTOCHECK_MESSAGE message; DSTRING drive_name; DSTRING file_system_name; DSTRING label; DSTRING fat_name; DSTRING ntfs_name; DSTRING fat32_name; BOOLEAN quick = FALSE; BOOLEAN compress = FALSE; BOOLEAN error; FORMAT_ERROR_CODE success; BOOLEAN setup_output = FALSE; BOOLEAN textmode_output = FALSE; BIG_INT bigint; ULONG cluster_size = 0; int i;
LARGE_INTEGER delay_interval;
if (!file_system_name.Initialize()) { return 1; } if (!label.Initialize() || NULL == (dp_drive = NEW DP_DRIVE)) { return 1; }
//
// Parse the arguments.
//
if ( argc < 2 ) { return 1; }
//
// First argument is drive
//
if ( !drive_name.Initialize( argv[1] ) ) { return 1; } DebugPrintTrace(("drive name: %ws\n", drive_name.GetWSTR()));
//
// The rest of the arguments are flags.
//
for (i = 2; i < argc; i++) {
if ((argv[i][0] == '/' || argv[i][0] == '-') && (argv[i][1] == 'f' || argv[i][1] == 'F') && (argv[i][2] == 's' || argv[i][2] == 'S') && (argv[i][3] == ':')) {
if (!file_system_name.Initialize(&argv[i][4])) { return 1; } DebugPrintTrace(("fsname: %ws\n", file_system_name.GetWSTR())); continue; } if ((argv[i][0] == '/' || argv[i][0] == '-') && (argv[i][1] == 'v' || argv[i][1] == 'V') && (argv[i][2] == ':')) {
if (!label.Initialize(&argv[i][3])) { return 1; } continue; } if ((argv[i][0] == '/' || argv[i][0] == '-') && (argv[i][1] == 'a' || argv[i][1] == 'A') && (argv[i][2] == ':')) {
cluster_size = atoi(&argv[i][3]); continue; } if (0 == _stricmp(argv[i], "/Q") || 0 == _stricmp(argv[i], "-Q")) { quick = TRUE; continue; } if (0 == _stricmp(argv[i], "/C") || 0 == _stricmp(argv[i], "-C")) { compress = TRUE; continue; } if (0 == _stricmp(argv[i], "/S") || 0 == _stricmp(argv[i], "-S")) { setup_output = TRUE; } if (0 == _stricmp(argv[i], "/T") || 0 == _stricmp(argv[i], "-T")) { textmode_output = TRUE; } }
if (textmode_output) { message = NEW TM_AUTOCHECK_MESSAGE; } else if (setup_output) { message = NEW SP_AUTOCHECK_MESSAGE; DebugPrintTrace(("Using setup output\n")); } else { DebugPrintTrace(("Not using setup output\n")); message = NEW AUTOCHECK_MESSAGE; } if (NULL == message || !message->Initialize()) { return 1; }
#if 0 // Shouldn't limit the cluster size as long as it is reasonable.
if (cluster_size != 0 && cluster_size != 512 && cluster_size != 1024 && cluster_size != 2048 && cluster_size != 4096) {
message->Set(MSG_UNSUPPORTED_PARAMETER); message->Display();
DeRegister( argc, argv );
return 1; } #endif
if (0 == file_system_name.QueryChCount()) {
// attempt to get the current filesystem type from disk
if (!IFS_SYSTEM::QueryFileSystemName(&drive_name, &file_system_name)) {
message->Set( MSG_FS_NOT_DETERMINED ); message->Display( "%W", &drive_name );
DeRegister( argc, argv ); return 1; } file_system_name.Strupr(); }
if (!fat_name.Initialize("FAT") || !ntfs_name.Initialize("NTFS") || !fat32_name.Initialize("FAT32")) {
return 1; }
file_system_name.Strupr();
//
// If compression is requested, make sure it's available.
//
if (compress && file_system_name != ntfs_name) {
message->Set(MSG_COMPRESSION_NOT_AVAILABLE); message->Display("%W", &file_system_name); DeRegister( argc, argv ); return 1; }
// Since autoformat will often be put in place by Setup
// to run after AutoSetp, delay for 3 seconds to give the
// file system time to clean up detritus of deleted files.
//
delay_interval = RtlConvertLongToLargeInteger( -30000000 );
NtDelayExecution( TRUE, &delay_interval );
if (!dp_drive->Initialize(&drive_name, message)) { DeRegister( argc, argv ); return 1; }
if (dp_drive->IsFloppy()) { // MJB: refuse to format
DeRegister( argc, argv ); return 1; }
switch (dp_drive->QueryDriveType()) { case UnknownDrive: message->Set(MSG_NONEXISTENT_DRIVE); message->Display(""); DeRegister( argc, argv ); return 1;
case RemoteDrive: // it probably won't get that far
message->Set(MSG_FORMAT_NO_NETWORK); message->Display(""); DeRegister( argc, argv ); return 1;
case RamDiskDrive: // it probably won't get that far
message->Set(MSG_FORMAT_NO_RAMDISK); message->Display(""); DeRegister( argc, argv ); return 1;
default: break; }
//
// Print the "formatting <size>" message.
//
if (quick) { message->Set(MSG_QUICKFORMATTING_MB); } else { message->Set(MSG_FORMATTING_MB); }
bigint = dp_drive->QuerySectors() * dp_drive->QuerySectorSize() / 1048576;
DebugAssert(bigint.GetHighPart() == 0);
message->Display("%d", bigint.GetLowPart());
if (file_system_name == fat_name || file_system_name == fat32_name) {
BOOLEAN old_fat_vol = TRUE;
if( file_system_name == fat32_name ) { old_fat_vol = FALSE; }
if( !(fat_volume = NEW FAT_VOL) || NoError != fat_volume->Initialize( &drive_name, message, FALSE, !quick, Unknown )) {
DeRegister( argc, argv ); return 1; }
success = fat_volume->Format(&label, message, old_fat_vol ? FORMAT_BACKWARD_COMPATIBLE : 0, cluster_size);
DebugPrintTrace(("Format return code: %d\n", success));
DELETE( fat_volume );
} else if (file_system_name == ntfs_name) {
if (dp_drive->QueryDriveType() == CdRomDrive) { message->Set(MSG_FMT_NO_NTFS_ALLOWED); message->Display(); DeRegister( argc, argv ); return 1; }
if( !(ntfs_volume = NEW NTFS_VOL) || NoError != ntfs_volume->Initialize( &drive_name, message, FALSE, !quick, Unknown )) {
DeRegister( argc, argv ); return 1; }
success = ntfs_volume->Format(&label, message, 0, cluster_size);
DebugPrintTrace(("Format return code: %d\n", success));
DELETE( ntfs_volume );
} else {
message->Set( MSG_FS_NOT_SUPPORTED ); message->Display( "%s%W", "AUTOFMT", &file_system_name);
DeRegister( argc, argv ); return 1; }
// Truncate "fat32" back to "fat"...yuck..
if (file_system_name == fat32_name) { if (!file_system_name.Initialize("FAT")) { DeRegister( argc, argv ); return 1; } }
// Make sure the file system is installed.
if (!IFS_SYSTEM::IsFileSystemEnabled(&file_system_name)) { message->Set(MSG_FMT_INSTALL_FILE_SYSTEM); message->Display("%W", &file_system_name);
if (!IFS_SYSTEM::EnableFileSystem(&file_system_name)) { message->Set(MSG_FMT_CANT_INSTALL_FILE_SYSTEM); message->Display(); return 1; }
message->Set(MSG_FMT_FILE_SYSTEM_INSTALLED); message->Display(); }
if (compress && !IFS_SYSTEM::EnableVolumeCompression(&drive_name)) { message->Set(MSG_CANNOT_ENABLE_COMPRESSION); message->Display();
DeRegister( argc, argv );
return 1; }
DeRegister( argc, argv );
return (success != NoError); }
BOOLEAN DeRegister( int argc, char** argv ) /*++
Routine Description:
This function removes the registry entry which triggered autoconvert.
Arguments:
argc -- Supplies the number of arguments given to autoconv argv -- supplies the arguments given to autoconv
Return Value:
TRUE upon successful completion.
--*/ { DSTRING CommandLineString1, CommandLineString2, CurrentArgString, OneSpace;
int i;
// Reconstruct the command line and remove it from
// the registry. First, reconstruct the primary
// string, which is "autoconv arg1 arg2...".
//
if( !CommandLineString1.Initialize( L"autofmt" ) || !OneSpace.Initialize( L" " ) ) {
return FALSE; }
for( i = 1; i < argc; i++ ) {
if( !CurrentArgString.Initialize( argv[i] ) || !CommandLineString1.Strcat( &OneSpace ) || !CommandLineString1.Strcat( &CurrentArgString ) ) {
return FALSE; } }
// Now construct the secondary string, which is
// "autocheck arg0 arg1 arg2..."
//
if( !CommandLineString2.Initialize( "autocheck " ) || !CommandLineString2.Strcat( &CommandLineString1 ) ) {
return FALSE; }
return( AUTOREG::DeleteEntry( &CommandLineString1 ) && AUTOREG::DeleteEntry( &CommandLineString2 ) ); }
|