windows-nt/Source/XPSP1/NT/admin/wmi/wbem/adapters/oledb/extbuff.cpp
2020-09-26 16:20:57 +08:00

200 lines
6.7 KiB
C++

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Microsoft WMIOLE DB Provider
// (C) Copyright 1999 Microsoft Corporation. All Rights Reserved.
//
// This class provides an array-based access to a big block of memory. You pass in the fixed size of each element
// to the constructor.
// Get (read) an element with GetItemOfExtBuffer.
// Set (write) an element with InsertIntoExtBuffer.
// You must also pass in the system page size (found with GetSystemInfo). 'hItem' is the index into the array,
// beginning with 1. The array always contains m_cItem elements.
//
// GetItemOfExtBuffer returns element hItem, where hItem=1 is the first element.
// (Copies block to caller's memory.)
//
// InsertIntoExtBuffer always appends elements to the tail of the array,
// and returns the index of the newly appended element.
// (So adding first element will return 1.)
//
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "headers.h"
#include "extbuff.h"
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Constructor for this class
//
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CExtBuffer::CExtBuffer ( void )
{
m_cItem = 0;
m_cbAlloc = 0;
m_rgItem = NULL;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Destructor for this class
//
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
CExtBuffer:: ~CExtBuffer ( void )
{
if (m_cbAlloc){
VirtualFree((VOID *) m_rgItem, m_cbAlloc, MEM_DECOMMIT );
}
if (m_rgItem){
VirtualFree((VOID *) m_rgItem, 0, MEM_RELEASE );
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Allocate and Initialize Buffer
//
// HRESULT indicating routines status
// S_OK Initialization succeeded
// E_OUTOFMEMORY Not enough memory to allocate buffer
//
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CExtBuffer::FInit ( ULONG cItemMax, // IN Maximum number of items ever
ULONG cbItem, // IN Size of each item, in bytes
ULONG cbPage ) // IN Size of system page size (from SysInfo)
{
BYTE *pb=NULL;
HRESULT hr = S_OK;
m_cbReserved = ((cbItem *cItemMax) / cbPage + 1) *cbPage;
m_rgItem = (BYTE *) VirtualAlloc( NULL, m_cbReserved, MEM_RESERVE, PAGE_READWRITE );
if (m_rgItem == NULL){
hr = E_OUTOFMEMORY;
}
else{
m_cbItem = cbItem;
m_dbAlloc = (cbItem / cbPage + 1) *cbPage;
pb = (BYTE *) VirtualAlloc( m_rgItem, m_dbAlloc, MEM_COMMIT, PAGE_READWRITE );
if (pb == NULL){
VirtualFree((VOID *) m_rgItem, 0, MEM_RELEASE );
m_rgItem = NULL;
hr = E_OUTOFMEMORY;
}
else{
m_cbAlloc = m_dbAlloc;
}
}
return hr;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Retrieves a pointer to the value at given index
//
// If index is within the range of 1 to m_cItems then a valid pointer is returned, else NULL is returned.
//
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void* CExtBuffer::operator[] ( ULONG hItem ) // IN Index of element in buffer
{
//====================================================================
// Return ptr to element [n], where n = 1...m_cItem.
// Returns NULL if 'n' is out of range.
//
// You must use InsertIntoExtBuffer to add new elements.
// Thereafter you can use this operator to retrieve the address of the item.
// (You can't delete an element, but you can overwrite its space.)
//====================================================================
if (1 <= hItem && hItem <= m_cItem)
return m_rgItem + (hItem - 1) *m_cbItem;
else
return NULL;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Add Data to the fixed buffers and return the index it was added at.
//
// HRESULT indicating routines status
// S_OK Data copied successfully
// E_OUTOFMEMORY Not enough memory to allocate buffer
//
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CExtBuffer::InsertIntoExtBuffer ( VOID* pvItem, // IN Pointer to buffer to copy
ULONG &hItem ) // OUT Index of where data was placed
{
HRESULT hr = S_OK;
ULONG cbOffset;
cbOffset = m_cItem*m_cbItem;
if ((cbOffset + m_cbItem) > m_cbAlloc){
BYTE *pb;
if ((m_cbAlloc + m_dbAlloc) > m_cbReserved){
pb = NULL;
}
else{
pb = (BYTE *) VirtualAlloc( m_rgItem + m_cbAlloc, m_dbAlloc, MEM_COMMIT, PAGE_READWRITE );
}
if (pb == NULL){
hr = E_OUTOFMEMORY;
}
else{
m_cbAlloc += m_dbAlloc;
}
}
if( S_OK == hr ){
memcpy((m_rgItem + cbOffset), (BYTE *) pvItem, m_cbItem );
m_cItem++;
hItem = m_cItem;
}
return hr;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Obtain a pointer to the data at a given index into the buffer
//
// HRESULT indicating routines status
// S_OK | pvItem contains a pointer to the data requested
// E_INVALIDARG | Invalid Index passed in
//
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CExtBuffer::GetItemOfExtBuffer( HACCESSOR hItem, // IN Index of item to get
VOID* pvItem ) // OUT Pointer to block at index
{
HRESULT hr = S_OK;
if ((hItem > m_cItem) || (hItem == 0) ){
hr = E_INVALIDARG;
}
else{
memcpy((BYTE *) pvItem, (m_rgItem + (hItem - 1) *m_cbItem), m_cbItem );
}
return hr;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Get the extents of the currently allocated buffers
//
// HRESULT indicating routines status
// S_OK Extents were obtained successfuly
//
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
STDMETHODIMP CExtBuffer::GetFirstLastItemH( HACCESSOR &hItemFirst, // OUT First item allocated
HACCESSOR &hItemLast )// OUT Last item allocated
{
hItemFirst = 1;
hItemLast = m_cItem;
return S_OK;
}