2025-04-27 07:49:33 -04:00

309 lines
8.7 KiB
C++

/*************************************************************************
* @doc SHROOM EXTERNAL API *
* *
* CATALOG.CPP *
* *
* Copyright (C) Microsoft Corporation 1997 *
* All Rights reserved. *
* *
* This file contains the implementation of the catalog object *
* *
* *
**************************************************************************
* *
* Written By : Erin Foxford *
* Current Owner: erinfox *
* *
**************************************************************************/
// I'd like to get rid of this, but for now we include it so this compiles
#ifdef _DEBUG
static char s_aszModule[] = __FILE__; /* For error report */
#endif
#include <atlinc.h> // includes for ATL.
// MediaView (InfoTech) includes
#include <mvopsys.h>
#include <_mvutil.h>
#include <wwheel.h>
#include <itcc.h> // needed for STDPROP_UID def.
#include <ITDB.h>
#include <ITPropl.h>
#include <itrs.h>
#include <itww.h>
#include <itgroup.h>
#include <itquery.h>
#include <ccfiles.h>
#include <itcat.h>
#include "catalog.h"
/********************************************************************
* @method STDMETHODIMP | IITCatalog | Open |
* Opens catalog
*
* @parm IITDatabase* | lpITDB | Pointer to database object
* @parm LPCWSTR | lpszwName | Name of catalog to open. If NULL, the
* default catalog will be open. NULL is the default parameter value.
*
* @rvalue E_ALREADYOPEN | Catalog is already open
* @rvalue STG_E_* | Any of the IStorage errors that could occur
* while opening a storage
* @rvalue S_OK | The catalog was successfully opened
*
********************************************************************/
STDMETHODIMP CITCatalogLocal::Open(IITDatabase* lpITDB, LPCWSTR lpszwName)
{
HRESULT hr;
DWORD cbSize = 0;
DWORD cbRead;
// Open catalog substorage
if (FAILED(hr = lpITDB->GetObjectPersistence(
(lpszwName == NULL ? SZ_CATALOG_STORAGE : lpszwName),
IITDB_OBJINST_NULL, (LPVOID *) &m_pCatalog, FALSE)))
{
return (hr);
}
// Open catalog B-tree
if (NULL == (m_hbt = HbtOpenBtreeSz(SZ_BTREE_BTREE, m_pCatalog,
fFSOpenReadOnly, &hr)))
{
exit0:
m_pCatalog->Release();
m_pCatalog = NULL;
return hr;
}
// Open catalog property header and read it into a buffer
IStream* pHdr;
hr = m_pCatalog->OpenStream(SZ_BTREE_HEADER, NULL, STGM_READ, 0, &pHdr);
if (FAILED(hr))
{
exit1:
RcCloseBtreeHbt(m_hbt);
goto exit0;
}
// Read header size
hr = pHdr->Read(&cbSize, sizeof(DWORD), &cbRead);
if (FAILED(hr))
{
exit2:
pHdr->Release();
goto exit1;
}
// ALLOCATE memory
if (NULL == (m_pHdr = new BYTE[cbSize]))
{
hr = E_OUTOFMEMORY;
goto exit2;
}
// Read in the bytes
hr = pHdr->Read(m_pHdr, cbSize, &cbRead);
if (FAILED(hr))
{
exit3:
delete m_pHdr;
goto exit2;
}
// Open catalog data file
hr = m_pCatalog->OpenStream(SZ_BTREE_DATA, NULL, STGM_READ, 0, &m_pDataStr);
if (FAILED(hr))
goto exit3;
// release header stream
pHdr->Release();
// Initiate a block of memory
if (NULL == (m_pScratchBuffer = BlockInitiate((DWORD)65500, 0, 0, 0)))
return E_OUTOFMEMORY;
return hr;
}
/********************************************************************
* @method STDMETHODIMP | IITCatalog | Close |
* Closes catalog
*
********************************************************************/
STDMETHODIMP CITCatalogLocal::Close()
{
// close b-tree
if (m_hbt)
{
RcCloseBtreeHbt(m_hbt);
m_hbt = NULL;
}
// free memory
if (m_pHdr)
{
delete m_pHdr;
m_pHdr = NULL;
}
// close data stream
if (m_pDataStr)
{
m_pDataStr->Release();
m_pDataStr = NULL;
}
// close catalog substorage
if (m_pCatalog)
{
m_pCatalog->Release();
m_pCatalog = NULL;
}
// free scratch memory
if (m_pScratchBuffer)
{
BlockFree(m_pScratchBuffer);
m_pScratchBuffer = NULL;
}
return S_OK;
}
/********************************************************************
* @method STDMETHODIMP | IITCatalog | Lookup |
* Takes an input result set, which contains a set of UIDs, and
* fills in properties found in the catalog, either in the same result
* set object or in another.
*
* @parm IITResultSet* | pRSIn | Result set containing UIDs
* @parm IITResultSet* | pRSOut | Result set to fill with properties
* stored in catalog. If you pass NULL, which is the default value, the properties
* will be returned in pRSIn.
*
* @rvalue E_INVALIDARG | pRSIn is NULL
* @rvalue E_OUTOFMEMORY | Internal memory allocation failed
* @rvalue E_FAIL | The input result set has no rows
* @rvalue S_FALSE | The catalog does not contain any properties specified in
* the result set, but no failure occurred
* @rvalue S_OK | The properties were successfully filled in the result set
*
********************************************************************/
STDMETHODIMP CITCatalogLocal::Lookup(IITResultSet* pRSIn, IITResultSet* pRSOut)
{
HRESULT hr;
DWORD dwOffset;
LONG lColumnIndex;
LONG lNumberOfRows;
CProperty Prop;
LONG iRow; // Loop index
LPBYTE pPropBuffer;
DWORD cbSize;
DWORD cbRead;
LARGE_INTEGER dlibMove; // For seeking
ULARGE_INTEGER libNewPos;
if (NULL == pRSIn)
return E_INVALIDARG;
// Get column corresponding to UID property.
// If it doesn't exist, return
hr = pRSIn->GetColumnFromPropID(STDPROP_UID, lColumnIndex);
if (FAILED(hr))
return hr;
// There has to be at least one row
pRSIn->GetRowCount(lNumberOfRows);
if (0 == lNumberOfRows)
return E_FAIL;
// Loop over all rows in result set
for (iRow = 0; iRow < lNumberOfRows; iRow++)
{
hr = pRSIn->Get(iRow, lColumnIndex, Prop);
// look up UID in btree and get the offset
hr = RcLookupByKey(m_hbt, (KEY)&Prop.dwValue, NULL, &dwOffset);
if (FAILED(hr))
{
// not finding the UID in the catalog is OK, we
// just don't fill in anything.
if (hr == E_NOTEXIST)
{
hr = S_FALSE;
continue;
}
break;
}
// seek to offset in data file
dlibMove.QuadPart = dwOffset;
hr = m_pDataStr->Seek(dlibMove, STREAM_SEEK_SET, &libNewPos);
if (FAILED(hr))
break;
// read data into buffer
hr = m_pDataStr->Read(&cbSize, sizeof(DWORD), &cbRead);
if (FAILED(hr) || 0 == cbSize)
break;
// REVIEW TODO BUGUG - johnrush
// Remove this stuff. The Block Manager is not appropriate for
// this purpose. We should replace this with some combination
// of stack buffer and dynamic memory.
BlockReset(m_pScratchBuffer);
if (NULL == (pPropBuffer = (LPBYTE) BlockCopy(m_pScratchBuffer, NULL, cbSize, 0)))
return E_OUTOFMEMORY;
hr = m_pDataStr->Read(pPropBuffer, cbSize, &cbRead);
if (FAILED(hr))
break;
// fill result set
if (pRSOut)
hr = pRSOut->Append(m_pHdr, pPropBuffer);
else
hr = pRSIn->Set(iRow, m_pHdr, pPropBuffer);
// Optimization: if ResultSet methods return S_FALSE, that
// means no columns correspond to properties in header.
// Don't even bother trying to set other rows.
if (S_FALSE == hr)
break;
}
return hr;
}
/********************************************************************
* @method STDMETHODIMP | IITCatalog | GetColumns |
* Adds columns to given result set for all catalog properties
*
* @parm IITResultSet* | pRSIn | Result set
* @rvalue S_OK | The properties were successfully filled in the result set.
*
* @comm This method does not add a column for the "key" column. In the
* case of the Catalog, the "key" column is the STDPROP_UID property.
* If you intend to use this API in conjunction with the <om .lookup>
* API, you must manually add the STDPROP_UID property as an additional column
* to the result set after calling GetColumns, and before calling Lookup.
*
********************************************************************/
STDMETHODIMP CITCatalogLocal::GetColumns(IITResultSet* pRS)
{
return pRS->Add(m_pHdr);
}