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

📄 cfileimpdrvnt.cpp

📁 PGP8.0源码 请认真阅读您的文件包然后写出其具体功能
💻 CPP
字号:
/*____________________________________________________________________________
		Copyright (C) 2002 PGP Corporation
        All rights reserved.

        $Id: CFileImpDrvNT.cpp,v 1.7 2002/11/21 18:42:55 wjb Exp $
____________________________________________________________________________*/

#include "pgpClassesConfig.h"

#include "UDebug.h"
	
#include "CFileImpDrvNT.h"
#include "CUnicodeString.h"

_USING_PGP

_UNNAMED_BEGIN

// Constants

enum
{
	kPagingIoResourceOffsetInFCB	= 0x0c, 
	kReplaceResourceWaitIntervalMs	= 50
};

_UNNAMED_END

// Class CFileImpDrvNT member functions

CFileImpDrvNT::CFileImpDrvNT() : 
	mFileHandle(NULL), mPOldPagingIoResource(NULL), mPPPagingIoResource(NULL)
{
}

CFileImpDrvNT::~CFileImpDrvNT()
{
	if (IsOpened())
		Close();
}

CComboError 
CFileImpDrvNT::GetLength(PGPUInt64& length) const
{
	pgpAssert(IsOpened());

	CComboError					error;
	FILE_STANDARD_INFORMATION	fileInfo;
	IO_STATUS_BLOCK				ioStatus;
	
	error.err = ZwQueryInformationFile(mFileHandle, &ioStatus, &fileInfo, 
		sizeof(fileInfo), FileStandardInformation);

	if (error.HaveNonPGPError())
		error.pgpErr = kPGPError_FileOpFailed;

	if (error.IsntError())
		length = fileInfo.EndOfFile.QuadPart;

	return error;
}

CComboError 
CFileImpDrvNT::GetUniqueFileId(PGPUInt64& fileId) const
{
	pgpDebugMsg("PGPdisk: Unimplemented function.\n");
	return CComboError(CComboError::kPGPError, kPGPError_FeatureNotAvailable);
}

CComboError 
CFileImpDrvNT::SetIsCompressed(PGPBoolean isCompressed)
{
	pgpDebugMsg("PGPdisk: Unimplemented function.\n");
	return CComboError(CComboError::kPGPError, kPGPError_FeatureNotAvailable);
}

CComboError 
CFileImpDrvNT::SetLength(PGPUInt64 length)
{
	pgpDebugMsg("PGPdisk: Unimplemented function.\n");
	return CComboError(CComboError::kPGPError, kPGPError_FeatureNotAvailable);
}

void 
CFileImpDrvNT::Flush()
{
	pgpDebugMsg("PGPdisk: Unimplemented function.\n");
}

