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

📄 pgpmemorymgrwin32.c

📁 vc环境下的pgp源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*____________________________________________________________________________
	Copyright (C) 1997 Network Associates Inc. and affiliated companies.
	All rights reserved.

	Win32-specific functions to plug into the PGPMemoryMgr:
		pgpCreateStandardMemoryMgr
		pgpDisposeStandardMemoryMgrUserValue
	
	$Id: pgpMemoryMgrWin32.c,v 1.13 1999/03/10 02:53:26 heller Exp $
____________________________________________________________________________*/
#include "pgpPFLErrors.h"
#include "pgpMem.h"

#include "pgpMemoryMgrPriv.h"



#define INTEGRITY_CHECKS		PGP_DEBUG

#if PGP_WIN32

#define WIN32_LEAN_AND_MEAN
#include <windows.h>

/* header containing device driver definitions */
#include "pgpMemLockWin32.h"



/* names of device drivers used for memory locking */
static const char	kPGPMemLockDriver95Name[] = "\\\\.\\PGPMemLock.vxd";
static const char	kPGPMemLockDriverNTName[] = "\\\\.\\PGPMEMLOCK";

#else

typedef void *	HANDLE;

#endif


/*____________________________________________________________________________
	[Secure memory only]
	
	kPageSize		page size suitable for VM allocation and locking
	kMinHeapSize	minimum size of heap we'll create
	kChunkSize		granularity of allocation and alignment value
					nothing smaller can be allocated and therefore,
					every allocation is aligned to this value.
	kMinLeftoverBytes	dont create a free block with fewer bytes than this
____________________________________________________________________________*/

#define kPageSize			( (PGPSize)4096 )
#define kMinHeapSizeBytes	( kPageSize * 2 )
#define kChunkSize			( 32 )
#define kMinLeftoverBytes	pgpMax( kChunkSize, sizeof( ChunkHeader ) )


/*____________________________________________________________________________
	[Secure memory only]
	
	Free space is linked together in a list in each heap.
	'numChunks' contains the total size of the block, in chunks, which
	includes the ChunkHeader itself.
____________________________________________________________________________*/
typedef struct ChunkHeader
{
	struct ChunkHeader *	next;
	struct ChunkHeader *	prev;
	PGPUInt32				numChunks;
} ChunkHeader;



/*____________________________________________________________________________
	[Secure memory only]
	
	A PageHeap keeps a memory heap on a contiguous range of pages.
	Free space is maintained in a free list; there is no overhead to
	allocated items other than our chunk size requirement.
____________________________________________________________________________*/
typedef struct PageHeap
{
	struct PageHeap *	next;
	struct PageHeap *	prev;
	
	HANDLE			hDriver;
	
	void *			pages;
	PGPUInt32		numPages;
	PGPBoolean		isNonPageable;
	
	PGPUInt32		numFreeChunks;
	
	ChunkHeader *	freeList;
} PageHeap;

/*____________________________________________________________________________
	[Secure memory only]
	
	A pointer to this struct is stored as the customValue of the MemoryMgr.
____________________________________________________________________________*/
typedef struct MyData
{
	/* handle of loaded driver; NULL=>no driver loaded */
	HANDLE		hDriver;
	
	PageHeap *	heapList;
	PageHeap *	lastHeapUsed;
} MyData;




static PageHeap *	sCreateHeap( HANDLE hDriver, PGPSize heapSize );
static void			sDisposeHeap( HANDLE hDriver, PageHeap *heap );

static PageHeap *	sCreateAndAddHeap( MyData * myData, PGPSize heapSize );
static void			sRemoveAndDisposeHeap( MyData *myData, PageHeap *heap );
static PGPBoolean	sHeapOwnsAllocation( PageHeap const *heap,
						void const *allocation );
static PGPBoolean	sHeapIsEmpty( PageHeap const *heap );

static void *	sAllocateBytes( MyData *myData,
					PGPSize requestSize, PGPBoolean *isNonPageable );
static void 	sFreeBytes( MyData *myData,
					void *allocation, PGPSize allocationSize );

static void *	sHeapAllocateChunks( PageHeap *heap,
					PGPUInt32 allocChunks, PGPBoolean *isNonPageable );
