943 lines
26 KiB
C++
943 lines
26 KiB
C++
/*++
|
||
|
||
Copyright (c) 1991-2001 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
autoconv.cxx
|
||
|
||
Abstract:
|
||
|
||
This is the main program for the autoconv version of convert.
|
||
|
||
Author:
|
||
|
||
Ramon J. San Andres (ramonsa) 04-Dec-91
|
||
|
||
--*/
|
||
|
||
#include "ulib.hxx"
|
||
#include "wstring.hxx"
|
||
#include "achkmsg.hxx"
|
||
#include "spackmsg.hxx"
|
||
#include "ifssys.hxx"
|
||
#include "rtmsg.h"
|
||
#if defined(FE_SB) && defined(_X86_)
|
||
#include "machine.hxx"
|
||
#endif
|
||
#include "ifsentry.hxx"
|
||
#include "convfat.hxx"
|
||
#include "fatvol.hxx"
|
||
#include "autoreg.hxx"
|
||
#include "autoentr.hxx"
|
||
#include "arg.hxx"
|
||
#include "rcache.hxx"
|
||
|
||
#if INCLUDE_OFS==1
|
||
#include "fatofs.hxx"
|
||
//#include "initexcp.hxx"
|
||
#endif // INCLUDE_OFS
|
||
|
||
extern "C" BOOLEAN
|
||
InitializeUfat(
|
||
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 DriveName
|
||
);
|
||
|
||
BOOLEAN
|
||
FileDelete(
|
||
IN PCWSTRING DriveName,
|
||
IN PCWSTRING FileName
|
||
);
|
||
|
||
#if INCLUDE_OFS==1
|
||
|
||
BOOLEAN
|
||
IsRestartFatToOfs( WSTRING const & DriveName,
|
||
WSTRING const & CurrentFsName,
|
||
WSTRING const & TargetFileSystem )
|
||
{
|
||
|
||
DSTRING OfsName;
|
||
DSTRING FatName;
|
||
|
||
|
||
if ( !OfsName.Initialize( L"OFS" ) )
|
||
return FALSE;
|
||
|
||
if ( CurrentFsName != OfsName || TargetFileSystem != OfsName )
|
||
return FALSE;
|
||
|
||
PWSTR pwszDriveName = DriveName.QueryWSTR();
|
||
|
||
BOOLEAN fIsRestart = IsFatToOfsRestart( pwszDriveName );
|
||
DELETE( pwszDriveName );
|
||
|
||
return fIsRestart;
|
||
}
|
||
|
||
BOOLEAN
|
||
IsFatToOfs( WSTRING const & CurrentFsName, WSTRING const & TargetFsName )
|
||
{
|
||
DSTRING FatName;
|
||
DSTRING OfsName;
|
||
|
||
if ( !FatName.Initialize( L"FAT" ) )
|
||
return FALSE;
|
||
|
||
if ( !OfsName.Initialize( L"OFS" ) )
|
||
return FALSE;
|
||
|
||
return 0 == CurrentFsName.Stricmp(&FatName) &&
|
||
0 == TargetFsName.Stricmp(&OfsName);
|
||
}
|
||
|
||
BOOLEAN
|
||
FatToOfs(
|
||
IN PCWSTRING NtDriveName,
|
||
IN OUT PMESSAGE Message,
|
||
IN BOOLEAN Verbose,
|
||
IN BOOLEAN fInSetup,
|
||
OUT PCONVERT_STATUS Status )
|
||
{
|
||
|
||
PWSTR pwszNtDriveName = NtDriveName->QueryWSTR();
|
||
FAT_OFS_CONVERT_STATUS cnvStatus;
|
||
BOOLEAN fResult= ConvertFatToOfs(
|
||
pwszNtDriveName,
|
||
Message,
|
||
Verbose,
|
||
fInSetup,
|
||
&cnvStatus );
|
||
|
||
DELETE( pwszNtDriveName );
|
||
|
||
if ( FAT_OFS_CONVERT_SUCCESS == cnvStatus )
|
||
{
|
||
*Status = CONVERT_STATUS_CONVERTED;
|
||
}
|
||
else
|
||
{
|
||
*Status = CONVERT_STATUS_ERROR;
|
||
}
|
||
|
||
return fResult;
|
||
}
|
||
|
||
#else
|
||
|
||
BOOLEAN
|
||
IsRestartFatToOfs( WSTRING const & DriveName, WSTRING const & CurrentFsName,
|
||
WSTRING const & TargetFileSystem )
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
BOOLEAN
|
||
IsFatToOfs( WSTRING const & CurrentFsName, WSTRING const & TargetFsName )
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
BOOLEAN
|
||
FatToOfs(
|
||
IN PCWSTRING NtDriveName,
|
||
IN OUT PMESSAGE Message,
|
||
IN BOOLEAN Verbose,
|
||
IN BOOLEAN fInSetup,
|
||
OUT PCONVERT_STATUS Status )
|
||
{
|
||
*Status = CONVERT_STATUS_CONVERSION_NOT_AVAILABLE;
|
||
return FALSE;
|
||
}
|
||
|
||
#endif // INCLUDE_OFS
|
||
|
||
int __cdecl
|
||
main(
|
||
int argc,
|
||
char** argv,
|
||
char** envp,
|
||
ULONG DebugParameter
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine is the main program for AutoConv
|
||
|
||
Arguments:
|
||
|
||
argc, argv - Supplies the fully qualified NT path name of the
|
||
the drive to check. The syntax of the autoconv
|
||
command line is:
|
||
|
||
AUTOCONV drive-name /FS:target-file-system [/v] [/s] [/o] [/cvtarea:filename]
|
||
|
||
/v -- verbose output
|
||
/s -- run from setup
|
||
/o -- pause before the final reboot (oem setup)
|
||
/cvtarea:filename
|
||
-- convert zone file name
|
||
/nochkdsk
|
||
-- skips chkdsk and go straight to conversion
|
||
|
||
|
||
Return Value:
|
||
|
||
0 - Success.
|
||
1 - Failure.
|
||
|
||
--*/
|
||
{
|
||
|
||
#if INCLUDE_OFS==1
|
||
InitExceptionSystem();
|
||
#endif // INCLUDE_OFS==1
|
||
|
||
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)
|
||
) {
|
||
DebugPrintTrace(( "Failed to initialize U* Dlls" ));
|
||
return 1;
|
||
}
|
||
|
||
#if defined(FE_SB) && defined(_X86_)
|
||
InitializeMachineId();
|
||
#endif
|
||
|
||
PAUTOCHECK_MESSAGE message;
|
||
DSTRING DriveName;
|
||
DSTRING FileSystemName;
|
||
DSTRING CvtZoneFileName;
|
||
DSTRING CurrentFsName;
|
||
DSTRING FatName;
|
||
DSTRING Fat32Name;
|
||
DSTRING QualifiedName;
|
||
FSTRING Backslash;
|
||
BOOLEAN Converted;
|
||
BOOLEAN Verbose = FALSE;
|
||
BOOLEAN NoChkdsk = FALSE;
|
||
BOOLEAN NoSecurity = FALSE;
|
||
BOOLEAN Error;
|
||
CONVERT_STATUS Status;
|
||
int i;
|
||
BOOLEAN fInSetup = FALSE;
|
||
BOOLEAN Pause = FALSE;
|
||
|
||
LARGE_INTEGER DelayInterval;
|
||
|
||
DSTRING StrippedDriveName;
|
||
BOOLEAN enabled;
|
||
NTSTATUS status;
|
||
UNICODE_STRING driverName;
|
||
ULONG flags;
|
||
|
||
status = RtlAdjustPrivilege(SE_LOAD_DRIVER_PRIVILEGE, TRUE, FALSE, &enabled);
|
||
|
||
RtlInitUnicodeString( &driverName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Ntfs" );
|
||
status = NtLoadDriver( &driverName );
|
||
|
||
status = RtlAdjustPrivilege(SE_LOAD_DRIVER_PRIVILEGE, enabled, FALSE, &enabled);
|
||
|
||
DebugPrintTrace(( "Entering autoconv argc=%ld\n", argc ));
|
||
for ( i = 0; i < argc; i++ )
|
||
{
|
||
DebugPrintTrace((" argv[%d] = %s\n", i, argv[i] ));
|
||
}
|
||
|
||
//
|
||
// Parse the arguments. The accepted arguments are:
|
||
//
|
||
// autoconv NtDrive /fs:<filesystem> [/v]
|
||
//
|
||
|
||
if ( argc < 3 ) {
|
||
return 1;
|
||
}
|
||
|
||
//
|
||
// First argument is drive
|
||
//
|
||
if ( !DriveName.Initialize( argv[1] ) ||
|
||
!StrippedDriveName.Initialize( argv[1] ) ) {
|
||
DebugPrintTrace(( "Failed to intialize DriveName \n" ));
|
||
return 1;
|
||
}
|
||
|
||
if (!IFS_SYSTEM::NtDriveNameToDosDriveName(&DriveName, &StrippedDriveName)) {
|
||
if (!StrippedDriveName.Initialize(&DriveName)) {
|
||
DebugPrint( "Out of memory.\n" );
|
||
return 1;
|
||
}
|
||
}
|
||
|
||
DebugPrintTrace(("drive name: %ws\n", StrippedDriveName.GetWSTR()));
|
||
|
||
//
|
||
// The rest of the arguments are flags.
|
||
//
|
||
for ( i = 2; i < argc; i++ ) {
|
||
|
||
if ( (strlen(argv[i]) >= 5) &&
|
||
(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 ( 0 != FileSystemName.QueryChCount() ||
|
||
!FileSystemName.Initialize( &(argv[i][4]) ) )
|
||
{
|
||
DebugPrintTrace(( "Failed to initialize FileSystemName \n" ));
|
||
return 1;
|
||
}
|
||
}
|
||
|
||
if (0 == _stricmp( argv[i], "/V" ) || 0 == _stricmp( argv[i], "-V" )) {
|
||
Verbose = TRUE;
|
||
}
|
||
|
||
if (0 == _stricmp(argv[i], "/S") || 0 == _stricmp(argv[i], "-S")) {
|
||
DebugPrintTrace(("Found /s option\n"));
|
||
fInSetup = TRUE;
|
||
}
|
||
|
||
if (0 == _stricmp(argv[i], "/O") || 0 == _stricmp(argv[i], "-O")) {
|
||
DebugPrintTrace(("Found /o option\n"));
|
||
Pause = TRUE;
|
||
}
|
||
|
||
if ( (strlen(argv[i]) >= 10) &&
|
||
(argv[i][0] == '/' || argv[i][0] == '-') &&
|
||
(argv[i][1] == 'c' || argv[i][1] == 'C') &&
|
||
(argv[i][2] == 'v' || argv[i][2] == 'V') &&
|
||
(argv[i][3] == 't' || argv[i][3] == 'T') &&
|
||
(argv[i][4] == 'a' || argv[i][4] == 'A') &&
|
||
(argv[i][5] == 'r' || argv[i][5] == 'R') &&
|
||
(argv[i][6] == 'e' || argv[i][6] == 'E') &&
|
||
(argv[i][7] == 'a' || argv[i][7] == 'A') &&
|
||
(argv[i][8] == ':') ) {
|
||
|
||
if ( 0 != CvtZoneFileName.QueryChCount() ||
|
||
!CvtZoneFileName.Initialize( &(argv[i][9]) ) )
|
||
{
|
||
DebugPrintTrace(( "Failed to initialize CvtZoneFileName \n" ));
|
||
return 1;
|
||
}
|
||
}
|
||
|
||
if ( (strlen(argv[i]) >= 9) &&
|
||
(argv[i][0] == '/' || argv[i][0] == '-') &&
|
||
(argv[i][1] == 'n' || argv[i][1] == 'N') &&
|
||
(argv[i][2] == 'o' || argv[i][2] == 'O') &&
|
||
(argv[i][3] == 'c' || argv[i][3] == 'C') &&
|
||
(argv[i][4] == 'h' || argv[i][4] == 'H') &&
|
||
(argv[i][5] == 'k' || argv[i][5] == 'K') &&
|
||
(argv[i][6] == 'd' || argv[i][6] == 'D') &&
|
||
(argv[i][7] == 's' || argv[i][7] == 'S') &&
|
||
(argv[i][8] == 'k' || argv[i][8] == 'K')
|
||
) {
|
||
NoChkdsk = TRUE;
|
||
}
|
||
|
||
if ( (strlen(argv[i]) >= 11) &&
|
||
(argv[i][0] == '/' || argv[i][0] == '-') &&
|
||
(argv[i][1] == 'n' || argv[i][1] == 'N') &&
|
||
(argv[i][2] == 'o' || argv[i][2] == 'O') &&
|
||
(argv[i][3] == 's' || argv[i][3] == 'S') &&
|
||
(argv[i][4] == 'e' || argv[i][4] == 'E') &&
|
||
(argv[i][5] == 'c' || argv[i][5] == 'C') &&
|
||
(argv[i][6] == 'u' || argv[i][6] == 'U') &&
|
||
(argv[i][7] == 'r' || argv[i][7] == 'R') &&
|
||
(argv[i][8] == 'i' || argv[i][8] == 'I') &&
|
||
(argv[i][9] == 't' || argv[i][9] == 'T') &&
|
||
(argv[i][10] == 'y' || argv[i][10] == 'Y')
|
||
) {
|
||
NoSecurity = TRUE;
|
||
}
|
||
}
|
||
|
||
if ( 0 == FileSystemName.QueryChCount() )
|
||
{
|
||
DebugPrintTrace(( "No FileSystem name specified\n" ));
|
||
return 1;
|
||
}
|
||
|
||
DebugPrintTrace(("AUTOCONV: TargetFileSystem=%ws\n", FileSystemName.GetWSTR() ));
|
||
|
||
if (fInSetup) {
|
||
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()) {
|
||
DebugPrintTrace(( "Failed to intitialize message structure\n" ));
|
||
return 1;
|
||
}
|
||
|
||
message->SetLoggingEnabled(TRUE);
|
||
|
||
if (!FatName.Initialize("FAT") ||
|
||
!Fat32Name.Initialize("FAT32")) {
|
||
message->Set(MSG_CONV_NO_MEMORY);
|
||
message->Display();
|
||
SaveMessageLog( message, &DriveName );
|
||
return 1;
|
||
}
|
||
|
||
// If this is the System Partition of an ARC machine, don't
|
||
// convert it.
|
||
//
|
||
if( IFS_SYSTEM::IsArcSystemPartition( &DriveName, &Error ) ) {
|
||
|
||
message->Set( MSG_CONV_ARC_SYSTEM_PARTITION );
|
||
message->Display( );
|
||
|
||
SaveMessageLog( message, &DriveName );
|
||
DeRegister( argc, argv );
|
||
return 1;
|
||
}
|
||
|
||
if (!IFS_SYSTEM::QueryFileSystemName( &DriveName, &CurrentFsName )) {
|
||
|
||
message->Set( MSG_FS_NOT_DETERMINED );
|
||
message->Display( "%W", &StrippedDriveName );
|
||
|
||
SaveMessageLog( message, &DriveName );
|
||
DeRegister( argc, argv );
|
||
return 1;
|
||
}
|
||
|
||
#if defined(FE_SB) && defined(_X86_)
|
||
if( IsPC98_N() ) {
|
||
DP_DRIVE dpdrive2;
|
||
if( !dpdrive2.Initialize(&DriveName, message) ) {
|
||
|
||
message->Set( MSG_CONV_CANNOT_AUTOCHK );
|
||
message->Display( "%W%W", &DriveName, &FileSystemName );
|
||
|
||
SaveMessageLog( message, &DriveName );
|
||
DeRegister( argc, argv );
|
||
return 1;
|
||
}
|
||
if( CurrentFsName == FatName ) { //***FAT***
|
||
if((dpdrive2.QuerySectorSize() != dpdrive2.QueryPhysicalSectorSize())||
|
||
(dpdrive2.QueryPhysicalSectorSize() == 2048)) {
|
||
|
||
message->Set( MSG_CONV_CONVERSION_FAILED );
|
||
message->Display( "%W%W", &DriveName, &FileSystemName );
|
||
|
||
SaveMessageLog( message, &DriveName );
|
||
DeRegister( argc, argv );
|
||
return 1;
|
||
}
|
||
} else { //***HPFS/NTFS**
|
||
if( dpdrive2.QueryPhysicalSectorSize() == 2048 ) {
|
||
|
||
message->Set( MSG_CONV_CONVERSION_FAILED );
|
||
message->Display( "%W%W", &DriveName, &FileSystemName );
|
||
SaveMessageLog( message, &DriveName );
|
||
DeRegister( argc, argv );
|
||
return 1;
|
||
}
|
||
}
|
||
}
|
||
#endif
|
||
|
||
CurrentFsName.Strupr();
|
||
FileSystemName.Strupr();
|
||
|
||
if ( CurrentFsName == FileSystemName ) {
|
||
|
||
int iReturn = 0;
|
||
|
||
if ( IsRestartFatToOfs( DriveName, CurrentFsName, FileSystemName ) ) {
|
||
|
||
if ( !FatToOfs( &DriveName, message, Verbose, fInSetup, &Status ) ) {
|
||
iReturn = 1;
|
||
}
|
||
}
|
||
else {
|
||
//
|
||
// The drive is already in the desired file system, our
|
||
// job is done. Delete the name conversion table (if
|
||
// specified) and take ourselves out of the registry.
|
||
// Do not save the message log--there's nothing interesting
|
||
// in it.
|
||
//
|
||
// If we're doing oem pre-install (Pause is TRUE) we don't
|
||
// want to print this "already converted" message.
|
||
//
|
||
|
||
message->SetLoggingEnabled(FALSE);
|
||
}
|
||
|
||
SaveMessageLog( message, &DriveName );
|
||
DeRegister( argc, argv );
|
||
return iReturn;
|
||
}
|
||
|
||
message->Set( MSG_FILE_SYSTEM_TYPE );
|
||
message->Display( "%W", &CurrentFsName );
|
||
|
||
// Determine whether the target file-system is enabled
|
||
// in the registry. If it is not, refuse to convert
|
||
// the drive.
|
||
//
|
||
if( !IFS_SYSTEM::IsFileSystemEnabled( &FileSystemName ) ) {
|
||
|
||
message->Set( MSG_CONVERT_FILE_SYSTEM_NOT_ENABLED );
|
||
message->Display( "%W", &FileSystemName );
|
||
|
||
SaveMessageLog( message, &DriveName );
|
||
DeRegister( argc, argv );
|
||
return 1;
|
||
}
|
||
|
||
// Since autoconvert 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.
|
||
//
|
||
DelayInterval = RtlConvertLongToLargeInteger( -30000000 );
|
||
|
||
NtDelayExecution( TRUE, &DelayInterval );
|
||
|
||
// Open a volume of the appropriate type. The volume is
|
||
// opened for exclusive write access.
|
||
//
|
||
if( CurrentFsName == FatName || CurrentFsName == Fat32Name) {
|
||
|
||
if (IsConversionAvailable(&FileSystemName)) {
|
||
message->Set( MSG_CONV_CONVERSION_NOT_AVAILABLE );
|
||
message->Display( "%W%W", &CurrentFsName, &FileSystemName );
|
||
SaveMessageLog( message, &DriveName );
|
||
DeRegister( argc, argv );
|
||
return 1;
|
||
}
|
||
|
||
{
|
||
DP_DRIVE dpdrive;
|
||
|
||
if( !dpdrive.Initialize(&DriveName, message) ) {
|
||
message->Set( MSG_CONV_CONVERSION_FAILED );
|
||
message->Display( "%W%W", &DriveName, &FileSystemName );
|
||
SaveMessageLog( message, &DriveName );
|
||
DeRegister( argc, argv );
|
||
return 1;
|
||
}
|
||
|
||
switch (dpdrive.QueryDriveType()) {
|
||
case UnknownDrive: // it probably won't get this far
|
||
message->Set( MSG_CONV_INVALID_DRIVE_SPEC );
|
||
message->Display();
|
||
SaveMessageLog( message, &DriveName );
|
||
DeRegister( argc, argv );
|
||
return 1;
|
||
|
||
case CdRomDrive:
|
||
message->Set( MSG_CONV_CANT_CDROM );
|
||
message->Display();
|
||
SaveMessageLog( message, &DriveName );
|
||
DeRegister( argc, argv );
|
||
return 1;
|
||
|
||
case RemoteDrive: // it probably won't get this far
|
||
message->Set( MSG_CONV_CANT_NETWORK );
|
||
message->Display();
|
||
SaveMessageLog( message, &DriveName );
|
||
DeRegister( argc, argv );
|
||
return 1;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (!NoChkdsk) {
|
||
|
||
PFAT_VOL FatVolume;
|
||
|
||
if( !(FatVolume = NEW FAT_VOL) ||
|
||
!FatVolume->Initialize( message, &DriveName) ||
|
||
!FatVolume->ChkDsk( TotalFix, message, 0, 0 ) ) {
|
||
|
||
DELETE (FatVolume);
|
||
|
||
message->Set( MSG_CONV_CANNOT_AUTOCHK );
|
||
message->Display( "%W%W", &StrippedDriveName, &FileSystemName );
|
||
|
||
SaveMessageLog( message, &DriveName );
|
||
DeRegister( argc, argv );
|
||
return 1;
|
||
}
|
||
|
||
DELETE (FatVolume);
|
||
}
|
||
|
||
message->Set( MSG_BLANK_LINE );
|
||
message->Display();
|
||
|
||
if ( IsFatToOfs( CurrentFsName, FileSystemName ) ) {
|
||
|
||
message->Set( MSG_CONV_CONVERTING );
|
||
message->Display( "%W%W", &StrippedDriveName, &FileSystemName );
|
||
|
||
Converted = FatToOfs( &DriveName,
|
||
message,
|
||
Verbose,
|
||
fInSetup,
|
||
&Status );
|
||
} else {
|
||
|
||
PLOG_IO_DP_DRIVE pDrive;
|
||
|
||
pDrive = NEW LOG_IO_DP_DRIVE;
|
||
|
||
if (pDrive == NULL) {
|
||
message->Set(MSG_CONV_NO_MEMORY);
|
||
message->Display();
|
||
SaveMessageLog( message, &DriveName );
|
||
DeRegister( argc, argv );
|
||
return 1;
|
||
}
|
||
|
||
if ( !pDrive->Initialize(&DriveName, message) ) {
|
||
message->Set( MSG_CONV_CONVERSION_FAILED );
|
||
message->Display( "%W%W", &DriveName, &FileSystemName );
|
||
SaveMessageLog( message, &DriveName );
|
||
DeRegister( argc, argv );
|
||
DELETE( pDrive );
|
||
return 1;
|
||
}
|
||
|
||
message->Set( MSG_CONV_CONVERTING );
|
||
message->Display( "%W%W", &StrippedDriveName, &FileSystemName );
|
||
|
||
//
|
||
// there is no need to pass in /NoChkdsk
|
||
//
|
||
flags = Verbose ? CONVERT_VERBOSE_FLAG : 0;
|
||
flags |= Pause ? CONVERT_PAUSE_FLAG : 0;
|
||
flags |= NoSecurity ? CONVERT_NOSECURITY_FLAG : 0;
|
||
|
||
Converted = ConvertFATVolume( pDrive,
|
||
&FileSystemName,
|
||
&CvtZoneFileName,
|
||
message,
|
||
flags,
|
||
&Status );
|
||
|
||
DELETE( pDrive );
|
||
}
|
||
|
||
} else {
|
||
|
||
message->Set( MSG_FS_NOT_SUPPORTED );
|
||
message->Display( "%s%W", "AUTOCONV", &CurrentFsName );
|
||
|
||
SaveMessageLog( message, &DriveName );
|
||
DeRegister( argc, argv );
|
||
return 1;
|
||
}
|
||
|
||
if ( Converted ) {
|
||
|
||
message->Set( MSG_CONV_CONVERSION_COMPLETE );
|
||
message->Display();
|
||
|
||
} else {
|
||
|
||
//
|
||
// The conversion was not successful. Determine what the problem was
|
||
// and return the appropriate CONVERT exit code.
|
||
//
|
||
switch ( Status ) {
|
||
|
||
case CONVERT_STATUS_CONVERTED:
|
||
//
|
||
// This is an inconsistent state, Convert should return
|
||
// TRUE if the conversion was successful!
|
||
//
|
||
message->Set( MSG_CONV_CONVERSION_MAYHAVE_FAILED );
|
||
message->Display( "%W%W", &StrippedDriveName, &FileSystemName );
|
||
break;
|
||
|
||
case CONVERT_STATUS_INVALID_FILESYSTEM:
|
||
//
|
||
// The conversion DLL does not recognize the target file system.
|
||
//
|
||
message->Set( MSG_CONV_INVALID_FILESYSTEM );
|
||
message->Display( "%W", &FileSystemName );
|
||
break;
|
||
|
||
case CONVERT_STATUS_CONVERSION_NOT_AVAILABLE:
|
||
//
|
||
// The target file system is valid, but the conversion is not
|
||
// available.
|
||
//
|
||
message->Set( MSG_CONV_CONVERSION_NOT_AVAILABLE );
|
||
message->Display( "%W%W", &CurrentFsName, &FileSystemName );
|
||
break;
|
||
|
||
case CONVERT_STATUS_NTFS_RESERVED_NAMES:
|
||
message->Set( MSG_CONV_NTFS_RESERVED_NAMES );
|
||
message->Display( "%W", &StrippedDriveName );
|
||
break;
|
||
|
||
case CONVERT_STATUS_WRITE_PROTECTED:
|
||
message->Set( MSG_CONV_WRITE_PROTECTED );
|
||
message->Display( "%W", &StrippedDriveName );
|
||
break;
|
||
|
||
case CONVERT_STATUS_INSUFFICIENT_FREE_SPACE:
|
||
case CONVERT_STATUS_CANNOT_LOCK_DRIVE:
|
||
case CONVERT_STATUS_DRIVE_IS_DIRTY:
|
||
case CONVERT_STATUS_ERROR:
|
||
//
|
||
// The conversion failed.
|
||
//
|
||
default:
|
||
//
|
||
// Invalid status code
|
||
//
|
||
message->Set( MSG_CONV_CONVERSION_FAILED );
|
||
message->Display( "%W%W", &StrippedDriveName, &FileSystemName );
|
||
DebugPrintTrace(("AUTOCONV: Failed %x\n", Status));
|
||
break;
|
||
}
|
||
}
|
||
|
||
SaveMessageLog( message, &DriveName );
|
||
DeRegister( argc, argv );
|
||
|
||
#if INCLUDE_OFS==1
|
||
CleanupExceptionSystem();
|
||
#endif // INCLUDE_OFS==1
|
||
|
||
return ( Converted ? 0 : 1 );
|
||
}
|
||
|
||
|
||
|
||
|
||
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"autoconv" ) ||
|
||
!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 ) );
|
||
|
||
}
|
||
|
||
|
||
BOOLEAN
|
||
SaveMessageLog(
|
||
IN OUT PMESSAGE Message,
|
||
IN PCWSTRING DriveName
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function writes the logged messages from the supplied
|
||
message object to the file "BOOTEX.LOG" in the root of the
|
||
specified drive.
|
||
|
||
Arguments:
|
||
|
||
Message -- Supplies the message object.
|
||
DriveName -- Supplies the name of the drive.
|
||
|
||
Return Value:
|
||
|
||
TRUE upon successful completion.
|
||
|
||
--*/
|
||
{
|
||
DSTRING QualifiedName;
|
||
FSTRING BootExString;
|
||
HMEM Mem;
|
||
ULONG Length;
|
||
|
||
if( !Message->IsLoggingEnabled() ) {
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
return( QualifiedName.Initialize( DriveName ) &&
|
||
BootExString.Initialize( L"\\BOOTEX.LOG" ) &&
|
||
QualifiedName.Strcat( &BootExString ) &&
|
||
Mem.Initialize() &&
|
||
Message->QueryPackedLog( &Mem, &Length ) &&
|
||
IFS_SYSTEM::WriteToFile( &QualifiedName,
|
||
Mem.GetBuf(),
|
||
Length,
|
||
TRUE ) );
|
||
}
|
||
|
||
BOOLEAN
|
||
FileDelete(
|
||
IN PCWSTRING DriveName,
|
||
IN PCWSTRING FileName
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function deletes a file. It is used to clean up the
|
||
name translation table.
|
||
|
||
Arguments:
|
||
|
||
DriveName -- Supplies the drive on which the file resides.
|
||
FileName -- Supplies the file name. Note that the file
|
||
should be in the root directory.
|
||
|
||
Return Value:
|
||
|
||
TRUE upon successful completion.
|
||
|
||
--*/
|
||
{
|
||
DSTRING QualifiedName;
|
||
FSTRING Backslash;
|
||
IO_STATUS_BLOCK IoStatusBlock;
|
||
OBJECT_ATTRIBUTES ObjectAttributes;
|
||
UNICODE_STRING UnicodeString;
|
||
FILE_DISPOSITION_INFORMATION DispositionInfo;
|
||
HANDLE FileHandle;
|
||
NTSTATUS Status;
|
||
|
||
if( !Backslash.Initialize( L"\\" ) ||
|
||
!QualifiedName.Initialize( DriveName ) ||
|
||
!QualifiedName.Strcat( &Backslash ) ||
|
||
!QualifiedName.Strcat( FileName ) ) {
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
UnicodeString.Buffer = (PWSTR)QualifiedName.GetWSTR();
|
||
UnicodeString.Length = (USHORT)( QualifiedName.QueryChCount() * sizeof( WCHAR ) );
|
||
UnicodeString.MaximumLength = UnicodeString.Length;
|
||
|
||
InitializeObjectAttributes( &ObjectAttributes,
|
||
&UnicodeString,
|
||
OBJ_CASE_INSENSITIVE,
|
||
0,
|
||
0 );
|
||
|
||
Status = NtOpenFile( &FileHandle,
|
||
FILE_GENERIC_READ | FILE_GENERIC_WRITE,
|
||
&ObjectAttributes,
|
||
&IoStatusBlock,
|
||
FILE_SHARE_DELETE,
|
||
FILE_NON_DIRECTORY_FILE );
|
||
|
||
if( NT_SUCCESS( Status ) ) {
|
||
|
||
DispositionInfo.DeleteFile = TRUE;
|
||
|
||
Status = NtSetInformationFile( FileHandle,
|
||
&IoStatusBlock,
|
||
&DispositionInfo,
|
||
sizeof( DispositionInfo ),
|
||
FileDispositionInformation );
|
||
}
|
||
|
||
if( !NT_SUCCESS( Status ) ) {
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
NtClose( FileHandle );
|
||
return TRUE;
|
||
}
|