CComboError 
CFileImpDrvNT::Open(const char *path, PGPUInt32 flags)
{
	pgpAssert(!IsOpened());
	pgpAssertStrValid(path);

	CComboError	error;
	error = mPath.Assign(path);

	if (error.IsntError())
	{
		CUnicodeString	uniPath;
		error = uniPath.Status();

		// Prepare the path. Must treat UNC paths special.
		if (error.IsntError())
		{
			if (IsUNCPath(path))
			{
				error = uniPath.Assign(path + 2);

				if (error.IsntError())
					error = uniPath.Prepend(kNTUNCLinkPathPrefix);
			}
			else
			{
				error = uniPath.Assign(path);

				if (error.IsntError())
					error = uniPath.Prepend(kNTLinkPathPrefix);
			}
		}

		if (error.IsntError())
		{
			IO_STATUS_BLOCK		ioStatus;
			OBJECT_ATTRIBUTES	objAttribs;

			uniPath.RemoveZeroTermination();

			// Initialize object attributes
			InitializeObjectAttributes(&objAttribs, uniPath.Get(), 
				OBJ_CASE_INSENSITIVE, NULL, NULL);

			// Set create options.
			PGPUInt32	createOpts	= FILE_NON_DIRECTORY_FILE | 
				FILE_SYNCHRONOUS_IO_NONALERT;

			if (flags & CFile::kNoBufferingFlag)
				createOpts |= FILE_NO_INTERMEDIATE_BUFFERING;

			// Set access flags.
			ACCESS_MASK	accessMask	= FILE_GENERIC_READ | SYNCHRONIZE;

			if (!(flags & CFile::kReadOnlyFlag))
				accessMask |= FILE_GENERIC_WRITE;

			// Set share flags.
			PGPUInt32	shareAccess	= NULL;

			if (!(flags & CFile::kDenyReadFlag))
				shareAccess |= FILE_SHARE_READ;

			if (flags & CFile::kShareWriteFlag)
				shareAccess |= FILE_SHARE_WRITE;

			// Set the create disposition.
			PGPUInt32	createDisp;

			if (flags & CFile::kCreateIfFlag)
				createDisp = FILE_OPEN_IF;
			else
				createDisp = FILE_OPEN;

			// Open the file handle.
			error.err = ZwCreateFile(&mFileHandle, accessMask, &objAttribs, 
				&ioStatus, NULL, FILE_ATTRIBUTE_NORMAL, shareAccess, 
				createDisp, createOpts, NULL, 0);

			if (error.HaveNonPGPError())
				error.pgpErr = kPGPError_CantOpenFile;

			if (error.IsntError())
			{
			#if	(_WIN32_WINNT < 0x0500)
				// Fix deadlock possibility.
				if (flags & CFile::kNoBufferingFlag)
					error = ReplacePagingIoResource();
			#endif	// _WIN32_WINNT < 0x5000

				if (error.IsntError())
				{
					mIsOpened = TRUE;
					mOpenFlags = flags;
				}

				if (error.IsError())
				{
					ZwClose(mFileHandle);
					mFileHandle = NULL;
				}
			}
		}
	}

	return error;
}

CComboError 
CFileImpDrvNT::Close()
{
	pgpAssert(IsOpened());

	CComboError	error;

#if	(_WIN32_WINNT < 0x0500)
	if (mOpenFlags & CFile::kNoBufferingFlag)
		RestorePagingIoResource();
#endif	// _WIN32_WINNT < 0x5000

	error.err = ZwClose(mFileHandle);

	if (error.HaveNonPGPError())
		error.pgpErr = kPGPError_FileOpFailed;

	if (error.IsntError())
	{
		mIsOpened	= FALSE;
		mFileHandle	= NULL;
		mOpenFlags	= CFile::kNoFlags;
	}

	return error;
}

CComboError 
CFileImpDrvNT::CloseAndReopen()
{
	CComboError	error;
	const char  *path;
	PGPUInt16	flags	= CFile::kNoBufferingFlag;

	error = Close();

	if (error.IsError())
		return error;

	// reopen again.
	path = Path();

	pgpAssert(!IsOpened());
	pgpAssertStrValid(path);

	if (error.IsntError())
	{
		CUnicodeString	uniPath;
		error = uniPath.Status();

		// Prepare the path. Must treat UNC paths special.
		if (error.IsntError())
		{
			if (IsUNCPath(path))
			{
				error = uniPath.Assign(path + 2);

				if (error.IsntError())
					error = uniPath.Prepend(kNTUNCLinkPathPrefix);
			}
			else
			{
				error = uniPath.Assign(path);

				if (error.IsntError())
					error = uniPath.Prepend(kNTLinkPathPrefix);
			}
		}

		if (error.IsntError())
		{
			IO_STATUS_BLOCK		ioStatus;
			OBJECT_ATTRIBUTES	objAttribs;

			uniPath.RemoveZeroTermination();

			// Initialize object attributes
			InitializeObjectAttributes(&objAttribs, uniPath.Get(), 
				OBJ_CASE_INSENSITIVE, NULL, NULL);

			// Set create options.
			PGPUInt32	createOpts	= FILE_NON_DIRECTORY_FILE | 
				FILE_SYNCHRONOUS_IO_NONALERT;

			if (flags & CFile::kNoBufferingFlag)
				createOpts |= FILE_NO_INTERMEDIATE_BUFFERING;

			// Set access flags.
			ACCESS_MASK	accessMask	= FILE_GENERIC_READ | SYNCHRONIZE;

			if (!(flags & CFile::kReadOnlyFlag))
				accessMask |= FILE_GENERIC_WRITE;

			// Set share flags.
			PGPUInt32	shareAccess	= NULL;

			if (!(flags & CFile::kDenyReadFlag))
				shareAccess |= FILE_SHARE_READ;

			if (flags & CFile::kShareWriteFlag)
				shareAccess |= FILE_SHARE_WRITE;

			// Set the create disposition.
			PGPUInt32	createDisp;

			if (flags & CFile::kCreateIfFlag)
				createDisp = FILE_OPEN_IF;
			else
				createDisp = FILE_OPEN;

			// Open the file handle.
			error.err = ZwCreateFile(&mFileHandle, accessMask, &objAttribs, 
				&ioStatus, NULL, FILE_ATTRIBUTE_NORMAL, shareAccess, 
				createDisp, createOpts, NULL, 0);

			if (error.HaveNonPGPError())
				error.pgpErr = kPGPError_CantOpenFile;

			if (error.IsntError())
			{
			#if	(_WIN32_WINNT < 0x0500)
				// Fix deadlock possibility.
				if (flags & CFile::kNoBufferingFlag)
					error = ReplacePagingIoResource();
			#endif	// _WIN32_WINNT < 0x5000

				if (error.IsntError())
				{
					mIsOpened = TRUE;
					mOpenFlags = flags;
				}

				if (error.IsError())
				{
					ZwClose(mFileHandle);
					mFileHandle = NULL;
				}
			}
		}
	}

	return error;
}

