mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
351 lines
7.3 KiB
351 lines
7.3 KiB
/**********************************************************************/
|
|
/** 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 ******************************/
|