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

2121 lines
52 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1996 - 2002.
//
// File: ixsso.cxx
//
// Contents: Query SSO class
//
// History: 25 Oct 1996 Alanw Created
//
//----------------------------------------------------------------------------
#include "pch.cxx"
#pragma hdrstop
//-----------------------------------------------------------------------------
// Include Files
//-----------------------------------------------------------------------------
// debugging macros
#include "ssodebug.hxx"
DECLARE_INFOLEVEL( ixsso )
// class declaration
#include "stdcf.hxx"
#include "ixsso.hxx"
#include <string.hxx>
#include <codepage.hxx>
#include <initguid.h>
#include <adoid.h> // ADO CLSID and IID definitions
#include <adoint.h> // ADO interface definition
const WCHAR * pwcDefaultDialect = L"2";
extern WCHAR * g_pwszProgIdQuery;
#if CIDBG
extern ULONG g_ulObjCount;
extern LONG g_lQryCount;
#endif // CIDBG
//-----------------------------------------------------------------------------
//
// Member: CixssoQuery::CixssoQuery - public
//
// Synopsis: Constructor of CixssoQuery
//
// Arguments: [pitlb] - pointer to ITypeLib for ixsso
// [pIAdoRecordsetCF] - pointer to the class factory for ADO
// recordsets
//
// History: 06 Nov 1996 Alanw Created
//
//-----------------------------------------------------------------------------
CixssoQuery::CixssoQuery( ITypeLib * pitlb,
IClassFactory * pIAdoRecordsetCF,
BOOL fAdoV15,
const CLSID & ssoClsid) :
_pwszRestriction( 0 ),
_pwszSort( 0 ),
_pwszGroup( 0 ),
_pwszColumns( 0 ),
_pwszCatalog( 0 ),
_pwszDialect( 0 ),
_cScopes( 0 ),
_apwszScope( 0 ),
_aulDepth( 0 ),
_fAllowEnumeration( FALSE ),
_dwOptimizeFlags( eOptHitCount | eOptRecall ),
_maxResults( 0 ),
_cFirstRows( 0 ),
_iResourceFactor( 0 ),
_StartHit( 0 ),
_lcid( GetSystemDefaultLCID() ),
_ulCodepage( CP_ACP ),
_err( IID_IixssoQuery ),
_pIAdoRecordsetCF( pIAdoRecordsetCF ),
_fAdoV15( fAdoV15 ),
_pIRowset( 0 ),
_pIRowsetQueryStatus( 0 ),
_fSequential( FALSE ),
_PropertyList( _ulCodepage )
{
_cRef = 1;
Win4Assert(g_pTheGlobalIXSSOVariables);
SCODE sc;
if ( CLSID_CissoQueryEx == ssoClsid )
{
_err = IID_IixssoQueryEx;
sc = pitlb->GetTypeInfoOfGuid( IID_IixssoQueryEx, &_ptinfo );
}
else if ( CLSID_CissoQuery == ssoClsid )
{
sc = pitlb->GetTypeInfoOfGuid( IID_IixssoQuery, &_ptinfo );
}
else
THROW( CException(E_INVALIDARG));
if (FAILED(sc))
{
ixssoDebugOut(( DEB_ERROR, "GetTypeInfoOfGuid failed (%x)\n", sc ));
Win4Assert(SUCCEEDED(sc));
THROW( CException(sc) );
}
#if CIDBG
LONG cAdoRecordsetRefs =
#endif // CIDBG
_pIAdoRecordsetCF->AddRef();
XInterface<IColumnMapper> xColumnMapper;
ISimpleCommandCreator *pCmdCreator = 0;
pCmdCreator = g_pTheGlobalIXSSOVariables->xCmdCreator.GetPointer();
g_pTheGlobalIXSSOVariables->xColumnMapperCreator->GetColumnMapper(
LOCAL_MACHINE,
INDEX_SERVER_DEFAULT_CAT,
(IColumnMapper **)xColumnMapper.GetQIPointer());
if (0 == pCmdCreator)
THROW(CException(REGDB_E_CLASSNOTREG));
_xCmdCreator.Set(pCmdCreator);
#if CIDBG
LONG cCmdCreatorRefs =
#endif // CIDBG
pCmdCreator->AddRef();
Win4Assert(xColumnMapper.GetPointer());
_PropertyList.SetDefaultList(xColumnMapper.GetPointer());
INC_OBJECT_COUNT();
ixssoDebugOut((DEB_REFCOUNTS, "[DLL]: Create query: refcounts: glob %d qry %d AdoRSCF %d CmdCtor %d\n",
g_ulObjCount,
g_lQryCount,
cAdoRecordsetRefs,
cCmdCreatorRefs ));
}
CixssoQuery::~CixssoQuery( )
{
Reset();
if (_ptinfo)
_ptinfo->Release();
#if CIDBG
LONG cAdoRecordsetRefs = -2;
#endif // CIDBG
if (_pIAdoRecordsetCF)
#if CIDBG
cAdoRecordsetRefs =
#endif // CIDBG
_pIAdoRecordsetCF->Release();
DEC_OBJECT_COUNT();
#if CIDBG
LONG l = InterlockedDecrement( &g_lQryCount );
Win4Assert( l >= 0 );
#endif //CIDBG
ixssoDebugOut((DEB_REFCOUNTS, "[DLL]: Delete query: refcounts: glob %d qry %d AdoRSCF %d\n",
g_ulObjCount,
g_lQryCount,
cAdoRecordsetRefs ));
}
//+---------------------------------------------------------------------------
//
// Member: CixssoQuery::Reset - public
//
// Synopsis: Clear any internal state in the object
//
// Arguments: - none -
//
// Notes: Doesn't currently clear lcid or property list.
//
// History: 05 Mar 1997 Alanw Created
//
//----------------------------------------------------------------------------
HRESULT CixssoQuery::Reset(void)
{
_maxResults = 0;
_cFirstRows = 0;
_cScopes = 0;
_fAllowEnumeration = FALSE;
_dwOptimizeFlags = eOptHitCount | eOptRecall;
if (_pIRowset)
{
_pIRowset->Release();
_pIRowset = 0;
}
if (_pIRowsetQueryStatus)
{
_pIRowsetQueryStatus->Release();
_pIRowsetQueryStatus = 0;
}
delete _pwszRestriction;
_pwszRestriction = 0;
delete _pwszSort;
_pwszSort = 0;
delete _pwszGroup;
_pwszGroup = 0;
delete _pwszColumns;
_pwszColumns = 0;
delete _pwszCatalog;
_pwszCatalog = 0;
delete _pwszDialect;
_pwszDialect = 0;
// Unneeded since cScopes is set to zero.
// _apwszScope.Clear();
_StartHit.Destroy();
return S_OK;
}
//
// ASP Methods
//
#include <asp/asptlb.h>
STDMETHODIMP CixssoQuery::OnStartPage (IUnknown* pUnk)
{
// reset the error structure
_err.Reset();
SCODE sc;
IScriptingContext *piContext = 0;
IRequest* piRequest = 0;
IRequestDictionary *piRequestDict = 0;
ISessionObject* piSession = 0;
do
{
//Get IScriptingContext Interface
sc = pUnk->QueryInterface(IID_IScriptingContext, (void**)&piContext);
if (FAILED(sc))
break;
//Get Request Object Pointer
sc = piContext->get_Request(&piRequest);
if (FAILED(sc))
break;
//Get ServerVariables Pointer
sc = piRequest->get_ServerVariables(&piRequestDict);
if (FAILED(sc))
break;
VARIANT vtOut;
VariantInit(&vtOut);
//
// Get the HTTP_ACCEPT_LANGUAGE Item. Don't need to check the
// return code; use a default value for the locale ID
//
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,
"OnStartPage: HTTP_ACCEPT_LANGAUGE was not set in ServerVariables; using lcid=0x%x\n",
GetSystemDefaultLCID() ));
put_LocaleID( GetSystemDefaultLCID() );
}
VariantClear(&vtOut);
_ulCodepage = LocaleToCodepage( _lcid );
//Get Session Object Pointer
sc = piContext->get_Session(&piSession);
if (FAILED(sc))
{
// Don't fail request if sessions are not enabled. This specific
// error is given when AspAllowSessionState is zero.
if (TYPE_E_ELEMENTNOTFOUND == sc)
sc = S_OK;
break;
}
LONG cp = CP_ACP;
sc = piSession->get_CodePage( &cp );
if (FAILED(sc))
{
// sc = S_OK;
break;
}
if (cp != CP_ACP)
_ulCodepage = cp;
} while (FALSE);
if (piSession)
piSession->Release();
if (piRequestDict)
piRequestDict->Release();
if (piRequest)
piRequest->Release();
if (piContext)
piContext->Release();
return sc;
}
//-----------------------------------------------------------------------------
// CixssoQuery IUnknown Methods
//-----------------------------------------------------------------------------
STDMETHODIMP
CixssoQuery::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_IixssoQuery )
*ppv = (IixssoQuery *) this;
else if (iid == IID_IixssoQueryPrivate )
*ppv = (IixssoQueryPrivate *) this;
else if ( iid == IID_IixssoQueryEx )
*ppv = (IixssoQueryEx *) this;
#if 0
else if ( iid == IID_IObjectSafety )
*ppv = (IObjectSafety *) this;
#endif
else if ( iid == IID_IObjectWithSite )
*ppv = (IObjectWithSite *) this;
else
return E_NOINTERFACE;
AddRef();
return S_OK;
}
STDMETHODIMP_(ULONG)
CixssoQuery::AddRef(void)
{
return InterlockedIncrement((long *)&_cRef);
}
STDMETHODIMP_(ULONG)
CixssoQuery::Release(void)
{
ULONG uTmp = InterlockedDecrement((long *)&_cRef);
if (uTmp == 0)
{
delete this;
return 0;
}
return uTmp;
}
//-----------------------------------------------------------------------------
// CixssoQuery IDispatch Methods
//-----------------------------------------------------------------------------
STDMETHODIMP
CixssoQuery::GetTypeInfoCount(UINT * pctinfo)
{
*pctinfo = 1;
return S_OK;
}
STDMETHODIMP
CixssoQuery::GetTypeInfo(
UINT itinfo,
LCID lcid,
ITypeInfo * * pptinfo)
{
_ptinfo->AddRef();
*pptinfo = _ptinfo;
return S_OK;
}
STDMETHODIMP
CixssoQuery::GetIDsOfNames(
REFIID riid,
OLECHAR * * rgszNames,
UINT cNames,
LCID lcid,
DISPID * rgdispid)
{
return DispGetIDsOfNames(_ptinfo, rgszNames, cNames, rgdispid);
}
STDMETHODIMP
CixssoQuery::Invoke(
DISPID dispidMember,
REFIID riid,
LCID lcid,
WORD wFlags,
DISPPARAMS * pParams,
VARIANT * pvarResult,
EXCEPINFO * pexcepinfo,
UINT * puArgErr)
{
ixssoDebugOut((DEB_IDISPATCH, "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
CixssoQuery::InterfaceSupportsErrorInfo(
REFIID riid)
{
if (IID_IixssoQueryEx == riid || IID_IixssoQuery == riid )
return S_OK;
else
return S_FALSE;
}
//-----------------------------------------------------------------------------
// CixssoQuery property Methods
//-----------------------------------------------------------------------------
//+---------------------------------------------------------------------------
//
// 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 CixssoQuery::CopyWstrToBstr( BSTR * pbstr, WCHAR const * pwstr )
{
*pbstr = 0;
if (pwstr)
{
*pbstr = SysAllocString( pwstr );
if (0 == *pbstr)
return E_OUTOFMEMORY;
}
return S_OK;
}
//+---------------------------------------------------------------------------
//
// Member: CixssoQuery::CopyBstrToWstr - private inline
//
// Synopsis: Copies a BSTR to a Unicode string
//
// Arguments: [bstr] - string to be copied
// [rwstr] - destination string
//
// Returns: SCODE - status return
//
// History: 25 Oct 1996 Alanw Created
//
//----------------------------------------------------------------------------
inline
SCODE CixssoQuery::CopyBstrToWstr( BSTR bstr, LPWSTR & rwstr )
{
SCODE sc = S_OK;
if (rwstr)
{
delete rwstr;
rwstr = 0;
}
if (bstr)
{
CTranslateSystemExceptions translate;
TRY
{
unsigned cch = SysStringLen( bstr )+1;
if (cch > 1)
{
rwstr = new WCHAR[ cch ];
RtlCopyMemory( rwstr, bstr, cch*sizeof (WCHAR) );
}
}
CATCH (CException, e)
{
if (e.GetErrorCode() == STATUS_ACCESS_VIOLATION)
sc = E_FAIL;
else
sc = E_OUTOFMEMORY;
SetError( sc, OLESTR("PutProperty") );
}
END_CATCH
}
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CixssoQuery::CopyBstrToWstr - private inline
//
// Synopsis: Copies a BSTR to a Unicode string
//
// Arguments: [bstr] - string to be copied
// [apstr] - destination string array
// [i] - string array index
//
// Returns: SCODE - status return
//
// History: 25 Oct 1996 Alanw Created
//
//----------------------------------------------------------------------------
inline
SCODE CixssoQuery::CopyBstrToWstrArray( BSTR bstr,
CDynArray<WCHAR> &apstr,
unsigned i )
{
SCODE sc = S_OK;
if (bstr)
{
CTranslateSystemExceptions translate;
TRY
{
unsigned cch = SysStringLen( bstr )+1;
if (cch > 1)
{
XArray<WCHAR> wstr( cch );
RtlCopyMemory( wstr.GetPointer(), bstr, cch*sizeof (WCHAR) );
delete apstr.Acquire( i );
apstr.Add( wstr.GetPointer(), i );
wstr.Acquire();
}
else
apstr.Add( 0, i );
}
CATCH (CException, e)
{
if (e.GetErrorCode() == STATUS_ACCESS_VIOLATION)
sc = E_FAIL;
else
sc = E_OUTOFMEMORY;
SetError( sc, OLESTR("CopyBstrToWstrArray") );
}
END_CATCH
}
else
apstr.Add( 0, i );
return sc;
}
inline
SCODE CixssoQuery::GetBoolProperty( VARIANT_BOOL * pfVal, BOOL fMemberVal )
{
*pfVal = fMemberVal ? VARIANT_TRUE : VARIANT_FALSE;
return S_OK;
}
inline
SCODE CixssoQuery::PutBoolProperty( VARIANT_BOOL fInputVal, BOOL & fMemberVal )
{
fMemberVal = (fInputVal == VARIANT_TRUE) ? TRUE : FALSE;
return S_OK;
}
//-----------------------------------------------------------------------------
// CixssoQuery read-write properties
//-----------------------------------------------------------------------------
STDMETHODIMP
CixssoQuery::get_Query(BSTR * pstr)
{
_err.Reset();
return CopyWstrToBstr( pstr, _pwszRestriction );
}
STDMETHODIMP
CixssoQuery::put_Query(BSTR str)
{
_err.Reset();
return CopyBstrToWstr( str, _pwszRestriction );
}
STDMETHODIMP
CixssoQuery::get_GroupBy(BSTR * pstr)
{
_err.Reset();
#if IXSSO_CATEGORIZE == 1
return CopyWstrToBstr( pstr, _pwszGroup );
#else // IXSSO_CATEGORIZE
return E_NOTIMPL;
#endif // IXSSO_CATEGORIZE
}
STDMETHODIMP
CixssoQuery::put_GroupBy(BSTR str)
{
_err.Reset();
#if IXSSO_CATEGORIZE == 1
return CopyBstrToWstr( str, _pwszGroup );
#else // IXSSO_CATEGORIZE
return E_NOTIMPL;
#endif // IXSSO_CATEGORIZE
}
STDMETHODIMP
CixssoQuery::get_Columns(BSTR * pstr)
{
_err.Reset();
return CopyWstrToBstr( pstr, _pwszColumns );
}
STDMETHODIMP
CixssoQuery::put_Columns(BSTR str)
{
_err.Reset();
return CopyBstrToWstr( str, _pwszColumns );
}
STDMETHODIMP
CixssoQuery::get_LocaleID(LONG * plVal)
{
_err.Reset();
*plVal = _lcid;
return S_OK;
}
STDMETHODIMP
CixssoQuery::put_LocaleID(LONG lVal)
{
_err.Reset();
_lcid = lVal;
return S_OK;
}
STDMETHODIMP
CixssoQuery::get_CodePage(LONG * plVal)
{
_err.Reset();
*plVal = _ulCodepage;
return S_OK;
}
STDMETHODIMP
CixssoQuery::put_CodePage(LONG lVal)
{
_err.Reset();
if (0 == IsValidCodePage( lVal ) )
{
return E_INVALIDARG;
}
_ulCodepage = lVal;
return S_OK;
}
STDMETHODIMP
CixssoQuery::get_SortBy(BSTR * pstr)
{
_err.Reset();
return CopyWstrToBstr( pstr, _pwszSort );
}
STDMETHODIMP
CixssoQuery::put_SortBy(BSTR str)
{
_err.Reset();
return CopyBstrToWstr( str, _pwszSort );
}
STDMETHODIMP
CixssoQuery::get_CiScope(BSTR * pstr)
{
_err.Reset();
if (_cScopes > 1)
{
SetError( E_INVALIDARG, OLESTR("get CiScope") );
return _err.GetError();
}
return CopyWstrToBstr( pstr, _apwszScope.Get(0) );
}
STDMETHODIMP
CixssoQuery::put_CiScope(BSTR str)
{
_err.Reset();
if (_cScopes > 1)
{
SetError( E_INVALIDARG, OLESTR("set CiScope") );
return _err.GetError();
}
SCODE sc = CopyBstrToWstrArray( str, _apwszScope, 0 );
if (SUCCEEDED(sc))
{
_cScopes = (_apwszScope[0] == 0) ? 0 : 1;
}
return sc;
}
STDMETHODIMP
CixssoQuery::get_CiFlags(BSTR * pstr)
{
_err.Reset();
if (_cScopes > 1)
{
SetError( E_INVALIDARG, OLESTR("get CiFlags") );
return _err.GetError();
}
ULONG ulDepth = QUERY_DEEP;
if (_aulDepth.Count() > 0)
ulDepth = _aulDepth[0];
WCHAR * pwszDepth = ulDepth & QUERY_DEEP ? L"DEEP" : L"SHALLOW";
return CopyWstrToBstr( pstr, pwszDepth );
}
STDMETHODIMP
CixssoQuery::put_CiFlags(BSTR str)
{
_err.Reset();
SCODE sc = S_OK;
if (_cScopes > 1)
{
SetError( E_INVALIDARG, OLESTR("set CiFlags") );
return _err.GetError();
}
CTranslateSystemExceptions translate;
TRY
{
ULONG ulDepth = ParseCiDepthFlag( str );
_aulDepth[0] = ulDepth;
}
CATCH( CIxssoException, e )
{
sc = e.GetErrorCode();
Win4Assert( !SUCCEEDED(sc) );
SetError( sc, OLESTR("set CiFlags"), eIxssoError );
}
AND_CATCH( CException, e )
{
sc = e.GetErrorCode();
SetError( sc, OLESTR("set CiFlags") );
}
END_CATCH
return sc;
}
STDMETHODIMP
CixssoQuery::get_Catalog(BSTR * pstr)
{
_err.Reset();
return CopyWstrToBstr( pstr, _pwszCatalog );
}
STDMETHODIMP
CixssoQuery::put_Catalog(BSTR str)
{
_err.Reset();
return CopyBstrToWstr( str, _pwszCatalog );
}
STDMETHODIMP
CixssoQuery::get_Dialect(BSTR * pstr)
{
_err.Reset();
return CopyWstrToBstr( pstr,
_pwszDialect ? _pwszDialect : pwcDefaultDialect );
}
STDMETHODIMP
CixssoQuery::put_Dialect(BSTR str)
{
_err.Reset();
//
// Do some validation first
//
ULONG ulDialect = (ULONG) _wtoi( str );
if ( ulDialect < ISQLANG_V1 ||
ulDialect > ISQLANG_V2 )
{
SetError( E_INVALIDARG, OLESTR("set Dialect") );
return _err.GetError();
}
return CopyBstrToWstr( str, _pwszDialect );
}
STDMETHODIMP
CixssoQuery::get_OptimizeFor(BSTR * pstr)
{
_err.Reset();
WCHAR * pwszChoice = L"recall";
switch (_dwOptimizeFlags)
{
case 0:
pwszChoice = L"nohitcount";
break;
case eOptPerformance:
pwszChoice = L"performance,nohitcount";
break;
case eOptRecall:
pwszChoice = L"recall,nohitcount";
break;
case eOptPerformance|eOptHitCount:
pwszChoice = L"performance,hitcount";
break;
case eOptRecall|eOptHitCount:
pwszChoice = L"recall,hitcount";
break;
case eOptHitCount:
pwszChoice = L"hitcount";
break;
default:
Win4Assert( !"Invalid value in _dwOptimizeFlags!" );
}
return CopyWstrToBstr( pstr, pwszChoice );
}
STDMETHODIMP
CixssoQuery::put_OptimizeFor(BSTR str)
{
_err.Reset();
DWORD eChoice;
SCODE sc = ParseOptimizeFor( str, eChoice );
if (SUCCEEDED(sc))
{
_dwOptimizeFlags = eChoice;
return sc;
}
else
{
SetError( sc, OLESTR("set OptimizeFor") );
return _err.GetError();
}
}
STDMETHODIMP
CixssoQuery::get_AllowEnumeration(VARIANT_BOOL * pfFlag)
{
_err.Reset();
return GetBoolProperty( pfFlag, _fAllowEnumeration );
}
STDMETHODIMP
CixssoQuery::put_AllowEnumeration(VARIANT_BOOL fFlag)
{
_err.Reset();
return PutBoolProperty( fFlag, _fAllowEnumeration );
}
STDMETHODIMP
CixssoQuery::get_MaxRecords(LONG * plVal)
{
_err.Reset();
*plVal = _maxResults;
return S_OK;
}
STDMETHODIMP
CixssoQuery::put_MaxRecords(LONG lVal)
{
_err.Reset();
if (lVal < 0)
{
SetError( E_INVALIDARG, OLESTR("set MaxRecords") );
return _err.GetError();
}
else if (IsQueryActive())
{
SetError( MSG_IXSSO_QUERY_ACTIVE, OLESTR("set MaxRecords") );
return _err.GetError();
}
_maxResults = lVal;
return S_OK;
}
STDMETHODIMP
CixssoQuery::get_FirstRows(LONG * plVal)
{
_err.Reset();
*plVal = _cFirstRows;
return S_OK;
}
STDMETHODIMP
CixssoQuery::put_FirstRows(LONG lVal)
{
_err.Reset();
if (lVal < 0)
{
SetError( E_INVALIDARG, OLESTR("set FirstRows") );
return _err.GetError();
}
else if (IsQueryActive())
{
SetError( MSG_IXSSO_QUERY_ACTIVE, OLESTR("set FirstRows") );
return _err.GetError();
}
_cFirstRows = lVal;
return S_OK;
}
STDMETHODIMP
CixssoQuery::get_StartHit(VARIANT * pvar)
{
_err.Reset();
if (_StartHit.Get() != 0)
{
XGrowable<WCHAR> awchBuf;
FormatLongVector( _StartHit.Get(), awchBuf );
VariantInit( pvar );
V_BSTR(pvar) = SysAllocString( awchBuf.Get() );
if ( V_BSTR(pvar) != 0 )
{
V_VT(pvar) = VT_BSTR;
}
else
{
return E_OUTOFMEMORY;
}
}
else
{
V_VT(pvar) = VT_EMPTY;
}
return S_OK;
}
STDMETHODIMP
CixssoQuery::put_StartHit(VARIANT* pvar)
{
_err.Reset();
//
// NOTE: StartHit is not read-only with an active query so it can
// be set from the recordset prior to calling QueryToURL.
//
SCODE sc;
SAFEARRAY* psa;
XSafeArray xsa;
switch( V_VT(pvar) )
{
case VT_DISPATCH:
//
//pvar Contains an IDispatch Pointer. To fetch the value
//you must get the Default Value for the
//Object stored in pvar using VariantChangeType.
//
VariantChangeType(pvar, pvar, 0, VT_BSTR);
if (V_VT(pvar) != VT_BSTR)
{
return E_INVALIDARG;
}
// NOTE: fall through
case VT_BSTR:
{
CDynArrayInPlace<LONG> aStartHit( 0 );
ParseNumberVectorString( V_BSTR(pvar), aStartHit );
unsigned cHits = aStartHit.Count();
psa = SafeArrayCreateVector(VT_I4, 1, cHits);
if ( ! psa )
return E_OUTOFMEMORY;
xsa.Set(psa);
for (unsigned i=1; i<=cHits; i++)
{
long rgIx[1];
LONG lVal = aStartHit.Get(i-1);
rgIx[0] = (long)i;
sc = SafeArrayPutElement( xsa.Get(), rgIx, &lVal );
if ( FAILED(sc) )
break;
}
if ( FAILED(sc) )
return sc;
}
break;
case VT_ARRAY | VT_I4:
sc = SafeArrayCopy(V_ARRAY(pvar),&psa);
if ( FAILED(sc) )
return sc;
xsa.Set(psa);
if (SafeArrayGetDim(psa) != 1)
return E_INVALIDARG;
break;
case VT_I4:
case VT_I2:
psa = SafeArrayCreateVector(VT_I4,1,1);
if ( ! psa )
return E_OUTOFMEMORY;
xsa.Set(psa);
{
long rgIx[1];
rgIx[0] = 1;
long lVal = (V_VT(pvar) == VT_I4) ? V_I4(pvar) : V_I2(pvar);
sc = SafeArrayPutElement( xsa.Get(), rgIx, &lVal );
if ( FAILED( sc ) )
return sc;
}
break;
default:
SetError( E_INVALIDARG, OLESTR("set StartHit") );
return _err.GetError();
}
_StartHit.Destroy();
_StartHit.Set( xsa.Acquire() );
return S_OK;
}
STDMETHODIMP
CixssoQuery::get_ResourceUseFactor(LONG * plVal)
{
_err.Reset();
*plVal = _iResourceFactor;
return S_OK;
}
STDMETHODIMP
CixssoQuery::put_ResourceUseFactor(LONG lVal)
{
_err.Reset();
if (IsQueryActive())
{
SetError( MSG_IXSSO_QUERY_ACTIVE, OLESTR("set ResourceUseFactor") );
return _err.GetError();
}
_iResourceFactor = lVal;
return S_OK;
}
//-----------------------------------------------------------------------------
// CixssoQuery read-only properties
//-----------------------------------------------------------------------------
//+---------------------------------------------------------------------------
//
// Member: CixssoQuery::CheckQueryStatusBit - private inline
//
// Synopsis: Check a specific query status bit, set variant bool accordingly
//
// Arguments: [pfVal] - VARIANT_BOOL to be set
// [dwBit] - bit(s) in query status to be tested
//
// Returns: SCODE - status return
//
// History: 03 Jan 1997 Alanw Created
//
//----------------------------------------------------------------------------
inline
SCODE CixssoQuery::CheckQueryStatusBit( VARIANT_BOOL * pfVal, DWORD dwBit )
{
SCODE sc = S_OK;
CTranslateSystemExceptions translate;
TRY
{
DWORD dwStatus = GetQueryStatus( );
*pfVal = (dwStatus & dwBit) ? VARIANT_TRUE : VARIANT_FALSE;
}
CATCH( CIxssoException, e )
{
sc = e.GetErrorCode();
Win4Assert( !SUCCEEDED(sc) );
SetError( sc, OLESTR("CheckQueryStatus"), eIxssoError );
}
AND_CATCH( CException, e )
{
sc = e.GetErrorCode();
SetError( sc, OLESTR("CheckQueryStatus") );
}
END_CATCH
return sc;
}
STDMETHODIMP
CixssoQuery::get_QueryTimedOut(VARIANT_BOOL * pfFlag)
{
_err.Reset();
return CheckQueryStatusBit( pfFlag, STAT_TIME_LIMIT_EXCEEDED );
}
STDMETHODIMP
CixssoQuery::get_QueryIncomplete(VARIANT_BOOL * pfFlag)
{
_err.Reset();
return CheckQueryStatusBit( pfFlag, STAT_CONTENT_QUERY_INCOMPLETE );
}
STDMETHODIMP
CixssoQuery::get_OutOfDate(VARIANT_BOOL * pfFlag)
{
_err.Reset();
return CheckQueryStatusBit( pfFlag,
(STAT_CONTENT_OUT_OF_DATE | STAT_REFRESH_INCOMPLETE) );
}
//-----------------------------------------------------------------------------
// CixssoQuery Methods
//-----------------------------------------------------------------------------
STDMETHODIMP
CixssoQuery::AddScopeToQuery( BSTR bstrScope,
BSTR bstrDepth)
{
//
// This is an internally used method, so don't need to reset error object here.
//
if (0 == bstrScope || 0 == SysStringLen(bstrScope) )
{
THROW( CException(E_INVALIDARG) );
}
SCODE sc = CopyBstrToWstrArray( bstrScope, _apwszScope, _cScopes );
if (FAILED(sc))
{
THROW( CException(sc) );
}
ULONG ulDepth = ParseCiDepthFlag( bstrDepth );
_aulDepth[_cScopes] = ulDepth;
_cScopes++;
return S_OK;
}
STDMETHODIMP
CixssoQuery::DefineColumn( BSTR bstrColDefinition)
{
_err.Reset();
SCODE sc = S_OK;
CTranslateSystemExceptions translate;
TRY
{
CQueryScanner scanner( bstrColDefinition, FALSE );
XPtr<CPropEntry> xpropentry;
CPropertyList::ParseOneLine( scanner, 0, xpropentry );
if (xpropentry.GetPointer())
sc = _PropertyList.AddEntry( xpropentry, 0 );
}
CATCH( CPListException, e )
{
sc = e.GetPListError();
Win4Assert( !SUCCEEDED(sc) );
SetError( sc, OLESTR("DefineColumn"), ePlistError );
}
AND_CATCH( CException, e )
{
sc = e.GetErrorCode();
SetError( sc, OLESTR("DefineColumn") );
}
END_CATCH
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CixssoQuery::CreateRecordset - public
//
// Synopsis: Executes the query and returns a recordset
//
// Arguments: [bstrSequential] - one of "SEQUENTIAL" or "NONSEQUENTIAL",
// selects whether a nonsequential query is used.
// [ppDisp] - recordset is returned here.
//
// History: 06 Nov 1996 Alanw Created
//
//----------------------------------------------------------------------------
STDMETHODIMP
CixssoQuery::CreateRecordset( BSTR bstrSequential,
IDispatch * * ppDisp)
{
_err.Reset();
unsigned eErrorClass = 0;
BOOL fSetErrorNeeded = TRUE;
if (IsQueryActive())
{
SetError( MSG_IXSSO_QUERY_ACTIVE, OLESTR("CreateRecordset") );
return _err.GetError();
}
SCODE sc = S_OK;
CTranslateSystemExceptions translate;
TRY
{
IsSafeForScripting();
*ppDisp = 0;
if ( bstrSequential && 0 == _wcsicmp(bstrSequential, L"SEQUENTIAL") )
_fSequential = TRUE;
else if ( bstrSequential &&
(0 == _wcsicmp(bstrSequential, L"NONSEQUENTIAL") ||
0 == _wcsicmp(bstrSequential, L"NON-SEQUENTIAL")) )
_fSequential = FALSE;
else
{
SetError( E_INVALIDARG, OLESTR("CreateRecordset") );
return _err.GetError();
}
ExecuteQuery();
Win4Assert( _pIRowset != 0 );
Win4Assert( _pIRowsetQueryStatus != 0 );
//
// Create an empty recordset, and put our rowset in it.
//
IDispatch * pRecordset = 0;
sc = _pIAdoRecordsetCF->CreateInstance( 0,
IID_IDispatch,
(void **)&pRecordset );
ADORecordsetConstruction * pRecordsetConstruction = 0;
if ( SUCCEEDED(sc) )
{
sc = pRecordset->QueryInterface( IID_IADORecordsetConstruction,
(void **)&pRecordsetConstruction );
}
if (SUCCEEDED(sc))
{
sc = pRecordsetConstruction->put_Rowset( _pIRowset );
pRecordsetConstruction->Release();
}
if (SUCCEEDED(sc))
{
*ppDisp = pRecordset;
}
if (FAILED(sc))
{
if (pRecordset)
pRecordset->Release();
pRecordset = 0;
_pIRowset->Release();
_pIRowset = 0;
_pIRowsetQueryStatus->Release();
_pIRowsetQueryStatus = 0;
}
fSetErrorNeeded = FAILED(sc);
}
CATCH( CPListException, e )
{
sc = e.GetPListError();
eErrorClass = ePlistError;
Win4Assert( !SUCCEEDED(sc) );
}
AND_CATCH( CIxssoException, e )
{
sc = e.GetErrorCode();
eErrorClass = eIxssoError;
Win4Assert( !SUCCEEDED(sc) );
}
AND_CATCH( CParserException, e )
{
sc = e.GetParseError();
eErrorClass = eParseError;
Win4Assert( !SUCCEEDED(sc) );
}
AND_CATCH( CPostedOleDBException, e )
{
//
// When the execution error was detected, the Ole DB error
// info was retrieved and stored in the exception object.
// We retrieve that here and compose the error message.
//
sc = e.GetErrorCode();
Win4Assert( !SUCCEEDED(sc) );
XInterface <IErrorInfo> xErrorInfo(e.AcquireErrorInfo());
if (xErrorInfo.GetPointer())
{
BSTR bstrErrorDescription = 0;
xErrorInfo->GetDescription(&bstrErrorDescription);
if (bstrErrorDescription)
{
SetError( sc, OLESTR("CreateRecordset"), (WCHAR const *)bstrErrorDescription);
SysFreeString(bstrErrorDescription);
fSetErrorNeeded = FALSE;
}
else
eErrorClass = eDefaultError;
}
}
AND_CATCH( CException, e )
{
sc = e.GetErrorCode();
eErrorClass = eDefaultError;
Win4Assert( !SUCCEEDED(sc) );
}
END_CATCH
if (! SUCCEEDED(sc) && fSetErrorNeeded)
SetError( sc, OLESTR("CreateRecordset"), eErrorClass );
return sc;
}
//+---------------------------------------------------------------------------
//
// Member: CixssoQuery::ParseOptimizeFor - private static
//
// Synopsis: Parse the input string for the OptimizeFor property
//
// Arguments: [wcsOptString] - input string
// [eChoice] - OptimizeFor choice expressed in wcsOptString
//
// Returns: SCODE - status return
//
// History: 05 Mar 1997 Alanw Created
//
//----------------------------------------------------------------------------
SCODE CixssoQuery::ParseOptimizeFor( WCHAR const * wcsOptString,
DWORD & eChoice )
{
eChoice = eOptHitCount;
while (wcsOptString && *wcsOptString)
{
WCHAR * wcsNext = wcschr( wcsOptString, ',' );
ULONG cch = (wcsNext) ? CiPtrToUlong( wcsNext - wcsOptString ) :
wcslen( wcsOptString );
if ( 11 == cch && _wcsnicmp(wcsOptString, L"performance", 11) == 0)
{
eChoice |= eOptPerformance;
}
else if ( 6 == cch && _wcsnicmp(wcsOptString, L"recall", 6) == 0)
{
eChoice |= eOptRecall;
}
else if ( 8 == cch && _wcsnicmp(wcsOptString, L"hitcount", 8) == 0)
{
eChoice |= eOptHitCount;
}
else if ( 10 == cch && _wcsnicmp(wcsOptString, L"nohitcount", 10) == 0)
{
eChoice &= ~eOptHitCount;
}
else
return E_INVALIDARG;
wcsOptString = wcsNext;
if (wcsOptString)
{
wcsOptString++;
while (iswspace( *wcsOptString ))
wcsOptString++;
}
}
// 'performance' and 'recall' are mutually exclusive. Check if both
// were set.
if ( (eChoice & (eOptRecall | eOptPerformance)) ==
(eOptRecall | eOptPerformance) )
return E_INVALIDARG;
return S_OK;
}
//+---------------------------------------------------------------------------
//
// Member: CixssoQuery::ParseCiDepthFlag, private
//
// Synopsis: Parses the flags attribute
//
// Arguments: [bstrFlags] -- flags
//
// Returns: ULONG - query scope flags
//
// History: 96/Jan/03 DwightKr created
//
//----------------------------------------------------------------------------
ULONG CixssoQuery::ParseCiDepthFlag( BSTR bstrFlags )
{
if ( 0 == bstrFlags || 0 == SysStringLen(bstrFlags) )
{
return QUERY_DEEP;
}
ULONG ulFlags;
if ( _wcsicmp(bstrFlags, L"SHALLOW") == 0 )
{
ulFlags = QUERY_SHALLOW;
}
else if ( _wcsicmp(bstrFlags, L"DEEP") == 0 )
{
ulFlags = QUERY_DEEP;
}
else
{
THROW( CIxssoException(MSG_IXSSO_EXPECTING_SHALLOWDEEP, 0) );
}
return ulFlags;
}
//+---------------------------------------------------------------------------
//
// Member: CixssoQuery::SetLocaleString - private
//
// Synopsis: Parse the input string for a recognizable locale name
//
// Arguments: [bstrLocale] - input string
//
// Returns: SCODE - status return
//
// History: 13 Mar 1997 Alanw Created
//
//----------------------------------------------------------------------------
SCODE CixssoQuery::SetLocaleString(BSTR str)
{
LCID lcidTemp = GetLCIDFromString( str );
if (lcidTemp == -1)
{
return E_INVALIDARG;
}
_lcid = lcidTemp;
return S_OK;
}
//+---------------------------------------------------------------------------
//
// Function: ParseNumberVectorString - public
//
// Synopsis: Parses a string consisting of ',' separated numeric values
// into an array.
//
// Arguments: [pwszValue] - input string
// [aNum] - dynamic array where numbers are placed.
//
// History: 10 Jun 1997 Alanw Created
//
//----------------------------------------------------------------------------
void ParseNumberVectorString( WCHAR * pwszValue, CDynArrayInPlace<LONG> & aNum )
{
while (pwszValue)
{
LONG lNum = _wtoi( pwszValue );
aNum[aNum.Count()] = lNum;
pwszValue = wcschr(pwszValue, L',');
if (pwszValue)
pwszValue++;
}
}
void FormatLongVector( SAFEARRAY * psa, XGrowable<WCHAR> & awchBuf )
{
Win4Assert( SafeArrayGetDim( psa ) == 1 &&
SafeArrayGetElemsize( psa ) == sizeof (LONG) );
LONG iLBound = 0;
LONG iUBound = 0;
SCODE sc = SafeArrayGetLBound( psa, 1, &iLBound );
if (SUCCEEDED(sc))
sc = SafeArrayGetUBound( psa, 1, &iUBound );
unsigned cch = 0;
for (int i=iLBound; i<= iUBound; i++)
{
LONG lValue;
LONG ix[1];
ix[0] = i;
sc = SafeArrayGetElement( psa, ix, &lValue );
awchBuf.SetSize(cch + 20);
if (i != iLBound)
{
awchBuf[cch] = L',';
cch++;
}
_itow( lValue, &awchBuf[cch], 10 );
cch += wcslen( &awchBuf[cch] );
}
}
// CIXSSOPropertyList methods
//+-------------------------------------------------------------------------
//
// Member: CIXSSOPropertyList::CIXSSOPropertyList, public
//
// Synopsis: Constructs a property mapper for the ixsso's use.
//
// Parameters: [pDefaultList] -- The default column mapper.
//
// History: 26-Aug-97 KrishnaN Created
//
//--------------------------------------------------------------------------
CIXSSOPropertyList::CIXSSOPropertyList(ULONG ulCodePage)
: _cRefs( 1 ),
_ulCodePage( ulCodePage ),
_xDefaultList(0)
{
// default list is not known. Use SetDefaultList to set that
}
// Set the defualt list
void CIXSSOPropertyList::SetDefaultList(IColumnMapper *pDefaultList)
{
Win4Assert(pDefaultList);
_xDefaultList.Set(pDefaultList);
_xDefaultList->AddRef();
}
//+-------------------------------------------------------------------------
//
// Member: CIXSSOPropertyList::QueryInterface, public
//
// Arguments: [ifid] -- Interface id
// [ppiuk] -- Interface return pointer
//
// History: 26-Aug-97 KrishnaN Created
//
//--------------------------------------------------------------------------
STDMETHODIMP CIXSSOPropertyList::QueryInterface( REFIID ifid, void ** ppiuk )
{
if (0 == ppiuk)
return E_INVALIDARG;
if ( IID_IUnknown == ifid )
{
AddRef();
*ppiuk = (void *)((IUnknown *)this);
return S_OK;
}
else if (IID_IColumnMapper == ifid )
{
AddRef();
*ppiuk = (void *)((IColumnMapper *)this);
return S_OK;
}
else
{
*ppiuk = 0;
return E_NOINTERFACE;
}
}
//+-------------------------------------------------------------------------
//
// Member: CIXSSOPropertyList::AddRef, public
//
// Synopsis: Reference the virtual table.
//
// History: 26-Aug-97 KrishnaN Created
//
//--------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CIXSSOPropertyList::AddRef(void)
{
InterlockedIncrement( &_cRefs );
return( _cRefs );
}
//+-------------------------------------------------------------------------
//
// Member: CIXSSOPropertyList::Release, public
//
// Synopsis: De-Reference the virtual table.
//
// Effects: If the ref count goes to 0 then the table is deleted.
//
// History: 26-Aug-97 KrishnaN Created
//
//--------------------------------------------------------------------------
STDMETHODIMP_(ULONG) CIXSSOPropertyList::Release(void)
{
unsigned long uTmp = InterlockedDecrement( &_cRefs );
if (0 == uTmp)
{
delete this;
}
return(uTmp);
}
//
// IColumnMapper methods
//
//+-------------------------------------------------------------------------
//
// Member: CIXSSOPropertyList::GetPropInfoFromName, public
//
// Synopsis: Get property info. from name.
//
// Parameters: [wcsPropName] -- Property name to look up.
// [ppPropId] -- Ptr to return Id of the property.
// [pPropType] -- Ptr to return type of the property.
// [puiWidth] -- Ptr to return property width.
//
// History: 26-Aug-97 KrishnaN Created
//
//--------------------------------------------------------------------------
SCODE CIXSSOPropertyList::GetPropInfoFromName(const WCHAR *wcsPropName,
DBID * *ppPropId,
DBTYPE *pPropType,
unsigned int *puiWidth)
{
//
// Callers can pass in 0 for pPropType and puiWidth if they
// don't care about them.
//
if (0 == wcsPropName || 0 == ppPropId)
return E_INVALIDARG;
Win4Assert(_xDefaultList.GetPointer());
//
// First check in the default list, then in the override list.
//
SCODE sc = _xDefaultList->GetPropInfoFromName(wcsPropName,
ppPropId,
pPropType,
puiWidth);
if (FAILED(sc) && 0 != _xOverrideList.GetPointer())
{
sc = _xOverrideList->GetPropInfoFromName(wcsPropName,
ppPropId,
pPropType,
puiWidth);
}
return sc;
}
//+-------------------------------------------------------------------------
//
// Member: CIXSSOPropertyList::GetPropInfoFromId, public
//
// Synopsis: Get property info. from dbid.
//
// Parameters: [pPropId] -- Ptr to prop to look up.
// [pwcsName] -- Ptr to return property name.
// [pPropType] -- Ptr to return type of the property.
// [puiWidth] -- Ptr to return property width.
//
// History: 26-Aug-97 KrishnaN Created
//
//--------------------------------------------------------------------------
SCODE CIXSSOPropertyList::GetPropInfoFromId(const DBID *pPropId,
WCHAR * *pwcsName,
DBTYPE *pPropType,
unsigned int *puiWidth)
{
Win4Assert(!"Not available!");
return E_NOTIMPL;
#if 0 // complete, working implementation, but not needed.
//
// Callers can pass in 0 for pPropType and puiWidth if they
// don't care about them.
//
if (0 == pwcsName || 0 == pPropId)
return E_INVALIDARG;
//
// First check in the default list, then in the override list.
//
SCODE sc = _xDefaultList->GetPropInfoFromId(pPropId,
pwcsName,
pPropType,
puiWidth);
if (FAILED(sc) && 0 != _xOverrideList.GetPointer())
{
sc = _xOverrideList->GetPropInfoFromId(pPropId,
pwcsName,
pPropType,
puiWidth);
}
return sc;
#endif // 0
}
//+-------------------------------------------------------------------------
//
// Member: CIXSSOPropertyList::EnumPropInfo, public
//
// Synopsis: Gets the i-th entry from the list of properties.
//
// Parameters: [iEntry] -- i-th entry to retrieve (0-based).
// [pwcsName] -- Ptr to return property name.
// [ppPropId] -- Ptr to return Id of the property.
// [pPropType] -- Ptr to return type of the property.
// [puiWidth] -- Ptr to return property width.
//
// History: 26-Aug-97 KrishnaN Created
//
//--------------------------------------------------------------------------
SCODE CIXSSOPropertyList::EnumPropInfo(ULONG iEntry,
const WCHAR * *pwcsName,
DBID * *ppPropId,
DBTYPE *pPropType,
unsigned int *puiWidth)
{
Win4Assert(!"Not available!");
return E_NOTIMPL;
}
//+-------------------------------------------------------------------------
//
// Member: CIXSSOPropertyList::IsMapUpToDate, public
//
// Synopsis: Indicates if the column map is up to date.
//
// History: 26-Aug-97 KrishnaN Created
//
//--------------------------------------------------------------------------
SCODE CIXSSOPropertyList::IsMapUpToDate()
{
Win4Assert(_xDefaultList.GetPointer());
// return the IsMapUpToDate of the default list.
// the override list is always considered to be
// upto date.
return _xDefaultList->IsMapUpToDate();
}
//+---------------------------------------------------------------------------
//
// Member: CIXSSOPropertyList::AddEntry, private
//
// Synopsis: Adds a CPropEntry to the overriding list. Verifies that the name
// isn't already in the default list or the overriding list.
//
// Arguments: [xPropEntry] -- CPropEntry to add. Acquired on success
// [iLine] -- line number we're parsing
//
// Returns: S_OK on success or S_
//
// History: 11-Sep-97 KrishnaN Created.
//
//----------------------------------------------------------------------------
SCODE CIXSSOPropertyList::AddEntry( XPtr<CPropEntry> & xPropEntry, int iLine )
{
Win4Assert(_xDefaultList.GetPointer());
SCODE sc = S_OK;
// protect _xOverrideList
CLock lock(_mtxAdd);
//
// We do not allow entries in the override list that have the same name
// as the default list.
//
DBID *pPropId;
DBTYPE PropType;
unsigned uWidth;
if ( S_OK == GetPropInfoFromName( xPropEntry->GetName(),
&pPropId,
&PropType,
&uWidth ))
{
if ( PropType != xPropEntry->GetPropType() ||
( uWidth != xPropEntry->GetWidth() &&
xPropEntry->GetWidth() != PLIST_DEFAULT_WIDTH ) )
{
THROW( CPListException( QPLIST_E_DUPLICATE, iLine ) );
}
else
sc = QPLIST_S_DUPLICATE;
}
if ( S_OK == sc )
{
if (0 == _xOverrideList.GetPointer())
_xOverrideList.Set(new CPropertyList(_ulCodePage));
_xOverrideList->AddEntry( xPropEntry.GetPointer(), iLine);
xPropEntry.Acquire();
}
return sc;
} //AddEntry
#if 0
HRESULT CixssoQuery::GetInterfaceSafetyOptions(
REFIID riid,
DWORD * pdwSupportedOptions,
DWORD * pdwEnabledOptions )
{
if ( 0 == pdwSupportedOptions ||
0 == pdwEnabledOptions )
return E_POINTER;
ixssoDebugOut(( DEB_ITRACE, "get safety options called...\n" ));
*pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER;
*pdwEnabledOptions = 0;
return S_OK;
} //GetInterfaceSafetyOptions
HRESULT CixssoQuery::SetInterfaceSafetyOptions(
REFIID riid,
DWORD dwOptionSetMask,
DWORD dwEnabledOptions )
{
ixssoDebugOut(( DEB_ITRACE, "set setmask: %#x\n", dwOptionSetMask ));
ixssoDebugOut(( DEB_ITRACE, "set enabled: %#x\n", dwEnabledOptions ));
_dwSafetyOptions = (dwEnabledOptions & dwOptionSetMask);
return S_OK;
} //SetInterfaceSafetyOptions
#endif
//+-------------------------------------------------------------------------
//
// Member: CixssoQuery::SetSite, public
//
// Synopsis: Sets the current site (if any). Called by containers of
// CixssoQuery like IE. Not called by other containers like
// ASP and CScript.
//
// Arguments: [pSite] -- The container of this query object
//
// Returns: HRESULT
//
// History: 09-Nov-00 dlee Created
//
//--------------------------------------------------------------------------
HRESULT CixssoQuery::SetSite( IUnknown * pSite )
{
_xSite.Free();
if ( 0 != pSite )
{
pSite->AddRef();
_xSite.Set( pSite );
}
ixssoDebugOut(( DEB_ITRACE, "setting site: %#x\n", pSite ));
return S_OK;
} //SetSite
//+-------------------------------------------------------------------------
//
// Member: CixssoQuery::GetSite, public
//
// Synopsis: Retrieves the current site (if any)
//
// Arguments: [riid] -- IID requested
// [ppvSite] -- Where the interface pointer is returned
//
// Returns: HRESULT like a QueryInterface()
//
// History: 09-Nov-00 dlee Created
//
//--------------------------------------------------------------------------
HRESULT CixssoQuery::GetSite(
REFIID riid,
void ** ppvSite )
{
ixssoDebugOut(( DEB_ITRACE, "getsite\n" ));
if ( 0 == ppvSite )
return E_POINTER;
*ppvSite = 0;
if ( _xSite.IsNull() )
return E_NOINTERFACE;
return _xSite->QueryInterface( riid, ppvSite );
} //GetSite
//+-------------------------------------------------------------------------
//
// Member: CixssoQuery::IsSafeForScripting, private
//
// Synopsis: Checks if it's ok to execute in the current context. Throws
// an exception if it's not safe or on error. It's not safe
// to execute script off a remote machine.
//
// History: 09-Nov-00 dlee Created
//
//--------------------------------------------------------------------------
void CixssoQuery::IsSafeForScripting()
{
XInterface<IServiceProvider> xServiceProvider;
SCODE sc = GetSite( IID_IServiceProvider,
xServiceProvider.GetQIPointer() );
//
// When queries are run in IIS the container does not call
// SetSite, so there is no site and we'll have E_NOINTERFACE
// at this point. Same for cscript.exe queries.
// If that ever changes, the check below for file:// URLs will
// fail and no IIS queries will ever work.
//
if ( E_NOINTERFACE == sc )
return;
if ( FAILED( sc ) )
THROW( CException( sc ) );
XInterface<IWebBrowser2> xWebBrowser;
sc = xServiceProvider->QueryService( SID_SWebBrowserApp,
IID_IWebBrowser2,
xWebBrowser.GetQIPointer() );
if ( E_NOINTERFACE == sc )
return;
if ( FAILED( sc ) )
THROW( CException( sc ) );
BSTR bstrURL;
sc = xWebBrowser->get_LocationURL( &bstrURL );
if ( FAILED( sc ) )
THROW( CException( sc ) );
XBStr xURL( bstrURL );
ixssoDebugOut(( DEB_ITRACE, "url: %ws\n", bstrURL ));
WCHAR buf[32];
URL_COMPONENTS uc;
RtlZeroMemory( &uc, sizeof uc );
uc.dwStructSize = sizeof uc;
uc.lpszScheme = buf;
uc.dwSchemeLength = sizeof buf / sizeof WCHAR;
INTERNET_SCHEME scheme = INTERNET_SCHEME_UNKNOWN;
if ( InternetCrackUrl( bstrURL, wcslen( bstrURL ), ICU_DECODE, &uc ) )
scheme = uc.nScheme;
// The URL has to be a file:/// URL or we won't allow it.
if ( INTERNET_SCHEME_FILE != scheme )
THROW( CException( E_ACCESSDENIED ) );
// OK, now it can't be a UNC path. Look for a drive letter and a colon
// file:///c: the length should at least be 10
if ( wcslen( bstrURL ) <= 9 )
THROW( CException( E_ACCESSDENIED ) );
WCHAR const * pwcPath = bstrURL + 8;
WCHAR const * pwcColon = wcschr( pwcPath, L':' );
ixssoDebugOut(( DEB_ITRACE, "Path is: %ws\n", pwcPath ));
if ( ( 0 == pwcColon ) ||
( pwcColon > ( pwcPath + 1 ) ) )
THROW( CException( E_ACCESSDENIED ) );
WCHAR wcDrive = * ( pwcColon - 1 );
ixssoDebugOut(( DEB_ITRACE, "wcDrive is: %wc\n", wcDrive ));
wcDrive = towupper( wcDrive );
if ( ( wcDrive < L'A' ) || ( wcDrive > L'Z' ) )
THROW( CException( E_ACCESSDENIED ) );
} //IsSafeForScripting