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

📄 volume.cpp

📁 vc环境下的pgp源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:

	pgpAssert(Mounted());
	pgpAssert(!AttachedToLocalVolume());

	hasOpenFiles = lockedDown = FALSE;

	if (!isThisEmergency)
	{
		// Check for open files.
		derr = Driver->HasOpenFiles(mDrive, &hasOpenFiles);

		if (derr.IsntError())
		{
			if (hasOpenFiles)
				derr = DualErr(kPGDMinorError_FilesOpenOnDrive);
		}

		if (derr.IsntError())
		{
			// Flush the volume.
			VolFlush(mDrive, NULL);

			// Get a lock on the drive.
			oldLock = Driver->GetLockLevel(mDrive);
			derr = Driver->AcquireLogicalVolLock(mDrive, kLock_L3);

			lockedDown = derr.IsntError();
		}
	}

	if (derr.IsntError())
	{
		// Some people tell me this should be done to prevent hangs. (?)
		NotifyVolumeRemoval(GetDrive());

		// We make a system call to disassociate the mounted DCB with its
		// drive letter, thereby unmounting the volume.

		if (!IspDisassociateDcb(GetDrive()))
			derr = DualErr(kPGDMinorError_IspDisassocDcbFailed);
	}

	if (derr.IsntError())
	{
		CleanUpMountedVars();
	}

	if (derr.IsError())
	{
		if (lockedDown)
			Driver->AcquireLogicalVolLock(mDrive, oldLock);
	}

	return derr;
}

// LockVolumeForReadWrite locks the mounted volume for direct read/write
// access.

DualErr 
Volume::LockVolumeForReadWrite()
{
	DualErr derr;
	
	pgpAssert(Mounted());
	pgpAssert(!LockedForReadWrite() && !LockedForFormat());

	derr = Driver->AcquireLogicalVolLock(mDrive, kLock_L3);

	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 = Driver->GetFormatLockOnDrive(mDrive);

	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());

	if (LockedForReadWrite())
		derr = Driver->AcquireLogicalVolLock(mDrive, ::kLock_None);
	else
		derr = Driver->ReleaseFormatLockOnDrive(mDrive);

	if (derr.IsntError())
	{
		mLockState = kLock_None;
	}

	return derr;
}

// Read reads 'nBlocks' sectors from the logical mounted volume from sector
// position 'pos'.

DualErr 
Volume::Read(
	PGPUInt8			*buf, 
	PGPUInt64			pos, 
	PGPUInt32			nBlocks, 
	GenericCallbackInfo	*upInfo)
{
	pgpAssertAddrValid(buf, PGPUInt8);

	return DiskAccess(IOR_READ, buf, pos, nBlocks, upInfo);
}

// Write reads 'nBlocks' sectors from the logical mounted volume from sector
// position 'pos'.

DualErr 
Volume::Write(
	PGPUInt8			*buf, 
	PGPUInt64			pos, 
	PGPUInt32			nBlocks, 
	GenericCallbackInfo	*upInfo)
{
	pgpAssertAddrValid(buf, PGPUInt8);

	return DiskAccess(IOR_WRITE, buf, pos, nBlocks, upInfo);
}


////////////////////////////////////////
// Class Volume private member functions
////////////////////////////////////////

// InitMountedVars initializes some variables that describe a mounted volume
// and/or can be used to perform I/O on that volume.

DualErr 
Volume::InitMountedVars(PGPUInt8 drive, PDCB pDcb)
{
	DualErr derr;

	pgpAssert(IsLegalDriveNumber(drive));
	pgpAssert(Unmounted());
	pgpAssertAddrValid(pDcb, DCB);

	// Allocate a buffer for bootblock and devparam requests.
	if (derr.IsntError())
	{
		derr = GetByteBuffer(ExtractBlockSize(pDcb), (PGPUInt8 **) &mBBlock);
	}

	if (derr.IsntError())
	{
		mMountState = kVol_Mounted;
		mDrive = drive;

		mPDcb = pDcb;
	}

	return derr;
}

// CleanUpMountedVars cleans up those variables we initialized in
// InitMountedVars.

void 
Volume::CleanUpMountedVars()
{
	pgpAssert(Mounted());
	pgpAssertAddrValid(mBBlock, PGPUInt8);

	mMountState = kVol_Unmounted;

	FreeByteBuffer(mBBlock);

	mDrive = kInvalidDrive;

	mBBlock = NULL;
	mPDcb = NULL;
}

