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

📄 pgpmemorymgrwin32.c

📁 vc环境下的pgp源码
💻 C
📖 第 1 页 / 共 2 页
字号:
		{
			sInternalFree( heap );
			heap	= NULL;
			err	= kPGPError_OutOfMemory;
		}
	}
	
	return( heap );
}


/*____________________________________________________________________________
	Dispose the heap, releasing all the memory it references.
____________________________________________________________________________*/
	static void
sDisposeHeap(
	HANDLE		hDriver,
	PageHeap *	heap )
{
	/* free chunks better be all of them... */
	pgpAssert( IsntNull( heap ) &&
		( heap->numPages * kPageSize ) / kChunkSize );
	
	sFreePages( hDriver, heap->pages, heap->numPages, heap->isNonPageable );
	
	sInternalFree( heap );
}


	static PageHeap *
sCreateAndAddHeap(
	MyData *	myData,
	PGPSize		heapSize )
{
	PGPError	err	= kPGPError_NoErr;
	PageHeap *	heap	= NULL;
	
	pgpAssert( ( heapSize % kPageSize ) == 0 );
		
	heap	= sCreateHeap( myData->hDriver, heapSize);
	if ( IsntNull( heap ) )
	{
		heap->prev	= NULL;
		heap->next	= NULL;
			
		if ( IsNull( myData->heapList ) )
		{
			myData->heapList	= heap;
		}
		else
		{
			heap->next	= myData->heapList;
			myData->heapList->prev	= heap;
			myData->heapList		= heap;
		}
		sHeapValidate( heap );
	}
	
	return( heap );
}


	static void
sRemoveAndDisposeHeap(
	MyData *	myData,
	PageHeap *	heap )
{
	PageHeap *	next;
	
	if ( heap == myData->lastHeapUsed )
		myData->lastHeapUsed	= NULL;
		
	sHeapValidate( heap );
	
	next	= heap->next;
	
	if ( heap == myData->heapList )
	{
		myData->heapList	= next;
	}

	if ( IsntNull( heap->prev ) )
	{
		heap->prev->next	= heap->next;
	}
	if ( IsntNull( heap->next ) )
	{
		heap->next->prev	= heap->prev;
	}
	
	sDisposeHeap( myData->hDriver, heap );
}


	static void *
sAllocateChunksFromExistingHeaps(
	MyData *		myData,
	PGPSize			allocChunks,
	PGPBoolean *	isNonPageable )
{
	void *		alloc	= NULL;
	PageHeap *	heap	= NULL;
	
	heap	= myData->lastHeapUsed;
	if ( IsntNull( heap ) )
	{
		alloc	= sHeapAllocateChunks( heap, allocChunks, isNonPageable);
	}
	
	if ( IsNull( alloc ) )
	{
		heap	= myData->heapList;
		while ( IsntNull( heap ) )
		{
			if ( heap->numFreeChunks >= allocChunks )
			{
				alloc	= sHeapAllocateChunks( heap,
							allocChunks,isNonPageable );
				if ( IsntNull( alloc ) )
				{
					break;
				}
			}
			heap	= heap->next;
		}
	}
	
	myData->lastHeapUsed	= heap;
	
	return( alloc );
}

	static PGPSize
sSizeToChunks( PGPSize allocationSize )
{
	PGPSize	allocChunks;
	
	allocChunks	= allocationSize / kChunkSize;
	if ( (allocationSize % kChunkSize) != 0 )
		++allocChunks;
	return( allocChunks );
}

	static void *
