|
|
/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
mb.cxx
Abstract:
This module implements the MB class.
Author:
Keith Moore (keithmo) 05-Feb-1997 Moved from "inlines" in MB.HXX.
Revision History:
--*/
#include "imiscp.hxx"
//
// Default timeout
//
#define MB_TIMEOUT (30 * 1000)
//
// Default timeout for SaveData
//
#define MB_SAVE_TIMEOUT (10 * 1000) // milliseconds
MB::MB( IMDCOM * pMBCom ) : _pMBCom( pMBCom ), _hMB ( NULL ) { DBG_ASSERT( _pMBCom ); }
MB::~MB( VOID ) { Close(); _pMBCom = NULL; }
BOOL MB::EnumObjects( const CHAR * pszPath, CHAR * Name, DWORD Index ) { HRESULT hRes = _pMBCom->ComMDEnumMetaObjects( _hMB, (BYTE *)pszPath, (BYTE *)Name, Index );
if ( SUCCEEDED( hRes )) { return TRUE; }
SetLastError( HRESULTTOWIN32( hRes )); return FALSE; }
BOOL MB::AddObject( const CHAR * pszPath ) { HRESULT hRes = _pMBCom->ComMDAddMetaObject( _hMB, (BYTE *)pszPath ); if ( SUCCEEDED( hRes )) { return TRUE; }
SetLastError( HRESULTTOWIN32( hRes )); return FALSE; }
BOOL MB::DeleteObject( const CHAR * pszPath ) { HRESULT hRes = _pMBCom->ComMDDeleteMetaObject( _hMB, (BYTE *)pszPath );
if ( SUCCEEDED( hRes )) { return TRUE; }
SetLastError( HRESULTTOWIN32( hRes )); return FALSE; }
BOOL MB::ReleaseReferenceData( DWORD dwTag ) { HRESULT hRes = _pMBCom->ComMDReleaseReferenceData( dwTag );
if ( SUCCEEDED( hRes )) { return TRUE; }
SetLastError( HRESULTTOWIN32( hRes )); return FALSE; }
BOOL MB::Save( VOID ) { HRESULT hRes; METADATA_HANDLE mdhRoot;
//
// First try to lock the tree
//
hRes = _pMBCom->ComMDOpenMetaObjectW(METADATA_MASTER_ROOT_HANDLE, NULL, METADATA_PERMISSION_READ, MB_SAVE_TIMEOUT, &mdhRoot);
//
// If failed, then someone has a write handle open,
// and there might be an inconsistent data state, so don't save.
//
if (SUCCEEDED(hRes)) { //
// call metadata com api
//
hRes = _pMBCom->ComMDSaveData(mdhRoot);
_pMBCom->ComMDCloseMetaObject(mdhRoot);
}
if ( SUCCEEDED( hRes )) { return TRUE; }
SetLastError( HRESULTTOWIN32( hRes )); return FALSE; }
BOOL MB::GetSystemChangeNumber( DWORD *pdwChangeNumber ) { HRESULT hRes = _pMBCom->ComMDGetSystemChangeNumber(pdwChangeNumber);
if ( SUCCEEDED( hRes )) { return TRUE; }
SetLastError( HRESULTTOWIN32( hRes )); return FALSE; }
BOOL MB::DeleteData(const CHAR * pszPath, DWORD dwPropID, DWORD dwUserType, DWORD dwDataType ) { HRESULT hRes = _pMBCom->ComMDDeleteMetaData( _hMB, (LPBYTE) pszPath, dwPropID, dwDataType );
if ( SUCCEEDED( hRes )) { return TRUE; } SetLastError( HRESULTTOWIN32( hRes )); return(FALSE); }
BOOL MB::Close( VOID ) { if ( _hMB ) { DBG_REQUIRE( SUCCEEDED(_pMBCom->ComMDCloseMetaObject( _hMB )) ); _hMB = NULL; }
return TRUE; }
BOOL MB::Open( METADATA_HANDLE hOpenRoot, const CHAR * pszPath, DWORD dwFlags ) /*++
Routine Description:
Opens the metabase
Arguments:
hOpenRoot - Relative root or METADATA_MASTER_ROOT_HANDLE pszPath - Path to open dwFlags - Open flags
Return:
TRUE if success, FALSE on error, (call GetLastError())
--*/ { HRESULT hRes;
DBG_ASSERT(_hMB == NULL);
hRes = _pMBCom->ComMDOpenMetaObject( hOpenRoot, (BYTE *) pszPath, dwFlags, MB_TIMEOUT, &_hMB );
if ( SUCCEEDED( hRes )) { return TRUE; }
DBGPRINTF(( DBG_CONTEXT, "[MB::Open] Failed to open %s, error %x (%d)\n", pszPath, hRes, HRESULTTOWIN32( hRes ) ));
SetLastError( HRESULTTOWIN32( hRes ) );
return FALSE; }
BOOL MB::SetData( const CHAR * pszPath, DWORD dwPropID, DWORD dwUserType, DWORD dwDataType, VOID * pvData, DWORD cbData, DWORD dwFlags ) /*++
Routine Description:
Sets a metadata property on an openned metabase
Arguments:
pszPath - Path to set data on dwPropID - Metabase property ID dwUserType - User type for this property dwDataType - Type of data being set (dword, string etc) pvData - Pointer to data cbData - Size of data dwFlags - Inheritance flags
Return:
TRUE if success, FALSE on error, (call GetLastError())
--*/ { METADATA_RECORD mdRecord; HRESULT hRes;
DBG_ASSERT( _hMB );
mdRecord.dwMDIdentifier = dwPropID; mdRecord.dwMDAttributes = dwFlags; mdRecord.dwMDUserType = dwUserType; mdRecord.dwMDDataType = dwDataType; mdRecord.dwMDDataLen = cbData; mdRecord.pbMDData = (PBYTE) pvData;
hRes = _pMBCom->ComMDSetMetaData( _hMB, (LPBYTE) pszPath, &mdRecord );
if ( SUCCEEDED( hRes )) { return TRUE; }
DBGPRINTF(( DBG_CONTEXT, "[MB::SetData] Failed to open %s, error %x (%d)\n", pszPath, hRes, HRESULTTOWIN32( hRes ) ));
SetLastError( HRESULTTOWIN32( hRes ) );
return FALSE; }
BOOL MB::GetData( const CHAR * pszPath, DWORD dwPropID, DWORD dwUserType, DWORD dwDataType, VOID * pvData, DWORD * pcbData, DWORD dwFlags ) /*++
Routine Description:
Retrieves a metadata property on an openned metabase
Arguments:
pszPath - Path to set data on dwPropID - Metabase property ID dwUserType - User type for this property dwDataType - Type of data being set (dword, string etc) pvData - Pointer to data pcbData - Size of pvData, receives size of object dwFlags - Inheritance flags
Return:
TRUE if success, FALSE on error, (call GetLastError())
--*/ { DBG_ASSERT( _hMB ); DBG_ASSERT(pcbData);
METADATA_RECORD mdRecord; HRESULT hRes; DWORD dwRequiredLen = *pcbData;
mdRecord.dwMDIdentifier = dwPropID; mdRecord.dwMDAttributes = dwFlags; mdRecord.dwMDUserType = dwUserType; mdRecord.dwMDDataType = dwDataType; mdRecord.dwMDDataLen = *pcbData; mdRecord.pbMDData = (PBYTE) pvData;
hRes = _pMBCom->ComMDGetMetaData( _hMB, (LPBYTE) pszPath, &mdRecord, &dwRequiredLen );
if ( SUCCEEDED( hRes )) { *pcbData = mdRecord.dwMDDataLen; return TRUE; }
*pcbData = dwRequiredLen;
#if 0
DBGPRINTF(( DBG_CONTEXT, "[MB::GetData] Failed, PropID(%d), UserType(%d) Flags(%d) on %s, hRes = 0x%08x (%d)\n", dwPropID, dwUserType, dwFlags, pszPath, hRes, HRESULTTOWIN32( hRes ) )); #endif
SetLastError( HRESULTTOWIN32( hRes ) );
return FALSE; }
BOOL MB::ReferenceData( const CHAR * pszPath, DWORD dwPropID, DWORD dwUserType, DWORD dwDataType, VOID * * ppvData, DWORD * pcbData, DWORD * pdwTag, DWORD dwFlags ) /*++
Routine Description:
References a metadata property item
Arguments:
pszPath - Path to set data on dwPropID - Metabase property ID dwUserType - User type for this property dwDataType - Type of data being set (dword, string etc) ppvData - Receives pointer to referenced data pdwTag - Receives dword tag for releasing this reference dwFlags - flags (must have METADATA_REFERENCE)
Return:
TRUE if success, FALSE on error, (call GetLastError())
--*/ { METADATA_RECORD mdRecord; HRESULT hRes; DWORD dwRequiredLen;
DBG_ASSERT( _hMB );
mdRecord.dwMDIdentifier = dwPropID; mdRecord.dwMDAttributes = dwFlags; mdRecord.dwMDUserType = dwUserType; mdRecord.dwMDDataType = dwDataType; mdRecord.dwMDDataLen = 0; mdRecord.pbMDData = NULL;
hRes = _pMBCom->ComMDGetMetaData( _hMB, (LPBYTE) pszPath, &mdRecord, &dwRequiredLen );
if ( SUCCEEDED( hRes )) { *ppvData = mdRecord.pbMDData; *pcbData = mdRecord.dwMDDataLen; *pdwTag = mdRecord.dwMDDataTag;
return TRUE; }
SetLastError( HRESULTTOWIN32( hRes ) );
return FALSE; }
BOOL MB::GetAll( const CHAR * pszPath, DWORD dwFlags, DWORD dwUserType, BUFFER * pBuff, DWORD * pcRecords, DWORD * pdwDataSetNumber ) /*++
Routine Description:
Retrieves all the metabase properties on this path of the request type
Arguments:
pszPath - Path to set data on dwFlags - Inerhitance flags dwPropID - Metabase property ID dwUserType - User type for this property dwDataType - Type of data being set (dword, string etc) pvData - Pointer to data pcbData - Size of pvData, receives size of object dwFlags - Inheritance flags
Return:
TRUE if success, FALSE on error, (call GetLastError())
--*/ { DWORD RequiredSize; HRESULT hRes;
DBG_ASSERT( _hMB );
TryAgain:
hRes = _pMBCom->ComMDGetAllMetaData( _hMB, (unsigned char *)pszPath, dwFlags, dwUserType, ALL_METADATA, pcRecords, pdwDataSetNumber, pBuff->QuerySize(), (PBYTE)pBuff->QueryPtr(), &RequiredSize );
// See if we got it, and if we failed because of lack of buffer space
// try again.
if ( SUCCEEDED(hRes) ) { return TRUE; }
// Some sort of error, most likely not enough buffer space. Keep
// trying until we get a non-fatal error.
if (HRESULT_FACILITY(hRes) == FACILITY_WIN32 && HRESULT_CODE(hRes) == ERROR_INSUFFICIENT_BUFFER) {
// Not enough buffer space. RequiredSize contains the amount
// the metabase thinks we need.
if ( !pBuff->Resize(RequiredSize) ) {
// Not enough memory to resize.
return FALSE; }
goto TryAgain;
}
return FALSE; }
BOOL MB::GetDataSetNumber( const CHAR * pszPath, DWORD * pdwDataSetNumber ) /*++
Routine Description:
Retrieves the data set number and size of the data from the metabase.
Arguments:
pszPath - Path to set data on pdwDataSetNumber - Where to return the data set number.
Return:
TRUE if success, FALSE on error, (call GetLastError())
--*/ { HRESULT hRes;
//
// We allow _hMB to be null (root handle) for this API (though technically
// all the APIs allow the metabase handle to be null)
//
hRes = _pMBCom->ComMDGetDataSetNumber( _hMB, (unsigned char *)pszPath, pdwDataSetNumber );
return SUCCEEDED(hRes); }
BOOL MB::GetStr( const CHAR * pszPath, DWORD dwPropID, DWORD dwUserType, STR * pstrValue, DWORD dwFlags, const CHAR * pszDefault ) /*++
Routine Description:
Retrieves the string from the metabase. If the value wasn't found and a default is supplied, then the default value is copied to the string.
Arguments:
pszPath - Path to get data on dwPropID - property id to retrieve dwUserType - User type for this property pstrValue - string that receives the value dwFlags - Metabase flags pszDefault - Default value to use if the string isn't found, NULL for no default value (i.e., will return an error).
Return:
TRUE if success, FALSE on error, (call GetLastError())
--*/ { DWORD cbSize = pstrValue->QuerySize();
TryAgain:
if ( !GetData( pszPath, dwPropID, dwUserType, STRING_METADATA, pstrValue->QueryStr(), &cbSize, dwFlags )) { if ( GetLastError() == MD_ERROR_DATA_NOT_FOUND ) { if ( pszDefault != NULL ) { return pstrValue->Copy( pszDefault ); }
return FALSE; } else if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER && pstrValue->Resize( cbSize ) ) { goto TryAgain; }
return FALSE; }
DBG_REQUIRE( pstrValue->SetLen( cbSize ? (cbSize - 1) : 0 ));
return TRUE; }
BOOL MB::GetMultisz( const CHAR * pszPath, DWORD dwPropID, DWORD dwUserType, MULTISZ * multiszValue, DWORD dwFlags ) /*++
Routine Description:
Retrieves the string from the metabase. If the value wasn't found and a default is supplied, then the default value is copied to the string.
Arguments:
pszPath - Path to get data on dwPropID - property id to retrieve dwUserType - User type for this property multiszValue - multi-string that receives the value dwFlags - Metabase flags
Return:
TRUE if success, FALSE on error, (call GetLastError())
--*/ { DWORD cbSize = multiszValue->QuerySize();
TryAgain:
if ( !GetData( pszPath, dwPropID, dwUserType, MULTISZ_METADATA, multiszValue->QueryStr(), &cbSize, dwFlags )) { if ( GetLastError() == MD_ERROR_DATA_NOT_FOUND ) { return FALSE; } else if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER && multiszValue->Resize( cbSize ) ) { goto TryAgain; }
return FALSE; }
//
// Value was read directly into the buffer so update the member
// variables
//
multiszValue->RecalcLen();
return TRUE; }
BOOL MB::GetDataPaths( const CHAR * pszPath, DWORD dwPropID, DWORD dwDataType, BUFFER * pBuff ) /*++
Routine Description:
Retrieves all the metabase properties on this path of the request type
Arguments:
pszPath - Path to set data on dwFlags - Inerhitance flags dwPropID - Metabase property ID dwUserType - User type for this property dwDataType - Type of data being set (dword, string etc) pvData - Pointer to data pcbData - Size of pvData, receives size of object dwFlags - Inheritance flags
Return:
TRUE if success, FALSE on error, (call GetLastError())
--*/ { DWORD RequiredSize; HRESULT hRes;
DBG_ASSERT( _hMB ); DBG_ASSERT( pBuff != NULL );
TryAgain:
hRes = _pMBCom->ComMDGetMetaDataPaths( _hMB, (unsigned char *)pszPath, dwPropID, dwDataType, pBuff->QuerySize(), (PBYTE)pBuff->QueryPtr(), &RequiredSize );
// See if we got it, and if we failed because of lack of buffer space
// try again.
if ( SUCCEEDED(hRes) ) { return TRUE; }
// Some sort of error, most likely not enough buffer space. Keep
// trying until we get a non-fatal error.
if (HRESULT_FACILITY(hRes) == FACILITY_WIN32 && HRESULT_CODE(hRes) == ERROR_INSUFFICIENT_BUFFER) {
// Not enough buffer space. RequiredSize contains the amount
// the metabase thinks we need.
if ( !pBuff->Resize(RequiredSize) ) {
// Not enough memory to resize.
return FALSE; }
goto TryAgain;
}
return FALSE; }
|