|
|
/**********************************************************************/ /** Microsoft Windows/NT **/ /** Copyright(c) Microsoft Corp., 1991-1996 **/ /**********************************************************************/
/*
buffer.cxx Implementation of the BUFFER class.
FILE HISTORY: MuraliK 3-July-1996 Rewrote the buffer class */
#include "precomp.hxx"
#include <buffer.hxx>
#include "dbgutil.h"
#include <auxctrs.h>
#include <irtlmisc.h>
LONG g_SBAuxCounters[NUM_AUX_COUNTERS];
BUFFER::~BUFFER(void) { if ( IsDynAlloced()) { /* INTRINSA suppress = all */ ::IisFree( m_pb ); } }
/*******************************************************************
NAME: BUFFER::GetNewStorage
SYNOPSIS: Given an object with no allocated storage, allocate the initial memory.
ENTRY: cbRequested - amount of storage requested in bytes
EXIT: Either storage alloc'd, or error reported Sets m_cb, m_pb and m_fIsDynAlloced
RETURNS: TRUE if successful, FALSE for GetLastError()
NOTES: Private member function.
********************************************************************/
BOOL BUFFER::GetNewStorage( UINT cbRequested ) { AcIncrement( CacBufferAllocs);
if ( cbRequested <= m_cb) {
return TRUE; }
DBG_ASSERT( !IsDynAlloced()); // otherwise I should free up the block :(
m_pb = (BYTE*) ::IisMalloc( cbRequested );
if ( !m_pb ) { SetLastError( ERROR_NOT_ENOUGH_MEMORY ); } else { m_pb[0] = '\0'; // just store null
m_cb = cbRequested; m_fIsDynAlloced = 1; }
return (m_pb != NULL); } // BUFFER::GetNewStorage()
/*******************************************************************
NAME: BUFFER::ReallocStorage
SYNOPSIS: Do a "hard" reallocation to the new size
ENTRY: cbNewRequested - new size, in bytes
EXIT: Storage realloc'd. m_pb, m_cb, m_fIsDynAlloced changed
RETURNS: TRUE if successful, FALSE for GetLastError()
********************************************************************/
BOOL BUFFER::ReallocStorage( UINT cbNewRequested ) { if ( cbNewRequested <= m_cb) {
return (TRUE); }
BYTE* pb = (BYTE*) ((IsDynAlloced()) ? (::IisReAlloc(m_pb, cbNewRequested)) : (::IisMalloc(cbNewRequested)) );
AcIncrement( CacBufferReallocs);
if (pb == NULL) { SetLastError( ERROR_NOT_ENOUGH_MEMORY ); return FALSE; }
if ( !IsDynAlloced()) { // First time this block is allocated. Copy over old contents.
CopyMemory( pb, m_pb, m_cb); m_fIsDynAlloced = 1; }
m_pb = pb; m_cb = cbNewRequested;
DBG_ASSERT( m_pb != NULL );
return TRUE; } // BUFFER::ReallocStorage()
/*******************************************************************
NAME: BUFFER::VerifyState
SYNOPSIS: Verifies the state of the object. Asserts out if the state is invalid, i.e. if an internal error took place.
NOTES: This function does nothing in the retail version.
********************************************************************/
VOID BUFFER::VerifyState() const { //
// 1. If Dynamically Allocated ==>
// m_pb points to something other than m_rgb &
// m_cb > INLINED_BUFFER_LEN
// 2. If not Dynamicall Allocated ==>
// (a) it can be using user-supplied buffer & any sized
// (b) it can be using inlined buffer & m_cb == INLINED_BUFFER_LEN
//
DBG_ASSERT(( IsDynAlloced() && (m_pb != m_rgb) && (m_cb > INLINED_BUFFER_LEN)) || ( !IsDynAlloced() && ( m_pb != m_rgb || m_cb == INLINED_BUFFER_LEN) ) );
} // BUFFER::VerifyState()
/*******************************************************************
NAME: BUFFER::FreeMemory
SYNOPSIS: Frees the heap memory associated with this buffer object
********************************************************************/
VOID BUFFER::FreeMemory( VOID ) { if ( IsDynAlloced()) { ::IisFree( m_pb ); m_pb = m_rgb; m_cb = INLINED_BUFFER_LEN; m_fIsDynAlloced = 0; }
m_rgb[0] = '\0'; // reset the contents
}
BOOL BUFFER_CHAIN::AppendBuffer( BUFFER_CHAIN_ITEM * pBCI ) /*++
Routine Description:
Adds a new buffer chain item to the end of the buffer chain
Arguments:
pBCI - Chain item to append
Return Value:
TRUE if successful, FALSE on error
--*/ { DBG_ASSERT( pBCI ); DBG_ASSERT( pBCI->_ListEntry.Flink == NULL );
InsertTailList( &_ListHead, &pBCI->_ListEntry );
return TRUE; }
DWORD BUFFER_CHAIN::DeleteChain( VOID ) /*++
Routine Description:
Deletes all of the buffers in this chain
Return Value:
Total number of allocated bytes freed by this call
--*/ { BUFFER_CHAIN_ITEM * pBCI; DWORD cbFreed = 0;
while ( !IsListEmpty( &_ListHead )) { pBCI = CONTAINING_RECORD( _ListHead.Flink, BUFFER_CHAIN_ITEM, _ListEntry );
DBG_ASSERT( pBCI->_ListEntry.Flink != NULL );
RemoveEntryList( &pBCI->_ListEntry );
cbFreed += pBCI->QuerySize();
delete pBCI; }
return cbFreed; }
BUFFER_CHAIN_ITEM * BUFFER_CHAIN::NextBuffer( BUFFER_CHAIN_ITEM * pBCI ) /*++
Routine Description:
Returns the next buffer in the chain. Start the enumeration by passing pBCI as NULL. Continue it by passing the return value
Arguments:
pBCI - Previous item in enumeration
Return Value:
Pointer to next item in chain, NULL when done
--*/ { if ( pBCI != NULL ) { if ( pBCI->_ListEntry.Flink != &_ListHead ) { return CONTAINING_RECORD( pBCI->_ListEntry.Flink, BUFFER_CHAIN_ITEM, _ListEntry ); } else { return NULL; } }
if ( !IsListEmpty( &_ListHead )) { return CONTAINING_RECORD( _ListHead.Flink, BUFFER_CHAIN_ITEM, _ListEntry ); }
return NULL; }
DWORD BUFFER_CHAIN::CalcTotalSize( BOOL fUsed ) const /*++
Routine Description:
Returns the total amount of memory allocated by this buffer chain excluding the size of the structures themselves
Arguments:
fUsed - If FALSE, returns total allocated by chain, if TRUE returns total used by chain
Return Value:
Total bytes allocated or total bytes used
--*/ { LIST_ENTRY * pEntry; BUFFER_CHAIN_ITEM * pBCI; DWORD cbRet = 0;
for ( pEntry = _ListHead.Flink; pEntry != &_ListHead; pEntry = pEntry->Flink ) { pBCI = CONTAINING_RECORD( pEntry, BUFFER_CHAIN_ITEM, _ListEntry );
if ( fUsed == FALSE ) cbRet += pBCI->QuerySize(); else cbRet += pBCI->QueryUsed(); }
return cbRet; }
/***************************** End Of File ******************************/
|