CComboError 
CFileImpDrvNT::Delete(const char *path)
{
	pgpDebugMsg("PGPdisk: Unimplemented function.\n");
	return CComboError(CComboError::kPGPError, kPGPError_FeatureNotAvailable);
}

CComboError 
CFileImpDrvNT::Move(const char *oldPath, const char *newPath)
{
	pgpDebugMsg("PGPdisk: Unimplemented function.\n");
	return CComboError(CComboError::kPGPError, kPGPError_FeatureNotAvailable);
}

CComboError 
CFileImpDrvNT::Read(void *buf, PGPUInt64 pos, PGPUInt32 nBytes) const
{
	pgpAssert(IsOpened());
	pgpAssertAddrValid(buf, VoidAlign);

	CComboError		error;
	IO_STATUS_BLOCK	ioStatus;
	LARGE_INTEGER	bigPos;

	bigPos.QuadPart = pos;

	error.err = ZwReadFile(mFileHandle, NULL, NULL, NULL, &ioStatus, buf, 
		nBytes, &bigPos, NULL);

	if (error.HaveNonPGPError())
		error.pgpErr = kPGPError_ReadFailed;

	return error;
}

CComboError 
//CFileImpDrvNT::Write(const void *buf, PGPUInt64 pos, PGPUInt32 nBytes) const
CFileImpDrvNT::Write(const void *buf, PGPUInt64 pos, PGPUInt32 nBytes)
{
	KIRQL	Irql;

	pgpAssert(!IsReadOnly());
	pgpAssert(IsOpened());
	pgpAssertAddrValid(buf, VoidAlign);

	CComboError		error;
	IO_STATUS_BLOCK	ioStatus;
	LARGE_INTEGER	bigPos;

	Irql = KeGetCurrentIrql();
	ASSERT(Irql == PASSIVE_LEVEL);

	bigPos.QuadPart = pos;

	error.err = ZwWriteFile(mFileHandle, NULL, NULL, NULL, &ioStatus, 
		const_cast<void *>(buf), nBytes, &bigPos, NULL);

	if (error.HaveNonPGPError())
	{
		UDebug::DebugOut("PGPdisk: ZwWriteFile Failed with Error %X.", error.err); 

		error = CloseAndReopen();

		if (error.IsntError())
		{
			error.err = ZwWriteFile(mFileHandle, NULL, NULL, NULL, &ioStatus, 
				const_cast<void *>(buf), nBytes, &bigPos, NULL);

			if (error.HaveNonPGPError())
			{
				error.pgpErr = kPGPError_WriteFailed;
			}
		}
	}

	return error;
}

