/*++ 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 " ); _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 " ); _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 " ); _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 " ); _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 // // 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 " ); // 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 " ); _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 " ); _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 " ); _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 // // 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 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; }