// DiskAccess performs either an IOR_READ or an IOR_WRITE operation on the
// mounted volume.

DualErr 
Volume::DiskAccess(
	PGPUInt16			func, 
	PGPUInt8			*buf, 
	PGPUInt64			pos, 
	PGPUInt32			nBlocks, 
	GenericCallbackInfo	*upInfo)
{
	DualErr		derr;
	PIOP		pIop;
	PIOR		pIor;
	PGPBoolean	useAsync;
	PGPUInt16	offset, size;
	PVRP		pVrp;

	pgpAssertAddrValid(buf, PGPUInt8);

	pgpAssert((func == IOR_READ) || (func == IOR_WRITE));

	// Is this request asynchronous?
	useAsync = IsntNull(upInfo);

	pgpAssert(Mounted());
	pgpAssertAddrValid(mPDcb, DCB);
	pgpAssert(!mVolumeReq.isInUse);

	// Prepare the request.
	mVolumeReq.isInUse = TRUE;
	
	if (useAsync)
	{
		mVolumeReq.upInfo = upInfo;
		mVolumeReq.downInfo.refData[0] = (PGPUInt32) this;
	}

	// Make sure we check that the VRP field in the DCB exists; the system
	// has a habit of nullifying it when an I/O error occurs.

	if (!(pVrp = (PVRP) mPDcb->DCB_cmn.DCB_vrp_ptr))
		derr = DualErr(kPGDMinorError_InvalidVRP);

	// Create our IOP/IOR.
	if (derr.IsntError())
	{
		size = (PGPUInt16) pVrp->VRP_max_req_size + 
			pVrp->VRP_max_sgd*sizeof(SGD);
		offset = (PGPUInt16) pVrp->VRP_delta_to_ior;

		pIop = IspCreateIop(size, offset, ISP_M_FL_INTERRUPT_TIME);

		if (!pIop)
			derr = DualErr(kPGDMinorError_IorAllocationFailed);
	}

	// Now we fill in the fields of our IOR structure prior to sending the
	// I/O request to the IOS subsystem.

	if (derr.IsntError())
	{
		pIor = &pIop->IOP_ior;
		pIop->IOP_timer_orig = pIop->IOP_timer = kDefaultIopTimeOut;

		mVolumeReq.pIor = pIor;

		pIor->IOR_next		= NULL;					// must be NULL
		pIor->IOR_func		= func;					// IOR_READ or IOR_WRITE
		pIor->IOR_status	= 0;					// result code goes here
		pIor->IOR_flags		= IORF_VERSION_002		// means we are using IOR
							| IORF_HIGH_PRIORITY			// high priority
							| IORF_LOGICAL_START_SECTOR		// in partition
							| IORF_DOUBLE_BUFFER;			// copy buffer

		// We have to set the start address, transfer count, and buffer fields
		// with the passed information.

		pIor->IOR_start_addr[0]		= GetLowDWord(pos);		// low sector
		pIor->IOR_start_addr[1]		= GetHighDWord(pos);	// high sector
		pIor->IOR_xfer_count		= nBlocks;				// # secs
		pIor->IOR_buffer_ptr		= (PGPUInt32) buf;		// buffer
		pIor->IOR_private_client	= kPGPdiskIopMagic;		// comes from us
		pIor->IOR_req_vol_handle	= (PGPUInt32) pVrp;		// vrp pointer
		pIor->IOR_sgd_lin_phys		= (PGPUInt32) (pIor + 1);	// SGDs here
		pIor->IOR_num_sgds			= 0;					// system fills in
		pIor->IOR_vol_designtr		= GetDrive();

		// Initialize the callback info.
		if (useAsync)
		{
			pIor->IOR_callback = (CMDCPLT) VolumeCallback;
			pIor->IOR_req_req_handle = (PGPUInt32) &mVolumeReq.downInfo;
		}
		else
		{
			pIor->IOR_flags |= IORF_SYNC_COMMAND;
			pIor->IOR_callback = NULL;
		}

		// The IlbIoCriteria routine must be run on the IOR in order to let
		// the system massage some of the fields in the IOR into a form that
		// it likes.

		if (!IlbIoCriteria(pIor))
			DebugOut("PGPdisk: IlbIoCriteria in DiskAccess failed");

		DebugOut(
			"PGPdisk: Vol Access IOR %X func %u pos %u nBlocks %u drive %u", 
			pIor, func, (PGPUInt32) pos, nBlocks, GetDrive());

		// Send the request to the IOS for processing synchronously.
		__asm push edi
		IOS_SendCommand(pIor, mPDcb);
		__asm pop edi

		DebugOut("PGPdisk: Exiting Vol Access IOR %X", pIor);
	}

	// If we are sync and called down the IOP we need to cleanup now
	// since there is no callback.

	if (derr.IsntError())
	{
		if (!useAsync)
		{
			derr = CleanUpRequest();	// extract derr from IOR
			mVolumeReq.isInUse = FALSE;
		}
	}

	// If an error calling down the IOP, we need to callback if we were
	// called async.

	if (derr.IsError())
	{
		if (useAsync)
		{
			CleanUpRequest();
			ScheduleAsyncCallback(derr);
		}
	}

	return derr;
}

