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.
942 lines
27 KiB
942 lines
27 KiB
/*++
|
|
|
|
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;
|
|
}
|