⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cpgpdiskformatter.cpp

📁 PGP8.0源码 请认真阅读您的文件包然后写出其具体功能
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*____________________________________________________________________________
		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 + -