554 lines
15 KiB
C++
554 lines
15 KiB
C++
/*++
|
|
|
|
Module Name:
|
|
|
|
wrapmb.cpp
|
|
|
|
Abstract:
|
|
|
|
wrapper classes for the metabase class. Yes, I am wrapping a wrapper. Why?
|
|
because including mb.hxx totally screws up the headers in my stdafx based
|
|
MFC files. This way they can just include wrapmb.h and not have to worry
|
|
about including all the other stuff. Also, I can set INITGUID here. That
|
|
way I can use precompiled headers in the main project to Greatly increase
|
|
compile times. If that isn't reason enough, then I can also manage the pointer
|
|
to the interface object itself here.
|
|
|
|
Author:
|
|
|
|
Boyd Multerer boydm
|
|
|
|
--*/
|
|
#include "stdafx.h"
|
|
#include <objbase.h>
|
|
#include <initguid.h>
|
|
#include <iadmw.h>
|
|
|
|
#include "iiscnfgp.h"
|
|
#include "wrapmb.h"
|
|
|
|
#ifdef _NO_TRACING_
|
|
DECLARE_DEBUG_PRINTS_OBJECT();
|
|
#endif
|
|
|
|
#define MB_TIMEOUT 5000
|
|
|
|
|
|
// a macro to automatically cast the pointer to the mb object
|
|
//#define _pmb ((MB*)m_pvMB)
|
|
|
|
|
|
// globals
|
|
IMSAdminBase* g_pMBCom = NULL;
|
|
|
|
|
|
|
|
//----------------------------------------------------------------
|
|
BOOL FInitMetabaseWrapperEx( OLECHAR* pocMachineName, IMSAdminBase ** ppiab )
|
|
{
|
|
IClassFactory * pcsfFactory = NULL;
|
|
COSERVERINFO csiMachineName;
|
|
COSERVERINFO * pcsiParam = NULL;
|
|
|
|
HRESULT hresError;
|
|
|
|
if(!ppiab)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//fill the structure for CoGetClassObject
|
|
ZeroMemory( &csiMachineName, sizeof(csiMachineName) );
|
|
// csiMachineName.pAuthInfo = NULL;
|
|
// csiMachineName.dwFlags = 0;
|
|
// csiMachineName.pServerInfoExt = NULL;
|
|
csiMachineName.pwszName = pocMachineName;
|
|
pcsiParam = &csiMachineName;
|
|
|
|
hresError = CoGetClassObject(
|
|
GETAdminBaseCLSID(TRUE),
|
|
CLSCTX_SERVER,
|
|
pcsiParam,
|
|
IID_IClassFactory,
|
|
(void**) &pcsfFactory
|
|
);
|
|
|
|
if (FAILED(hresError))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
// create the instance of the interface
|
|
hresError = pcsfFactory->CreateInstance(NULL, IID_IMSAdminBase, (void **)ppiab);
|
|
if (FAILED(hresError))
|
|
{
|
|
*ppiab = NULL;
|
|
return FALSE;
|
|
}
|
|
|
|
// release the factory
|
|
pcsfFactory->Release();
|
|
|
|
// success
|
|
return TRUE;
|
|
}
|
|
|
|
//----------------------------------------------------------------
|
|
BOOL FCloseMetabaseWrapperEx(IMSAdminBase ** ppiab)
|
|
{
|
|
if ( ppiab && *ppiab)
|
|
{
|
|
(*ppiab)->Release();
|
|
*ppiab = NULL;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
//----------------------------------------------------------------
|
|
BOOL FInitMetabaseWrapper( OLECHAR * pocMachineName )
|
|
{
|
|
//release previous interface if needed
|
|
if( g_pMBCom != NULL )
|
|
{
|
|
g_pMBCom->Release();
|
|
g_pMBCom = NULL;
|
|
}
|
|
|
|
return FInitMetabaseWrapperEx(pocMachineName, &g_pMBCom);
|
|
}
|
|
|
|
//----------------------------------------------------------------
|
|
BOOL FCloseMetabaseWrapper()
|
|
{
|
|
return FCloseMetabaseWrapperEx(&g_pMBCom);
|
|
}
|
|
|
|
|
|
//=================================================================== The wrapper class
|
|
|
|
//----------------------------------------------------------------
|
|
CWrapMetaBase::CWrapMetaBase():
|
|
m_pMetabase( NULL ),
|
|
m_hMeta( NULL ),
|
|
m_count(0),
|
|
m_pBuffer( NULL ),
|
|
m_cbBuffer(0),
|
|
m_pPathBuffer( NULL ),
|
|
m_cchPathBuffer( 0 )
|
|
{
|
|
// attempt to allocate the general buffer
|
|
m_pBuffer = GlobalAlloc( GPTR, BUFFER_SIZE );
|
|
if ( m_pBuffer )
|
|
m_cbBuffer = BUFFER_SIZE;
|
|
}
|
|
|
|
//----------------------------------------------------------------
|
|
CWrapMetaBase::~CWrapMetaBase()
|
|
{
|
|
// make sure the metabase handle is closed
|
|
Close();
|
|
|
|
// free the buffer
|
|
if ( m_pBuffer )
|
|
GlobalFree( m_pBuffer );
|
|
m_pBuffer = NULL;
|
|
}
|
|
|
|
//----------------------------------------------------------------
|
|
BOOL CWrapMetaBase::FInit( PVOID pMBCom )
|
|
{
|
|
BOOL fAnswer = FALSE;
|
|
|
|
// NULL was passed in, use the global reference - most cases will do this
|
|
if ( pMBCom )
|
|
{
|
|
m_pMetabase = (IMSAdminBase *)pMBCom;
|
|
}
|
|
else
|
|
{
|
|
m_pMetabase = g_pMBCom;
|
|
}
|
|
|
|
// if the interface is not there, fail
|
|
if ( !m_pMetabase )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
// return success
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//==========================================================================================
|
|
// open, close and save the object and such
|
|
|
|
//----------------------------------------------------------------
|
|
BOOL CWrapMetaBase::Open( LPCTSTR pszPath, DWORD dwFlags )
|
|
{
|
|
return Open( METADATA_MASTER_ROOT_HANDLE, pszPath, dwFlags );
|
|
}
|
|
|
|
//----------------------------------------------------------------
|
|
BOOL CWrapMetaBase::Open( METADATA_HANDLE hOpenRoot, LPCTSTR pszPath, DWORD dwFlags )
|
|
{
|
|
m_count++;
|
|
HRESULT hRes;
|
|
|
|
// if a metabase handle is already open, close it
|
|
if ( m_hMeta )
|
|
Close();
|
|
|
|
hRes = m_pMetabase->OpenKey( hOpenRoot, pszPath, dwFlags, MB_TIMEOUT, &m_hMeta );
|
|
|
|
if ( SUCCEEDED( hRes ))
|
|
return TRUE;
|
|
SetLastError( HRESULTTOWIN32( hRes ) );
|
|
return FALSE;
|
|
}
|
|
|
|
//----------------------------------------------------------------
|
|
BOOL CWrapMetaBase::Close( void )
|
|
{
|
|
if ( m_hMeta )
|
|
{
|
|
m_count--;
|
|
m_pMetabase->CloseKey( m_hMeta );
|
|
}
|
|
m_hMeta = NULL;
|
|
return TRUE;
|
|
}
|
|
|
|
//----------------------------------------------------------------
|
|
BOOL CWrapMetaBase::Save( void )
|
|
{
|
|
HRESULT hRes = m_pMetabase->SaveData();
|
|
|
|
if ( SUCCEEDED( hRes ))
|
|
return TRUE;
|
|
SetLastError( HRESULTTOWIN32( hRes ));
|
|
return FALSE;
|
|
}
|
|
|
|
// enumerate the objects
|
|
//----------------------------------------------------------------
|
|
// fortunately, we know that there is a max length to the name of any individual
|
|
// key in the metabase of 256 characters
|
|
BOOL CWrapMetaBase::EnumObjects(
|
|
LPCTSTR pszPath,
|
|
LPTSTR pName,
|
|
DWORD cbNameBuf,
|
|
DWORD Index
|
|
)
|
|
{
|
|
// enumerate into the wide character buffer
|
|
HRESULT hRes = m_pMetabase->EnumKeys( m_hMeta, pszPath, pName, Index );
|
|
|
|
// Check for success
|
|
if ( SUCCEEDED( hRes ))
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
SetLastError( HRESULTTOWIN32( hRes ));
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//==========================================================================================
|
|
// Add and delete objects
|
|
//----------------------------------------------------------------
|
|
BOOL CWrapMetaBase::AddObject( LPCTSTR pszPath )
|
|
{
|
|
HRESULT hRes = m_pMetabase->AddKey( m_hMeta, pszPath );
|
|
|
|
if ( SUCCEEDED( hRes ))
|
|
return TRUE;
|
|
SetLastError( HRESULTTOWIN32( hRes ));
|
|
return FALSE;
|
|
}
|
|
|
|
//----------------------------------------------------------------
|
|
BOOL CWrapMetaBase::DeleteObject( LPCTSTR pszPath )
|
|
{
|
|
HRESULT hRes = m_pMetabase->DeleteKey( m_hMeta, pszPath );
|
|
|
|
if ( SUCCEEDED( hRes ))
|
|
return TRUE;
|
|
SetLastError( HRESULTTOWIN32( hRes ));
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//==========================================================================================
|
|
// access the metahandle
|
|
//----------------------------------------------------------------
|
|
METADATA_HANDLE CWrapMetaBase::QueryHandle()
|
|
{
|
|
return m_hMeta;
|
|
}
|
|
|
|
|
|
//==========================================================================================
|
|
// setting values
|
|
//----------------------------------------------------------------
|
|
BOOL CWrapMetaBase::SetDword( LPCTSTR pszPath, DWORD dwPropID, DWORD dwUserType,
|
|
DWORD dwValue, DWORD dwFlags )
|
|
{
|
|
return SetData( pszPath,
|
|
dwPropID,
|
|
dwUserType,
|
|
DWORD_METADATA,
|
|
(PVOID) &dwValue,
|
|
sizeof( DWORD ),
|
|
dwFlags );
|
|
}
|
|
|
|
//----------------------------------------------------------------
|
|
BOOL CWrapMetaBase::SetString( LPCTSTR pszPath, DWORD dwPropID, DWORD dwUserType,
|
|
LPCTSTR pszValue, DWORD dwFlags )
|
|
{
|
|
int len = wcslen( pszValue )+1;
|
|
DWORD cbWide = len * sizeof(WCHAR);
|
|
|
|
// set the string into place
|
|
BOOL fAnswer = SetData( pszPath,
|
|
dwPropID,
|
|
dwUserType,
|
|
STRING_METADATA,
|
|
(PVOID)pszValue,
|
|
cbWide, // string length ignored for inprocess clients
|
|
dwFlags );
|
|
|
|
// return the answer
|
|
return fAnswer;
|
|
}
|
|
|
|
//==========================================================================================
|
|
// getting values
|
|
//----------------------------------------------------------------
|
|
BOOL CWrapMetaBase::GetDword( LPCTSTR pszPath, DWORD dwPropID, DWORD dwUserType,
|
|
DWORD* pdwValue, DWORD dwFlags )
|
|
{
|
|
DWORD cb = sizeof(DWORD);
|
|
return GetData( pszPath,
|
|
dwPropID,
|
|
dwUserType,
|
|
DWORD_METADATA,
|
|
pdwValue,
|
|
&cb,
|
|
dwFlags );
|
|
}
|
|
|
|
//----------------------------------------------------------------
|
|
BOOL CWrapMetaBase::GetString( LPCTSTR pszPath, DWORD dwPropID, DWORD dwUserType,
|
|
LPTSTR pszValue, DWORD cchValue, DWORD dwFlags )
|
|
{
|
|
BOOL fAnswer = FALSE;
|
|
|
|
// get the data and put it right into the buffer - this is the wide version
|
|
if ( GetData( pszPath,
|
|
dwPropID,
|
|
dwUserType,
|
|
STRING_METADATA,
|
|
pszValue,
|
|
&cchValue,
|
|
dwFlags ) )
|
|
{
|
|
fAnswer = TRUE;
|
|
}
|
|
|
|
// return the answer
|
|
return fAnswer;
|
|
}
|
|
|
|
BOOL CWrapMetaBase::GetMultiSZString(
|
|
LPCTSTR pszPath,
|
|
DWORD dwPropID,
|
|
DWORD dwUserType,
|
|
LPTSTR pszValue,
|
|
DWORD cchValue,
|
|
DWORD dwFlags)
|
|
{
|
|
BOOL fAnswer = FALSE;
|
|
|
|
// get the data and put it right into the buffer - this is the wide version
|
|
if (GetData( pszPath,
|
|
dwPropID,
|
|
dwUserType,
|
|
MULTISZ_METADATA,
|
|
pszValue,
|
|
&cchValue,
|
|
dwFlags ) )
|
|
{
|
|
fAnswer = TRUE;
|
|
}
|
|
|
|
// return the answer
|
|
return fAnswer;
|
|
}
|
|
|
|
//==========================================================================================
|
|
// deleting values
|
|
//----------------------------------------------------------------
|
|
BOOL CWrapMetaBase::DeleteData( LPCTSTR pszPath, DWORD dwPropID, DWORD dwDataType )
|
|
{
|
|
// go right ahead and delete it
|
|
HRESULT hRes = m_pMetabase->DeleteData( m_hMeta, pszPath, dwPropID, dwDataType );
|
|
|
|
// test for success
|
|
if ( SUCCEEDED( hRes ))
|
|
return TRUE;
|
|
|
|
// clean up after a failure
|
|
SetLastError( HRESULTTOWIN32( hRes ));
|
|
return(FALSE);
|
|
}
|
|
|
|
//----------------------------------------------------------------
|
|
BOOL CWrapMetaBase::RenameObject( LPCTSTR pszPathOld, LPCTSTR pszNewName )
|
|
{
|
|
// rename the key
|
|
HRESULT hRes = m_pMetabase->RenameKey( m_hMeta, pszPathOld, pszNewName );
|
|
|
|
// test for success
|
|
if ( SUCCEEDED( hRes ))
|
|
return TRUE;
|
|
|
|
// clean up after a failure
|
|
SetLastError( HRESULTTOWIN32( hRes ));
|
|
return FALSE;
|
|
}
|
|
|
|
//=====================================================================================
|
|
|
|
//----------------------------------------------------------------
|
|
BOOL CWrapMetaBase::SetData( LPCTSTR pszPath, DWORD dwPropID, DWORD dwUserType, DWORD dwDataType,
|
|
PVOID pData, DWORD cbData, DWORD dwFlags )
|
|
{
|
|
METADATA_RECORD mdRecord;
|
|
HRESULT hRes;
|
|
|
|
// prepare the set data record
|
|
mdRecord.dwMDIdentifier = dwPropID;
|
|
mdRecord.dwMDAttributes = dwFlags;
|
|
mdRecord.dwMDUserType = dwUserType;
|
|
mdRecord.dwMDDataType = dwDataType;
|
|
mdRecord.dwMDDataLen = cbData;
|
|
mdRecord.pbMDData = (PBYTE)pData;
|
|
|
|
// set the data
|
|
hRes = m_pMetabase->SetData( m_hMeta, pszPath, &mdRecord );
|
|
|
|
// test for success
|
|
if ( SUCCEEDED( hRes ))
|
|
return TRUE;
|
|
|
|
// there was an error, clean up
|
|
SetLastError( HRESULTTOWIN32( hRes ) );
|
|
return FALSE;
|
|
}
|
|
|
|
//----------------------------------------------------------------
|
|
BOOL CWrapMetaBase::GetData( LPCTSTR pszPath, DWORD dwPropID, DWORD dwUserType, DWORD dwDataType,
|
|
PVOID pData, DWORD* pcbData, DWORD dwFlags )
|
|
{
|
|
METADATA_RECORD mdRecord;
|
|
HRESULT hRes;
|
|
DWORD dwRequiredLen;
|
|
|
|
// prepare the get data record
|
|
mdRecord.dwMDIdentifier = dwPropID;
|
|
mdRecord.dwMDAttributes = dwFlags;
|
|
mdRecord.dwMDUserType = dwUserType;
|
|
mdRecord.dwMDDataType = dwDataType;
|
|
mdRecord.dwMDDataLen = *pcbData;
|
|
mdRecord.pbMDData = (PBYTE)pData;
|
|
|
|
// get the data
|
|
hRes = m_pMetabase->GetData( m_hMeta, pszPath, &mdRecord, &dwRequiredLen );
|
|
|
|
// test for success
|
|
if ( SUCCEEDED( hRes ))
|
|
{
|
|
*pcbData = mdRecord.dwMDDataLen;
|
|
return TRUE;
|
|
}
|
|
|
|
// there was a failure - clean up
|
|
*pcbData = dwRequiredLen;
|
|
SetLastError( HRESULTTOWIN32( hRes ) );
|
|
return FALSE;
|
|
}
|
|
|
|
//----------------------------------------------------------------
|
|
// another form of GetData that automatically allocates the buffer. It should then be
|
|
// freed using GlobalFree(p);
|
|
PVOID CWrapMetaBase::GetData( LPCTSTR pszPath, DWORD dwPropID, DWORD dwUserType, DWORD dwDataType,
|
|
DWORD* pcbData, DWORD dwFlags )
|
|
{
|
|
PVOID pData = m_pBuffer;
|
|
DWORD cbData = m_cbBuffer;
|
|
DWORD err = 0;
|
|
BOOL f;
|
|
|
|
// first - attempt to get the data in the buffer that has already been allocated;
|
|
f = GetData( pszPath, dwPropID, dwUserType, dwDataType, pData, &cbData, dwFlags );
|
|
|
|
// if the get data function worked, we can pretty much leave
|
|
if ( f )
|
|
{
|
|
// set the data size
|
|
*pcbData = cbData;
|
|
// return the allocated buffer
|
|
return pData;
|
|
}
|
|
|
|
// check the error - it could be some sort of memory error
|
|
err = GetLastError();
|
|
|
|
// it is ok that the GetData failed, but the reason had better be ERROR_INSUFFICIENT_BUFFER
|
|
// otherwise, it is something we can't handle
|
|
if ( err != ERROR_INSUFFICIENT_BUFFER )
|
|
return NULL;
|
|
|
|
// allocate the buffer
|
|
pData = GlobalAlloc( GPTR, cbData );
|
|
if ( !pData )
|
|
return NULL;
|
|
|
|
// first, get the size of the data that we are looking for
|
|
f = GetData( pszPath, dwPropID, dwUserType, dwDataType, pData, &cbData, dwFlags );
|
|
|
|
// if that getting failed, we need to cleanup
|
|
if ( !f )
|
|
{
|
|
GlobalFree( pData );
|
|
pData = NULL;
|
|
}
|
|
|
|
// set the data size
|
|
*pcbData = cbData;
|
|
|
|
// return the allocated buffer
|
|
return pData;
|
|
}
|
|
|
|
//----------------------------------------------------------------
|
|
// free memory returned by GetData
|
|
void CWrapMetaBase::FreeWrapData( PVOID pData )
|
|
{
|
|
// if it is trying to free the local buffer, do nothing
|
|
if ( pData == m_pBuffer )
|
|
{
|
|
return;
|
|
}
|
|
|
|
// ah - but it was not the local buffer - we should dispose of it
|
|
if ( pData )
|
|
{
|
|
GlobalFree( pData );
|
|
}
|
|
}
|