windows-nt/Source/XPSP1/NT/ds/security/tools/keytab2/opt/cleanup.c
2020-09-26 16:20:57 +08:00

258 lines
4 KiB
C

/*++
CLEANUP.C
CleanupOptionData code.
Created, 6/25/1997 when it was impossible to keep making myself believe
that I could go without allocating any memory in the option parser.
Now, if you care, you're supposed to call CleanupOptionData().
--*/
#include "private.h"
/* OptionDealloc:
same as free() right now. It should change if/when OptionAlloc
changes */
VOID
OptionDealloc( IN PVOID pTarget ) {
ASSERT( pTarget != NULL );
free ( pTarget );
}
BOOL
OptionAddToList( IN PVOID pQueue,
IN PVOID pItem,
IN DEALLOC_METHOD eDealloc) {
PSAVENODE pNode;
PSAVEQUEUE pList;
if ( !pQueue ) {
return TRUE; // vacuous
} else {
pList = (PSAVEQUEUE) pQueue;
}
if( OptionAlloc( NULL, &pNode, sizeof( SAVENODE ) ) ) {
pNode->DataElement = pItem;
pNode->DeallocMethod = eDealloc;
pNode->next = NULL;
if ( pList->FirstNode == NULL ) {
ASSERT( pList->LastNode == NULL );
pList->FirstNode = pNode;
} else {
pList->LastNode->next = pNode;
}
pList->LastNode = pNode;
return TRUE;
}
return FALSE;
}
BOOL
OptionResizeMemory( IN PVOID pSaveQueue,
OUT PVOID *ppResizedMemory,
IN ULONG newSize ) {
ASSERT( ppResizedMemory != NULL );
ASSERT( newSize > 0 );
// ASSERT( *ppResizedMemory != NULL ); // unuseful assertion.
if ( *ppResizedMemory ) {
PSAVENODE pNode = NULL;
PVOID pDataElement;
pDataElement = *ppResizedMemory;
if ( pSaveQueue ) {
PSAVEQUEUE pQ;
pQ = (PSAVEQUEUE) pSaveQueue;
for ( pNode = pQ->FirstNode ;
pNode != NULL;
pNode = pNode->next ) {
if ( pNode->DataElement == pDataElement ) {
break;
}
}
if ( !pNode ) {
return FALSE;
}
}
pDataElement = realloc( pDataElement, newSize ) ;
if ( pDataElement == NULL ) {
fprintf( stderr,
"OptionResizeMemory failed to realloc for %d bytes.\n",
newSize );
// allocation failed.
return FALSE;
} else {
*ppResizedMemory = pDataElement;
if ( pNode ) {
// must change this within the list as well.
pNode->DataElement = pDataElement;
}
return TRUE;
}
} else {
/* just like realloc, if you pass NULL, we'll just malloc the data
anyway. This is just more convenient. */
return OptionAlloc( pSaveQueue, ppResizedMemory, newSize );
}
}
/* OptionAlloc:
currently, malloc.
if you change the method of allocation, you must also change
OptionDealloc above */
BOOL
OptionAlloc( IN PSAVEQUEUE pQueue,
OUT PVOID *pTarget,
IN ULONG size ) {
PVOID ret;
ASSERT( pTarget != NULL );
ASSERT( size > 0 );
ret = malloc( size );
if ( ret ) {
memset( ret, 0, size );
if ( OptionAddToList( pQueue, ret, DeallocWithOptionDealloc ) ) {
*pTarget = ret;
return TRUE;
} else {
free( ret );
// fallthrough
}
}
*pTarget = NULL;
return FALSE;
}
VOID
CleanupOptionDataEx( IN PVOID pVoid ) {
ULONG i;
PSAVEQUEUE pQueue;
ASSERT( pVoid != NULL );
pQueue = ( PSAVEQUEUE ) pVoid;
if ( pQueue->FirstNode != NULL ) {
PSAVENODE p;
PSAVENODE q;
ASSERT( pQueue->LastNode != NULL );
OPTIONS_DEBUG( "CleanupOptionDataEx: Freelist is nonempty.\n" );
for ( p = pQueue->FirstNode ;
p != NULL ;
p = q ) {
q = p->next;
switch( p->DeallocMethod ) {
case DeallocWithFree:
free( p->DataElement );
break;
case DeallocWithLocalFree:
LocalFree( p->DataElement );
break;
case DeallocWithOptionDealloc:
OptionDealloc( p->DataElement );
break;
default:
ASSERT_NOTREACHED( "unknown dealloc flag. Bleah!" );
return;
}
OptionDealloc( p );
}
} else {
OPTIONS_DEBUG( "CleanupOptionDataEx: Freelist is empty.\n" );
ASSERT( pQueue->LastNode == NULL );
}
}