sAllocateBytes(
	MyData *		myData,
	PGPSize			requestSize,
	PGPBoolean *	isNonPageable )
{
	void *		alloc	= NULL;
	PGPUInt32	allocChunks;
	
	pgpAssert( IsntNull( isNonPageable ) );
	
	*isNonPageable	= FALSE;
	
	allocChunks	= sSizeToChunks( requestSize );
	
	alloc = sAllocateChunksFromExistingHeaps( myData, allocChunks,
				isNonPageable );
	if ( IsNull( alloc ) )
	{
		PGPSize		heapSize;
		PageHeap *	heap	= NULL;
		
		/* make heap size meet minimum & be multiple of page size */
		heapSize	= allocChunks * kChunkSize;
		if ( heapSize < kMinHeapSizeBytes )
			heapSize	= kMinHeapSizeBytes;
		if ( ( heapSize % kPageSize ) != 0 )
			heapSize	+= kPageSize - (heapSize % kPageSize);

		heap	= sCreateAndAddHeap( myData, heapSize );
		if ( IsntNull( heap ) )
		{
			alloc	= sHeapAllocateChunks( heap, allocChunks, isNonPageable);
		}
	}
	
	return( alloc );
}
					
	
	static PGPBoolean
sHeapOwnsAllocation(
	PageHeap const *	heap,
	void const *		allocation )
{
	PGPBoolean	ownsIt	= FALSE;
	
	if ( allocation >= heap->pages )
	{
		void *last;
	
		last	= (char *)heap->pages + ( (heap->numPages * kPageSize) -1 );
		if ( allocation <= last )
			ownsIt	= TRUE;
	}
	
	return( ownsIt );
}

	
	static PGPBoolean
sHeapIsEmpty( PageHeap const *	heap)
{
	PGPSize	numChunks	= (heap->numPages * kPageSize ) / kChunkSize;
	
	return( heap->numFreeChunks == numChunks );
}


	static void
sFreeBytes(
	MyData *		myData,
	void *			allocation,
	PGPSize			allocationSize )
{
	PageHeap *	heap;
	PGPSize		allocChunks;
	
	allocChunks	= sSizeToChunks( allocationSize );
	
	heap	= myData->heapList;
	while ( IsntNull( heap ) )
	{
		sHeapValidate( heap );
		
		if ( sHeapOwnsAllocation( heap, allocation ) )
		{
			sHeapFreeChunks( heap, allocation, allocChunks );
			
			if ( sHeapIsEmpty( heap ) )
			{
				sRemoveAndDisposeHeap( myData, heap );
			}
			break;
		}
		heap	= heap->next;
	}
}


	static void *
sHeapAllocateChunks(
	PageHeap *		heap,
	PGPUInt32 		allocChunks,
	PGPBoolean *	isNonPageable )
{
	void *			result	= NULL;
	ChunkHeader *	chunk	= NULL;
	
	pgpAssert( IsntNull( isNonPageable ) );
	*isNonPageable	= FALSE;
	
	sHeapValidate( heap );
	
	chunk	= heap->freeList;
	while ( IsntNull( chunk ) )
	{
		if ( chunk->numChunks >= allocChunks )
		{
			ChunkHeader *	remainder;
			PGPUInt32		leftoverChunks;
			PGPUInt32		actualChunksUsed	= 0;
			
			result	= (void *)chunk;
			
			remainder	= (ChunkHeader *)
							((char *)chunk + (allocChunks * kChunkSize ));
			leftoverChunks	= chunk->numChunks - allocChunks;
			
			if ( leftoverChunks != 0 &&
					(leftoverChunks * kChunkSize >= kMinLeftoverBytes) )
			{
				actualChunksUsed	= allocChunks;
				
				remainder->numChunks	= leftoverChunks;
				remainder->next			= chunk->next;
				remainder->prev			= chunk->prev;
				
				/* need to make a new chunk out of leftover */
				if ( chunk == heap->freeList )
				{
					heap->freeList	= remainder;
				}
				else
				{
					chunk->prev->next	= chunk->next;
				}
				if ( IsntNull( remainder->next ) )
					remainder->next->prev	= remainder;
				if ( IsntNull( remainder->prev ) )
					remainder->prev->next	= remainder;
			}
			else
			{
				actualChunksUsed	= allocChunks + leftoverChunks;
				
				/* remove the chunk from the list */
				if ( chunk == heap->freeList )
				{
					heap->freeList	= chunk->next;
				}
				else
				{
					chunk->prev->next	= chunk->next;
				}
				if ( IsntNull( chunk->next ) )
					chunk->next->prev	= chunk->prev;
			}
			
			heap->numFreeChunks	-= actualChunksUsed;
			
			*isNonPageable	= heap->isNonPageable;
			break;
		}
		chunk	= chunk->next;
	}
	
	sHeapValidate( heap );
	
	return( result );
}


	static PGPBoolean
