Leaked source code of windows server 2003
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

/*++
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()