360 lines
8.4 KiB
C++
360 lines
8.4 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 "nntpcmn.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;
|
||
|
}
|
||
|
}
|
||
|
|