sChunksAreAdjacent( ChunkHeader const * chunkHeader )
{
	ChunkHeader const *	next	= NULL;
	PGPSize		chunkBytes;
	
	pgpAssert( IsntNull( chunkHeader ) );
	next	= chunkHeader->next;
	if ( IsNull( next ) )
		return( FALSE );
	
	chunkBytes	= chunkHeader->numChunks * kChunkSize;
	
	return( (char *)chunkHeader + chunkBytes == (char *)next );
}

	static void
sMergeChunks( ChunkHeader *chunkHeader )
{
	ChunkHeader *	next	= chunkHeader->next;
	
	pgpAssert( sChunksAreAdjacent( chunkHeader ) );
	
	chunkHeader->numChunks	+= next->numChunks;
	if ( IsntNull( next->next ) )
		next->next->prev	= chunkHeader;
	chunkHeader->next	= next->next;
}

	static void
sMergeFree( ChunkHeader *chunkHeader )
{
	ChunkHeader *	prev	= NULL;
	
	pgpAssert( IsntNull( chunkHeader ) );
	
	if ( sChunksAreAdjacent( chunkHeader ) )
	{
		sMergeChunks( chunkHeader );
	}
	prev	= chunkHeader->prev;
	if ( IsntNull( prev ) && sChunksAreAdjacent( prev ) )
	{
		sMergeChunks( prev );
		chunkHeader	= NULL;
	}
}

/*____________________________________________________________________________
	Free an allocation within a heap of specified size.
____________________________________________________________________________*/
	static void
sHeapFreeChunks(
	PageHeap *	heap,
	void *		allocation,
	PGPUInt32 	allocChunks )
{
	ChunkHeader *	chunkHeader;
	ChunkHeader *	cur;
	ChunkHeader *	preceeding	= NULL;
	
	pgpAssert( sHeapOwnsAllocation( heap, allocation ) );
	
	sHeapValidate( heap );
	
	heap->numFreeChunks	+= allocChunks;
	
	chunkHeader	= (ChunkHeader *)allocation;
	chunkHeader->numChunks	= allocChunks;
	
	/* find the first chunk which precedes this one */
	cur	= heap->freeList;
	while ( IsntNull( cur ) )
	{
		if ( chunkHeader < cur )
		{
			preceeding	= cur->prev;
			break;
		}
		cur	= cur->next;
	}
	
	if ( IsNull( preceeding ) )
	{
		chunkHeader->next	= heap->freeList;
		chunkHeader->prev	= NULL;
		if ( IsntNull( chunkHeader->next ) )
			chunkHeader->next->prev	= chunkHeader;
		heap->freeList		= chunkHeader;
	}
	else
	{
		chunkHeader->prev	= preceeding;
		chunkHeader->next	= preceeding->next;
		if ( IsntNull( preceeding->next ) )
			preceeding->next->prev	= chunkHeader;
		preceeding->next	= chunkHeader;
	}
	
	sMergeFree( chunkHeader );
	
	sHeapValidate( heap );
}


#if INTEGRITY_CHECKS	/* [ */
	static void
sHeapValidate( PageHeap const *	heap )
{
	ChunkHeader *	cur;
	PGPSize			freeChunks	= 0;
	
	/* verify that free chunks match count in heap */
	cur	= heap->freeList;
	while ( IsntNull( cur ) )
	{
		pgpAssert( cur->numChunks != 0 );
		freeChunks	+= cur->numChunks;
		
		/* verify next item points back at cur */
		if ( IsntNull( cur->next ) )
		{
			pgpAssert( cur->next->prev == cur );
		}
		cur	= cur->next;
	}
	pgpAssert( heap->numFreeChunks == freeChunks );
}
#endif	/* ] */


#if PGP_WIN32	/* [ */
					
/*____________________________________________________________________________
	Win32 version of sLockMemory()

	Win32 supports locking of pages into memory only by using
	special purpose drivers (VxD under Win95, kernel mode driver
	under WinNT).  Note, the current driver implementations take
	the virtual (linear) address to lock and the number of bytes.
	This memory must have been allocated on a page-boundary and 
	committed using the Win32 API function VirtualAlloc (see routine
	sNewSecureDataHeader).

	Here we attempt to use such drivers if they have been successfully
	loaded (if the handle is non-NULL).  In this case, the return
	codes from the DeviceIoControl call and the driver are used to 
	ascertain if the lock was successful.

	If the driver has not been loaded, we revert back to the "old" 
	method of calling the Win32 APIs "VirtualLock" and "VirtualUnlock".
	Under Windows95 these functions do absolutely nothing.  
	Under WindowsNT they prevent the specified memory range from being 
	paged to disk *while this process is executing*.  When all threads 
	of this process become pre-empted, the OS is free to page whatever 
	it wants (including "VirtualLock-ed" memory) to disk.

	Assign a value of "TRUE" to 'isNonPageable' only if we have
	a valid driver loaded and the driver successfully locks the page
	in memory. 
____________________________________________________________________________*/

	static void
sLockMemory(
	HANDLE			hDriver,
	void *			mem,
	PGPSize			numBytes,
	PGPBoolean *	isNonPageable )
{
	PGPMEMLOCKSTRUCT	mls;
	DWORD				dw;
	BOOL				bDIOreturn;

	pgpAssert( IsntNull( isNonPageable ) );
	*isNonPageable	= FALSE;
 
	if ( IsntNull( hDriver ) ) 
	{
		mls.pMem = mem;
		mls.ulNumBytes = numBytes;
		bDIOreturn = DeviceIoControl(	hDriver, 
										IOCTL_PGPMEMLOCK_LOCK_MEMORY, 
										&mls, 
										sizeof( mls ), 
										&mls, 
										sizeof( mls ), 
										&dw, 
										NULL );
		pgpAssertMsg ( bDIOreturn, "DIOC error from page-locking driver" );
		if ( bDIOreturn )
		{
			pgpAssertMsg ( mls.ulError == 0, 
						  "Internal error in page-locking driver" );

			if ( mls.ulError == 0 ) 
			{
				*isNonPageable	= TRUE;
			}		
		}
	}
	else 
	{
	 	VirtualLock ( mem, numBytes );	/* call for good measure*/
	}
}


	static void
sUnlockMemory(
	HANDLE		hDriver,
	void *		mem,
	PGPSize		numBytes )
{
	PGPMEMLOCKSTRUCT	mls;
	DWORD				dw;
	BOOL				bDIOreturn;

	if ( IsntNull( hDriver ) )
	{
		mls.pMem = mem;
		mls.ulNumBytes = numBytes;
		bDIOreturn = DeviceIoControl(	hDriver, 
										IOCTL_PGPMEMLOCK_UNLOCK_MEMORY, 
										&mls, 
										sizeof( mls ), 
										&mls, 
										sizeof( mls ), 
										&dw, 
										NULL );
		pgpAssertMsg ( bDIOreturn, "DIOC error from page-locking driver" );
		if ( bDIOreturn )
		{
			pgpAssertMsg ( mls.ulError == 0, 
						  "Internal error in page-locking driver" );
		}
	}
	else 
	{
	 	VirtualUnlock ( mem, numBytes );	/* call for good measure*/
	}
}

#endif	/* ] PGP_WIN32 */

/*__Editor_settings____

	Local Variables:
	tab-width: 4
	End:
	vi: ts=4 sw=4
	vim: si
_____________________*/

⌨️ 快捷键说明

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