/////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // 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; }