You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
647 lines
17 KiB
647 lines
17 KiB
/*++
|
|
|
|
Copyright (c) 1997 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
simplemb.cxx
|
|
|
|
Abstract:
|
|
|
|
based on mb.cxx from the iisrearc project
|
|
|
|
This module implements the MB class using the DCOM interface.
|
|
|
|
The old MB class (IIS4.0) was used internally within the IIS codebase to
|
|
access the metabase objects locally inprocess. This allowed access to
|
|
the metabase using the inprocess ANSI/COM interface.
|
|
|
|
In the current incarnation, MB class attempts to support the following:
|
|
o Support UNICODE only interface to items
|
|
o Use only the DCOM interface of the Metabase (IMSAdminBase interface)
|
|
o Expose similar functionality like the MB class.
|
|
|
|
Return Values:
|
|
Almost all MB class members return BOOL values.
|
|
TRUE indicates success in the operation and FALSE indicates a failure.
|
|
The class is expected to be used in-process for code that is mostly
|
|
reliant on the Win32 style error reporting, it sets the error code in
|
|
the thread and exposes them via GetLastError() interface.
|
|
Author:
|
|
|
|
Murali Krishnan (MuraliK) 03-Nov-1998
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
/************************************************************
|
|
* Include Headers
|
|
************************************************************/
|
|
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <windows.h>
|
|
|
|
#include <ole2.h>
|
|
|
|
#include <iadmw.h>
|
|
#include <simplemb.hxx>
|
|
#include "dbgutil.h"
|
|
|
|
//
|
|
// Default timeout
|
|
//
|
|
|
|
#define MB_TIMEOUT (30 * 1000)
|
|
|
|
//
|
|
// Default timeout for SaveData
|
|
//
|
|
|
|
#define MB_SAVE_TIMEOUT (10 * 1000) // milliseconds
|
|
|
|
|
|
/************************************************************
|
|
* Member Functions of SimpleMB
|
|
************************************************************/
|
|
|
|
SimpleMB::SimpleMB( IMSAdminBase * pAdminBase )
|
|
: m_pAdminBase( pAdminBase ),
|
|
m_hMBPath ( NULL)
|
|
{
|
|
DBG_ASSERT( m_pAdminBase != NULL);
|
|
|
|
//
|
|
// Add ref the admin base object so that we can keep this object around.
|
|
//
|
|
m_pAdminBase->AddRef();
|
|
}
|
|
|
|
SimpleMB::~SimpleMB( VOID )
|
|
{
|
|
//
|
|
// Close the metabase handle if we have it open
|
|
//
|
|
if ( NULL != m_hMBPath) {
|
|
//
|
|
// Close can sometimes fail with error RPC_E_DISCONNECTED.
|
|
// Do not Assert
|
|
//
|
|
Close();
|
|
}
|
|
|
|
//
|
|
// Release the AdminBase object here
|
|
//
|
|
if ( NULL != m_pAdminBase) {
|
|
m_pAdminBase->Release();
|
|
m_pAdminBase = NULL;
|
|
}
|
|
} // SimpleMB::~SimpleMB()
|
|
|
|
|
|
|
|
|
|
/*********************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Opens the metabase and saves the metabase handle in the current object.
|
|
Note: If there is already an opened handle, this method will fail.
|
|
|
|
Arguments:
|
|
|
|
hOpenRoot - Relative root or METADATA_MASTER_ROOT_HANDLE
|
|
pwszPath - Path to open
|
|
dwFlags - Open flags
|
|
|
|
Return:
|
|
|
|
TRUE if success, FALSE on error, (call GetLastError())
|
|
The handle opened is stored inside the MB object.
|
|
|
|
--*********************************************************************/
|
|
BOOL
|
|
SimpleMB::Open( METADATA_HANDLE hOpenRoot,
|
|
LPCWSTR pwszPath,
|
|
DWORD dwFlags )
|
|
{
|
|
HRESULT hr;
|
|
|
|
if ( m_hMBPath != NULL) {
|
|
SetLastError( ERROR_PATH_NOT_FOUND );
|
|
return (FALSE);
|
|
}
|
|
|
|
hr = m_pAdminBase->OpenKey( hOpenRoot,
|
|
pwszPath,
|
|
dwFlags,
|
|
MB_TIMEOUT,
|
|
&m_hMBPath );
|
|
|
|
if ( SUCCEEDED( hr ))
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
SetLastError( HRESULTTOWIN32( hr ) );
|
|
return FALSE;
|
|
} // SimpleMB::Open()
|
|
|
|
|
|
|
|
/*********************************************************************++
|
|
Routine Descrition:
|
|
This function closes the metabase handle that we have open in
|
|
this MB object
|
|
|
|
Arguments:
|
|
None
|
|
|
|
Returns:
|
|
TRUE on success
|
|
FALSE if there are any errors. Use GetLastError() to retrieve the error
|
|
on failure.
|
|
--*********************************************************************/
|
|
|
|
BOOL SimpleMB::Close( VOID )
|
|
{
|
|
if ( m_hMBPath )
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = m_pAdminBase->CloseKey( m_hMBPath );
|
|
|
|
if (FAILED(hr)) {
|
|
SetLastError( HRESULTTOWIN32( hr));
|
|
return (FALSE);
|
|
}
|
|
|
|
m_hMBPath = NULL;
|
|
}
|
|
|
|
return TRUE;
|
|
} // SimpleMB::Close()
|
|
|
|
|
|
|
|
/*********************************************************************++
|
|
Routine Descrition:
|
|
This function saves all the changes that we have made using current
|
|
metabase object.
|
|
|
|
Arguments:
|
|
None
|
|
|
|
Returns:
|
|
TRUE on success
|
|
FALSE if there are any errors. Use GetLastError() to retrieve the error
|
|
on failure.
|
|
--*********************************************************************/
|
|
BOOL SimpleMB::Save( VOID )
|
|
{
|
|
HRESULT hr;
|
|
|
|
if ( NULL != m_pAdminBase) {
|
|
hr = m_pAdminBase->SaveData();
|
|
|
|
if ( FAILED( hr)) {
|
|
SetLastError( HRESULTTOWIN32( hr));
|
|
return (FALSE);
|
|
}
|
|
}
|
|
|
|
return (TRUE);
|
|
} // SimpleMB::Save()
|
|
|
|
|
|
|
|
|
|
/*********************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Retrieves all the metabase properties on this path of the request type
|
|
|
|
Arguments:
|
|
|
|
pszPath - Path to get the 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())
|
|
|
|
--*********************************************************************/
|
|
BOOL
|
|
SimpleMB::GetAll( IN LPCWSTR pszPath,
|
|
DWORD dwFlags,
|
|
DWORD dwUserType,
|
|
BUFFER * pBuff,
|
|
DWORD * pcRecords,
|
|
DWORD * pdwDataSetNumber )
|
|
{
|
|
DWORD RequiredSize;
|
|
HRESULT hr;
|
|
|
|
DBG_ASSERT( m_pAdminBase != NULL);
|
|
DBG_ASSERT( m_hMBPath != NULL);
|
|
|
|
do {
|
|
|
|
hr = m_pAdminBase->
|
|
GetAllData( m_hMBPath,
|
|
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(hr) ) {
|
|
return TRUE;
|
|
}
|
|
|
|
//
|
|
// Some sort of error, most likely not enough buffer space. Keep
|
|
// trying until we get a non-fatal error.
|
|
//
|
|
|
|
if (HRESULT_FACILITY(hr) == FACILITY_WIN32 &&
|
|
HRESULT_CODE(hr) == 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;
|
|
}
|
|
} else {
|
|
|
|
//
|
|
// Some other failure: return the failure to caller
|
|
//
|
|
|
|
SetLastError(HRESULTTOWIN32(hr));
|
|
break;
|
|
}
|
|
} while (FAILED(hr));
|
|
|
|
return FALSE;
|
|
} // SimpleMB::GetAll()
|
|
|
|
|
|
|
|
/*********************************************************************++
|
|
Routine Description:
|
|
This function retrieves the data set number from the metabase
|
|
for the given path.
|
|
|
|
Arguments:
|
|
pszPath - pointer to string containing the path for metabase item
|
|
pdwDataSetNumber - pointer to DWORD that will contain the dataset
|
|
number on return.
|
|
|
|
Returns:
|
|
TRUE on success. FALSE for failure
|
|
--*********************************************************************/
|
|
BOOL
|
|
SimpleMB::GetDataSetNumber(IN LPCWSTR pszPath,
|
|
OUT DWORD * pdwDataSetNumber)
|
|
{
|
|
HRESULT hr;
|
|
|
|
DBG_ASSERT ( m_pAdminBase != NULL);
|
|
|
|
//
|
|
// NULL metabase handle is permitted here
|
|
//
|
|
|
|
hr = m_pAdminBase->GetDataSetNumber( m_hMBPath, pszPath, pdwDataSetNumber);
|
|
if (FAILED (hr)) {
|
|
SetLastError( HRESULTTOWIN32( hr));
|
|
return (FALSE);
|
|
}
|
|
|
|
return (TRUE);
|
|
} // SimpleMB::GetDataSetNumber()
|
|
|
|
|
|
|
|
/*********************************************************************++
|
|
Routine Description:
|
|
Enumerates and obtain the name of the object at given index position
|
|
within the given path in the tree.
|
|
|
|
Arguments:
|
|
pszPath - pointer to string containing the path for metabase item
|
|
pszName - pointer to a buffer that will contain the name of the item
|
|
at index position [dwIndex]. The buffer should at least be
|
|
ADMINDATA_MAX_NAME_LEN+1 character in length
|
|
dwIndex - index for the item to be enumerated.
|
|
|
|
Returns:
|
|
TRUE on success. FALSE for failure.
|
|
ERROR_NO_MORE_ITEMS when the end of the list is reached.
|
|
|
|
A typical use is to enumerate for all items starting at index 0 and
|
|
enumerating till the return value is FALSE with error = ERROR_NO_MORE_ITEMS
|
|
--*********************************************************************/
|
|
BOOL
|
|
SimpleMB::EnumObjects( IN LPCWSTR pszPath,
|
|
OUT LPWSTR pszName,
|
|
IN DWORD dwIndex )
|
|
{
|
|
HRESULT hr = m_pAdminBase->EnumKeys( m_hMBPath,
|
|
pszPath,
|
|
pszName,
|
|
dwIndex );
|
|
|
|
if ( SUCCEEDED( hr ))
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
SetLastError( HRESULTTOWIN32( hr ));
|
|
return FALSE;
|
|
} // SimpleMB::EnumObjects()
|
|
|
|
|
|
BOOL
|
|
SimpleMB::AddObject( IN LPCWSTR pszPath)
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = m_pAdminBase->AddKey( m_hMBPath, pszPath);
|
|
if (SUCCEEDED(hr)) {
|
|
return ( TRUE);
|
|
}
|
|
|
|
SetLastError( HRESULTTOWIN32( hr));
|
|
return (FALSE);
|
|
|
|
} // SimpleMB::AddObject()
|
|
|
|
|
|
BOOL
|
|
SimpleMB::DeleteObject( IN LPCWSTR pszPath)
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = m_pAdminBase->DeleteKey( m_hMBPath, pszPath);
|
|
if (SUCCEEDED(hr)) {
|
|
return ( TRUE);
|
|
}
|
|
|
|
SetLastError( HRESULTTOWIN32( hr));
|
|
return (FALSE);
|
|
} // SimpleMB::DeleteObject()
|
|
|
|
|
|
BOOL
|
|
SimpleMB::DeleteData(
|
|
IN LPCWSTR pszPath,
|
|
IN DWORD dwPropID,
|
|
IN DWORD /*dwUserType*/,
|
|
IN DWORD dwDataType )
|
|
{
|
|
HRESULT hr = m_pAdminBase->DeleteData( m_hMBPath,
|
|
pszPath,
|
|
dwPropID,
|
|
dwDataType
|
|
);
|
|
if ( SUCCEEDED( hr ))
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
SetLastError( HRESULTTOWIN32( hr ));
|
|
return(FALSE);
|
|
} // SimpleMB::DeleteData()
|
|
|
|
|
|
BOOL
|
|
SimpleMB::GetSystemChangeNumber( OUT DWORD * pdwChangeNumber)
|
|
{
|
|
HRESULT hr = m_pAdminBase->GetSystemChangeNumber( pdwChangeNumber);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
return ( TRUE);
|
|
}
|
|
|
|
SetLastError( HRESULTTOWIN32( hr));
|
|
return (FALSE);
|
|
}
|
|
|
|
|
|
/*********************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Sets a metadata property on an opened metabase path.
|
|
|
|
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 buffer containing the data.
|
|
cbData - Size of data
|
|
dwFlags - Inheritance flags
|
|
|
|
Return:
|
|
|
|
TRUE if success, FALSE on error, (call GetLastError())
|
|
|
|
--*********************************************************************/
|
|
BOOL
|
|
SimpleMB::SetData( IN LPCWSTR pszPath,
|
|
IN DWORD dwPropID,
|
|
IN DWORD dwUserType,
|
|
IN DWORD dwDataType,
|
|
IN VOID * pvData,
|
|
IN DWORD cbData,
|
|
IN DWORD dwFlags )
|
|
{
|
|
HRESULT hr;
|
|
METADATA_RECORD mdr;
|
|
|
|
DBG_ASSERT( m_pAdminBase != NULL);
|
|
DBG_ASSERT( m_hMBPath != NULL);
|
|
|
|
mdr.dwMDIdentifier = dwPropID;
|
|
mdr.dwMDAttributes = dwFlags;
|
|
mdr.dwMDUserType = dwUserType;
|
|
mdr.dwMDDataType = dwDataType;
|
|
mdr.dwMDDataLen = cbData;
|
|
mdr.pbMDData = (BYTE * ) pvData;
|
|
|
|
hr = m_pAdminBase->SetData(m_hMBPath, pszPath, &mdr);
|
|
if (SUCCEEDED(hr)) {
|
|
return ( TRUE);
|
|
}
|
|
|
|
SetLastError( HRESULTTOWIN32( hr));
|
|
return (FALSE);
|
|
|
|
} // SimpleMB::SetData()
|
|
|
|
|
|
|
|
|
|
/*********************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Obtains the metadata requested in the call.
|
|
It uses the current opened metabase path for getting the data.
|
|
|
|
Arguments:
|
|
|
|
pszPath - Path to get data on
|
|
dwPropID - Metabase property ID
|
|
dwUserType - User type for this property
|
|
dwDataType - Type of data being set (dword, string etc)
|
|
pvData - Pointer to buffer in which the data will be obtained
|
|
pcbData - Size of data
|
|
dwFlags - Inheritance flags
|
|
|
|
Return:
|
|
|
|
TRUE if success, FALSE on error, (call GetLastError())
|
|
|
|
--*********************************************************************/
|
|
BOOL
|
|
SimpleMB::GetData( IN LPCWSTR pszPath,
|
|
IN DWORD dwPropID,
|
|
IN DWORD dwUserType,
|
|
IN DWORD dwDataType,
|
|
OUT VOID * pvData,
|
|
IN OUT DWORD * pcbData,
|
|
IN DWORD dwFlags)
|
|
{
|
|
HRESULT hr;
|
|
METADATA_RECORD mdr;
|
|
DWORD dwRequiredDataLen;
|
|
|
|
DBG_ASSERT( m_pAdminBase != NULL);
|
|
DBG_ASSERT( m_hMBPath != NULL);
|
|
|
|
mdr.dwMDIdentifier = dwPropID;
|
|
mdr.dwMDAttributes = dwFlags;
|
|
mdr.dwMDUserType = dwUserType;
|
|
mdr.dwMDDataType = dwDataType;
|
|
mdr.dwMDDataLen = *pcbData;
|
|
mdr.pbMDData = (BYTE * ) pvData;
|
|
|
|
hr = m_pAdminBase->GetData(m_hMBPath, pszPath, &mdr, &dwRequiredDataLen);
|
|
|
|
if (SUCCEEDED(hr)) {
|
|
*pcbData = mdr.dwMDDataLen;
|
|
return ( TRUE);
|
|
}
|
|
|
|
*pcbData = dwRequiredDataLen;
|
|
|
|
SetLastError( HRESULTTOWIN32( hr));
|
|
return (FALSE);
|
|
} // SimpleMB::GetData()
|
|
|
|
|
|
|
|
/*********************************************************************++
|
|
|
|
Routine Description:
|
|
|
|
Obtains the paths beneath the given path in the metadata tree.
|
|
It uses the current opened metabase path for getting the data.
|
|
|
|
Arguments:
|
|
|
|
pszPath - Path to get data on
|
|
dwPropID - Metabase property ID
|
|
dwDataType - Type of data being set (dword, string etc)
|
|
pBuff - pointer to BUFFER object that will contain the resulting data
|
|
|
|
Return:
|
|
|
|
TRUE if success, FALSE on error, (call GetLastError())
|
|
|
|
--*********************************************************************/
|
|
BOOL
|
|
SimpleMB::GetDataPaths(IN LPCWSTR pszPath,
|
|
IN DWORD dwPropID,
|
|
IN DWORD dwDataType,
|
|
IN BUFFER * pBuff )
|
|
{
|
|
HRESULT hr;
|
|
DWORD cchRequiredDataLen;
|
|
|
|
DBG_ASSERT( m_pAdminBase != NULL);
|
|
DBG_ASSERT( m_hMBPath != NULL);
|
|
|
|
do {
|
|
|
|
hr = m_pAdminBase->GetDataPaths( m_hMBPath,
|
|
pszPath,
|
|
dwPropID,
|
|
dwDataType,
|
|
pBuff->QuerySize() / sizeof(WCHAR),
|
|
(LPWSTR ) pBuff->QueryPtr(),
|
|
&cchRequiredDataLen
|
|
);
|
|
|
|
if ( SUCCEEDED( hr)) {
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
// Some sort of error, most likely not enough buffer space. Keep
|
|
// trying until we get a non-fatal error.
|
|
|
|
if (HRESULT_FACILITY(hr) == FACILITY_WIN32 &&
|
|
HRESULT_CODE(hr) == ERROR_INSUFFICIENT_BUFFER)
|
|
{
|
|
|
|
// Not enough buffer space.
|
|
// cchRequiredDataLen contains the # of wide chars that metabase
|
|
// thinks we need.
|
|
|
|
if ( !pBuff->Resize( (cchRequiredDataLen + 1) * sizeof(WCHAR)) )
|
|
{
|
|
|
|
// Not enough memory to resize.
|
|
return FALSE;
|
|
}
|
|
} else {
|
|
|
|
// unknown failure. return failure
|
|
break;
|
|
}
|
|
|
|
} while (FAILED(hr));
|
|
|
|
DBG_ASSERT( FAILED(hr));
|
|
|
|
SetLastError( HRESULTTOWIN32( hr));
|
|
return (FALSE);
|
|
} // SimpleMB::GetDataPaths()
|