static void		sHeapFreeChunks( PageHeap *heap,
					void *ptr, PGPUInt32 numChunks );

#if INTEGRITY_CHECKS	/* [ */
static void		sHeapValidate( PageHeap const *heap );
#else
#define sHeapValidate( heap )		/* nothing */
#endif

static PGPError	sInitMyData( MyData *myData );
static PGPError	sCleanupMyData( MyData *myData );

static void		sLockMemory( HANDLE hDriver, void *mem, PGPSize numBytes,
					PGPBoolean *isNonPageable );
static void		sUnlockMemory( HANDLE hDriver, void *mem, PGPSize numBytes );



	static void *
sInternalAlloc( PGPSize numBytes )
{
	void *	result	= malloc( numBytes );
	
	if ( IsntNull( result ) )
	{
		pgpClearMemory( result, numBytes );
	}
	
	return( result );
}

	static void
sInternalFree( void *ptr )
{
	if ( IsntNull( ptr ) )
		free( ptr );
}


/*____________________________________________________________________________
	For non-secure memory allocation, we just use standard malloc/realloc/free
____________________________________________________________________________*/
	static void *
sWin32MemoryAllocationProc(
	PGPMemoryMgrRef		mgr,
	PGPUserValue		customValue,
	PGPSize 			allocationSize,
	PGPMemoryMgrFlags	flags )
{
	(void) mgr;
	(void) flags;
	(void) customValue;
	return( malloc( allocationSize ) );
}


	static PGPError
sWin32MemoryDeallocationProc(
	PGPMemoryMgrRef		mgr,
	PGPUserValue		customValue,
	void *				allocation,
	PGPSize				allocationSize )
{
	(void) mgr;
	(void) allocationSize;
	(void) customValue;
	free( allocation );
	return( kPGPError_NoErr );
}


	static PGPError
sWin32MemoryReallocationProc(
	PGPMemoryMgrRef		mgr,
	PGPUserValue		customValue,
	void **				allocation,
	PGPSize 			newAllocationSize,
	PGPMemoryMgrFlags	flags,
	PGPSize				existingSize )
{
	PGPError	err;
	void *		oldPtr	= *allocation;
	void *		newPtr	= NULL;
	
	(void) mgr;
	(void) flags;
	(void) existingSize;
	(void) customValue;

	newPtr = realloc( oldPtr, newAllocationSize );
	if ( IsNull( newPtr ) )
	{
		err	= kPGPError_OutOfMemory;
	}
	else
	{
		err	= kPGPError_NoErr;
		*allocation	= newPtr;
	}
	
	return( err );
}




/*____________________________________________________________________________
	Win32 version

	Under Win32 we can lock individual pages or ranges of pages by using
	APIs which are available only to device drivers.  In order to avoid any 
	potential problems derived from locking pages in the process heaps, 
	we restrict ourselves to locking pages which are directly assigned to
	us from the OS using the Win32 API function VirtualAlloc.  Using 
	VirtualAlloc we can obtain virtual pages of memory from our process's 
	private address space and which are outside the process heaps.  Also,
	VirtualAlloc gives us committed and page-aligned memory, two other 
	requirements for pagelocking.

	Memory is allocated with a granularity of 4K bytes (the page size
	in Win32).
____________________________________________________________________________*/
	static void *
sWin32SecureMemoryAllocationProc(
	PGPMemoryMgrRef		mgr,
	PGPUserValue 		customValue,
	PGPSize 			allocationSize,
	PGPMemoryMgrFlags	flags,
	PGPBoolean *		isNonPageable )
{
	void *		result;
	MyData *	myData	= (MyData *)customValue;
	
	(void) mgr;
	(void) flags;

	*isNonPageable	= FALSE;
	
	result	= sAllocateBytes( myData, allocationSize, isNonPageable );
	
	return( result );
}


/*____________________________________________________________________________
	Win32 secure memory deallocator.
____________________________________________________________________________*/
	static PGPError