CComboError 
CFileImpDrvNT::ReplacePagingIoResource()
{
	CComboError	error;

	// Replace the PagingIoResource of the FCB of the newly opened file
	// with our own. LONG story, see NTFSD archives for July 1999.

	// Reference the file object.
	PFILE_OBJECT	fileObject;

    error.err = ObReferenceObjectByHandle(mFileHandle, FILE_READ_DATA, NULL, 
		KernelMode, reinterpret_cast<void **>(&fileObject), NULL);

	if (error.HaveNonPGPError())
		error.pgpErr = kPGPError_NTDrvObjectOpFailed;

	if (error.IsntError())
	{
		// Get pointer to the PagingIoResource in the FCB header.
		mPPPagingIoResource	= reinterpret_cast<PERESOURCE *>(
			reinterpret_cast<PGPByte *>(fileObject->FsContext) + 
			kPagingIoResourceOffsetInFCB);

		// Save pointer to the old resource. It may be NULL.
		mPOldPagingIoResource = *mPPPagingIoResource;

		if (IsntNull(mPOldPagingIoResource))
		{
			// Create a new resource.
			error.err = ExInitializeResourceLite(&mNewPagingIoResource);

			if (error.HaveNonPGPError())
				error.pgpErr = kPGPError_SyncObjOpFailed;

			// Replace the old resource with the new resource.
			if (error.IsntError())
			{
				SafeReplaceResource(*mPPPagingIoResource, 
					&mNewPagingIoResource);
			}
		}

		ObDereferenceObject(fileObject);
	}

	return error;
}

void 
CFileImpDrvNT::RestorePagingIoResource()
{
	if (IsntNull(mPOldPagingIoResource))
	{
		// Put back the old resource.
		SafeReplaceResource(*mPPPagingIoResource, mPOldPagingIoResource);

		// Delete the new resource.
		ExDeleteResourceLite(&mNewPagingIoResource);

		mPPPagingIoResource = NULL;
		mPOldPagingIoResource = NULL;
	}
}

void 
CFileImpDrvNT::SafeReplaceResource(
	PERESOURCE&	pOldResource, 
	PERESOURCE	pNewResource)
{
	pgpAssertAddrValid(pOldResource, ERESOURCE);
	pgpAssertAddrValid(pNewResource, ERESOURCE);

	LARGE_INTEGER	shortWait	= RtlConvertLongToLargeInteger(0 - 
		static_cast<PGPInt32>(kReplaceResourceWaitIntervalMs * 
		PFLConstants::kHundredNsPerMs));

	while (TRUE)
	{
		// Acquire the old resource exclusive.
		ExAcquireResourceExclusiveLite(pOldResource, TRUE);

		// Go to dispatch level and check if there are waiters.
		KIRQL	oldIrql;
		KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);

		if ((ExGetExclusiveWaiterCount(pOldResource) == 0) && 
			ExGetSharedWaiterCount(pOldResource) == 0)
		{
			// There are no waiters, perform the replace.
			PERESOURCE	tempOldResource	= pOldResource;
			pOldResource = pNewResource;

			ExReleaseResourceForThreadLite(tempOldResource, 
				ExGetCurrentResourceThread());

			KeLowerIrql(oldIrql);

			break;
		}
		else
		{
			// There are waiters, release the exclusive lock and try again.
			ExReleaseResourceForThreadLite(pOldResource, 
				ExGetCurrentResourceThread());
			KeLowerIrql(oldIrql);

			// Let the waiters have a chance to finish.
			KeDelayExecutionThread(KernelMode, TRUE, &shortWait);
		}
	}
}

PGPBoolean 
CFileImpDrvNT::IsUNCPath(const char *path) const
{
	pgpAssertStrValid(path);

	if (!IsSlashChar(path[0]) || !IsSlashChar(path[1]))
		return FALSE;

	PGPUInt32	length		= strlen(path);
	PGPUInt32	numSlashes	= 0;

	for (PGPUInt32	i = 0; i < length; i++)
	{
		if (IsSlashChar(path[i]))
			numSlashes++;

		if (numSlashes >= 3)
			return TRUE;
	}

	return FALSE;
}

⌨️ 快捷键说明

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