📄 volume.cpp
字号:
//////////////////////////////////////////////////////////////////////////////
// Volume.cpp
//
// Implementation of class Volume.
//////////////////////////////////////////////////////////////////////////////
// $Id: Volume.cpp,v 1.5 1998/12/14 18:58:55 nryan Exp $
// Copyright (C) 1998 by Network Associates, Inc.
// All rights reserved.
#include "StdAfx.h"
#include <Dbt.h>
#include <Shlobj.h>
#include "Required.h"
#include "DriverComm.h"
#include "UtilityFunctions.h"
#include "WindowsVersion.h"
#include "Globals.h"
#include "Volume.h"
////////////
// Constants
////////////
const PGPUInt32 kSHNotifySleepDelayMs = 500;
const PGPUInt64 kMaxBlocksDiskWeFormat =
(2047*kBytesPerMeg)/kDefaultBlockSize;
static LPCSTR kVWin32DriverString = "\\\\.\\VWIN32";
static LPCSTR kVolumeOpenString = "\\\\.\\%c:";
const PGPUInt32 kMaxBlocksPerWrite = 2000;
const PGPUInt32 kMinBlocksPerWrite = 10;
const PGPUInt32 kIdealNumWritesPerData = 10;
///////////////////////////////////////
// Class Volume public member functions
///////////////////////////////////////
// The Class Volume constructor.
Volume::Volume(PGPUInt8 drive)
{
if (drive != kInvalidDrive)
mMountState = kVol_Mounted;
else
mMountState = kVol_Unmounted;
mLockState = kLock_None;
mDrive = drive;
mAttachedToLocalVol = FALSE;
mBlockSize = 0;
}
// The Volume destructor unmounted the volume if was mounted by us.
Volume::~Volume()
{
DualErr derr;
if (Mounted())
{
if (AttachedToLocalVolume())
DetachLocalVolume();
}
}
// GetDrive returns the drive number the volume is mounted on.
PGPUInt8
Volume::GetDrive()
{
return mDrive;
}
// GetBlockSize returns the block size of the mounted volume.
PGPUInt16
Volume::GetBlockSize()
{
pgpAssert(Mounted());
return mBlockSize;
}
// GetTotalBlocks returns the total number of blocks on the volume.
PGPUInt64
Volume::GetTotalBlocks()
{
pgpAssert(Mounted());
return mTotalBlocks;
}
// Mounted returns TRUE if the Volume is mounted.
PGPBoolean
Volume::Mounted()
{
return (mMountState == kVol_Mounted);
}
// Unmounted returns TRUE if the Volume is unmounted.
PGPBoolean
Volume::Unmounted()
{
return (mMountState == kVol_Unmounted);
}
// AttachedToLocalVolume returns TRUE if the Volume object is attached to a
// local volume, FALSE if not.
PGPBoolean
Volume::AttachedToLocalVolume()
{
return mAttachedToLocalVol;
}
// HasOpenFiles returns TRUE if the volume has open files, FALSE otherwise.
PGPBoolean
Volume::HasOpenFiles()
{
DualErr derr;
PGPBoolean hasOpenFiles;
pgpAssert(Mounted());
derr = AreFilesOpenOnDrive(mDrive, &hasOpenFiles);
if (derr.IsntError())
return hasOpenFiles;
else
return TRUE;
}
// LockedForReadWrite returns TRUE if the volume is mounted and locked for
// read/write access, FALSE otherwise.
PGPBoolean
Volume::LockedForReadWrite()
{
return (Mounted() && (mLockState == kLock_ReadWrite));
}
// LockedForReadWrite returns TRUE if the volume is mounted and locked for
// format access, FALSE otherwise.
PGPBoolean
Volume::LockedForFormat()
{
return (Mounted() && (mLockState == kLock_Format));
}
// BrowseToVolume opens a view to the volume in an explorer window.
void
Volume::BrowseToVolume()
{
CString root;
pgpAssert(Mounted());
if (MakeRoot(mDrive, &root).IsntError())
{
ShellExecute(NULL, "explore", root, NULL, NULL, SW_SHOWNORMAL);
}
}
// GetVolumeLabel retrieves the volume label associated with a mounted volume.
DualErr
Volume::GetVolumeLabel(LPSTR label, PGPUInt32 size)
{
DualErr derr;
CString root;
pgpAssertAddrValid(label, LPSTR);
pgpAssert(Mounted());
derr = MakeRoot(mDrive, &root);
if (derr.IsntError())
{
if (GetVolumeInformation(root, label, size, NULL, NULL, NULL, NULL,
0))
{
derr = DualErr(kPGDMinorError_GetVolumeInfoFailed,
GetLastError());
}
}
return derr;
}
// SetVolumeLabel sets the 11-character label of the mounted volume.
DualErr
Volume::SetVolumeLabel(LPCSTR label)
{
DualErr derr;
CString volName, root;
pgpAssertStrValid(label);
pgpAssert(Mounted());
derr = CanonicalizeVolumeName(label, &volName);
if (derr.IsntError())
{
derr = MakeRoot(mDrive, &root);
}
if (derr.IsntError())
{
if (!::SetVolumeLabel(root, volName))
{
derr = DualErr(kPGDMinorError_SetVolumeLabelFailed,
GetLastError());
}
}
return derr;
}
// AttachLocalVolume initializes this Volume object for access to an already
// mounted volume on the local computer.
DualErr
Volume::AttachLocalVolume(PGPUInt8 drive)
{
DualErr derr;
pgpAssert(IsLegalDriveNumber(drive));
pgpAssert(!Mounted());
pgpAssert(!AttachedToLocalVolume());
if (!App->IsVolumeValid(drive))
derr = DualErr(kPGDMinorError_InvalidParameter);
if (derr.IsntError())
{
mMountState = kVol_Mounted;
mLockState = kLock_None;
mDrive = drive;
mAttachedToLocalVol = TRUE;
if (FillInVolInfo().IsError())
{
mBlockSize = kDefaultBlockSize;
mTotalBlocks = 0;
}
}
return derr;
}
// DetachLocalVolume marks this Volume object as no longer being associated
// with a local volume.
void
Volume::DetachLocalVolume()
{
pgpAssert(Mounted());
pgpAssert(AttachedToLocalVolume());
mMountState = kVol_Unmounted;
mLockState = kLock_None;
mDrive = kInvalidDrive;
mAttachedToLocalVol = FALSE;
}
// LockVolumeForReadWrite locks the mounted volume for direct read/write
// access.
DualErr
Volume::LockVolumeForReadWrite()
{
DualErr derr;
pgpAssert(Mounted());
pgpAssert(!LockedForReadWrite() && !LockedForFormat());
derr = LockUnlockVolume(mDrive, kLO_LockReadWrite);
if (derr.IsntError())
{
mLockState = kLock_ReadWrite;
}
return derr;
}
// LockVolumeForFormat locks the mounted volume for formatting.
DualErr
Volume::LockVolumeForFormat()
{
DualErr derr;
pgpAssert(Mounted());
pgpAssert(!LockedForReadWrite() && !LockedForFormat());
derr = LockUnlockVolume(mDrive, kLO_LockFormat);
if (derr.IsntError())
{
mLockState = kLock_Format;
}
return derr;
}
// UnlockVolume removes any outstanding locks on the volume;
DualErr
Volume::UnlockVolume()
{
DualErr derr;
pgpAssert(Mounted());
pgpAssert(LockedForReadWrite() || LockedForFormat());
derr = LockUnlockVolume(mDrive, (LockedForReadWrite() ?
kLO_UnlockReadWrite : kLO_UnlockFormat));
if (derr.IsntError())
{
mLockState = kLock_None;
}
return derr;
}
// Read reads blocks from the locked mounted volume.
DualErr
Volume::Read(PGPUInt8 *buf, PGPUInt64 pos, PGPUInt32 nBlocks)
{
DualErr derr;
pgpAssertAddrValid(buf, PGPUInt8);
pgpAssert(Mounted());
pgpAssert(LockedForReadWrite() || LockedForFormat());
derr = DirectDiskRead(mDrive, buf, nBlocks * GetBlockSize(), pos,
nBlocks);
return derr;
}
// Write writes blocks to the locked mounted volume.
DualErr
Volume::Write(PGPUInt8 *buf, PGPUInt64 pos, PGPUInt32 nBlocks)
{
DualErr derr;
pgpAssertAddrValid(buf, PGPUInt8);
pgpAssert(Mounted());
pgpAssert(LockedForReadWrite() || LockedForFormat());
derr = DirectDiskWrite(mDrive, buf, nBlocks * GetBlockSize(), pos,
nBlocks);
return derr;
}
// Format formats the mounted volume using our own algorithms.
DualErr
Volume::Format()
{
DualErr derr;
FatData fat;
PGPBoolean allocedBlockBuf, lockedForFormat;
PGPUInt8 *blockBuf;
PGPUInt64 megsDisk;
pgpAssert(Mounted());
pgpAssert(!LockedForReadWrite() || !LockedForFormat());
allocedBlockBuf = lockedForFormat = FALSE;
megsDisk = (GetTotalBlocks() * kDefaultBlockSize) / kBytesPerMeg;
// Can only format drives with standard block sizes.
if (GetBlockSize() != kDefaultBlockSize)
derr = DualErr(kPGDMinorError_CantFormatDrive);
// Too big for format?
if (derr.IsntError())
{
if (GetBlockSize() > kMaxBlocksDiskWeFormat)
derr = DualErr(kPGDMinorError_DiskTooBigToFormat);
}
// Get block buffer.
if (derr.IsntError())
{
derr = GetByteBuffer(kDefaultBlockSize, &blockBuf);
allocedBlockBuf = derr.IsntError();
}
// Lock the volume for format.
if (derr.IsntError())
{
derr = LockVolumeForFormat();
lockedForFormat = derr.IsntError();
}
if (derr.IsntError())
{
// Initialize FAT data.
fat.fdFsId = kFS_FAT16;
if (megsDisk < 2)
{
fat.fdFsId = kFS_FAT12;
}
else if ((megsDisk >= kMinFat32Megs) &&
IsWin95OSR2CompatibleMachine())
{
fat.fdFsId = kFS_FAT32;
}
InitFatData(&fat, GetBlockSize());
derr = ClearBlocks(0, fat.fdFirstSecData);
}
// Write out the FAT data structures.
if (derr.IsntError())
{
BigFatBootFSInfo bfInfo;
BootSector12 bb12;
BootSector16 bb16;
BootSector32 bb32;
PGPUInt32 fat16Sig;
PGPUInt64 pos;
pgpAssert(sizeof(bb12) == kDefaultBlockSize);
pgpAssert(sizeof(bb16) == kDefaultBlockSize);
pgpAssert(sizeof(bb32) == kDefaultBlockSize);
pgpClearMemory(blockBuf, kDefaultBlockSize);
pos = 0;
switch (fat.fdFsId)
{
case kFS_FAT12:
// Init the boot block.
InitFAT12BootBlock(GetBlockSize(), &fat, &bb12);
// Write the boot block.
derr = Write((PGPUInt8 *) &bb12, pos, 1);
// Write the first FAT.
if (derr.IsntError())
{
pgpCopyMemory((PGPUInt8 *) &kFat12Sig, blockBuf,
sizeof(kFat12Sig));
pos += fat.fdReservedSecs;
derr = Write(blockBuf, pos, 1);
}
// Write the second FAT.
if (derr.IsntError())
{
pos += fat.fdFatSize;
derr = Write(blockBuf, pos, 1);
}
break;
case kFS_FAT16:
// Init the boot block.
InitFAT16BootBlock(GetBlockSize(), &fat, &bb16);
// Decide on a FAT signature.
fat16Sig = (megsDisk < 16 ? kUnder16MbFat16Sig :
kOver16MbFat16Sig);
// Write the boot block.
derr = Write((PGPUInt8 *) &bb16, pos, 1);
// Write the first FAT.
if (derr.IsntError())
{
pgpCopyMemory((PGPUInt8 *) &fat16Sig, blockBuf,
sizeof(fat16Sig));
pos += fat.fdReservedSecs;
derr = Write(blockBuf, pos, 1);
}
// Write the second FAT.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -