windows-nt/Source/XPSP1/NT/inetsrv/query/web/ixsso/ixsutil.cxx

765 lines
20 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1997 - 2000.
//
// File: ixsutil.cxx
//
// Contents: Utility SSO class
//
// History: 04 Apr 1997 Alanw Created
//
//----------------------------------------------------------------------------
#include "pch.cxx"
#pragma hdrstop
//-----------------------------------------------------------------------------
// Include Files
//-----------------------------------------------------------------------------
// debugging macros
#include "ssodebug.hxx"
// class declaration
#include "stdcf.hxx"
#include "ixsso.hxx"
#include "ixsutil.hxx"
#include <string.hxx>
#include <htmlchar.hxx>
extern WCHAR * g_pwszProgIdUtil;
#if CIDBG
extern ULONG g_ulObjCount;
extern LONG g_lUtlCount;
#endif // CIDBG
//-----------------------------------------------------------------------------
//
// Member: CixssoUtil::CixssoUtil - public
//
// Synopsis: Constructor of CixssoUtil
//
// Arguments: [pitlb] - pointer to ITypeLib for ixsso
//
// History: 04 Apr 1997 Alanw Created
//
//-----------------------------------------------------------------------------
CixssoUtil::CixssoUtil( ITypeLib * pitlb ) :
_ptinfo( 0 ),
_err( IID_IixssoUtil )
{
_cRef = 1;
SCODE sc = pitlb->GetTypeInfoOfGuid( IID_IixssoUtil, &_ptinfo );
if (FAILED(sc))
{
ixssoDebugOut(( DEB_ERROR, "Util - GetTypeInfoOfGuid failed (%x)\n", sc ));
Win4Assert(SUCCEEDED(sc));
THROW( CException(sc) );
}
INC_OBJECT_COUNT();
ixssoDebugOut((DEB_REFCOUNTS, "[DLL]: Create util: refcounts: glob %d util %d\n",
g_ulObjCount,
g_lUtlCount ));
} //CixssoUtil
//-----------------------------------------------------------------------------
//
// Member: CixssoUtil::~CixssoUtil - public
//
// Synopsis: Destructor of CixssoUtil
//
// History: 04 Apr 1997 Alanw Created
//
//-----------------------------------------------------------------------------
CixssoUtil::~CixssoUtil( )
{
if (_ptinfo)
_ptinfo->Release();
DEC_OBJECT_COUNT();
#if CIDBG
extern LONG g_lUtlCount;
LONG l = InterlockedDecrement( &g_lUtlCount );
Win4Assert( l >= 0 );
#endif //CIDBG
ixssoDebugOut((DEB_REFCOUNTS, "[DLL]: Delete util: refcounts: glob %d util %d\n",
g_ulObjCount,
g_lUtlCount ));
} //~CixssoUtl
#if 0 // NOTE: OnStartPage and OnEndPage are unneeded
//
// ASP Methods
//
#include <asp/asptlb.h>
STDMETHODIMP CixssoUtil::OnStartPage (IUnknown* pUnk)
{
// reset the error structure
_err.Reset();
SCODE sc;
IScriptingContext *piContext;
//Get IScriptingContext Interface
sc = pUnk->QueryInterface(IID_IScriptingContext, (void**)&piContext);
if (FAILED(sc))
return E_FAIL;
//Get Request Object Pointer
IRequest* piRequest = NULL;
sc = piContext->get_Request(&piRequest);
//Get ServerVariables Pointer
IRequestDictionary *piRequestDict = NULL;
sc = piRequest->get_ServerVariables(&piRequestDict);
VARIANT vtOut;
VariantInit(&vtOut);
//Get the HTTP_ACCEPT_LANGUAGE Item
sc = piRequestDict->get_Item(g_vtAcceptLanguageHeader, &vtOut);
//vtOut Contains an IDispatch Pointer. To fetch the value
//for HTTP_ACCEPT_LANGUAGE you must get the Default Value for the
//Object stored in vtOut using VariantChangeType.
if (V_VT(&vtOut) != VT_BSTR)
VariantChangeType(&vtOut, &vtOut, 0, VT_BSTR);
if (V_VT(&vtOut) == VT_BSTR)
{
ixssoDebugOut((DEB_TRACE, "OnStartPage: HTTP_ACCEPT_LANGUAGE = %ws\n",
V_BSTR(&vtOut) ));
SetLocaleString(V_BSTR(&vtOut));
}
else
{
ixssoDebugOut(( DEB_TRACE,
"OnStart: HTTP_ACCEPT_LANGAUGE was not set is ServerVariables; using lcid=0x%x\n",
GetSystemDefaultLCID() ));
put_LocaleID( GetSystemDefaultLCID() );
}
VariantClear(&vtOut);
piRequestDict->Release();
piRequest->Release();
piContext->Release();
return S_OK;
}
HRESULT CixssoUtil::OnEndPage(void)
{
return S_OK;
}
#endif // 0 NOTE: OnStartPage and OnEndPage are unneeded
//-----------------------------------------------------------------------------
// CixssoUtil IUnknown Methods
//-----------------------------------------------------------------------------
STDMETHODIMP
CixssoUtil::QueryInterface(REFIID iid, void * * ppv)
{
*ppv = 0;
if (iid == IID_IUnknown || iid == IID_IDispatch)
*ppv = (IDispatch *)this;
else if (iid == IID_ISupportErrorInfo )
*ppv = (ISupportErrorInfo *) this;
else if (iid == IID_IixssoUtil )
*ppv = (IixssoUtil *) this;
else
return E_NOINTERFACE;
AddRef();
return S_OK;
} //QueryInterface
STDMETHODIMP_(ULONG)
CixssoUtil::AddRef(void)
{
return InterlockedIncrement((long *)&_cRef);
}
STDMETHODIMP_(ULONG)
CixssoUtil::Release(void)
{
ULONG uTmp = InterlockedDecrement((long *)&_cRef);
if (uTmp == 0)
{
delete this;
return 0;
}
return uTmp;
}
//-----------------------------------------------------------------------------
// CixssoUtil IDispatch Methods
//-----------------------------------------------------------------------------
STDMETHODIMP
CixssoUtil::GetTypeInfoCount(UINT * pctinfo)
{
*pctinfo = 1;
return S_OK;
}
STDMETHODIMP
CixssoUtil::GetTypeInfo(
UINT itinfo,
LCID lcid,
ITypeInfo * * pptinfo)
{
_ptinfo->AddRef();
*pptinfo = _ptinfo;
return S_OK;
}
STDMETHODIMP
CixssoUtil::GetIDsOfNames(
REFIID riid,
OLECHAR * * rgszNames,
UINT cNames,
LCID lcid,
DISPID * rgdispid)
{
return DispGetIDsOfNames(_ptinfo, rgszNames, cNames, rgdispid);
}
STDMETHODIMP
CixssoUtil::Invoke(
DISPID dispidMember,
REFIID riid,
LCID lcid,
WORD wFlags,
DISPPARAMS * pParams,
VARIANT * pvarResult,
EXCEPINFO * pexcepinfo,
UINT * puArgErr)
{
ixssoDebugOut((DEB_IDISPATCH, "Util - Invoking method dispid=%d wFlags=%d\n",
dispidMember, wFlags ));
_err.Reset();
SCODE sc = DispInvoke( this, _ptinfo,
dispidMember, wFlags, pParams,
pvarResult, pexcepinfo, puArgErr );
if ( _err.IsError() )
sc = DISP_E_EXCEPTION;
return sc;
}
STDMETHODIMP
CixssoUtil::InterfaceSupportsErrorInfo(
REFIID riid)
{
if (riid == IID_IixssoUtil)
return S_OK;
else
return S_FALSE;
}
//+---------------------------------------------------------------------------
//
// Member: CixssoQuery::CopyWstrToBstr - private inline
//
// Synopsis: Copies a Unicode string to a BSTR
//
// Arguments: [pbstr] - destination BSTR
// [pwstr] - string to be copied
//
// Returns: SCODE - status return
//
// History: 25 Oct 1996 Alanw Created
//
//----------------------------------------------------------------------------
inline
SCODE CixssoUtil::CopyWstrToBstr( BSTR * pbstr, WCHAR const * pwstr )
{
*pbstr = 0;
if (pwstr)
{
*pbstr = SysAllocString( pwstr );
if (0 == *pbstr)
return E_OUTOFMEMORY;
}
return S_OK;
}
//-----------------------------------------------------------------------------
// CixssoUtil Methods
//-----------------------------------------------------------------------------
//+---------------------------------------------------------------------------
//
// Member: CixssoUtil::ISOToLocaleID - public
//
// Synopsis: Parse the input string for a recognizable locale name
//
// Arguments: [bstrLocale] - input string
// [pLcid] - pointer where corresponding LCID is returned
//
// Returns: SCODE - status return
//
// History: 04 Apr 1997 Alanw Created
//
//----------------------------------------------------------------------------
STDMETHODIMP
CixssoUtil::ISOToLocaleID(BSTR bstrLocale, LONG *pLcid)
{
_err.Reset();
if ( 0 == pLcid )
return E_INVALIDARG;
*pLcid = GetLCIDFromString( bstrLocale );
return S_OK;
}
//+---------------------------------------------------------------------------
//
// Member: CixssoUtil::LocaleIDToISO - public
//
// Synopsis: Return the ISO locale name for an LCID
//
// Arguments: [Lcid] - input LCID
// [pstr] - pointer where output string is returned
//
// Returns: SCODE - status return
//
// History: 04 Apr 1997 Alanw Created
//
//----------------------------------------------------------------------------
STDMETHODIMP
CixssoUtil::LocaleIDToISO(LONG lcid, BSTR * pstr)
{
_err.Reset();
if ( 0 == pstr )
return E_INVALIDARG;
WCHAR awc[100];
GetStringFromLCID( lcid, awc );
return CopyWstrToBstr( pstr, awc );
}
//+---------------------------------------------------------------------------
//
// Member: CixssoUtil::AddScopeToQuery - public
//
// Synopsis: Parse the input string for a recognizable locale name
//
// Arguments: [pDisp] - an IDispatch for the query object
// [bstrScope] - input scope
// [bstrDepth] - input depth (optional)
//
// Returns: SCODE - status return
//
// Notes: In the future, this will operate by modifying the query
// property to include a scope restriction.
// For now, it just adds the scope and depth via a private
// interface.
//
// History: 04 Apr 1997 Alanw Created
//
//----------------------------------------------------------------------------
STDMETHODIMP
CixssoUtil::AddScopeToQuery( IDispatch * pDisp,
BSTR bstrScope,
BSTR bstrDepth)
{
_err.Reset();
SCODE sc = S_OK;
CTranslateSystemExceptions translate;
TRY
{
if ( 0 == pDisp )
THROW( CException( E_INVALIDARG ) );
IixssoQueryPrivate * pIQueryPvt = 0;
sc = pDisp->QueryInterface( IID_IixssoQueryPrivate, (void **)&pIQueryPvt );
if (FAILED(sc))
{
THROW(CException(sc));
}
XInterface<IixssoQueryPrivate> pQry(pIQueryPvt);
pQry->AddScopeToQuery( bstrScope, bstrDepth );
}
CATCH( CIxssoException, e )
{
sc = e.GetErrorCode();
SetError( sc, OLESTR("AddScopeToQuery"), eIxssoError );
}
AND_CATCH( CException, e )
{
sc = e.GetErrorCode();
SetError( sc, OLESTR("AddScopeToQuery") );
}
END_CATCH
return sc;
} //AddScopeToQuery
//+---------------------------------------------------------------------------
//
// Member: CixssoUtil::TruncateToWhitespace - public
//
// Synopsis: Truncate a string, preferably at a white space character.
//
// Arguments: [bstrIn] - input string
// [maxLen] - maximum number of characters in output string
// [pbstrOut] - pointer where output string is returned
//
// Returns: SCODE - status return
//
// Notes: The implementation does not take into account real word breaks.
// This may not work too well on far eastern languages.
//
// History: 04 Apr 1997 Alanw Created
//
//----------------------------------------------------------------------------
STDMETHODIMP
CixssoUtil::TruncateToWhitespace(BSTR bstrIn, LONG maxLen, BSTR * pbstrOut)
{
_err.Reset();
ULONG cchString = 0;
if (maxLen <= 0)
return E_INVALIDARG;
if (0 != bstrIn)
cchString = SysStringLen(bstrIn);
if (cchString > (unsigned)maxLen)
{
cchString = maxLen;
for (unsigned i=0; i <= (unsigned)maxLen; i++)
{
if (iswspace(bstrIn[i]))
cchString = i;
}
}
*pbstrOut = SysAllocStringLen( bstrIn, cchString );
if (0 == *pbstrOut)
return E_OUTOFMEMORY;
return S_OK;
} //TruncateToWhitespace
class XVariant
{
public:
XVariant() : _pVar( 0 ) {}
XVariant( VARIANT & var ) : _pVar( &var ) {}
~XVariant() { if ( 0 != _pVar ) VariantClear( _pVar ); }
void Set( VARIANT & var ) { Win4Assert( 0 == _pVar ); _pVar = &var; }
private:
VARIANT * _pVar;
};
//+---------------------------------------------------------------------------
//
// Member: CixssoUtil::GetArrayElement - public
//
// Synopsis: Returns an element in an array as a variant
//
// Arguments: [pVarIn] - The input array (IDispatch or VT_ARRAY)
// [iElement] - The element to retrieve
// [pVarOut] - Where the array element result is written
//
// Returns: SCODE - status return
//
// History: 10 Sep 1997 dlee Created
// 18 Jan 2000 KLam DECIMAL needs to fit into a VARIANT
// on Win64 VARIANT is bigger than DECIMAL
//
//----------------------------------------------------------------------------
STDMETHODIMP CixssoUtil::GetArrayElement(
VARIANT * pVarIn,
LONG iElement,
VARIANT * pVarOut )
{
_err.Reset();
//
// Validate the variant arguments.
//
if ( ( 0 == pVarIn ) || ( 0 == pVarOut ) )
return SetError( E_INVALIDARG, OLESTR( "GetArrayElement" ) );
//
// Get the source array, either from the IDispatch or just copy it.
//
XVariant xvar;
VARIANT varArray;
VariantInit( &varArray );
if ( VT_DISPATCH == pVarIn->vt )
{
//
// The first argument is an IDispatch, not the array value, so we
// have to invoke it to get the value out.
//
if ( 0 == pVarIn->pdispVal )
return SetError( E_INVALIDARG, OLESTR( "GetArrayElement" ) );
DISPPARAMS dispparamsNoArgs = {NULL, NULL, 0, 0};
SCODE sc = pVarIn->pdispVal->Invoke( DISPID_VALUE,
IID_NULL,
GetSystemDefaultLCID(),
DISPATCH_PROPERTYGET,
&dispparamsNoArgs,
&varArray,
0,
0 );
ixssoDebugOut(( DEB_ITRACE, "result of invoke: 0x%x\n", sc ));
if ( FAILED( sc ) )
return SetError( sc, OLESTR( "GetArrayElement" ) );
xvar.Set( varArray );
}
else
{
varArray = *pVarIn;
}
ixssoDebugOut(( DEB_ITRACE, "value vt: 0x%x\n", varArray.vt ));
//
// Check for a valid variant array argument.
//
if ( ( 0 == ( VT_ARRAY & varArray.vt ) ) ||
( 0 == varArray.parray ) )
return SetError( E_INVALIDARG, OLESTR( "GetArrayElement" ) );
SAFEARRAY *psa = varArray.parray;
//
// This function only deals with 1-dimensional safearrays.
//
if ( 1 != SafeArrayGetDim( psa ) )
return SetError( E_INVALIDARG, OLESTR( "GetArrayElement" ) );
//
// Make sure iElement is in the bounds of the array.
//
long lLowBound;
SCODE sc = SafeArrayGetLBound( psa, 1, &lLowBound );
if ( FAILED( sc ) )
return SetError( sc, OLESTR( "GetArrayElement" ) );
long lUpBound;
sc = SafeArrayGetUBound( psa, 1, &lUpBound );
if ( FAILED( sc ) )
return SetError( sc, OLESTR( "GetArrayElement" ) );
if ( ( iElement < lLowBound ) || ( iElement > lUpBound ) )
return SetError( E_INVALIDARG, OLESTR( "GetArrayElement" ) );
//
// Get a pointer to the element.
//
void * pvData;
sc = SafeArrayPtrOfIndex( psa, &iElement, &pvData );
if ( FAILED( sc ) )
return SetError( sc, OLESTR( "GetArrayElement" ) );
//
// Put the element in a local variant so it can be copied.
//
VARIANT var;
VariantInit( &var );
var.vt = varArray.vt & (~VT_ARRAY);
unsigned cbElem = SafeArrayGetElemsize( psa );
if ( VT_VARIANT == var.vt )
{
Win4Assert( sizeof( VARIANT ) == cbElem );
RtlCopyMemory( &var, pvData, cbElem );
}
else if ( VT_DECIMAL == var.vt )
{
Win4Assert( sizeof( VARIANT ) >= cbElem &&
sizeof( DECIMAL ) == cbElem );
RtlCopyMemory( &var, pvData, cbElem );
var.vt = VT_DECIMAL;
}
else
{
Win4Assert( cbElem <= 8 );
RtlCopyMemory( &var.lVal, pvData, cbElem );
}
//
// Make a copy of the value into another local variant.
//
VARIANT varCopy;
VariantInit( &varCopy );
sc = VariantCopy( &varCopy, &var );
if ( FAILED( sc ) )
return SetError( sc, OLESTR( "GetArrayElement" ) );
//
// Free anything still allocated in the output variant, and transfer
// the value to the output variant.
//
VariantClear( pVarOut );
*pVarOut = varCopy;
return S_OK;
} //GetArrayElement
//+---------------------------------------------------------------------------
//
// Member: CixssoUtil::HTMLEncode - public
//
// Synopsis: Encode a string for use in HTML. Take the output code page
// into account so that unicode characters not representable in
// the code page are output as HTML numeric entities.
//
// Arguments: [bstrIn] - input string
// [codepage] - code page for output string
// [pbstrOut] - pointer where output string is returned
//
// Returns: SCODE - status return
//
// History: 04 Apr 1997 Alanw Created
//
//----------------------------------------------------------------------------
STDMETHODIMP
CixssoUtil::HTMLEncode(BSTR bstrIn, LONG codepage, BSTR * pbstrOut)
{
_err.Reset();
SCODE sc = S_OK;
CTranslateSystemExceptions translate;
TRY
{
if ( ( codepage < 0 ) || ( 0 == pbstrOut ) )
THROW( CException( E_INVALIDARG ) );
CVirtualString vString( 512 );
if ( 0 != bstrIn )
HTMLEscapeW( bstrIn, vString, codepage );
BSTR bstr = SysAllocStringLen( vString.GetPointer(), vString.StrLen() );
if ( 0 == bstr )
THROW( CException( E_OUTOFMEMORY ) );
*pbstrOut = bstr;
}
CATCH( CException, e )
{
sc = e.GetErrorCode();
SetError( sc, OLESTR("HTMLEncode"), eIxssoError );
}
END_CATCH;
return sc;
} //HTMLEncode
//+---------------------------------------------------------------------------
//
// Member: CixssoUtil::URLEncode - public
//
// Synopsis: Encode a string for use in a URL. Take the output code page
// into account so that unicode characters not representable in
// the code page are output as %uxxxx escapes.
//
// Arguments: [bstrIn] - input string
// [codepage] - code page for output string
// [pbstrOut] - pointer where output string is returned
//
// Returns: SCODE - status return
//
// History: 04 Apr 1997 Alanw Created
//
//----------------------------------------------------------------------------
STDMETHODIMP
CixssoUtil::URLEncode(BSTR bstrIn, LONG codepage, BSTR * pbstrOut)
{
_err.Reset();
SCODE sc = S_OK;
CTranslateSystemExceptions translate;
TRY
{
if ( ( codepage < 0 ) || ( 0 == pbstrOut ) )
THROW( CException( E_INVALIDARG ) );
CVirtualString vString( 512 );
if ( 0 != bstrIn )
URLEscapeW( bstrIn, vString, codepage, FALSE );
BSTR bstr = SysAllocStringLen( vString.GetPointer(), vString.StrLen() );
if ( 0 == bstr )
THROW( CException( E_OUTOFMEMORY ) );
*pbstrOut = bstr;
}
CATCH( CException, e )
{
sc = e.GetErrorCode();
SetError( sc, OLESTR("URLEncode"), eIxssoError );
}
END_CATCH;
return sc;
} //URLEncode