207 lines
5.9 KiB
C++
207 lines
5.9 KiB
C++
//--------------------------------------------------------------------
|
|
// Microsoft OLE DB Sample Provider
|
|
// (C) Copyright 1991 - 1999 Microsoft Corporation. All Rights Reserved.
|
|
//
|
|
// @doc
|
|
//
|
|
// @module EXTBUFF.CPP | 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"
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
// @mfunc Constructor for this class
|
|
//
|
|
// @rdesc NONE
|
|
//
|
|
CExtBuffer::CExtBuffer
|
|
(
|
|
void
|
|
)
|
|
{
|
|
m_cItem = 0;
|
|
m_cbAlloc = 0;
|
|
m_rgItem = NULL;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
// @mfunc Destructor for this class
|
|
//
|
|
// @rdesc NONE
|
|
//
|
|
CExtBuffer:: ~CExtBuffer
|
|
(
|
|
void
|
|
)
|
|
{
|
|
if (m_cbAlloc)
|
|
VirtualFree((VOID *) m_rgItem, m_cbAlloc, MEM_DECOMMIT );
|
|
|
|
if (m_rgItem)
|
|
VirtualFree((VOID *) m_rgItem, 0, MEM_RELEASE );
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
// @mfunc Allocate and Initialize Buffer
|
|
//
|
|
// @rdesc HRESULT indicating routines status
|
|
// @flag S_OK | Initialization succeeded
|
|
// @flag E_OUTOFMEMORY | Not enough memory to allocate buffer
|
|
//
|
|
STDMETHODIMP CExtBuffer::FInit
|
|
(
|
|
ULONG cItemMax, //@parm IN | Maximum number of items ever
|
|
ULONG cbItem, //@parm IN | Size of each item, in bytes
|
|
ULONG cbPage //@parm IN | Size of system page size (from SysInfo)
|
|
)
|
|
{
|
|
BYTE *pb;
|
|
|
|
m_cbReserved = ((cbItem *cItemMax) / cbPage + 1) *cbPage;
|
|
m_rgItem = (BYTE *) VirtualAlloc( NULL, m_cbReserved, MEM_RESERVE, PAGE_READWRITE );
|
|
|
|
if (m_rgItem == NULL)
|
|
return ResultFromScode( E_OUTOFMEMORY );
|
|
|
|
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;
|
|
return ResultFromScode( E_OUTOFMEMORY );
|
|
}
|
|
|
|
m_cbAlloc = m_dbAlloc;
|
|
return ResultFromScode( S_OK );
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
// @mfunc Retrieves a pointer to the value at given index
|
|
//
|
|
// @rdesc If index is within the range of 1 to m_cItems then a valid
|
|
// pointer is returned, else NULL is returned.
|
|
//
|
|
void* CExtBuffer::operator[]
|
|
(
|
|
DBCOUNTITEM hItem //@parm 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;
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
// @mfunc Add Data to the fixed buffers and return the index it was
|
|
// added at.
|
|
//
|
|
// @rdesc HRESULT indicating routines status
|
|
// @flag S_OK | Data copied successfully
|
|
// @flag E_OUTOFMEMORY | Not enough memory to allocate buffer
|
|
//
|
|
STDMETHODIMP CExtBuffer::InsertIntoExtBuffer
|
|
(
|
|
VOID* pvItem, //@parm IN | Pointer to buffer to copy
|
|
HACCESSOR &hItem //@parm OUT | Index of where data was placed
|
|
)
|
|
{
|
|
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)
|
|
{
|
|
return ResultFromScode( E_OUTOFMEMORY );
|
|
}
|
|
m_cbAlloc += m_dbAlloc;
|
|
}
|
|
|
|
memcpy((m_rgItem + cbOffset), (BYTE *) pvItem, m_cbItem );
|
|
m_cItem++;
|
|
hItem = m_cItem;
|
|
|
|
return ResultFromScode( S_OK );
|
|
}
|
|
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
// @mfunc Obtain a pointer to the data at a given index into the buffer
|
|
//
|
|
// @rdesc HRESULT indicating routines status
|
|
// @flag S_OK | pvItem contains a pointer to the data requested
|
|
// @flag E_INVALIDARG | Invalid Index passed in
|
|
//
|
|
STDMETHODIMP CExtBuffer::GetItemOfExtBuffer
|
|
(
|
|
HACCESSOR hItem, //@parm IN | Index of item to get
|
|
VOID* pvItem //@parm OUT | Pointer to block at index
|
|
)
|
|
{
|
|
if ((hItem > m_cItem) || (hItem == 0) ) {
|
|
*((PACCESSOR *)pvItem) = NULL;
|
|
return ResultFromScode( DB_E_BADACCESSORHANDLE );
|
|
}
|
|
|
|
memcpy((BYTE *) pvItem, (m_rgItem + (hItem - 1) *m_cbItem), m_cbItem );
|
|
return ResultFromScode( S_OK );
|
|
}
|
|
|
|
|
|
//--------------------------------------------------------------------
|
|
// @mfunc Get the extents of the currently allocated buffers
|
|
//
|
|
// @rdesc HRESULT indicating routines status
|
|
// @flag S_OK | Extents were obtained successfuly
|
|
//
|
|
STDMETHODIMP CExtBuffer::GetFirstLastItemH
|
|
(
|
|
HACCESSOR &hItemFirst, //@parm OUT | First item allocated
|
|
HACCESSOR &hItemLast //@parm OUT | Last item allocated
|
|
)
|
|
{
|
|
hItemFirst = 1;
|
|
hItemLast = m_cItem;
|
|
return ResultFromScode( S_OK );
|
|
}
|
|
|