sWin32SecureMemoryDeallocationProc(
	PGPMemoryMgrRef	mgr,
	PGPUserValue 	customValue,
	void *			allocation,
	PGPSize			allocationSize,
	PGPBoolean		nonPageable)
{
	MyData *	myData	= (MyData *)customValue;

	(void) mgr;
	(void) allocationSize;
	(void) nonPageable;

	sFreeBytes( myData, allocation, allocationSize );
	
	return( kPGPError_NoErr );
}






	static HANDLE
sGetMyDriver( void )
{

	HANDLE			hDriver	= NULL;
#if PGP_WIN32
	OSVERSIONINFO	osid;

	osid.dwOSVersionInfoSize = sizeof ( osid );
	GetVersionEx ( &osid );

	/*	load correct memory-locking driver on basis of which 
		OS we're running under	*/
	switch ( osid.dwPlatformId ) {

		/* Windows 95 */
		case VER_PLATFORM_WIN32_WINDOWS :
			hDriver = 
				CreateFile (	kPGPMemLockDriver95Name, 
								GENERIC_READ | GENERIC_WRITE, 
								0, 
								NULL, 
								OPEN_EXISTING, 
								FILE_FLAG_DELETE_ON_CLOSE, 
								NULL );
//			pgpFixBeforeShip ("Need to do something if driver load fails");
///				pgpAssertMsg ( hDriver != INVALID_HANDLE_VALUE,
///							  "Could not load page-locking driver" ); 
			if ( hDriver == INVALID_HANDLE_VALUE ) 
			{
				hDriver = NULL;
			}
			break;

		/* Windows NT */
		case VER_PLATFORM_WIN32_NT :
			hDriver = 
				CreateFile (	kPGPMemLockDriverNTName,
								GENERIC_READ | GENERIC_WRITE,
								0,
								NULL,
								OPEN_EXISTING,
								FILE_ATTRIBUTE_NORMAL,
								NULL );
//			pgpFixBeforeShip ("Need to do something if driver load fails");
///				pgpAssertMsg ( hDriver != INVALID_HANDLE_VALUE,
///							  "Could not load page-locking driver" ); 
			if ( hDriver == INVALID_HANDLE_VALUE ) 
			{
				hDriver = NULL;
			}
			break;

		/* all other OSes */
		default :
			pgpDebugMsg( "unknown platform" );
			break;	
	}
#endif

	return( hDriver );
}


/*____________________________________________________________________________
	Initialize MyData data structure.  It has already been allocated.
____________________________________________________________________________*/
	static PGPError
sInitMyData( MyData *myData )
{
	PGPError		err		= kPGPError_NoErr;

	PGPValidatePtr( myData );
	
	myData->hDriver	= sGetMyDriver();
	myData->heapList		= NULL;
	myData->lastHeapUsed	= NULL;

	return err;
}


/*____________________________________________________________________________
	Dispose MyData data structure contents and free it.
____________________________________________________________________________*/
	static PGPError
sCleanupMyData( MyData *myData )
{
	PageHeap *	heap	= NULL;
	
	pgpAssertMsg( IsNull( myData->heapList ),
		"sCleanupMyData(): WARNING: secure memory is being leaked" );

	while ( IsntNull( myData->heapList ) )
	{
		sRemoveAndDisposeHeap( myData, myData->heapList );
	}
	
#if PGP_WIN32
	if ( myData->hDriver != NULL ) 
	{
		CloseHandle ( myData->hDriver );
		myData->hDriver = NULL;
	}
#endif

	sInternalFree( myData );

	return kPGPError_NoErr;
}




	PGPError
