NT4/private/ole32/stg/ofsstg/ofscs.cxx
2020-09-30 17:12:29 +02:00

1017 lines
27 KiB
C++

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1992 - 1993.
//
// File: ofscs.cxx
//
// Contents: COfsCatalogFile implementation
//
// Classes: COfsCatalogFile
//
// History: Oct-93 DaveMont Created
//
//----------------------------------------------------------------------------
#include "headers.cxx"
#pragma hdrstop // Remove for MAC build
#include <align.h>
#include <iofs.h>
#include <stgprop.h>
#include <logfile.hxx>
#include <ofscs.hxx>
#include <stgutil.hxx>
extern VOID SetRtlUnicodeCallouts(VOID);
//+-----------------------------------------------------------------------
//
// Method: GetOfsViewFunctionAddr, private
//
// Synopsis: Hoop jumping so that ole32 need not link with query.
//
// History: 28-Aug-95 DaveStr Created
//
// Notes:
//
//------------------------------------------------------------------------
#define OFS_CREATE_VIEW 0
#define OFS_DELETE_VIEW 1
#define OFS_ENUMERATE_VIEWS 2
FARPROC rpfnOfsView[3] = { NULL, NULL, NULL };
HRESULT GetOfsViewFunctionAddr(
ULONG fid, // function identifier
VOID **ppfn)
{
if ( fid > OFS_ENUMERATE_VIEWS )
{
OutputDebugStringA("\n!!! Bad ofs view function id !!!\n");
return(E_INVALIDARG);
}
if ( NULL == rpfnOfsView[fid] )
{
const CHAR *pszFunction;
switch ( fid )
{
case OFS_CREATE_VIEW:
pszFunction = "CreateView";
break;
case OFS_DELETE_VIEW:
pszFunction = "DeleteView";
break;
case OFS_ENUMERATE_VIEWS:
pszFunction = "EnumerateViews";
break;
}
HINSTANCE hDll = LoadLibraryA("query");
if ( NULL == hDll )
{
OutputDebugStringA("\n!!! query.dll not found !!!\n");
return(ERROR_FILE_NOT_FOUND);
}
rpfnOfsView[fid] = GetProcAddress(hDll, pszFunction);
if ( NULL == rpfnOfsView[fid] )
{
OutputDebugStringA("\n!!! View function not in query.dll !!!\n");
return(E_FAIL);
}
}
*ppfn = rpfnOfsView[fid];
return(S_OK);
}
//+---------------------------------------------------------------------------
//
// Member: COfsCatalogFile::InitFromHandle, public
//
// Synopsis: From-handle constructor
//
// Arguments: [h] - Handle of directory
// [grfMode] - Mode of handle
//
// Returns: Appropriate status code
//
// History: 29-Jun-93 DrewB Created
//
// Notes: Takes a new reference on the handle
//
//----------------------------------------------------------------------------
SCODE COfsCatalogFile::InitFromHandle(HANDLE h, DWORD grfMode,
const WCHAR *pwcsName)
{
SCODE sc;
olDebugOut((DEB_ITRACE, "In COfsCatalogFile::InitFromHandle:%p(%p, %lX)\n",
this, h, grfMode));
olChk(ValidateMode(grfMode));
_h = h;
ssAssert (_h != NULL);
_grfMode = grfMode;
_sig = COfsDocStorage_SIG;
_fRoot = TRUE;
_wcDrive = GetDriveLetter (pwcsName);
olDebugOut((DEB_ITRACE, "Out COfsCatalogFile::InitFromHandle\n"));
EH_Err:
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: COfsCatalogFile::InitFromPath, public
//
// Synopsis: From-path constructor
//
// Arguments: [hParent] - Handle of parent directory
// [pwcsName] - Name of directory
// [grfMode] - Mode
// [fCreate] - Create or open
// [pssSecurity] - Security
//
// Returns: Appropriate status code
//
// History: 24-Jun-93 DrewB Created
//
//----------------------------------------------------------------------------
SCODE COfsCatalogFile::InitFromPath(HANDLE hParent,
WCHAR const *pwcsName,
DWORD grfMode,
CREATEOPEN co,
LPSECURITY_ATTRIBUTES pssSecurity)
{
SCODE sc;
olDebugOut((DEB_ITRACE, "In COfsCatalogFile::InitFromPath:%p("
"%p, %ws, %lX, %d, %p)\n", this, hParent, pwcsName, grfMode,
co, pssSecurity));
olChk(ValidateMode(grfMode));
olChk(GetNtHandle(hParent, pwcsName, grfMode, 0, co, FD_CATALOG,
pssSecurity, &_h));
_grfMode = grfMode;
_sig = COfsDocStorage_SIG;
_fRoot = TRUE;
_wcDrive = GetDriveLetter (pwcsName);
olDebugOut((DEB_ITRACE, "Out COfsCatalogFile::InitFromPath\n"));
EH_Err:
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: COfsCatalogFile::InitPath, public
//
// Synopsis: initialize and save the path
//
// Arguments: [pwszPath] - the path of the object being opened/created
//
// Returns: Appropriate status code
//
//----------------------------------------------------------------------------
SCODE COfsCatalogFile::InitPath(WCHAR const *pwszPath)
{
SCODE sc = S_OK;
if (NULL != pwszPath)
{
// bugbug, save the path until can QI for IQuery on IStorage
_pwszName = (WCHAR*) CoTaskMemAlloc ((wcslen(pwszPath)+1)*sizeof(WCHAR));
if ( _pwszName != NULL )
wcscpy(_pwszName, pwszPath);
else
sc = E_OUTOFMEMORY;
} // otherwise pwszname is left null
return(sc);
}
//+---------------------------------------------------------------------------
//
// Member: COfsCatalogFile::QueryInterface, public
//
// Synopsis: Return supported interfaces
//
// Arguments: [riid] - Interface
// [ppv] - Object return
//
// Returns: Appropriate status code
//
//----------------------------------------------------------------------------
STDMETHODIMP COfsCatalogFile::QueryInterface(REFIID riid, void **ppv)
{
SCODE sc;
olDebugOut((DEB_TRACE, "In COfsCatalogFile::QueryInterface:%p(riid, %p)\n",
this, ppv));
if (!IsValidIid(riid))
ssErr(EH_Err, STG_E_INVALIDPARAMETER);
ssChk(Validate());
if (IsEqualIID(riid, IID_ISummaryCatalogStorage))
{
*ppv = (ISummaryCatalogStorage *)this;
COfsCatalogFile::AddRef();
}
else if (IsEqualIID(riid, IID_ISummaryCatalogStorageView))
{
*ppv = (ISummaryCatalogStorageView *)this;
COfsCatalogFile::AddRef();
}
else if (IsEqualIID(riid, IID_ICatalogStorage))
{
*ppv = (ICatalogStorage *)this;
COfsCatalogFile::AddRef();
}
else if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IStorage))
{
*ppv = (IStorage *)this;
COfsCatalogFile::AddRef();
}
else if (IsEqualIID(riid, IID_IPropertySetStorage))
{
*ppv = (IPropertySetStorage *)this;
COfsCatalogFile::AddRef();
}
else if (IsEqualIID(riid, IID_INativeFileSystem))
{
*ppv = (INativeFileSystem *)this;
COfsCatalogFile::AddRef();
}
else if (IsEqualIID(riid, IID_IStorageReplica))
{
*ppv = (IStorageReplica *)this;
COfsCatalogFile::AddRef();
}
else
{
sc = E_NOINTERFACE;
*ppv = NULL;
}
olDebugOut((DEB_TRACE, "Out COfsCatalogFile::QueryInterface => %p\n",
*ppv));
EH_Err:
return ResultFromScode(sc);
}
//+---------------------------------------------------------------------------
//
// Member: COfsCatalogFile::GetSCPath, public
//
// Synopsis: Return the path to the catalog storage
// (used by Summary Catalog class code to
// get IQuery interface via EvalQuery3)
//
// Arguments: [pwszPath] - path of the catalog storage
//
// Returns: Appropriate status code
//
//----------------------------------------------------------------------------
STDMETHODIMP COfsCatalogFile::GetSCPath(PWCHAR * pwszPath)
{
SCODE sc;
if ( NULL == _pwszName)
{
sc = E_FAIL; // bugbug scaffolding error return
} else
{
*pwszPath = (WCHAR*)CoTaskMemAlloc ((wcslen(_pwszName)+1)*sizeof(WCHAR));
if ( (*pwszPath) != NULL )
{
wcscpy(*pwszPath, _pwszName);
sc = S_OK;
}
else
sc = E_OUTOFMEMORY;
}
return ssResult(sc);
}
//+---------------------------------------------------------------------------
//
// Member: COfsCatalogFile::SetRows, public
//
// Synopsis: Sets or updates rows in a summary catalog
//
// Arguments: [pcols] - the columns to set in the rows to set
// [pwids] - array of wids of rows to update
// [crows] - the number of rows to set
// [prows] - the variants of the rows, in the same form
// as returned by query
//
// Returns: Appropriate status code
//
// Notes: There is a inconsistency in the way the fourth parameter
// is passed in. We require an array of table rows rather than
// a pointer to an array of table rows, i.e., we require a
// TABLEROW * rather than a TABLEROW**.
//
//----------------------------------------------------------------------------
STDMETHODIMP COfsCatalogFile::SetRows(COLUMNSET * pcols,
LONG * pwids,
ULONG cRows,
TABLEROW ** prows)
{
SCODE sc = S_OK;
NTSTATUS Status;
HANDLE h;
TABLEROW *pTableRow = *prows;
SetRtlUnicodeCallouts();
sc = GetHandle(&h);
if ((sc == S_OK) && (cRows > 0)) {
ULONG cColumns = pcols->cCol;
CATALOG_ROW_INFO *pRowInfo;
pRowInfo = (CATALOG_ROW_INFO *) CoTaskMemAlloc(sizeof(CATALOG_ROW_INFO) * cRows);
if (pRowInfo != NULL) {
ULONG i;
for (i = 0; i < cRows; i++) {
if (pwids != NULL) {
pRowInfo[i].RowId = pwids[i];
} else {
pRowInfo[i].RowId = CATALOGSTG_ROWID_INVALID;
}
pRowInfo[i].dwReserved = 0;
pRowInfo[i].aVariants = pTableRow[i].aValue;
}
// Invoke the appropriate NT API.
Status = RtlUpdateCatalog(h,
cColumns,
(FULLPROPSPEC const *) pcols->aCol,
cRows,
pRowInfo);
if (!NT_SUCCESS(Status)) {
sc = HRESULT_FROM_NT(Status);
}
CoTaskMemFree(pRowInfo);
} else {
sc = E_OUTOFMEMORY;
}
}
olDebugOut((DEB_ITRACE, "Out COfsCatalogFile::SetRows\n"));
return ResultFromScode(sc);
}
//-----------------------------------------------------------------------------
//
// Member: CSCStorage::DeleteRow - public
//
// Synopsis: Deletes a row specified by wid in a catalog storage,
//
// Arguments: [wid] - the wid of the row to delete
//
// Returns: the apropriate error code.
//
//-----------------------------------------------------------------------------
STDMETHODIMP COfsCatalogFile::DeleteRow(ULONG wid)
{
SCODE sc = S_OK;
olDebugOut((DEB_ITRACE, "In COfsCatalogFile::DeleteRow:%p("
"%lu)\n", this, wid));
NTSTATUS Status;
HANDLE h;
SetRtlUnicodeCallouts();
sc = GetHandle(&h);
if (sc == S_OK) {
Status = RtlDeleteCatalogRows(h,1,((CATALOGSTG_ROWID *)&wid));
sc = HRESULT_FROM_NT(Status);
}
olDebugOut((DEB_ITRACE, "Out COfsCatalogFile::DeleteRow\n"));
return(sc);
}
//+-----------------------------------------------------------------------
//
// Method: COfsCatalogFile::UpdateRows, public
//
// Synopsis: Updates catalog rows. Maps NILE-ized arguments down to
// pre-NILE structures.
//
// History: 27-Jun-95 DaveStr Created
//
// Notes: Not necessarily efficient - temporary until VicH finalizes
// ntdll catalog APIs.
//
//------------------------------------------------------------------------
HRESULT COfsCatalogFile::UpdateRows(
ULONG cCol,
DBID *rDBCOLID,
ULONG cBinding,
DBBINDING *rDBBINDING,
ULONG cRow,
CATALOG_UPDATE_ROWINFO *rROWINFO)
{
olDebugOut((DEB_ITRACE, "In COfsCatalogFile::UpdateRows\n"));
// Validate parameters.
if ( (0 == cCol) ||
(NULL == rDBCOLID) ||
(0 == cBinding) ||
(NULL == rDBBINDING) ||
(0 == cRow) ||
(NULL == rROWINFO) )
{
return(E_INVALIDARG);
}
// Disallow NAME-only column identifiers.
for ( ULONG col = 0; col < cCol; col++ )
if ( DBKIND_NAME == rDBCOLID[col].eKind )
return(E_INVALIDARG);
// Validate CATALOG_UPDATE_ROWINFOs.
for ( ULONG row = 0; row < cRow; row++ )
{
if ( (CATALOGSTG_DELETE < rROWINFO[row].wAction) ||
(0 != rROWINFO[row].wReserved) ||
((CATALOGSTG_NOACTION != rROWINFO[row].wAction) &&
(NULL == rROWINFO[row].pData)) )
{
return(E_INVALIDARG);
}
}
HRESULT hr;
HANDLE hCatalog;
SetRtlUnicodeCallouts();
hr = GetHandle(&hCatalog);
if ( FAILED(hr) )
return(hr);
NTSTATUS status = RtlUpdateCatalogRows(hCatalog,
cCol,
rDBCOLID,
cBinding,
rDBBINDING,
cRow,
rROWINFO);
if ( !NT_SUCCESS(status) )
hr = HRESULT_FROM_NT(status);
return(hr);
}
//+-----------------------------------------------------------------------
//
// Method: COfsCatalogFile::CreateView, public
//
// Synopsis: Create a view over a summary catalog.
//
// History: 12-Jul-95 DaveStr Created
// 31-Jul-95 DaveStr Implemented
// 30-Oct-95 DaveStr Removed columns which are keys
//
// Notes:
//
//------------------------------------------------------------------------
HRESULT COfsCatalogFile::CreateView(
CATALOG_VIEW *pView,
BOOL fWait)
{
olDebugOut((DEB_ITRACE, "In COfsCatalogFile::CreateView\n"));
if ( (NULL == pView) ||
(0 == pView->cCols) ||
(NULL == pView->rCols) )
{
return(E_INVALIDARG);
}
HRESULT hr = S_OK;
HANDLE hCatalog;
hr = GetHandle(&hCatalog);
if ( FAILED(hr) )
return(hr);
// Map non-key columns in CATALOG_VIEW to a COLUMNSET and key columns
// to a SORTSET.
ULONG cKeys = 0;
ULONG cCols = pView->cCols;
for ( ULONG i = 0; i < pView->cCols; i++ )
{
if ( pView->rCols[i].fSortKey )
{
cKeys++;
cCols--;
}
}
COLUMNSET colset = { cCols, NULL };
SORTSET sortset = { cKeys, NULL };
if ( 0 != cCols )
{
colset.aCol = (FULLPROPSPEC *)
CoTaskMemAlloc(cCols * sizeof(FULLPROPSPEC));
if ( NULL == colset.aCol )
return(E_OUTOFMEMORY);
}
if ( 0 != cKeys )
{
sortset.aCol = (SORTKEY *) CoTaskMemAlloc(cKeys * sizeof(SORTKEY));
if ( NULL == sortset.aCol )
{
CoTaskMemFree(colset.aCol);
return(E_OUTOFMEMORY);
}
}
ULONG iKey = 0;
ULONG iCol = 0;
for ( i = 0; i < pView->cCols; i++ )
{
FULLPROPSPEC fps;
switch ( pView->rCols[i].colid.eKind )
{
case DBKIND_GUID_NAME:
fps.guidPropSet = pView->rCols[i].colid.guid;
fps.psProperty.ulKind = PRSPEC_LPWSTR;
fps.psProperty.lpwstr = (WCHAR *) pView->rCols[i].colid.pwszName;
break;
case DBKIND_GUID_PROPID:
fps.guidPropSet = pView->rCols[i].colid.guid;
fps.psProperty.ulKind = PRSPEC_PROPID;
fps.psProperty.lpwstr = (WCHAR *) pView->rCols[i].colid.ulPropid;
break;
case DBKIND_PGUID_NAME:
fps.guidPropSet = *pView->rCols[i].colid.pguid;
fps.psProperty.ulKind = PRSPEC_LPWSTR;
fps.psProperty.lpwstr = (WCHAR *) pView->rCols[i].colid.pwszName;
break;
case DBKIND_PGUID_PROPID:
fps.guidPropSet = *pView->rCols[i].colid.pguid;
fps.psProperty.ulKind = PRSPEC_PROPID;
fps.psProperty.lpwstr = (WCHAR *) pView->rCols[i].colid.ulPropid;
break;
default:
CoTaskMemFree(sortset.aCol);
CoTaskMemFree(colset.aCol);
return(E_INVALIDARG);
}
if ( pView->rCols[i].fSortKey )
{
sortset.aCol[iKey].propColumn = fps;
sortset.aCol[iKey].dwOrder = pView->rCols[i].sortOrder;
sortset.aCol[iKey].locale = pView->rCols[i].locale;
iKey++;
}
else
{
colset.aCol[iCol] = fps;
iCol++;
}
}
NTSTATUS (*pfn)(HANDLE, RESTRICTION *, COLUMNSET *, SORTSET *);
NTSTATUS nts;
hr = GetOfsViewFunctionAddr(OFS_CREATE_VIEW, (void **) &pfn);
if ( SUCCEEDED(hr) )
{
nts = (pfn)(hCatalog,
(RESTRICTION *) NULL,
&colset,
&sortset);
if ( !NT_SUCCESS(nts) )
{
hr = HRESULT_FROM_NT(nts);
}
}
CoTaskMemFree(sortset.aCol);
CoTaskMemFree(colset.aCol);
if ( SUCCEEDED(hr) && fWait )
{
while ( TRUE )
{
LONG_OPERATION_STATUS lstatus;
IO_STATUS_BLOCK iosb;
nts = NtFsControlFile(hCatalog, NULL, NULL, NULL, &iosb,
FSCTL_OFS_LONG_OPERATION_STATUS,
NULL, 0, &lstatus, sizeof(lstatus));
if ( !NT_SUCCESS(nts) )
{
hr = HRESULT_FROM_NT(nts);
break;
}
if ( !lstatus.fPending )
break;
Sleep(10); // 10 ms
}
}
olDebugOut((DEB_ITRACE, "Out COfsCatalogFile::CreateView\n"));
return(hr);
}
//+-----------------------------------------------------------------------
//
// Method: MapSingleView, internal helper
//
// Synopsis: Maps a single VIEW_INDEX_ENTRY to a single CATALOG_VIEW.
// All fields allocated via CoTaskMemAlloc - see ReleaseViews.
// Returned DBID are always either DBKIND_GUID_PROPID or
// DBKIND_GUID_NAME.
//
// History: 31-Jul-95 DaveStr Created
//
// Notes:
//
//------------------------------------------------------------------------
HRESULT MapSingleView(
VIEW_INDEX_ENTRY *pvie,
CATALOG_VIEW *pcv)
{
pcv->id = pvie->id;
pcv->cCols = pvie->ccol;
pcv->rCols = (CATALOG_VIEW_COLUMN *)
CoTaskMemAlloc(pcv->cCols * sizeof(CATALOG_VIEW_COLUMN));
if ( NULL == pcv->rCols )
return(E_OUTOFMEMORY);
// pvie->avc can not be indexed via subscript because VIEW_COLUMN
// structs are varying length! Use pointer instead.
VIEW_COLUMN *pCurViewCol = &pvie->avc[0];
for ( ULONG i = 0; i < pcv->cCols; i++ )
{
// First pvie->ckey columns are sort key columns.
pcv->rCols[i].fSortKey = (i < pvie->ckey);
// BUGBUG - manufacture an LCID since Ofs APIs don't return it.
pcv->rCols[i].locale = 0xffffffff;
pcv->rCols[i].sortOrder = pCurViewCol->dwOrder;
pcv->rCols[i].colid.guid = pCurViewCol->PropertySet;
if ( 0 == pCurViewCol->cwcName )
{
pcv->rCols[i].colid.eKind = DBKIND_GUID_PROPID;
pcv->rCols[i].colid.ulPropid = pCurViewCol->propid;
}
else
{
pcv->rCols[i].colid.eKind = DBKIND_GUID_NAME;
// VIEW_COLUMN.cwcName field does not include the L'\0',
// even though the appended name *is* terminated.
pcv->rCols[i].colid.pwszName = (WCHAR *)
CoTaskMemAlloc(sizeof(WCHAR) * (1 + pCurViewCol->cwcName));
if ( NULL == pcv->rCols[i].colid.pwszName )
{
for ( ULONG j = 0; j < i; j++ )
if ( DBKIND_GUID_NAME == pcv->rCols[j].colid.eKind )
CoTaskMemFree((WCHAR *) pcv->rCols[j].colid.pwszName);
CoTaskMemFree(pcv->rCols);
pcv->rCols = NULL;
return(E_OUTOFMEMORY);
}
wcscpy((WCHAR *) pcv->rCols[i].colid.pwszName,
(WCHAR *) ((BYTE *) pCurViewCol + sizeof(VIEW_COLUMN)));
}
// Advance to next VIEW_COLUMN in pvie->avc[].
ULONG cwcSave = pCurViewCol->cwcName;
PBYTE pb = (PBYTE) pCurViewCol;
pb += (sizeof(VIEW_COLUMN) +
((0 == cwcSave)
? 0
: sizeof(WCHAR) * (1 + cwcSave)));
pCurViewCol = (VIEW_COLUMN *) ROUND_UP_POINTER(pb, ALIGN_DWORD);
}
return(S_OK);
}
//+-----------------------------------------------------------------------
//
// Method: COfsCatalogFile::GetViews, public
//
// Synopsis: Return the views defined on a summary catalog.
//
// History: 12-Jul-95 DaveStr Created
// 31-Jul-95 DaveStr Implemented
//
// Notes: Assumption is made that this is an infrequent call and
// not overly performance sensitive.
//
//------------------------------------------------------------------------
HRESULT COfsCatalogFile::GetViews(
ULONG *pcViews,
CATALOG_VIEW **prViews)
{
olDebugOut((DEB_ITRACE, "In COfsCatalogFile::GetViews\n"));
if ( (NULL == pcViews) ||
(NULL == prViews) )
{
return(E_INVALIDARG);
}
*pcViews = 0;
*prViews = NULL;
HRESULT hr = S_OK;
HANDLE hCatalog;
hr = GetHandle(&hCatalog);
if ( FAILED(hr) )
return(hr);
#define VIEW_INCREMENT 5 // view allocation increment
#define BUFFER_INCREMENT 4096 // buffer allocation increment
// Allocate EnumerateViews buffer.
ULONG cbvie = BUFFER_INCREMENT;
VIEW_INDEX_ENTRY *pvie = (VIEW_INDEX_ENTRY *) CoTaskMemAlloc(cbvie);
if ( NULL == pvie )
return(E_OUTOFMEMORY);
NTSTATUS (*pfn)(HANDLE, ULONG, VIEW_INDEX_ENTRY *, ULONG);
hr = GetOfsViewFunctionAddr(OFS_ENUMERATE_VIEWS, (void **) &pfn);
if ( FAILED(hr) )
return(hr);
// Make successive EnumerateView calls and map/copy the data to a
// CATALOG_VIEW array. (re)Allocate the return array as needed.
NTSTATUS nts;
ULONG id = 0;
while ( TRUE )
{
nts = (pfn)(hCatalog, id, pvie, cbvie);
// Grow buffer and retry if it is too small.
if ( STATUS_BUFFER_OVERFLOW == nts )
{
CoTaskMemFree(pvie);
cbvie += BUFFER_INCREMENT;
pvie = (VIEW_INDEX_ENTRY *) CoTaskMemAlloc(cbvie);
if ( NULL == pvie )
{
hr = E_OUTOFMEMORY;
break;
}
continue;
}
else if ( (STATUS_NO_MORE_FILES == nts) ||
(STATUS_NO_SUCH_FILE == nts) )
{
hr = S_OK;
break;
}
else if ( !NT_SUCCESS(nts) )
{
hr = HRESULT_FROM_NT(nts);
break;
}
// There is at least one complete view in pvie.
// Iterate through views in pvie and copy to return array.
VIEW_INDEX_ENTRY *pvieCur = pvie;
while ( TRUE )
{
// (re)Allocate output buffer as required.
if ( 0 == (*pcViews % VIEW_INCREMENT) )
{
CATALOG_VIEW *pcvTmp = *prViews;
*prViews = (CATALOG_VIEW *) CoTaskMemAlloc(
(*pcViews + VIEW_INCREMENT) * sizeof(CATALOG_VIEW));
if ( NULL == *prViews )
{
CoTaskMemFree(pcvTmp);
hr = E_OUTOFMEMORY;
break;
}
if ( NULL != pcvTmp )
{
memcpy(*prViews,
pcvTmp,
*pcViews * sizeof(CATALOG_VIEW));
}
}
// Map/copy the view.
hr = MapSingleView(pvieCur, &(*prViews)[*pcViews]);
if ( SUCCEEDED(hr) )
*pcViews += 1;
else
break;
// Advance to next view in buffer or set up for next
// EnumerateView call.
if ( 0 == pvieCur->ibEntry )
{
id = pvieCur->id + 1;
break;
}
else
{
pvieCur = (VIEW_INDEX_ENTRY *)
((BYTE *) pvieCur + pvieCur->ibEntry);
}
} // while ( more views in pvie buffer )
if ( FAILED(hr) )
break;
} // while ( more views available via EnumerateViews )
CoTaskMemFree(pvie);
if ( FAILED(hr) )
{
*pcViews = 0;
CoTaskMemFree(*prViews);
*prViews = NULL;
}
olDebugOut((DEB_ITRACE, "Out COfsCatalogFile::GetViews\n"));
return(hr);
}
//+-----------------------------------------------------------------------
//
// Method: COfsCatalogFile::DeleteView, public
//
// Synopsis: Delete a view defined on a summary catalog.
//
// History: 12-Jul-95 DaveStr Created
// 31-Jul-95 DaveStr Implemented
//
// Notes:
//
//------------------------------------------------------------------------
HRESULT COfsCatalogFile::DeleteView(
ULONG id)
{
olDebugOut((DEB_ITRACE, "In COfsCatalogFile::DeleteView\n"));
HRESULT hr;
HANDLE hCatalog;
NTSTATUS nts;
NTSTATUS (*pfn)(HANDLE, ULONG);
hr = GetHandle(&hCatalog);
if ( FAILED(hr) )
return(hr);
hr = GetOfsViewFunctionAddr(OFS_DELETE_VIEW, (void **) &pfn);
if ( FAILED(hr) )
return(hr);
nts = (pfn)(hCatalog, id);
if ( !NT_SUCCESS(nts) )
return(HRESULT_FROM_NT(nts));
olDebugOut((DEB_ITRACE, "Out COfsCatalogFile::DeleteView\n"));
return(S_OK);
}
//+-----------------------------------------------------------------------
//
// Method: COfsCatalogFile::ReleaseViews, public
//
// Synopsis: Release a set of CATALOG_VIEW returned by GetViews.
// See comments on MapSingleView.
//
// History: 12-Jul-95 DaveStr Created
// 31-Jul-95 DaveStr Implemented
//
// Notes:
//
//------------------------------------------------------------------------
HRESULT COfsCatalogFile::ReleaseViews(
ULONG cViews,
CATALOG_VIEW *rViews)
{
olDebugOut((DEB_ITRACE, "In COfsCatalogFile::ReleaseViews\n"));
if ( NULL != rViews )
{
for ( ULONG i = 0; i < cViews; i++ )
{
if ( NULL != rViews[i].rCols )
{
for ( ULONG j = 0; j < rViews[i].cCols; j++ )
{
if ( DBKIND_GUID_NAME == rViews[i].rCols[j].colid.eKind )
CoTaskMemFree((WCHAR *) rViews[i].rCols[j].colid.pwszName);
}
CoTaskMemFree(rViews[i].rCols);
}
}
CoTaskMemFree(rViews);
}
olDebugOut((DEB_ITRACE, "Out COfsCatalogFile::ReleaseViews\n"));
return(S_OK);
}