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

805 lines
16 KiB
C++

/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
oleutil.cpp
Abstract:
Provides Useful functions for dealing with OLE.
Author:
Magnus Hedlund (MagnusH) --
Revision History:
--*/
#include "stdafx.h"
#include "iadm.h"
#include "oleutil.h"
#include "cmultisz.h"
#include "resource.h"
//$-------------------------------------------------------------------
//
// UpdateChangedMask
//
// Description:
//
// Marks a field as changed in the given bit vector
//
// Parameters:
//
// pbvChangedProps - points to the bit vector
// dwBitMask - Bit to turn on. (must have only one bit on)
//
//--------------------------------------------------------------------
static void UpdateChangedMask ( DWORD * pbvChangedProps, DWORD dwBitMask )
{
if ( pbvChangedProps == NULL ) {
// Legal, means that the caller doesn't want change tracking.
return;
}
_ASSERT ( dwBitMask != 0 );
*pbvChangedProps |= dwBitMask;
}
HRESULT LongArrayToVariantArray ( SAFEARRAY * psaLongs, SAFEARRAY ** ppsaVariants )
{
_ASSERT ( psaLongs );
HRESULT hr = NOERROR;
long lLBound = 0;
long lUBound = 0;
long i;
SAFEARRAYBOUND bounds;
SAFEARRAY * psaVariants;
*ppsaVariants = NULL;
_ASSERT ( SafeArrayGetDim ( psaLongs ) == 1 );
SafeArrayGetLBound ( psaLongs, 1, &lLBound );
SafeArrayGetUBound ( psaLongs, 1, &lUBound );
bounds.lLbound = lLBound;
bounds.cElements = lUBound - lLBound + 1;
psaVariants = SafeArrayCreate ( VT_VARIANT, 1, &bounds );
for ( i = lLBound; i <= lUBound; i++ ) {
VARIANT var;
long lTemp;
VariantInit ( &var );
hr = SafeArrayGetElement ( psaLongs, &i, &lTemp );
if ( FAILED(hr) ) {
goto Exit;
}
V_VT (&var) = VT_I4;
V_I4 (&var) = lTemp;
hr = SafeArrayPutElement ( psaVariants, &i, &var );
if ( FAILED(hr) ) {
goto Exit;
}
VariantClear ( &var );
}
*ppsaVariants = psaVariants;
Exit:
return hr;
}
HRESULT StringArrayToVariantArray ( SAFEARRAY * psaStrings, SAFEARRAY ** ppsaVariants )
{
_ASSERT ( psaStrings );
HRESULT hr = NOERROR;
long lLBound = 0;
long lUBound = 0;
long i;
SAFEARRAYBOUND bounds;
SAFEARRAY * psaVariants;
*ppsaVariants = NULL;
_ASSERT ( SafeArrayGetDim ( psaStrings ) == 1 );
SafeArrayGetLBound ( psaStrings, 1, &lLBound );
SafeArrayGetUBound ( psaStrings, 1, &lUBound );
bounds.lLbound = lLBound;
bounds.cElements = lUBound - lLBound + 1;
psaVariants = SafeArrayCreate ( VT_VARIANT, 1, &bounds );
for ( i = lLBound; i <= lUBound; i++ ) {
VARIANT var;
CComBSTR strTemp;
VariantInit ( &var );
hr = SafeArrayGetElement ( psaStrings, &i, &strTemp );
if ( FAILED(hr) ) {
goto Exit;
}
V_VT (&var) = VT_BSTR;
V_BSTR (&var) = ::SysAllocString ( strTemp );
hr = SafeArrayPutElement ( psaVariants, &i, &var );
if ( FAILED(hr) ) {
goto Exit;
}
VariantClear ( &var );
}
*ppsaVariants = psaVariants;
Exit:
return hr;
}
HRESULT VariantArrayToStringArray ( SAFEARRAY * psaVariants, SAFEARRAY ** ppsaStrings )
{
_ASSERT ( psaVariants );
HRESULT hr = NOERROR;
long lLBound = 0;
long lUBound = 0;
long i;
SAFEARRAYBOUND bounds;
SAFEARRAY * psaStrings;
_ASSERT ( SafeArrayGetDim ( psaVariants ) == 1 );
*ppsaStrings = NULL;
SafeArrayGetLBound ( psaVariants, 1, &lLBound );
SafeArrayGetUBound ( psaVariants, 1, &lUBound );
bounds.lLbound = lLBound;
bounds.cElements = lUBound - lLBound + 1;
psaStrings = SafeArrayCreate ( VT_BSTR, 1, &bounds );
for ( i = lLBound; i <= lUBound; i++ ) {
VARIANT var;
CComBSTR strTemp;
VariantInit ( &var );
hr = SafeArrayGetElement ( psaVariants, &i, &var );
if ( FAILED(hr) ) {
goto Exit;
}
strTemp = V_BSTR (&var);
hr = SafeArrayPutElement ( psaStrings, &i, strTemp );
if ( FAILED(hr) ) {
goto Exit;
}
VariantClear (&var);
}
*ppsaStrings = psaStrings;
Exit:
return hr;
}
//$-------------------------------------------------------------------
//
// StdPropertyGet < BSTR, long, DWORD, DATE >
//
// Description:
//
// Performs a default Property Get on a BSTR, long, DWORD or
// Ole DATE.
//
// Parameters:
//
// Property - The property to get.
// pOut - The resulting copy.
//
// Returns:
//
// E_POINTER - invalid arguments
// E_OUTOFMEMORY - Not enough memory to copy
// NOERROR - success.
//
//--------------------------------------------------------------------
HRESULT StdPropertyGet ( const BSTR strProperty, BSTR * pstrOut )
{
TraceQuietEnter ( "StdPropertyGet <BSTR>" );
_ASSERT ( pstrOut != NULL );
_ASSERT ( IS_VALID_OUT_PARAM ( pstrOut ) );
if ( pstrOut == NULL ) {
FatalTrace ( 0, "Bad return pointer" );
return E_POINTER;
}
*pstrOut = NULL;
if ( strProperty == NULL ) {
// If the property is NULL, use a blank string:
*pstrOut = ::SysAllocString ( _T("") );
}
else {
_ASSERT ( IS_VALID_STRING ( strProperty ) );
// Copy the property into the result:
*pstrOut = ::SysAllocString ( strProperty );
}
if ( *pstrOut == NULL ) {
// Allocation failed.
FatalTrace ( 0, "Out of memory" );
return E_OUTOFMEMORY;
}
return NOERROR;
}
HRESULT StdPropertyGet ( long lProperty, long * plOut )
{
TraceQuietEnter ( "StdPropertyGet <long>" );
_ASSERT ( plOut != NULL );
_ASSERT ( IS_VALID_OUT_PARAM ( plOut ) );
if ( plOut == NULL ) {
FatalTrace ( 0, "Bad return pointer" );
return E_POINTER;
}
*plOut = lProperty;
return NOERROR;
}
HRESULT StdPropertyGet ( DATE dateProperty, DATE * pdateOut )
{
TraceQuietEnter ( "StdPropertyGet <DATE>" );
_ASSERT ( pdateOut != NULL );
_ASSERT ( IS_VALID_OUT_PARAM ( pdateOut ) );
if ( pdateOut == NULL ) {
FatalTrace ( 0, "Bad return pointer" );
return E_POINTER;
}
*pdateOut = dateProperty;
return NOERROR;
}
HRESULT StdPropertyGet ( const CMultiSz * pmszProperty, SAFEARRAY ** ppsaStrings )
{
TraceFunctEnter ( "StdPropertyGet <MULTI_SZ>" );
_ASSERT ( pmszProperty );
_ASSERT ( IS_VALID_OUT_PARAM ( ppsaStrings ) );
HRESULT hr = NOERROR;
*ppsaStrings = pmszProperty->ToSafeArray ( );
if ( *ppsaStrings == NULL ) {
hr = E_OUTOFMEMORY;
goto Exit;
}
Exit:
TraceFunctLeave ();
return hr;
}
HRESULT StdPropertyGetBit ( DWORD bvBitVector, DWORD dwBit, BOOL * pfOut )
{
_ASSERT ( IS_VALID_OUT_PARAM ( pfOut ) );
if ( !pfOut ) {
return E_POINTER;
}
*pfOut = GetBitFlag ( bvBitVector, dwBit );
return NOERROR;
}
//$-------------------------------------------------------------------
//
// StdPropertyPut <BSTR, long, DWORD or DATE>
//
// Description:
//
// Performs a default Property Put on a BSTR, long, DWORD or
// Ole date.
//
// Parameters:
//
// pProperty - The property to put.
// New - The new value.
// pbvChangedProps [optional] - Bit Vector which holds which
// properties have changed.
// dwBitMask [optional] - This property's bitmask for the
// changed bit vector.
//
// Returns:
//
// E_POINTER - invalid arguments
// E_OUTOFMEMORY - Not enough memory to copy
// NOERROR - success.
//
//--------------------------------------------------------------------
HRESULT StdPropertyPut (
BSTR * pstrProperty,
const BSTR strNew,
DWORD * pbvChangedProps, // = NULL
DWORD dwBitMask // = 0
)
{
TraceQuietEnter ( "StdPropertyPut <BSTR>" );
// Validate Parameters:
_ASSERT ( pstrProperty != NULL );
_ASSERT ( IS_VALID_OUT_PARAM ( pstrProperty ) );
_ASSERT ( strNew != NULL );
_ASSERT ( IS_VALID_STRING ( strNew ) );
if ( pstrProperty == NULL ) {
FatalTrace ( 0, "Bad property pointer" );
return E_POINTER;
}
if ( strNew == NULL ) {
FatalTrace ( 0, "Bad pointer" );
return E_POINTER;
}
HRESULT hr = NOERROR;
BSTR strCopy = NULL;
// Copy the new string:
strCopy = ::SysAllocString ( strNew );
if ( strCopy == NULL ) {
hr = E_OUTOFMEMORY;
FatalTrace ( 0, "Out of memory" );
goto Error;
}
// Update the changed bit, if necessary:
if ( *pstrProperty && lstrcmp ( *pstrProperty, strCopy ) != 0 ) {
UpdateChangedMask ( pbvChangedProps, dwBitMask );
}
// Replace the old property with the new one.
SAFE_FREE_BSTR ( *pstrProperty );
*pstrProperty = strCopy;
Error:
return hr;
}
HRESULT StdPropertyPut (
long * plProperty,
long lNew,
DWORD * pbvChangedProps, // = NULL
DWORD dwBitMask // = 0
)
{
TraceQuietEnter ( "StdPropertyPut <long>" );
_ASSERT ( plProperty != NULL );
_ASSERT ( IS_VALID_OUT_PARAM ( plProperty ) );
if ( plProperty == NULL ) {
FatalTrace ( 0, "Bad pointer" );
return E_POINTER;
}
if ( *plProperty != lNew ) {
UpdateChangedMask ( pbvChangedProps, dwBitMask );
}
*plProperty = lNew;
return NOERROR;
}
HRESULT StdPropertyPut (
DATE * pdateProperty,
DATE dateNew,
DWORD * pbvChangedProps, // = NULL
DWORD dwBitMask // = 0
)
{
TraceQuietEnter ( "StdPropertyPut <DATE>" );
_ASSERT ( pdateProperty != NULL );
_ASSERT ( IS_VALID_OUT_PARAM ( pdateProperty ) );
if ( pdateProperty == NULL ) {
FatalTrace ( 0, "Bad pointer" );
return E_POINTER;
}
if ( *pdateProperty != dateNew ) {
UpdateChangedMask ( pbvChangedProps, dwBitMask );
}
*pdateProperty = dateNew;
return NOERROR;
}
HRESULT StdPropertyPut ( CMultiSz * pmszProperty, SAFEARRAY * psaStrings, DWORD * pbvChangedProps, DWORD dwBitMask )
{
TraceFunctEnter ( "StdPropertyPut <MULTI_SZ>" );
_ASSERT ( IS_VALID_IN_PARAM ( psaStrings ) );
_ASSERT ( IS_VALID_OUT_PARAM ( pmszProperty ) );
if ( psaStrings == NULL ) {
FatalTrace ( 0, "Bad return pointer" );
TraceFunctLeave ();
return E_POINTER;
}
HRESULT hr = NOERROR;
pmszProperty->FromSafeArray ( psaStrings );
if ( !*pmszProperty ) {
hr = E_OUTOFMEMORY;
goto Exit;
}
// Don't want to deal with comparing these properties:
UpdateChangedMask ( pbvChangedProps, dwBitMask );
Exit:
TraceFunctLeave ();
return hr;
}
HRESULT StdPropertyPutBit ( DWORD * pbvBitVector, DWORD dwBit, BOOL fIn )
{
_ASSERT ( IS_VALID_OUT_PARAM ( pbvBitVector ) );
_ASSERT ( dwBit );
SetBitFlag ( pbvBitVector, dwBit, fIn );
return NOERROR;
}
//$-------------------------------------------------------------------
//
// PV_MaxChars
//
// Description:
//
// Validates a string to make sure it's not too long.
//
// Parameters:
//
// strProperty - the string to check
// nMaxChars - the maximum number of characters in the string,
// not including the NULL terminator.
//
// Returns:
//
// FALSE if the string is too long.
//
//--------------------------------------------------------------------
BOOL PV_MaxChars ( const BSTR strProperty, DWORD nMaxChars )
{
TraceQuietEnter ( "PV_MaxChars" );
_ASSERT ( strProperty != NULL );
_ASSERT ( IS_VALID_STRING ( strProperty ) );
_ASSERT ( nMaxChars > 0 );
if ( strProperty == NULL ) {
// This error should be caught somewhere else.
return TRUE;
}
if ( (DWORD) lstrlen ( strProperty ) > nMaxChars ) {
ErrorTrace ( 0, "String too long" );
return FALSE;
}
return TRUE;
}
//$-------------------------------------------------------------------
//
// PV_MinMax <int, dword>
//
// Description:
//
// Makes sure a property is within a given range.
//
// Parameters:
//
// nProperty - the value to test
// nMin - The minimum value the property could have
// nMax - The maximum value the property could have
//
// Returns:
//
// TRUE if the property is in the range (inclusive).
//
//--------------------------------------------------------------------
BOOL PV_MinMax ( int nProperty, int nMin, int nMax )
{
TraceQuietEnter ( "PV_MinMax" );
_ASSERT ( nMin <= nMax );
if ( nProperty < nMin || nProperty > nMax ) {
ErrorTrace ( 0, "Integer out of range" );
return FALSE;
}
return TRUE;
}
BOOL PV_MinMax ( DWORD dwProperty, DWORD dwMin, DWORD dwMax )
{
TraceQuietEnter ( "PV_MinMax" );
_ASSERT ( dwMin <= dwMax );
if ( dwProperty < dwMin || dwProperty > dwMax ) {
ErrorTrace ( 0, "Dword out of range" );
return FALSE;
}
return TRUE;
}
BOOL PV_Boolean ( BOOL fProperty )
{
TraceQuietEnter ( "PV_Boolean" );
if ( fProperty != TRUE && fProperty != FALSE ) {
ErrorTrace ( 0, "Boolean property is not true or false" );
return FALSE;
}
return TRUE;
}
//$-------------------------------------------------------------------
//
// StdPropertyGetIDispatch
//
// Description:
//
// Gets a IDispatch pointer for the given cLSID
//
// Parameters:
//
// clsid - OLE CLSID of the object
// ppIDipsatch - the IDispatch pointer to that object.
//
// Returns:
//
// E_POINTER - invalid argument
// NOERROR - Success
// Others - defined by CoCreateInstance.
//
//--------------------------------------------------------------------
HRESULT StdPropertyGetIDispatch (
REFCLSID clsid,
IDispatch ** ppIDispatch
)
{
TraceFunctEnter ( "StdPropertyGetIDispatch" );
CComPtr<IDispatch> pNewIDispatch;
HRESULT hr = NOERROR;
_ASSERT ( ppIDispatch );
if ( ppIDispatch == NULL ) {
FatalTrace ( 0, "Bad return pointer" );
TraceFunctLeave ();
return E_POINTER;
}
*ppIDispatch = NULL;
hr = ::CoCreateInstance (
clsid,
NULL,
CLSCTX_ALL,
IID_IDispatch,
(void **) &pNewIDispatch
);
if ( FAILED (hr) ) {
DebugTraceX ( 0, "CoCreate(IDispatch) failed %x", hr );
FatalTrace ( 0, "Failed to create IDispatch" );
goto Exit;
}
*ppIDispatch = pNewIDispatch;
pNewIDispatch.p->AddRef ();
Exit:
TraceFunctLeave ();
return hr;
// Destructor releases pNewIDispatch
}
//$-------------------------------------------------------------------
//
// InetAddressToString
//
// Description:
//
// Converts a DWORD with an ip address to a string in the form
// "xxx.xxx.xxx.xxx"
//
// Parameters:
//
// dwAddress - The address to convert
// wszAddress - The resulting string
// cAddress - The maximum size of the resulting string
//
// Returns:
//
// TRUE if succeeded, FALSE otherwise.
//
//--------------------------------------------------------------------
BOOL InetAddressToString ( DWORD dwAddress, LPWSTR wszAddress, DWORD cAddress )
{
TraceFunctEnter ( "InetAddressToString" );
_ASSERT ( wszAddress );
if ( wszAddress == NULL ) {
FatalTrace ( 0, "Bad pointer" );
TraceFunctLeave ();
return FALSE;
}
struct in_addr addr;
LPSTR szAnsiAddress;
DWORD cchCopied;
addr.s_addr = dwAddress;
szAnsiAddress = inet_ntoa ( addr );
if ( szAnsiAddress == NULL ) {
ErrorTraceX ( 0, "inet_ntoa failed: %x", GetLastError() );
TraceFunctLeave ();
return FALSE;
}
cchCopied = MultiByteToWideChar (
CP_ACP,
MB_PRECOMPOSED,
szAnsiAddress,
-1,
wszAddress,
cAddress
);
if ( cchCopied == 0 ) {
ErrorTraceX ( 0, "MultiByteToWideChar failed: %x", GetLastError() );
TraceFunctLeave ();
return FALSE;
}
TraceFunctLeave ();
return TRUE;
}
//$-------------------------------------------------------------------
//
// StringToInetAddress
//
// Description:
//
// Converts a string in the form "xxx.xxx.xxx.xxx" to a DWORD
// IP Address.
//
// Parameters:
//
// wszAddress - The string to convert
// pdwAddress - The resulting address
//
// Returns:
//
// TRUE if succeeded, FALSE otherwise.
//
//--------------------------------------------------------------------
BOOL StringToInetAddress ( LPCWSTR wszAddress, DWORD * pdwAddress )
{
TraceFunctEnter ( "StringToInetAddress" );
_ASSERT ( wszAddress );
_ASSERT ( pdwAddress );
if ( wszAddress == NULL ) {
FatalTrace ( 0, "Bad pointer" );
TraceFunctLeave ();
return FALSE;
}
if ( pdwAddress == NULL ) {
FatalTrace ( 0, "Bad return pointer" );
TraceFunctLeave ();
return FALSE;
}
char szAnsiAddress[100];
DWORD cchCopied;
*pdwAddress = 0;
cchCopied = WideCharToMultiByte (
CP_ACP,
0,
wszAddress,
-1,
szAnsiAddress,
sizeof ( szAnsiAddress ),
NULL,
NULL
);
if ( cchCopied == 0 ) {
ErrorTraceX ( 0, "MultiByteToWideChar failed: %x", GetLastError() );
TraceFunctLeave ();
return FALSE;
}
*pdwAddress = inet_addr ( szAnsiAddress );
if ( !*pdwAddress ) {
ErrorTraceX ( 0, "inet_addr failed: %x", GetLastError () );
}
TraceFunctLeave ();
return TRUE;
}