pgpCreateStandardMemoryMgr( PGPMemoryMgrRef *newMemoryMgr )
{
	PGPError				err	= kPGPError_NoErr;
	MyData *				pmyData	= NULL;
	
	PGPValidatePtr( newMemoryMgr );
	*newMemoryMgr	= NULL;
	
	/* allocate private data which we will store as the customValue */
	pmyData	= (MyData *)sInternalAlloc( sizeof( MyData ) );
	if ( IsntNull( pmyData ) )
	{
		PGPNewMemoryMgrStruct	custom;
		
		pgpClearMemory( pmyData, sizeof( MyData ) );
		err	= sInitMyData( pmyData );
		if ( IsntPGPError( err ) )
		{
			pgpClearMemory( &custom, sizeof( custom ) );
		
			custom.customValue	= (PGPUserValue)pmyData;
			
			custom.sizeofStruct		= sizeof( custom );
			custom.allocProc		= sWin32MemoryAllocationProc;
			custom.reallocProc		= sWin32MemoryReallocationProc;
			custom.deallocProc		= sWin32MemoryDeallocationProc;
			
			custom.secureAllocProc		= sWin32SecureMemoryAllocationProc;
			custom.secureDeallocProc	= sWin32SecureMemoryDeallocationProc;
			
			err	= PGPNewMemoryMgrCustom( &custom, newMemoryMgr );
			if ( IsPGPError( err ) )
			{
				sCleanupMyData( pmyData );
			}
		}
		
		if ( IsPGPError( err ) )
		{
			/* creation failed...dispose our private data */
			sInternalFree( pmyData );
		}
	}
	else
	{
		err	= kPGPError_OutOfMemory;
	}
	
	return( err );
}



	PGPError
pgpDisposeStandardMemoryMgrUserValue( PGPUserValue customValue )
{
	MyData *	pmyData	= (MyData *)customValue;
	
	sCleanupMyData( pmyData );
	
	return( kPGPError_NoErr );
}



/*____________________________________________________________________________
	Allocate a page of memory from the VM system and make it non-pageable
	if possible.
____________________________________________________________________________*/
	static void *
sAllocatePages(
	HANDLE			hDriver,	/* may be NULL */
	PGPUInt32		numPages,
	PGPBoolean *	isNonPageable )
{
	void *	result	= NULL;
	
	pgpAssert( IsntNull( isNonPageable ) );
	
	*isNonPageable	= FALSE;
	
#if PGP_WIN32
	/* since the first parameter to VirtualAlloc is NULL, it automatically 
	   rounds allocation size up to next page boundary */
	result = VirtualAlloc ( NULL,
				numPages * kPageSize, MEM_COMMIT, PAGE_READWRITE );
	
	if ( IsntNull( result ) )
	{
		sLockMemory( hDriver, result, numPages * kPageSize, isNonPageable );
	}
#else
	(void)hDriver;
	result	= sInternalAlloc( numPages * kPageSize );
#endif
	
	return( result );
}


/*____________________________________________________________________________
	Free pages allocated with sAllocatePages()
____________________________________________________________________________*/
	static void
sFreePages(
	HANDLE		hDriver,	/* may be NULL */
	void *		pages,
	PGPUInt32	numPages,
	PGPBoolean	nonPageable )
{
#if PGP_WIN32
	/* we can assume it has already been safely cleared  */
	if ( nonPageable )
	{
		sUnlockMemory( hDriver, pages, numPages * kPageSize );
	}
	
	VirtualFree( pages, 0, MEM_RELEASE );
#else
	(void)hDriver;
	(void)numPages;
	(void)nonPageable;
	sInternalFree( (Ptr)pages );
#endif
}


/*____________________________________________________________________________
	Create a heap of the specified size.
____________________________________________________________________________*/
	static PageHeap *
sCreateHeap(
	HANDLE		hDriver,
	PGPSize		heapSize)
{
	PGPError	err	= kPGPError_NoErr;
	PageHeap *	heap	= NULL;
	PGPUInt32	numPages;
	PGPUInt32	numChunks;
	
	numPages	= heapSize / kPageSize;
	if ( ( heapSize % kPageSize ) != 0 )
		numPages	+= 1;
	
	numChunks	= ( numPages * kPageSize ) / kChunkSize;
	
	heap	= (PageHeap *)sInternalAlloc( sizeof( *heap ) );
	if ( IsntNull( heap ) )
	{
		heap->hDriver		= hDriver;
		heap->numPages		= numPages;
		heap->numFreeChunks	= numChunks;
		
		heap->pages	= sAllocatePages( hDriver,
						numPages, &heap->isNonPageable );
		if ( IsntNull( heap->pages ) )
		{
			ChunkHeader *	chunkHeader	= (ChunkHeader *)heap->pages;
			
			chunkHeader->next		= NULL;
			chunkHeader->prev		= NULL;
			chunkHeader->numChunks	= numChunks;
			heap->freeList	= chunkHeader;
		}
		else

⌨️ 快捷键说明

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