📄 cpgpdiskformatter.cpp
字号:
/*____________________________________________________________________________
Copyright (C) 2002 PGP Corporation
All rights reserved.
$Id: CPGPdiskFormatter.cpp,v 1.16 2002/09/26 01:32:11 wjb Exp $
____________________________________________________________________________*/
#include "pgpClassesConfig.h"
#include <shlobj.h>
#include "CMutex.h"
#include "UMath.h"
#include "UTime.h"
#include "CPath.h"
#include "USecurity.h"
#include "UUnicode.h"
#include "UWinVersion.h"
#include "CPGPdiskFormatter.h"
_USING_PGP
_UNNAMED_BEGIN
// Constants
const PGPUInt32 kMaxBlocksPerClear = 100;
const PGPUInt32 kMaxLockRetries = 20;
const PGPUInt32 kMaxVolNameLength = 11;
const PGPUInt32 kLockRetryMsDelay = 500;
const char *kFat12Or16FSString = "FAT";
const char *kDefaultOEMName = "PGPDISK ";
const char *kDefaultVolLabel = "UNNAMED ";
const char *kInvalidVolNameChars = "\"&*+./:;<=>?[\\]^|";
const char kInvalidVolCharReplacement = '_';
_UNNAMED_END
// Class CPGPdiskFormatter member variables
NewDiskStatusFuncType CPGPdiskFormatter::mUserCallback;
void *CPGPdiskFormatter::mUserValue;
CComboError CPGPdiskFormatter::mError;
// Class CPGPdiskFormatter member functions
void
CPGPdiskFormatter::Format(
const CPGPdiskContext& context,
const char *root,
const char *volName,
FileSys::Type fsType,
NewDiskStatusFuncType userCallback,
void *userValue)
{
pgpAssertStrValid(root);
pgpAssertStrValid(volName);
pgpAssertAddrValid(userCallback, FormatDiskStatusFuncType);
// Root must refer to a mounted PGPdisk volume.
CPGPdiskDiskSet diskSet(context);
CPGPdiskDiskIter diskIter(diskSet);
CPGPdiskDisk disk;
if (!diskIter.SearchOnRoot(root, disk))
THROW_PGPERROR(kPGPError_BadParams);
// Fixup volume name.
CString cvolName(volName);
CanonicalizeVolumeName(cvolName);
// Perform the conversion.
if (UWinVersion::IsWin95Compatible() ||
(UWinVersion::IsWinNT4Compatible() &&
!USecurity::IsCurrentUserAdmin()))
{
FormatCustomFat(disk, root, cvolName, fsType, userCallback,
userValue);
}
else if (UWinVersion::IsWinNT4Compatible())
{
FormatWinNT(disk, root, cvolName, fsType, userCallback, userValue);
}
else
{
THROW_PGPERROR(kPGPError_FeatureNotAvailable);
}
// Make sure volume label is set.
for (PGPUInt32 i = 0; i < 10; i++)
{
if (SetVolumeLabel(root, cvolName))
break;
Sleep(250);
}
}
void
CPGPdiskFormatter::GetValidFilesystems(
PGPUInt64 blocksDisk,
CArray<FileSysInfo>& fsInfos,
PGPUInt32& numFsInfos)
{
PGPUInt64 megsDisk = (blocksDisk*kPGPdiskBlockSize) /
PFLConstants::kBytesPerMb;
fsInfos.Resize(3);
numFsInfos = 0;
if (UWinVersion::IsWin95Compatible())
{
if (UFileSys::IsFileSysValidForSize(FileSys::kFat12Or16FileSys,
megsDisk))
{
fsInfos[numFsInfos].fsType = FileSys::kFat12Or16FileSys;
fsInfos[numFsInfos].fsString = GetFSStringForFormat(
FileSys::kFat12Or16FileSys);
numFsInfos++;
}
if (UFileSys::IsFileSysValidForSize(FileSys::kFat32FileSys, megsDisk) &&
UWinVersion::IsWin95OSR2Compatible())
{
fsInfos[numFsInfos].fsType = FileSys::kFat32FileSys;
fsInfos[numFsInfos].fsString = GetFSStringForFormat(
FileSys::kFat32FileSys);
numFsInfos++;
}
}
else if (UWinVersion::IsWinNT4Compatible())
{
if (UFileSys::IsFileSysValidForSize(FileSys::kFat12Or16FileSys,
megsDisk))
{
fsInfos[numFsInfos].fsType = FileSys::kFat12Or16FileSys;
fsInfos[numFsInfos].fsString = GetFSStringForFormat(
FileSys::kFat12Or16FileSys);
numFsInfos++;
}
if (UFileSys::IsFileSysValidForSize(FileSys::kFat32FileSys, megsDisk) &&
UWinVersion::IsWin2000Compatible())
{
// Ugly departure from Nick's pretty (complicated :-) coding
// style. W2K can't format FAT32 volumes over 32 GB.
// See MSKB Q253726. No reasons why given. The world
// may never know.. -wjb
if(megsDisk<32768)
{
fsInfos[numFsInfos].fsType = FileSys::kFat32FileSys;
fsInfos[numFsInfos].fsString = GetFSStringForFormat(
FileSys::kFat32FileSys);
numFsInfos++;
}
}
if (UFileSys::IsFileSysValidForSize(FileSys::kNTFSFileSys,
megsDisk) &&
USecurity::IsCurrentUserAdmin() &&
!(UWinVersion::IsWin2000Compatible() &&
USecurity::IsRemoteSession()))
{
fsInfos[numFsInfos].fsType = FileSys::kNTFSFileSys;
fsInfos[numFsInfos].fsString = GetFSStringForFormat(
FileSys::kNTFSFileSys);
numFsInfos++;
}
}
}
const char *
CPGPdiskFormatter::GetFSStringForFormat(FileSys::Type fsType)
{
switch (fsType)
{
case FileSys::kFat12FileSys:
case FileSys::kFat16FileSys:
case FileSys::kFat12Or16FileSys:
return kFat12Or16FSString;
case FileSys::kFat32FileSys:
return FileSys::kFat32IdStr;
case FileSys::kNTFSFileSys:
return FileSys::kNTFSIdStr;
default:
pgpAssert(FALSE);
return "";
}
}
void
CPGPdiskFormatter::CanonicalizeVolumeName(CString& volName) const
{
if (volName.Length() > kMaxVolNameLength)
{
volName.Resize(kMaxVolNameLength + 1);
volName.SetAt(kMaxVolNameLength, '\0');
}
PGPUInt32 lengthStr = volName.Length();
PGPUInt32 lengthInv = strlen(kInvalidVolNameChars);
for (PGPUInt32 i = 0; i < lengthStr; i++)
{
for (PGPUInt32 j = 0; j < lengthInv; j++)
{
if (volName[i] == kInvalidVolNameChars[j])
volName.SetAt(i, kInvalidVolCharReplacement);
}
}
}
void
CPGPdiskFormatter::ClearBlocks(
CPGPdiskDisk& disk,
PGPUInt64 startBlock,
PGPUInt32 numBlocks,
NewDiskStatusFuncType userCallback,
void *userValue) const
{
PGPUInt32 blocksPerClear = pgpMin(numBlocks/10, kMaxBlocksPerClear);
CArray<PGPUInt8> blanks(blocksPerClear * kPGPdiskBlockSize);
blanks.Wipe();
// Calculate information used for progress updates.
PGPUInt32 totalWrites = static_cast<PGPUInt32>(
UMath::CeilDiv<PGPUInt64>(numBlocks, blocksPerClear));
PGPUInt32 writesDone = 0;
PGPUInt32 writesPerUpdate = UMath::CeilDiv<PGPUInt32>(numBlocks, 100);
for (PGPUInt64 i = startBlock; i < numBlocks; i += blocksPerClear)
{
disk.WriteVolume(blanks.Get(), i, blocksPerClear);
PGPBoolean continueFormat = TRUE;
if (writesDone++ % writesPerUpdate == 0)
{
continueFormat = userCallback(TRUE, writesDone*100/totalWrites,
userValue);
}
if (!continueFormat)
THROW_PGPERROR(kPGPError_UserAbort);
}
}
void
CPGPdiskFormatter::InitBootSectorFat12(
PGPUInt32 blocksDisk,
const UFileSys::FatData& fatData,
FileSys::BootSectorFat12& bs12) const
{
pgpClearMemory(&bs12, sizeof(bs12));
PGPUInt64 megsDisk = static_cast<PGPUInt32>(
UFileSys::CalcMegsDisk(blocksDisk, kPGPdiskBlockSize));
PGPUInt32 secsPerTrack, tracksPerCyl;
PGPUInt64 cylinders;
UFileSys::CalcFakeFatGeom(kPGPdiskBlockSize, tracksPerCyl, cylinders,
secsPerTrack);
bs12.bsJump[0] = 0xEB; // fill in jmp instruction to look real
bs12.bsJump[1] = 0x3C;
bs12.bsJump[2] = 0x90;
strncpy(bs12.bsOemName, kDefaultOEMName, sizeof(bs12.bsOemName));
bs12.bsBytesPerSec = kPGPdiskBlockSize; // bytes per sector
bs12.bsSecPerClust = 1; // sectors per cluster
bs12.bsResSectors = fatData.fdReservedSecs; // reserved sectors
bs12.bsFats = fatData.fdFatCount; // number of FATs
bs12.bsRootDirEnts = fatData.fdRootDirEnts; // entries in root dir
bs12.bsSectors = blocksDisk;
bs12.bsMedia = FileSys::kFatMediaByte; // a hard disk
bs12.bsFatSecs = static_cast<PGPUInt16>(fatData.fdFatSize);
bs12.bsSecPerTrack = static_cast<PGPUInt16>(secsPerTrack);
bs12.bsHeads = static_cast<PGPUInt16>(tracksPerCyl);
bs12.bsHiddenSecs = 0; // no hidden sectors
bs12.bsHugeSectors = 0;
bs12.bsDriveNumber = FileSys::kFatHardDriveId; // a hard drive
bs12.bsBootSignature = FileSys::kFatFirstBootSig;
bs12.bsVolumeId = static_cast<PGPUInt32>(UTime::GetSystemTicks());
bs12.bsSignature = FileSys::kFatSecondBootSig;
strncpy(bs12.bsVolumeLabel, kDefaultVolLabel,
sizeof(bs12.bsVolumeLabel));
memset(bs12.bsFileSysType, ' ', sizeof(bs12.bsFileSysType));
strncpy(bs12.bsFileSysType, FileSys::kFat12IdStr,
strlen(FileSys::kFat12IdStr));
}
void
CPGPdiskFormatter::InitBootSectorFat16(
PGPUInt32 blocksDisk,
const UFileSys::FatData& fatData,
FileSys::BootSectorFat16& bs16) const
{
pgpClearMemory(&bs16, sizeof(bs16));
PGPUInt32 megsDisk = static_cast<PGPUInt32>(
UFileSys::CalcMegsDisk(blocksDisk, kPGPdiskBlockSize));
PGPUInt32 secsPerTrack, tracksPerCyl;
PGPUInt64 cylinders;
UFileSys::CalcFakeFatGeom(kPGPdiskBlockSize, tracksPerCyl, cylinders,
secsPerTrack);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -