📄 pgpmemorymgrwin32.c
字号:
{
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 + -