mirror of https://github.com/lianthony/NT4.0
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.
370 lines
8.8 KiB
370 lines
8.8 KiB
/*++
|
|
|
|
Copyright (c) 1990 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
cvthpfs.cxx
|
|
|
|
Abstract:
|
|
|
|
This module contains the declaration of ConvertHPFS, which is
|
|
the main entry point for this DLL.
|
|
|
|
Author:
|
|
|
|
Bill McJohn (billmc) 09-Jan-1992
|
|
|
|
Environment:
|
|
|
|
ULIB, User Mode
|
|
|
|
--*/
|
|
|
|
#include <pch.cxx>
|
|
|
|
#define _NTAPI_ULIB_
|
|
|
|
#include "ulib.hxx"
|
|
#include "message.hxx"
|
|
#include "rtmsg.h"
|
|
|
|
#include "drive.hxx"
|
|
#include "rwcache.hxx"
|
|
#include "intstack.hxx"
|
|
#include "numset.hxx"
|
|
|
|
#include "uhpfs.hxx"
|
|
#include "hpfsvol.hxx"
|
|
#include "hpfssa.hxx"
|
|
|
|
#include "cuhpfs.hxx"
|
|
#include "nametab.hxx"
|
|
|
|
DECLARE_CLASS( NAME_TABLE );
|
|
DECLARE_CLASS( NAME_LOOKUP_TABLE );
|
|
|
|
extern "C" BOOLEAN
|
|
InitializeCuhpfs (
|
|
PVOID DllHandle,
|
|
ULONG Reason,
|
|
PCONTEXT Context
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is the initialization entry point for CUHPFS.DLL.
|
|
At present, it's a null function, but this is where any initialization
|
|
goes if it's ever needed.
|
|
|
|
--*/
|
|
{
|
|
if( !DEFINE_CLASS_DESCRIPTOR( NAME_TABLE ) ||
|
|
!DEFINE_CLASS_DESCRIPTOR( NAME_LOOKUP_TABLE ) ) {
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN
|
|
FAR APIENTRY
|
|
ConvertHPFSVolume(
|
|
IN PHPFS_VOL HpfsVolume,
|
|
IN PCWSTRING TargetFileSystem,
|
|
IN PCNAME_LOOKUP_TABLE NameTable,
|
|
IN OUT PMESSAGE Message,
|
|
IN BOOLEAN Verbose,
|
|
OUT PCONVERT_STATUS Status
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function converts an opened HPFS Volume to a new file system.
|
|
|
|
Arguments:
|
|
|
|
Drive -- Supplies the drive to convert. Note that
|
|
it the caller must lock the drive (Convert)
|
|
or open it for exclusive write access
|
|
(Autoconvert).
|
|
TargetFileSystem -- Supplies the file system to which the drive
|
|
will be converted. Note that only "NTFS"
|
|
is presently supported.
|
|
Message -- Supplies an outlet for messages.
|
|
Verbose -- Supplies a flag indicating (if TRUE) that
|
|
conversion should be carried out in verbose mode.
|
|
Status -- Receives the status of the conversion.
|
|
|
|
|
|
--*/
|
|
{
|
|
PREAD_WRITE_CACHE RwCache;
|
|
NUMBER_SET BadSectorSet;
|
|
DSTRING FatString, HpfsString, NtfsString, CdfsString;
|
|
|
|
PHPFS_SA HpfsSuperArea;
|
|
PLBN BadLbnList;
|
|
|
|
ULONG NumberOfBadLbns, ActualNumberOfBadLbns, i;
|
|
BOOLEAN Result, Corrupt;
|
|
|
|
|
|
// Load in the read write cache.
|
|
|
|
if ((RwCache = NEW READ_WRITE_CACHE) &&
|
|
RwCache->Initialize( HpfsVolume, 75 )) {
|
|
|
|
HpfsVolume->SetCache(RwCache);
|
|
} else {
|
|
DELETE(RwCache);
|
|
}
|
|
|
|
|
|
|
|
// Check that this volume meets the requirements for conversion.
|
|
// It must be a clean HPFS volume with no hotfixes.
|
|
|
|
HpfsSuperArea = HpfsVolume->GetHPFSSuperArea();
|
|
|
|
if( !HpfsSuperArea->CheckSuperBlockSignatures() ) {
|
|
|
|
Message->Set( MSG_CONV_HPFS_NOT_HPFS );
|
|
Message->Display( "" );
|
|
|
|
*Status = CONVERT_STATUS_ERROR;
|
|
return FALSE;
|
|
}
|
|
|
|
if( HpfsSuperArea->GetSuper()->QueryVersion() != SUPERB_VERSION ||
|
|
( HpfsSuperArea->GetSuper()->QueryFuncVersion() != SUPERB_FVERSION_2 &&
|
|
HpfsSuperArea->GetSuper()->QueryFuncVersion() != SUPERB_FVERSION_3 ) ) {
|
|
|
|
Message->Set( MSG_HPFS_CHKDSK_WRONG_VERSION );
|
|
Message->Display( "" );
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
if( !HpfsSuperArea->IsClean() ) {
|
|
|
|
Message->Set( MSG_CONV_HPFS_DIRTY_VOLUME );
|
|
Message->Display( "" );
|
|
|
|
*Status = CONVERT_STATUS_ERROR;
|
|
return FALSE;
|
|
}
|
|
|
|
if( HpfsSuperArea->GetSpare()->QueryHotFixCount() != 0 ||
|
|
HpfsSuperArea->GetSpare()->IsHotFixesUsed() ) {
|
|
|
|
Message->Set( MSG_CONV_HPFS_HOTFIXES_PRESENT );
|
|
Message->Display( "" );
|
|
|
|
*Status = CONVERT_STATUS_ERROR;
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
// Fetch the list of bad lbns and bundle them up into an intstack.
|
|
|
|
NumberOfBadLbns = HpfsSuperArea->GetSuper()->QueryBadSectors();
|
|
|
|
if( (BadLbnList = (PLBN)MALLOC( NumberOfBadLbns * sizeof(LBN) )) ==
|
|
NULL ) {
|
|
|
|
Message->Set( MSG_CONV_NO_MEMORY );
|
|
Message->Display( "" );
|
|
|
|
DebugPrint( "Insufficient memory.\n" );
|
|
*Status = CONVERT_STATUS_ERROR;
|
|
return FALSE;
|
|
}
|
|
|
|
if( !HpfsSuperArea->QueryBadLbns( NumberOfBadLbns,
|
|
BadLbnList,
|
|
&ActualNumberOfBadLbns ) ) {
|
|
|
|
Message->Set( MSG_CONV_HPFS_CORRUPT_VOLUME );
|
|
Message->Display( "" );
|
|
|
|
FREE( BadLbnList );
|
|
*Status = CONVERT_STATUS_ERROR;
|
|
return FALSE;
|
|
}
|
|
|
|
if( !BadSectorSet.Initialize() ) {
|
|
|
|
Message->Set( MSG_CONV_NO_MEMORY );
|
|
Message->Display( "" );
|
|
|
|
FREE( BadLbnList );
|
|
*Status = CONVERT_STATUS_ERROR;
|
|
return FALSE;
|
|
}
|
|
|
|
for( i = 0; i < ActualNumberOfBadLbns; i++ ) {
|
|
|
|
if( !BadSectorSet.Add( BadLbnList[i] ) ) {
|
|
|
|
Message->Set( MSG_CONV_NO_MEMORY );
|
|
Message->Display( "" );
|
|
|
|
FREE( BadLbnList );
|
|
*Status = CONVERT_STATUS_ERROR;
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
// Tell the HPFS SuperArea to read its codepage information
|
|
|
|
if( !HpfsSuperArea->ReadCodepage() ) {
|
|
|
|
Message->Set( MSG_CONV_HPFS_CORRUPT_VOLUME );
|
|
Message->Display( "" );
|
|
|
|
FREE( BadLbnList );
|
|
*Status = CONVERT_STATUS_ERROR;
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
// Determine whether the target file system is supported. Set up
|
|
// a WSTRING for each recognized target file system.
|
|
|
|
if( !FatString.Initialize( "FAT" ) ||
|
|
!HpfsString.Initialize( "HPFS" ) ||
|
|
!NtfsString.Initialize( "NTFS" ) ||
|
|
!CdfsString.Initialize( "CDFS" ) ) {
|
|
|
|
Message->Set( MSG_CONV_NO_MEMORY );
|
|
Message->Display( "" );
|
|
|
|
FREE( BadLbnList );
|
|
*Status = CONVERT_STATUS_ERROR;
|
|
return FALSE;
|
|
}
|
|
|
|
if( *TargetFileSystem == NtfsString ) {
|
|
|
|
Result = ConvertToNtfs( HpfsVolume,
|
|
NameTable,
|
|
&BadSectorSet,
|
|
Message,
|
|
Verbose,
|
|
&Corrupt );
|
|
|
|
*Status = (Result) ? CONVERT_STATUS_CONVERTED : CONVERT_STATUS_ERROR;
|
|
|
|
if( !Result && Corrupt ) {
|
|
|
|
Message->Set( MSG_CONV_HPFS_CORRUPT_VOLUME );
|
|
Message->Display( "" );
|
|
}
|
|
|
|
} else if ( *TargetFileSystem == FatString ||
|
|
*TargetFileSystem == HpfsString ||
|
|
*TargetFileSystem == CdfsString ) {
|
|
|
|
// recognized but unsupported target
|
|
|
|
*Status = CONVERT_STATUS_CONVERSION_NOT_AVAILABLE;
|
|
Result = FALSE;
|
|
|
|
} else {
|
|
|
|
*Status = CONVERT_STATUS_INVALID_FILESYSTEM;
|
|
Result = FALSE;
|
|
}
|
|
|
|
|
|
FREE( BadLbnList );
|
|
return Result;
|
|
|
|
}
|
|
|
|
BOOLEAN
|
|
FAR APIENTRY
|
|
ConvertHPFS(
|
|
IN PCWSTRING NtDriveName,
|
|
IN PCWSTRING TargetFileSystem,
|
|
IN OUT PMESSAGE Message,
|
|
IN BOOLEAN Verbose,
|
|
OUT PCONVERT_STATUS Status
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function converts an HPFS volume to the target file system
|
|
in-place.
|
|
|
|
This function opens and locks the volume, so it is not suitable
|
|
for use by autoconvert.
|
|
|
|
Arguments:
|
|
|
|
NtDriveName -- Supplies the name of the drive.
|
|
TargetFileSystem -- Supplies the file system to which the drive
|
|
will be converted. Note that only "NTFS"
|
|
is presently supported.
|
|
Message -- Supplies an outlet for messages.
|
|
Verbose -- Supplies a flag indicating (if TRUE) that
|
|
conversion should be carried out in verbose mode.
|
|
Status -- Receives the status of the conversion.
|
|
|
|
Return Value:
|
|
|
|
TRUE upon successful completion.
|
|
|
|
--*/
|
|
{
|
|
HPFS_VOL HpfsVolume;
|
|
DP_DRIVE DpDrive;
|
|
|
|
// Make sure that the volume does not have a queer sector size.
|
|
|
|
if (!DpDrive.Initialize(NtDriveName, Message)) {
|
|
*Status = CONVERT_STATUS_ERROR;
|
|
return FALSE;
|
|
}
|
|
|
|
if (DpDrive.QuerySectorSize() != 512) {
|
|
Message->Set(MSG_CONVERT_UNSUPPORTED_SECTOR_SIZE);
|
|
Message->Display("%W", TargetFileSystem);
|
|
*Status = CONVERT_STATUS_ERROR;
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
// Initialize and lock the volume.
|
|
|
|
if( !HpfsVolume.Initialize( NtDriveName, Message )) {
|
|
|
|
*Status = CONVERT_STATUS_ERROR;
|
|
return FALSE;
|
|
}
|
|
|
|
// Lock the volume for exclusive access.
|
|
|
|
if( !HpfsVolume.Lock() ) {
|
|
|
|
*Status = CONVERT_STATUS_CANNOT_LOCK_DRIVE;
|
|
return FALSE;
|
|
}
|
|
|
|
return( ConvertHPFSVolume( &HpfsVolume,
|
|
TargetFileSystem,
|
|
NULL,
|
|
Message,
|
|
Verbose,
|
|
Status ) );
|
|
|
|
}
|