// CleanUpRequest performs housekeeping after a request has been completed.

DualErr 
Volume::CleanUpRequest()
{
	DualErr	derr;
	PIOR	pIor;

	pgpAssert(mVolumeReq.isInUse);
	pIor = mVolumeReq.pIor;

	// Convert possible error value to Windows standard.
	if (pIor->IOR_status >= IORS_ERROR_DESIGNTR)
	{
		if (pIor->IOR_func == IOR_READ)
		{
			derr = DualErr(kPGDMinorError_IorReadFailure, 
				IOSMapIORSToI21(pIor->IOR_status));
		}
		else
		{
			derr = DualErr(kPGDMinorError_IorWriteFailure, 
				IOSMapIORSToI21(pIor->IOR_status));
		}
	}

	// De-allocate the IOR if one was allocated.
	if (pIor)
	{
		PGPUInt16	offset;
		PVRP		pVrp;

		pVrp = (PVRP) mPDcb->DCB_cmn.DCB_vrp_ptr;
		
		// Hopefully our volume didn't go away.
		if (pVrp)
		{
			pgpAssertAddrValid(pVrp, VRP);

			offset = (PGPUInt16) pVrp->VRP_delta_to_ior;
			IspDeallocMem((PGPUInt8 *) pIor - offset);
		}
	}

	return derr;
}

// VolumeCallback is called by the system after it has finished processing
// the IOP we gave it. We extract the address of the Volume object in question
// and pass the callback to it.

void 
Volume::VolumeCallback(GenericCallbackInfo *downInfo)
{
	Volume *pVol;

	pgpAssertAddrValid(downInfo, GenericCallbackInfo);

	pVol = (Volume *) downInfo->refData[0];
	pgpAssertAddrValid(pVol, Volume);

	pVol->VolumeCallbackAux();
}

// VolumeCallbackAux is called by the static callback function
// 'VolumeCallback' so we don't have to type 'pVol' before every reference to
// an object member or method. (Not needed here but coded so we are parallel
// to higher classes such as FatParser and PGPdisk in this regard.)

void 
Volume::VolumeCallbackAux()
{
	DualErr derr;

	pgpAssert(mVolumeReq.isInUse);

	// Cleanup.
	derr = CleanUpRequest();

	// Call up.
	ScheduleAsyncCallback(derr);
}

// ScheduleAsyncCallback schedules a windows event that calls our function
// that will call the asynchronous request up.

void 
Volume::ScheduleAsyncCallback(DualErr derr)
{
	static RestrictedEvent_THUNK callbackThunk;

	pgpAssertAddrValid(mVolumeReq.upInfo, GenericCallbackInfo);
	mVolumeReq.upInfo->derr = derr;

	Call_Restricted_Event(0, NULL, PEF_ALWAYS_SCHED, (PVOID) this, 
		AsyncExecuteCallback, 0, &callbackThunk);
}

// AsyncExecuteCallback was scheduled by 'ScheduleAsyncCallback' for the
// purpose of calling back up the asynchronous request we received.

VOID __stdcall 
Volume::AsyncExecuteCallback(
	VMHANDLE		hVM, 
	THREADHANDLE	hThread, 
	PVOID			Refdata, 
	PCLIENT_STRUCT	pRegs)
{
	Volume *pVol;

	pVol = (Volume *) Refdata;
	pgpAssertAddrValid(pVol, Volume);

	pgpAssert(pVol->mVolumeReq.isInUse);
	pVol->mVolumeReq.isInUse = FALSE;

	pgpAssertAddrValid(pVol->mVolumeReq.upInfo, GenericCallbackInfo);
	pVol->mVolumeReq.upInfo->callback(pVol->mVolumeReq.upInfo);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -