Windows2003-3790/inetsrv/iis/svcs/smtp/adminsso/metautil.cpp
2020-09-30 16:53:55 +02:00

360 lines
8.8 KiB
C++

/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
metautil.cpp
Abstract:
Useful functions for dealing with the metabase
Author:
Magnus Hedlund (MagnusH) --
Revision History:
--*/
#include "stdafx.h"
#include "smtpcmn.h"
#include "cmultisz.h"
#include "oleutil.h"
#include "metautil.h"
#include "metakey.h"
// Metabase property manipulation:
BOOL StdGetMetabaseProp ( CMetabaseKey * pMB, DWORD dwID, BOOL fDefault, BOOL * pfOut, LPCWSTR wszPath, DWORD dwUserType, DWORD dwFlags )
{
TraceQuietEnter ( "StdGetMetabaseProp<BOOL>" );
HRESULT hr;
DWORD dwTemp;
hr = pMB->GetDword ( wszPath, dwID, &dwTemp, dwFlags, dwUserType );
if ( hr == MD_ERROR_DATA_NOT_FOUND ) {
// Couldn't find property, use defaults.
DebugTraceX ( 0, "Using default for ID: %d", dwID );
dwTemp = fDefault;
hr = NOERROR;
}
BAIL_ON_FAILURE(hr);
*pfOut = dwTemp;
Exit:
if ( FAILED(hr) ) {
ErrorTraceX ( 0, "Failed to get metabase property ID: %d, Error: %x", dwID, hr );
SetLastError ( HRESULTTOWIN32 ( hr ) );
}
return SUCCEEDED(hr);
}
BOOL StdGetMetabaseProp ( CMetabaseKey * pMB, DWORD dwID, DWORD dwDefault, DWORD * pdwOut, LPCWSTR wszPath, DWORD dwUserType, DWORD dwFlags )
{
TraceQuietEnter ( "StdGetMetabaseProp<DWORD>" );
DWORD dwTemp;
HRESULT hr;
hr = pMB->GetDword ( wszPath, dwID, &dwTemp, dwFlags, dwUserType );
if ( hr == MD_ERROR_DATA_NOT_FOUND ) {
// Couldn't find property, use defaults.
DebugTraceX ( 0, "Using default for ID: %d", dwID );
dwTemp = dwDefault;
hr = NOERROR;
}
BAIL_ON_FAILURE(hr);
*pdwOut = dwTemp;
Exit:
if ( FAILED(hr) ) {
ErrorTraceX ( 0, "Failed to get metabase property ID: %d, Error: %x", dwID, hr );
SetLastError ( HRESULTTOWIN32 ( hr ) );
}
return SUCCEEDED(hr);
}
BOOL StdGetMetabaseProp ( CMetabaseKey * pMB, DWORD dwID, LPCWSTR wszDefault, BSTR * pstrOut, LPCWSTR wszPath, DWORD dwUserType, DWORD dwFlags )
{
TraceQuietEnter ( "StdGetMetabaseProp <BSTR>" );
HRESULT hr = NOERROR;
BSTR strNew = NULL;
DWORD cbRequired = 0;
DWORD cchRequired = 0;
BOOL fUseDefault = FALSE;
// Get the length of the string to retrieve:
hr = pMB->GetDataSize ( wszPath, dwID, STRING_METADATA, &cbRequired, dwFlags, dwUserType );
cchRequired = cbRequired / sizeof ( WCHAR );
// Is the value there?
if ( hr == MD_ERROR_DATA_NOT_FOUND ) {
// No, so use the default that was passed in.
DebugTraceX ( 0, "Using default for ID: %d", dwID );
fUseDefault = TRUE;
hr = NOERROR;
}
BAIL_ON_FAILURE(hr);
if ( !fUseDefault ) {
strNew = ::SysAllocStringLen ( NULL, cbRequired );
if ( !strNew ) {
FatalTrace ( 0, "Out of memory" );
BAIL_WITH_FAILURE(hr, E_OUTOFMEMORY);
}
// Get the metabase string:
hr = pMB->GetString ( wszPath, dwID, strNew, cbRequired, dwFlags, dwUserType );
BAIL_ON_FAILURE(hr);
}
if ( fUseDefault ) {
// Use the default:
DebugTraceX ( 0, "Using default for ID: %d", dwID );
strNew = ::SysAllocString ( wszDefault );
if ( !strNew ) {
FatalTrace ( 0, "Out of memory" );
BAIL_WITH_FAILURE(hr, E_OUTOFMEMORY);
}
}
SAFE_FREE_BSTR ( *pstrOut );
*pstrOut = strNew;
Exit:
if ( FAILED(hr) ) {
ErrorTraceX ( 0, "Failed to get metabase property ID: %d, Error: %x", dwID, hr );
SetLastError ( HRESULTTOWIN32 ( hr ) );
}
return SUCCEEDED(hr);
}
BOOL StdGetMetabaseProp ( CMetabaseKey * pMB, DWORD dwID, LPCWSTR mszDefault, CMultiSz * pmszOut, LPCWSTR wszPath, DWORD dwUserType, DWORD dwFlags )
{
TraceQuietEnter ( "StdGetMetabaseProp <CMultiSz>" );
HRESULT hr = NOERROR;
BSTR strNew = NULL;
DWORD cbRequired = 0;
DWORD cchRequired = 0;
BOOL fUseDefault = FALSE;
LPWSTR msz = NULL;
// Get the length of the string to retrieve:
hr = pMB->GetDataSize ( wszPath, dwID, MULTISZ_METADATA, &cbRequired, dwFlags, dwUserType );
cchRequired = cbRequired / sizeof ( WCHAR );
// Is the value there?
if ( hr == MD_ERROR_DATA_NOT_FOUND ) {
// No, so use the default that was passed in.
DebugTraceX ( 0, "Using default for ID: %d", dwID );
fUseDefault = TRUE;
hr = NOERROR;
}
BAIL_ON_FAILURE(hr);
if ( !fUseDefault ) {
msz = new WCHAR [ cchRequired ];
if ( !msz ) {
FatalTrace ( 0, "Out of memory" );
BAIL_WITH_FAILURE(hr, E_OUTOFMEMORY);
}
// Get the metabase string:
hr = pMB->GetData ( wszPath, dwID, dwUserType, MULTISZ_METADATA, msz, &cbRequired, dwFlags );
BAIL_ON_FAILURE(hr);
*pmszOut = msz;
}
if ( fUseDefault ) {
// Use the default:
DebugTraceX ( 0, "Using default for ID: %d", dwID );
*pmszOut = mszDefault;
}
if ( !*pmszOut ) {
BAIL_WITH_FAILURE(hr, E_OUTOFMEMORY);
}
Exit:
delete msz;
if ( FAILED(hr) ) {
ErrorTraceX ( 0, "Failed to get metabase property ID: %d, Error: %x", dwID, hr );
SetLastError ( HRESULTTOWIN32 ( hr ) );
}
return SUCCEEDED(hr);
}
BOOL StdPutMetabaseProp ( CMetabaseKey * pMB, DWORD dwID, BOOL fValue, LPCWSTR wszPath, DWORD dwUserType, DWORD dwFlags )
{
TraceQuietEnter ( "StdPutMetabaseProp <BOOL>" );
HRESULT hr;
hr = pMB->SetDword ( wszPath, dwID, fValue, dwFlags, dwUserType );
if ( FAILED(hr) ) {
ErrorTraceX ( 0, "Failed to put metabase property ID: %d, Error: %x", dwID, hr );
SetLastError ( HRESULTTOWIN32 ( hr ) );
}
return SUCCEEDED(hr);
}
BOOL StdPutMetabaseProp ( CMetabaseKey * pMB, DWORD dwID, DWORD dwValue, LPCWSTR wszPath, DWORD dwUserType, DWORD dwFlags )
{
TraceQuietEnter ( "StdPutMetabaseProp <DWORD>" );
HRESULT hr;
hr = pMB->SetDword ( wszPath, dwID, dwValue, dwFlags, dwUserType );
if ( FAILED(hr) ) {
ErrorTraceX ( 0, "Failed to put metabase property ID: %d, Error: %x", dwID, hr );
SetLastError ( HRESULTTOWIN32 ( hr ) );
}
return SUCCEEDED(hr);
}
BOOL StdPutMetabaseProp ( CMetabaseKey * pMB, DWORD dwID, BSTR strValue, LPCWSTR wszPath, DWORD dwUserType, DWORD dwFlags )
{
TraceQuietEnter ( "StdPutMetabaseProp <BSTR>" );
_ASSERT ( strValue );
HRESULT hr;
if ( !strValue ) {
// Just skip it, but log the trace.
FatalTrace ( 0, "strValue should not be NULL here" );
return TRUE;
}
hr = pMB->SetString ( wszPath, dwID, strValue, dwFlags, dwUserType );
BAIL_ON_FAILURE (hr);
Exit:
if ( FAILED(hr) ) {
ErrorTraceX ( 0, "Failed to put metabase property ID: %d, Error: %x", dwID, hr );
SetLastError ( HRESULTTOWIN32 ( hr ) );
}
return SUCCEEDED(hr);
}
BOOL StdPutMetabaseProp ( CMetabaseKey * pMB, DWORD dwID, CMultiSz * pmszValue, LPCWSTR wszPath, DWORD dwUserType, DWORD dwFlags )
{
TraceQuietEnter ( "StdPutMetabaseProp <BSTR>" );
_ASSERT ( pmszValue );
if ( !*pmszValue ) {
// Just skip it, but log the trace.
FatalTrace ( 0, "strValue should not be NULL here" );
return TRUE;
}
HRESULT hr;
DWORD cbMultiSz;
LPCWSTR wszValue;
cbMultiSz = pmszValue->SizeInBytes ();
wszValue = *pmszValue;
hr = pMB->SetData ( wszPath, dwID, dwUserType, MULTISZ_METADATA, (void *) wszValue, cbMultiSz, dwFlags );
BAIL_ON_FAILURE (hr);
Exit:
if ( FAILED(hr) ) {
ErrorTraceX ( 0, "Failed to put metabase property ID: %d, Error: %x", dwID, hr );
SetLastError ( HRESULTTOWIN32 ( hr ) );
}
return SUCCEEDED(hr);
}
BOOL HasKeyChanged ( IMSAdminBase * pMetabase, METADATA_HANDLE hKey, const FILETIME * pftLastChanged, LPCWSTR wszSubKey )
{
TraceFunctEnter ( "HasKeyChanged" );
FILETIME ftNew;
HRESULT hr = NOERROR;
BOOL fResult = FALSE;
if ( pftLastChanged->dwHighDateTime == 0 && pftLastChanged->dwLowDateTime == 0 ) {
ErrorTrace ( 0, "Last changed time is NULL" );
// No setting, so say it hasn't changed:
goto Exit;
}
hr = pMetabase->GetLastChangeTime ( hKey, wszSubKey, &ftNew, FALSE );
if ( FAILED (hr) ) {
ErrorTrace ( 0, "Failed to get last change time: %x", hr );
// This is an unexpected error. Ignore it.
goto Exit;
}
// Has the metabase been changed since last time?
// Time can't go backwards:
_ASSERT ( ftNew.dwHighDateTime >= pftLastChanged->dwHighDateTime );
_ASSERT ( ftNew.dwLowDateTime >= pftLastChanged->dwLowDateTime ||
ftNew.dwHighDateTime > pftLastChanged->dwHighDateTime );
if ( ftNew.dwHighDateTime != pftLastChanged->dwHighDateTime ||
ftNew.dwLowDateTime != pftLastChanged->dwLowDateTime ) {
fResult = TRUE;
}
Exit:
TraceFunctLeave ();
return FALSE;
}
BOOL IsValidIntegerSubKey ( LPCWSTR wszSubKey )
{
TraceQuietEnter ( "IsValidIntegerSubKey" );
WCHAR wszIntegerKey [ METADATA_MAX_NAME_LEN ];
DWORD dwItemValue;
dwItemValue = _wtoi ( wszSubKey );
wsprintf ( wszIntegerKey, _T("%d"), dwItemValue );
// If the key is nonzero AND
// The key is just the itoa value of the number:
if ( dwItemValue != 0 &&
lstrcmp ( wszIntegerKey, wszSubKey ) == 0 ) {
return TRUE;
}
else {
return FALSE;
}
}