200 lines
6.7 KiB
C++
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;
|
||
|
}
|
||
|
|