Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2133 lines
55 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996 - 2002.
  5. //
  6. // File: ixsso.cxx
  7. //
  8. // Contents: Query SSO class
  9. //
  10. // History: 25 Oct 1996 Alanw Created
  11. //
  12. //----------------------------------------------------------------------------
  13. #include "pch.cxx"
  14. #pragma hdrstop
  15. //-----------------------------------------------------------------------------
  16. // Include Files
  17. //-----------------------------------------------------------------------------
  18. // debugging macros
  19. #include "ssodebug.hxx"
  20. DECLARE_INFOLEVEL( ixsso )
  21. // class declaration
  22. #include "stdcf.hxx"
  23. #include "ixsso.hxx"
  24. #include <string.hxx>
  25. #include <codepage.hxx>
  26. #include <initguid.h>
  27. #include <adoid.h> // ADO CLSID and IID definitions
  28. #include <adoint.h> // ADO interface definition
  29. const WCHAR * pwcDefaultDialect = L"2";
  30. extern WCHAR * g_pwszProgIdQuery;
  31. #if CIDBG
  32. extern ULONG g_ulObjCount;
  33. extern LONG g_lQryCount;
  34. #endif // CIDBG
  35. //-----------------------------------------------------------------------------
  36. //
  37. // Member: CixssoQuery::CixssoQuery - public
  38. //
  39. // Synopsis: Constructor of CixssoQuery
  40. //
  41. // Arguments: [pitlb] - pointer to ITypeLib for ixsso
  42. // [pIAdoRecordsetCF] - pointer to the class factory for ADO
  43. // recordsets
  44. //
  45. // History: 06 Nov 1996 Alanw Created
  46. //
  47. //-----------------------------------------------------------------------------
  48. CixssoQuery::CixssoQuery( ITypeLib * pitlb,
  49. IClassFactory * pIAdoRecordsetCF,
  50. BOOL fAdoV15,
  51. const CLSID & ssoClsid) :
  52. _pwszRestriction( 0 ),
  53. _pwszSort( 0 ),
  54. _pwszGroup( 0 ),
  55. _pwszColumns( 0 ),
  56. _pwszCatalog( 0 ),
  57. _pwszDialect( 0 ),
  58. _cScopes( 0 ),
  59. _apwszScope( 0 ),
  60. _aulDepth( 0 ),
  61. _fAllowEnumeration( FALSE ),
  62. _dwOptimizeFlags( eOptHitCount | eOptRecall ),
  63. _maxResults( 0 ),
  64. _cFirstRows( 0 ),
  65. _iResourceFactor( 0 ),
  66. _StartHit( 0 ),
  67. _lcid( GetSystemDefaultLCID() ),
  68. _ulCodepage( CP_ACP ),
  69. _err( IID_IixssoQuery ),
  70. _pIAdoRecordsetCF( pIAdoRecordsetCF ),
  71. _fAdoV15( fAdoV15 ),
  72. _pIRowset( 0 ),
  73. _pIRowsetQueryStatus( 0 ),
  74. _fSequential( FALSE ),
  75. _PropertyList( _ulCodepage )
  76. {
  77. _cRef = 1;
  78. Win4Assert(g_pTheGlobalIXSSOVariables);
  79. SCODE sc;
  80. if ( CLSID_CissoQueryEx == ssoClsid )
  81. {
  82. _err = IID_IixssoQueryEx;
  83. sc = pitlb->GetTypeInfoOfGuid( IID_IixssoQueryEx, &_ptinfo );
  84. }
  85. else if ( CLSID_CissoQuery == ssoClsid )
  86. {
  87. sc = pitlb->GetTypeInfoOfGuid( IID_IixssoQuery, &_ptinfo );
  88. }
  89. else
  90. THROW( CException(E_INVALIDARG));
  91. if (FAILED(sc))
  92. {
  93. ixssoDebugOut(( DEB_ERROR, "GetTypeInfoOfGuid failed (%x)\n", sc ));
  94. Win4Assert(SUCCEEDED(sc));
  95. THROW( CException(sc) );
  96. }
  97. #if CIDBG
  98. LONG cAdoRecordsetRefs =
  99. #endif // CIDBG
  100. _pIAdoRecordsetCF->AddRef();
  101. XInterface<IColumnMapper> xColumnMapper;
  102. ISimpleCommandCreator *pCmdCreator = 0;
  103. pCmdCreator = g_pTheGlobalIXSSOVariables->xCmdCreator.GetPointer();
  104. g_pTheGlobalIXSSOVariables->xColumnMapperCreator->GetColumnMapper(
  105. LOCAL_MACHINE,
  106. INDEX_SERVER_DEFAULT_CAT,
  107. (IColumnMapper **)xColumnMapper.GetQIPointer());
  108. if (0 == pCmdCreator)
  109. THROW(CException(REGDB_E_CLASSNOTREG));
  110. _xCmdCreator.Set(pCmdCreator);
  111. #if CIDBG
  112. LONG cCmdCreatorRefs =
  113. #endif // CIDBG
  114. pCmdCreator->AddRef();
  115. Win4Assert(xColumnMapper.GetPointer());
  116. _PropertyList.SetDefaultList(xColumnMapper.GetPointer());
  117. INC_OBJECT_COUNT();
  118. ixssoDebugOut((DEB_REFCOUNTS, "[DLL]: Create query: refcounts: glob %d qry %d AdoRSCF %d CmdCtor %d\n",
  119. g_ulObjCount,
  120. g_lQryCount,
  121. cAdoRecordsetRefs,
  122. cCmdCreatorRefs ));
  123. }
  124. CixssoQuery::~CixssoQuery( )
  125. {
  126. Reset();
  127. if (_ptinfo)
  128. _ptinfo->Release();
  129. #if CIDBG
  130. LONG cAdoRecordsetRefs = -2;
  131. #endif // CIDBG
  132. if (_pIAdoRecordsetCF)
  133. #if CIDBG
  134. cAdoRecordsetRefs =
  135. #endif // CIDBG
  136. _pIAdoRecordsetCF->Release();
  137. DEC_OBJECT_COUNT();
  138. #if CIDBG
  139. LONG l = InterlockedDecrement( &g_lQryCount );
  140. Win4Assert( l >= 0 );
  141. #endif //CIDBG
  142. ixssoDebugOut((DEB_REFCOUNTS, "[DLL]: Delete query: refcounts: glob %d qry %d AdoRSCF %d\n",
  143. g_ulObjCount,
  144. g_lQryCount,
  145. cAdoRecordsetRefs ));
  146. }
  147. //+---------------------------------------------------------------------------
  148. //
  149. // Member: CixssoQuery::Reset - public
  150. //
  151. // Synopsis: Clear any internal state in the object
  152. //
  153. // Arguments: - none -
  154. //
  155. // Notes: Doesn't currently clear lcid or property list.
  156. //
  157. // History: 05 Mar 1997 Alanw Created
  158. //
  159. //----------------------------------------------------------------------------
  160. HRESULT CixssoQuery::Reset(void)
  161. {
  162. _maxResults = 0;
  163. _cFirstRows = 0;
  164. _cScopes = 0;
  165. _fAllowEnumeration = FALSE;
  166. _dwOptimizeFlags = eOptHitCount | eOptRecall;
  167. if (_pIRowset)
  168. {
  169. _pIRowset->Release();
  170. _pIRowset = 0;
  171. }
  172. if (_pIRowsetQueryStatus)
  173. {
  174. _pIRowsetQueryStatus->Release();
  175. _pIRowsetQueryStatus = 0;
  176. }
  177. delete _pwszRestriction;
  178. _pwszRestriction = 0;
  179. delete _pwszSort;
  180. _pwszSort = 0;
  181. delete _pwszGroup;
  182. _pwszGroup = 0;
  183. delete _pwszColumns;
  184. _pwszColumns = 0;
  185. delete _pwszCatalog;
  186. _pwszCatalog = 0;
  187. delete _pwszDialect;
  188. _pwszDialect = 0;
  189. // Unneeded since cScopes is set to zero.
  190. // _apwszScope.Clear();
  191. _StartHit.Destroy();
  192. return S_OK;
  193. }
  194. //
  195. // ASP Methods
  196. //
  197. #include <asp/asptlb.h>
  198. STDMETHODIMP CixssoQuery::OnStartPage (IUnknown* pUnk)
  199. {
  200. if ( 0 == pUnk )
  201. return E_INVALIDARG;
  202. SCODE sc = S_OK;
  203. CTranslateSystemExceptions translate;
  204. TRY
  205. {
  206. // reset the error structure
  207. _err.Reset();
  208. SCODE sc;
  209. IScriptingContext *piContext = 0;
  210. IRequest* piRequest = 0;
  211. IRequestDictionary *piRequestDict = 0;
  212. ISessionObject* piSession = 0;
  213. do
  214. {
  215. //Get IScriptingContext Interface
  216. sc = pUnk->QueryInterface(IID_IScriptingContext, (void**)&piContext);
  217. if (FAILED(sc))
  218. break;
  219. //Get Request Object Pointer
  220. sc = piContext->get_Request(&piRequest);
  221. if (FAILED(sc))
  222. break;
  223. //Get ServerVariables Pointer
  224. sc = piRequest->get_ServerVariables(&piRequestDict);
  225. if (FAILED(sc))
  226. break;
  227. VARIANT vtOut;
  228. VariantInit(&vtOut);
  229. //
  230. // Get the HTTP_ACCEPT_LANGUAGE Item. Don't need to check the
  231. // return code; use a default value for the locale ID
  232. //
  233. piRequestDict->get_Item(g_vtAcceptLanguageHeader, &vtOut);
  234. //
  235. //vtOut Contains an IDispatch Pointer. To fetch the value
  236. //for HTTP_ACCEPT_LANGUAGE you must get the Default Value for the
  237. //Object stored in vtOut using VariantChangeType.
  238. //
  239. if (V_VT(&vtOut) != VT_BSTR)
  240. VariantChangeType(&vtOut, &vtOut, 0, VT_BSTR);
  241. if (V_VT(&vtOut) == VT_BSTR)
  242. {
  243. ixssoDebugOut((DEB_TRACE, "OnStartPage: HTTP_ACCEPT_LANGUAGE = %ws\n",
  244. V_BSTR(&vtOut) ));
  245. SetLocaleString(V_BSTR(&vtOut));
  246. }
  247. else
  248. {
  249. ixssoDebugOut(( DEB_TRACE,
  250. "OnStartPage: HTTP_ACCEPT_LANGAUGE was not set in ServerVariables; using lcid=0x%x\n",
  251. GetSystemDefaultLCID() ));
  252. put_LocaleID( GetSystemDefaultLCID() );
  253. }
  254. VariantClear(&vtOut);
  255. _ulCodepage = LocaleToCodepage( _lcid );
  256. //Get Session Object Pointer
  257. sc = piContext->get_Session(&piSession);
  258. if (FAILED(sc))
  259. {
  260. // Don't fail request if sessions are not enabled. This specific
  261. // error is given when AspAllowSessionState is zero.
  262. if (TYPE_E_ELEMENTNOTFOUND == sc)
  263. sc = S_OK;
  264. break;
  265. }
  266. LONG cp = CP_ACP;
  267. sc = piSession->get_CodePage( &cp );
  268. if (FAILED(sc))
  269. {
  270. // sc = S_OK;
  271. break;
  272. }
  273. if (cp != CP_ACP)
  274. _ulCodepage = cp;
  275. } while (FALSE);
  276. if (piSession)
  277. piSession->Release();
  278. if (piRequestDict)
  279. piRequestDict->Release();
  280. if (piRequest)
  281. piRequest->Release();
  282. if (piContext)
  283. piContext->Release();
  284. }
  285. CATCH( CException, e )
  286. {
  287. sc = e.GetErrorCode();
  288. }
  289. END_CATCH
  290. return sc;
  291. }
  292. //-----------------------------------------------------------------------------
  293. // CixssoQuery IUnknown Methods
  294. //-----------------------------------------------------------------------------
  295. STDMETHODIMP
  296. CixssoQuery::QueryInterface(REFIID iid, void * * ppv)
  297. {
  298. *ppv = 0;
  299. if (iid == IID_IUnknown || iid == IID_IDispatch)
  300. *ppv = (IDispatch *) this;
  301. else if (iid == IID_ISupportErrorInfo )
  302. *ppv = (ISupportErrorInfo *) this;
  303. else if (iid == IID_IixssoQuery )
  304. *ppv = (IixssoQuery *) this;
  305. else if (iid == IID_IixssoQueryPrivate )
  306. *ppv = (IixssoQueryPrivate *) this;
  307. else if ( iid == IID_IixssoQueryEx )
  308. *ppv = (IixssoQueryEx *) this;
  309. #if 0
  310. else if ( iid == IID_IObjectSafety )
  311. *ppv = (IObjectSafety *) this;
  312. #endif
  313. else if ( iid == IID_IObjectWithSite )
  314. *ppv = (IObjectWithSite *) this;
  315. else
  316. return E_NOINTERFACE;
  317. AddRef();
  318. return S_OK;
  319. }
  320. STDMETHODIMP_(ULONG)
  321. CixssoQuery::AddRef(void)
  322. {
  323. return InterlockedIncrement((long *)&_cRef);
  324. }
  325. STDMETHODIMP_(ULONG)
  326. CixssoQuery::Release(void)
  327. {
  328. ULONG uTmp = InterlockedDecrement((long *)&_cRef);
  329. if (uTmp == 0)
  330. {
  331. delete this;
  332. return 0;
  333. }
  334. return uTmp;
  335. }
  336. //-----------------------------------------------------------------------------
  337. // CixssoQuery IDispatch Methods
  338. //-----------------------------------------------------------------------------
  339. STDMETHODIMP
  340. CixssoQuery::GetTypeInfoCount(UINT * pctinfo)
  341. {
  342. *pctinfo = 1;
  343. return S_OK;
  344. }
  345. STDMETHODIMP
  346. CixssoQuery::GetTypeInfo(
  347. UINT itinfo,
  348. LCID lcid,
  349. ITypeInfo * * pptinfo)
  350. {
  351. _ptinfo->AddRef();
  352. *pptinfo = _ptinfo;
  353. return S_OK;
  354. }
  355. STDMETHODIMP
  356. CixssoQuery::GetIDsOfNames(
  357. REFIID riid,
  358. OLECHAR * * rgszNames,
  359. UINT cNames,
  360. LCID lcid,
  361. DISPID * rgdispid)
  362. {
  363. return DispGetIDsOfNames(_ptinfo, rgszNames, cNames, rgdispid);
  364. }
  365. STDMETHODIMP
  366. CixssoQuery::Invoke(
  367. DISPID dispidMember,
  368. REFIID riid,
  369. LCID lcid,
  370. WORD wFlags,
  371. DISPPARAMS * pParams,
  372. VARIANT * pvarResult,
  373. EXCEPINFO * pexcepinfo,
  374. UINT * puArgErr)
  375. {
  376. ixssoDebugOut((DEB_IDISPATCH, "Invoking method dispid=%d wFlags=%d\n",
  377. dispidMember, wFlags ));
  378. _err.Reset();
  379. SCODE sc = DispInvoke( this, _ptinfo,
  380. dispidMember, wFlags, pParams,
  381. pvarResult, pexcepinfo, puArgErr );
  382. if ( _err.IsError() )
  383. sc = DISP_E_EXCEPTION;
  384. return sc;
  385. }
  386. STDMETHODIMP
  387. CixssoQuery::InterfaceSupportsErrorInfo(
  388. REFIID riid)
  389. {
  390. if (IID_IixssoQueryEx == riid || IID_IixssoQuery == riid )
  391. return S_OK;
  392. else
  393. return S_FALSE;
  394. }
  395. //-----------------------------------------------------------------------------
  396. // CixssoQuery property Methods
  397. //-----------------------------------------------------------------------------
  398. //+---------------------------------------------------------------------------
  399. //
  400. // Member: CixssoQuery::CopyWstrToBstr - private inline
  401. //
  402. // Synopsis: Copies a Unicode string to a BSTR
  403. //
  404. // Arguments: [pbstr] - destination BSTR
  405. // [pwstr] - string to be copied
  406. //
  407. // Returns: SCODE - status return
  408. //
  409. // History: 25 Oct 1996 Alanw Created
  410. //
  411. //----------------------------------------------------------------------------
  412. inline
  413. SCODE CixssoQuery::CopyWstrToBstr( BSTR * pbstr, WCHAR const * pwstr )
  414. {
  415. *pbstr = 0;
  416. if (pwstr)
  417. {
  418. *pbstr = SysAllocString( pwstr );
  419. if (0 == *pbstr)
  420. return E_OUTOFMEMORY;
  421. }
  422. return S_OK;
  423. }
  424. //+---------------------------------------------------------------------------
  425. //
  426. // Member: CixssoQuery::CopyBstrToWstr - private inline
  427. //
  428. // Synopsis: Copies a BSTR to a Unicode string
  429. //
  430. // Arguments: [bstr] - string to be copied
  431. // [rwstr] - destination string
  432. //
  433. // Returns: SCODE - status return
  434. //
  435. // History: 25 Oct 1996 Alanw Created
  436. //
  437. //----------------------------------------------------------------------------
  438. inline
  439. SCODE CixssoQuery::CopyBstrToWstr( BSTR bstr, LPWSTR & rwstr )
  440. {
  441. SCODE sc = S_OK;
  442. if (rwstr)
  443. {
  444. delete rwstr;
  445. rwstr = 0;
  446. }
  447. if (bstr)
  448. {
  449. CTranslateSystemExceptions translate;
  450. TRY
  451. {
  452. unsigned cch = SysStringLen( bstr )+1;
  453. if (cch > 1)
  454. {
  455. rwstr = new WCHAR[ cch ];
  456. RtlCopyMemory( rwstr, bstr, cch*sizeof (WCHAR) );
  457. }
  458. }
  459. CATCH (CException, e)
  460. {
  461. if (e.GetErrorCode() == STATUS_ACCESS_VIOLATION)
  462. sc = E_FAIL;
  463. else
  464. sc = E_OUTOFMEMORY;
  465. SetError( sc, OLESTR("PutProperty") );
  466. }
  467. END_CATCH
  468. }
  469. return sc;
  470. }
  471. //+---------------------------------------------------------------------------
  472. //
  473. // Member: CixssoQuery::CopyBstrToWstr - private inline
  474. //
  475. // Synopsis: Copies a BSTR to a Unicode string
  476. //
  477. // Arguments: [bstr] - string to be copied
  478. // [apstr] - destination string array
  479. // [i] - string array index
  480. //
  481. // Returns: SCODE - status return
  482. //
  483. // History: 25 Oct 1996 Alanw Created
  484. //
  485. //----------------------------------------------------------------------------
  486. inline
  487. SCODE CixssoQuery::CopyBstrToWstrArray( BSTR bstr,
  488. CDynArray<WCHAR> &apstr,
  489. unsigned i )
  490. {
  491. SCODE sc = S_OK;
  492. if (bstr)
  493. {
  494. CTranslateSystemExceptions translate;
  495. TRY
  496. {
  497. unsigned cch = SysStringLen( bstr )+1;
  498. if (cch > 1)
  499. {
  500. XArray<WCHAR> wstr( cch );
  501. RtlCopyMemory( wstr.GetPointer(), bstr, cch*sizeof (WCHAR) );
  502. delete apstr.Acquire( i );
  503. apstr.Add( wstr.GetPointer(), i );
  504. wstr.Acquire();
  505. }
  506. else
  507. apstr.Add( 0, i );
  508. }
  509. CATCH (CException, e)
  510. {
  511. if (e.GetErrorCode() == STATUS_ACCESS_VIOLATION)
  512. sc = E_FAIL;
  513. else
  514. sc = E_OUTOFMEMORY;
  515. SetError( sc, OLESTR("CopyBstrToWstrArray") );
  516. }
  517. END_CATCH
  518. }
  519. else
  520. apstr.Add( 0, i );
  521. return sc;
  522. }
  523. inline
  524. SCODE CixssoQuery::GetBoolProperty( VARIANT_BOOL * pfVal, BOOL fMemberVal )
  525. {
  526. *pfVal = fMemberVal ? VARIANT_TRUE : VARIANT_FALSE;
  527. return S_OK;
  528. }
  529. inline
  530. SCODE CixssoQuery::PutBoolProperty( VARIANT_BOOL fInputVal, BOOL & fMemberVal )
  531. {
  532. fMemberVal = (fInputVal == VARIANT_TRUE) ? TRUE : FALSE;
  533. return S_OK;
  534. }
  535. //-----------------------------------------------------------------------------
  536. // CixssoQuery read-write properties
  537. //-----------------------------------------------------------------------------
  538. STDMETHODIMP
  539. CixssoQuery::get_Query(BSTR * pstr)
  540. {
  541. _err.Reset();
  542. return CopyWstrToBstr( pstr, _pwszRestriction );
  543. }
  544. STDMETHODIMP
  545. CixssoQuery::put_Query(BSTR str)
  546. {
  547. _err.Reset();
  548. return CopyBstrToWstr( str, _pwszRestriction );
  549. }
  550. STDMETHODIMP
  551. CixssoQuery::get_GroupBy(BSTR * pstr)
  552. {
  553. _err.Reset();
  554. #if IXSSO_CATEGORIZE == 1
  555. return CopyWstrToBstr( pstr, _pwszGroup );
  556. #else // IXSSO_CATEGORIZE
  557. return E_NOTIMPL;
  558. #endif // IXSSO_CATEGORIZE
  559. }
  560. STDMETHODIMP
  561. CixssoQuery::put_GroupBy(BSTR str)
  562. {
  563. _err.Reset();
  564. #if IXSSO_CATEGORIZE == 1
  565. return CopyBstrToWstr( str, _pwszGroup );
  566. #else // IXSSO_CATEGORIZE
  567. return E_NOTIMPL;
  568. #endif // IXSSO_CATEGORIZE
  569. }
  570. STDMETHODIMP
  571. CixssoQuery::get_Columns(BSTR * pstr)
  572. {
  573. _err.Reset();
  574. return CopyWstrToBstr( pstr, _pwszColumns );
  575. }
  576. STDMETHODIMP
  577. CixssoQuery::put_Columns(BSTR str)
  578. {
  579. _err.Reset();
  580. return CopyBstrToWstr( str, _pwszColumns );
  581. }
  582. STDMETHODIMP
  583. CixssoQuery::get_LocaleID(LONG * plVal)
  584. {
  585. _err.Reset();
  586. *plVal = _lcid;
  587. return S_OK;
  588. }
  589. STDMETHODIMP
  590. CixssoQuery::put_LocaleID(LONG lVal)
  591. {
  592. _err.Reset();
  593. _lcid = lVal;
  594. return S_OK;
  595. }
  596. STDMETHODIMP
  597. CixssoQuery::get_CodePage(LONG * plVal)
  598. {
  599. _err.Reset();
  600. *plVal = _ulCodepage;
  601. return S_OK;
  602. }
  603. STDMETHODIMP
  604. CixssoQuery::put_CodePage(LONG lVal)
  605. {
  606. _err.Reset();
  607. if (0 == IsValidCodePage( lVal ) )
  608. {
  609. return E_INVALIDARG;
  610. }
  611. _ulCodepage = lVal;
  612. return S_OK;
  613. }
  614. STDMETHODIMP
  615. CixssoQuery::get_SortBy(BSTR * pstr)
  616. {
  617. _err.Reset();
  618. return CopyWstrToBstr( pstr, _pwszSort );
  619. }
  620. STDMETHODIMP
  621. CixssoQuery::put_SortBy(BSTR str)
  622. {
  623. _err.Reset();
  624. return CopyBstrToWstr( str, _pwszSort );
  625. }
  626. STDMETHODIMP
  627. CixssoQuery::get_CiScope(BSTR * pstr)
  628. {
  629. _err.Reset();
  630. if (_cScopes > 1)
  631. {
  632. SetError( E_INVALIDARG, OLESTR("get CiScope") );
  633. return _err.GetError();
  634. }
  635. return CopyWstrToBstr( pstr, _apwszScope.Get(0) );
  636. }
  637. STDMETHODIMP
  638. CixssoQuery::put_CiScope(BSTR str)
  639. {
  640. _err.Reset();
  641. if (_cScopes > 1)
  642. {
  643. SetError( E_INVALIDARG, OLESTR("set CiScope") );
  644. return _err.GetError();
  645. }
  646. SCODE sc = CopyBstrToWstrArray( str, _apwszScope, 0 );
  647. if (SUCCEEDED(sc))
  648. {
  649. _cScopes = (_apwszScope[0] == 0) ? 0 : 1;
  650. }
  651. return sc;
  652. }
  653. STDMETHODIMP
  654. CixssoQuery::get_CiFlags(BSTR * pstr)
  655. {
  656. _err.Reset();
  657. if (_cScopes > 1)
  658. {
  659. SetError( E_INVALIDARG, OLESTR("get CiFlags") );
  660. return _err.GetError();
  661. }
  662. ULONG ulDepth = QUERY_DEEP;
  663. if (_aulDepth.Count() > 0)
  664. ulDepth = _aulDepth[0];
  665. WCHAR * pwszDepth = ulDepth & QUERY_DEEP ? L"DEEP" : L"SHALLOW";
  666. return CopyWstrToBstr( pstr, pwszDepth );
  667. }
  668. STDMETHODIMP
  669. CixssoQuery::put_CiFlags(BSTR str)
  670. {
  671. _err.Reset();
  672. SCODE sc = S_OK;
  673. if (_cScopes > 1)
  674. {
  675. SetError( E_INVALIDARG, OLESTR("set CiFlags") );
  676. return _err.GetError();
  677. }
  678. CTranslateSystemExceptions translate;
  679. TRY
  680. {
  681. ULONG ulDepth = ParseCiDepthFlag( str );
  682. _aulDepth[0] = ulDepth;
  683. }
  684. CATCH( CIxssoException, e )
  685. {
  686. sc = e.GetErrorCode();
  687. Win4Assert( !SUCCEEDED(sc) );
  688. SetError( sc, OLESTR("set CiFlags"), eIxssoError );
  689. }
  690. AND_CATCH( CException, e )
  691. {
  692. sc = e.GetErrorCode();
  693. SetError( sc, OLESTR("set CiFlags") );
  694. }
  695. END_CATCH
  696. return sc;
  697. }
  698. STDMETHODIMP
  699. CixssoQuery::get_Catalog(BSTR * pstr)
  700. {
  701. _err.Reset();
  702. return CopyWstrToBstr( pstr, _pwszCatalog );
  703. }
  704. STDMETHODIMP
  705. CixssoQuery::put_Catalog(BSTR str)
  706. {
  707. _err.Reset();
  708. return CopyBstrToWstr( str, _pwszCatalog );
  709. }
  710. STDMETHODIMP
  711. CixssoQuery::get_Dialect(BSTR * pstr)
  712. {
  713. _err.Reset();
  714. return CopyWstrToBstr( pstr,
  715. _pwszDialect ? _pwszDialect : pwcDefaultDialect );
  716. }
  717. STDMETHODIMP
  718. CixssoQuery::put_Dialect(BSTR str)
  719. {
  720. _err.Reset();
  721. //
  722. // Do some validation first
  723. //
  724. ULONG ulDialect = (ULONG) _wtoi( str );
  725. if ( ulDialect < ISQLANG_V1 ||
  726. ulDialect > ISQLANG_V2 )
  727. {
  728. SetError( E_INVALIDARG, OLESTR("set Dialect") );
  729. return _err.GetError();
  730. }
  731. return CopyBstrToWstr( str, _pwszDialect );
  732. }
  733. STDMETHODIMP
  734. CixssoQuery::get_OptimizeFor(BSTR * pstr)
  735. {
  736. _err.Reset();
  737. WCHAR * pwszChoice = L"recall";
  738. switch (_dwOptimizeFlags)
  739. {
  740. case 0:
  741. pwszChoice = L"nohitcount";
  742. break;
  743. case eOptPerformance:
  744. pwszChoice = L"performance,nohitcount";
  745. break;
  746. case eOptRecall:
  747. pwszChoice = L"recall,nohitcount";
  748. break;
  749. case eOptPerformance|eOptHitCount:
  750. pwszChoice = L"performance,hitcount";
  751. break;
  752. case eOptRecall|eOptHitCount:
  753. pwszChoice = L"recall,hitcount";
  754. break;
  755. case eOptHitCount:
  756. pwszChoice = L"hitcount";
  757. break;
  758. default:
  759. Win4Assert( !"Invalid value in _dwOptimizeFlags!" );
  760. }
  761. return CopyWstrToBstr( pstr, pwszChoice );
  762. }
  763. STDMETHODIMP
  764. CixssoQuery::put_OptimizeFor(BSTR str)
  765. {
  766. _err.Reset();
  767. DWORD eChoice;
  768. SCODE sc = ParseOptimizeFor( str, eChoice );
  769. if (SUCCEEDED(sc))
  770. {
  771. _dwOptimizeFlags = eChoice;
  772. return sc;
  773. }
  774. else
  775. {
  776. SetError( sc, OLESTR("set OptimizeFor") );
  777. return _err.GetError();
  778. }
  779. }
  780. STDMETHODIMP
  781. CixssoQuery::get_AllowEnumeration(VARIANT_BOOL * pfFlag)
  782. {
  783. _err.Reset();
  784. return GetBoolProperty( pfFlag, _fAllowEnumeration );
  785. }
  786. STDMETHODIMP
  787. CixssoQuery::put_AllowEnumeration(VARIANT_BOOL fFlag)
  788. {
  789. _err.Reset();
  790. return PutBoolProperty( fFlag, _fAllowEnumeration );
  791. }
  792. STDMETHODIMP
  793. CixssoQuery::get_MaxRecords(LONG * plVal)
  794. {
  795. _err.Reset();
  796. *plVal = _maxResults;
  797. return S_OK;
  798. }
  799. STDMETHODIMP
  800. CixssoQuery::put_MaxRecords(LONG lVal)
  801. {
  802. _err.Reset();
  803. if (lVal < 0)
  804. {
  805. SetError( E_INVALIDARG, OLESTR("set MaxRecords") );
  806. return _err.GetError();
  807. }
  808. else if (IsQueryActive())
  809. {
  810. SetError( MSG_IXSSO_QUERY_ACTIVE, OLESTR("set MaxRecords") );
  811. return _err.GetError();
  812. }
  813. _maxResults = lVal;
  814. return S_OK;
  815. }
  816. STDMETHODIMP
  817. CixssoQuery::get_FirstRows(LONG * plVal)
  818. {
  819. _err.Reset();
  820. *plVal = _cFirstRows;
  821. return S_OK;
  822. }
  823. STDMETHODIMP
  824. CixssoQuery::put_FirstRows(LONG lVal)
  825. {
  826. _err.Reset();
  827. if (lVal < 0)
  828. {
  829. SetError( E_INVALIDARG, OLESTR("set FirstRows") );
  830. return _err.GetError();
  831. }
  832. else if (IsQueryActive())
  833. {
  834. SetError( MSG_IXSSO_QUERY_ACTIVE, OLESTR("set FirstRows") );
  835. return _err.GetError();
  836. }
  837. _cFirstRows = lVal;
  838. return S_OK;
  839. }
  840. STDMETHODIMP
  841. CixssoQuery::get_StartHit(VARIANT * pvar)
  842. {
  843. _err.Reset();
  844. if (_StartHit.Get() != 0)
  845. {
  846. XGrowable<WCHAR> awchBuf;
  847. FormatLongVector( _StartHit.Get(), awchBuf );
  848. VariantInit( pvar );
  849. V_BSTR(pvar) = SysAllocString( awchBuf.Get() );
  850. if ( V_BSTR(pvar) != 0 )
  851. {
  852. V_VT(pvar) = VT_BSTR;
  853. }
  854. else
  855. {
  856. return E_OUTOFMEMORY;
  857. }
  858. }
  859. else
  860. {
  861. V_VT(pvar) = VT_EMPTY;
  862. }
  863. return S_OK;
  864. }
  865. STDMETHODIMP
  866. CixssoQuery::put_StartHit(VARIANT* pvar)
  867. {
  868. _err.Reset();
  869. //
  870. // NOTE: StartHit is not read-only with an active query so it can
  871. // be set from the recordset prior to calling QueryToURL.
  872. //
  873. SCODE sc;
  874. SAFEARRAY* psa;
  875. XSafeArray xsa;
  876. switch( V_VT(pvar) )
  877. {
  878. case VT_DISPATCH:
  879. //
  880. //pvar Contains an IDispatch Pointer. To fetch the value
  881. //you must get the Default Value for the
  882. //Object stored in pvar using VariantChangeType.
  883. //
  884. VariantChangeType(pvar, pvar, 0, VT_BSTR);
  885. if (V_VT(pvar) != VT_BSTR)
  886. {
  887. return E_INVALIDARG;
  888. }
  889. // NOTE: fall through
  890. case VT_BSTR:
  891. {
  892. CDynArrayInPlace<LONG> aStartHit( 0 );
  893. ParseNumberVectorString( V_BSTR(pvar), aStartHit );
  894. unsigned cHits = aStartHit.Count();
  895. psa = SafeArrayCreateVector(VT_I4, 1, cHits);
  896. if ( ! psa )
  897. return E_OUTOFMEMORY;
  898. xsa.Set(psa);
  899. for (unsigned i=1; i<=cHits; i++)
  900. {
  901. long rgIx[1];
  902. LONG lVal = aStartHit.Get(i-1);
  903. rgIx[0] = (long)i;
  904. sc = SafeArrayPutElement( xsa.Get(), rgIx, &lVal );
  905. if ( FAILED(sc) )
  906. break;
  907. }
  908. if ( FAILED(sc) )
  909. return sc;
  910. }
  911. break;
  912. case VT_ARRAY | VT_I4:
  913. sc = SafeArrayCopy(V_ARRAY(pvar),&psa);
  914. if ( FAILED(sc) )
  915. return sc;
  916. xsa.Set(psa);
  917. if (SafeArrayGetDim(psa) != 1)
  918. return E_INVALIDARG;
  919. break;
  920. case VT_I4:
  921. case VT_I2:
  922. psa = SafeArrayCreateVector(VT_I4,1,1);
  923. if ( ! psa )
  924. return E_OUTOFMEMORY;
  925. xsa.Set(psa);
  926. {
  927. long rgIx[1];
  928. rgIx[0] = 1;
  929. long lVal = (V_VT(pvar) == VT_I4) ? V_I4(pvar) : V_I2(pvar);
  930. sc = SafeArrayPutElement( xsa.Get(), rgIx, &lVal );
  931. if ( FAILED( sc ) )
  932. return sc;
  933. }
  934. break;
  935. default:
  936. SetError( E_INVALIDARG, OLESTR("set StartHit") );
  937. return _err.GetError();
  938. }
  939. _StartHit.Destroy();
  940. _StartHit.Set( xsa.Acquire() );
  941. return S_OK;
  942. }
  943. STDMETHODIMP
  944. CixssoQuery::get_ResourceUseFactor(LONG * plVal)
  945. {
  946. _err.Reset();
  947. *plVal = _iResourceFactor;
  948. return S_OK;
  949. }
  950. STDMETHODIMP
  951. CixssoQuery::put_ResourceUseFactor(LONG lVal)
  952. {
  953. _err.Reset();
  954. if (IsQueryActive())
  955. {
  956. SetError( MSG_IXSSO_QUERY_ACTIVE, OLESTR("set ResourceUseFactor") );
  957. return _err.GetError();
  958. }
  959. _iResourceFactor = lVal;
  960. return S_OK;
  961. }
  962. //-----------------------------------------------------------------------------
  963. // CixssoQuery read-only properties
  964. //-----------------------------------------------------------------------------
  965. //+---------------------------------------------------------------------------
  966. //
  967. // Member: CixssoQuery::CheckQueryStatusBit - private inline
  968. //
  969. // Synopsis: Check a specific query status bit, set variant bool accordingly
  970. //
  971. // Arguments: [pfVal] - VARIANT_BOOL to be set
  972. // [dwBit] - bit(s) in query status to be tested
  973. //
  974. // Returns: SCODE - status return
  975. //
  976. // History: 03 Jan 1997 Alanw Created
  977. //
  978. //----------------------------------------------------------------------------
  979. inline
  980. SCODE CixssoQuery::CheckQueryStatusBit( VARIANT_BOOL * pfVal, DWORD dwBit )
  981. {
  982. SCODE sc = S_OK;
  983. CTranslateSystemExceptions translate;
  984. TRY
  985. {
  986. DWORD dwStatus = GetQueryStatus( );
  987. *pfVal = (dwStatus & dwBit) ? VARIANT_TRUE : VARIANT_FALSE;
  988. }
  989. CATCH( CIxssoException, e )
  990. {
  991. sc = e.GetErrorCode();
  992. Win4Assert( !SUCCEEDED(sc) );
  993. SetError( sc, OLESTR("CheckQueryStatus"), eIxssoError );
  994. }
  995. AND_CATCH( CException, e )
  996. {
  997. sc = e.GetErrorCode();
  998. SetError( sc, OLESTR("CheckQueryStatus") );
  999. }
  1000. END_CATCH
  1001. return sc;
  1002. }
  1003. STDMETHODIMP
  1004. CixssoQuery::get_QueryTimedOut(VARIANT_BOOL * pfFlag)
  1005. {
  1006. _err.Reset();
  1007. return CheckQueryStatusBit( pfFlag, STAT_TIME_LIMIT_EXCEEDED );
  1008. }
  1009. STDMETHODIMP
  1010. CixssoQuery::get_QueryIncomplete(VARIANT_BOOL * pfFlag)
  1011. {
  1012. _err.Reset();
  1013. return CheckQueryStatusBit( pfFlag, STAT_CONTENT_QUERY_INCOMPLETE );
  1014. }
  1015. STDMETHODIMP
  1016. CixssoQuery::get_OutOfDate(VARIANT_BOOL * pfFlag)
  1017. {
  1018. _err.Reset();
  1019. return CheckQueryStatusBit( pfFlag,
  1020. (STAT_CONTENT_OUT_OF_DATE | STAT_REFRESH_INCOMPLETE) );
  1021. }
  1022. //-----------------------------------------------------------------------------
  1023. // CixssoQuery Methods
  1024. //-----------------------------------------------------------------------------
  1025. STDMETHODIMP
  1026. CixssoQuery::AddScopeToQuery( BSTR bstrScope,
  1027. BSTR bstrDepth)
  1028. {
  1029. //
  1030. // This is an internally used method, so don't need to reset error object here.
  1031. //
  1032. if (0 == bstrScope || 0 == SysStringLen(bstrScope) )
  1033. {
  1034. THROW( CException(E_INVALIDARG) );
  1035. }
  1036. SCODE sc = CopyBstrToWstrArray( bstrScope, _apwszScope, _cScopes );
  1037. if (FAILED(sc))
  1038. {
  1039. THROW( CException(sc) );
  1040. }
  1041. ULONG ulDepth = ParseCiDepthFlag( bstrDepth );
  1042. _aulDepth[_cScopes] = ulDepth;
  1043. _cScopes++;
  1044. return S_OK;
  1045. }
  1046. STDMETHODIMP
  1047. CixssoQuery::DefineColumn( BSTR bstrColDefinition)
  1048. {
  1049. _err.Reset();
  1050. SCODE sc = S_OK;
  1051. CTranslateSystemExceptions translate;
  1052. TRY
  1053. {
  1054. CQueryScanner scanner( bstrColDefinition, FALSE );
  1055. XPtr<CPropEntry> xpropentry;
  1056. CPropertyList::ParseOneLine( scanner, 0, xpropentry );
  1057. if (xpropentry.GetPointer())
  1058. sc = _PropertyList.AddEntry( xpropentry, 0 );
  1059. }
  1060. CATCH( CPListException, e )
  1061. {
  1062. sc = e.GetPListError();
  1063. Win4Assert( !SUCCEEDED(sc) );
  1064. SetError( sc, OLESTR("DefineColumn"), ePlistError );
  1065. }
  1066. AND_CATCH( CException, e )
  1067. {
  1068. sc = e.GetErrorCode();
  1069. SetError( sc, OLESTR("DefineColumn") );
  1070. }
  1071. END_CATCH
  1072. return sc;
  1073. }
  1074. //+---------------------------------------------------------------------------
  1075. //
  1076. // Member: CixssoQuery::CreateRecordset - public
  1077. //
  1078. // Synopsis: Executes the query and returns a recordset
  1079. //
  1080. // Arguments: [bstrSequential] - one of "SEQUENTIAL" or "NONSEQUENTIAL",
  1081. // selects whether a nonsequential query is used.
  1082. // [ppDisp] - recordset is returned here.
  1083. //
  1084. // History: 06 Nov 1996 Alanw Created
  1085. //
  1086. //----------------------------------------------------------------------------
  1087. STDMETHODIMP
  1088. CixssoQuery::CreateRecordset( BSTR bstrSequential,
  1089. IDispatch * * ppDisp)
  1090. {
  1091. _err.Reset();
  1092. unsigned eErrorClass = 0;
  1093. BOOL fSetErrorNeeded = TRUE;
  1094. if (IsQueryActive())
  1095. {
  1096. SetError( MSG_IXSSO_QUERY_ACTIVE, OLESTR("CreateRecordset") );
  1097. return _err.GetError();
  1098. }
  1099. SCODE sc = S_OK;
  1100. CTranslateSystemExceptions translate;
  1101. TRY
  1102. {
  1103. IsSafeForScripting();
  1104. *ppDisp = 0;
  1105. if ( bstrSequential && 0 == _wcsicmp(bstrSequential, L"SEQUENTIAL") )
  1106. _fSequential = TRUE;
  1107. else if ( bstrSequential &&
  1108. (0 == _wcsicmp(bstrSequential, L"NONSEQUENTIAL") ||
  1109. 0 == _wcsicmp(bstrSequential, L"NON-SEQUENTIAL")) )
  1110. _fSequential = FALSE;
  1111. else
  1112. {
  1113. SetError( E_INVALIDARG, OLESTR("CreateRecordset") );
  1114. return _err.GetError();
  1115. }
  1116. ExecuteQuery();
  1117. Win4Assert( _pIRowset != 0 );
  1118. Win4Assert( _pIRowsetQueryStatus != 0 );
  1119. //
  1120. // Create an empty recordset, and put our rowset in it.
  1121. //
  1122. IDispatch * pRecordset = 0;
  1123. sc = _pIAdoRecordsetCF->CreateInstance( 0,
  1124. IID_IDispatch,
  1125. (void **)&pRecordset );
  1126. ADORecordsetConstruction * pRecordsetConstruction = 0;
  1127. if ( SUCCEEDED(sc) )
  1128. {
  1129. sc = pRecordset->QueryInterface( IID_IADORecordsetConstruction,
  1130. (void **)&pRecordsetConstruction );
  1131. }
  1132. if (SUCCEEDED(sc))
  1133. {
  1134. sc = pRecordsetConstruction->put_Rowset( _pIRowset );
  1135. pRecordsetConstruction->Release();
  1136. }
  1137. if (SUCCEEDED(sc))
  1138. {
  1139. *ppDisp = pRecordset;
  1140. }
  1141. if (FAILED(sc))
  1142. {
  1143. if (pRecordset)
  1144. pRecordset->Release();
  1145. pRecordset = 0;
  1146. _pIRowset->Release();
  1147. _pIRowset = 0;
  1148. _pIRowsetQueryStatus->Release();
  1149. _pIRowsetQueryStatus = 0;
  1150. }
  1151. fSetErrorNeeded = FAILED(sc);
  1152. }
  1153. CATCH( CPListException, e )
  1154. {
  1155. sc = e.GetPListError();
  1156. eErrorClass = ePlistError;
  1157. Win4Assert( !SUCCEEDED(sc) );
  1158. }
  1159. AND_CATCH( CIxssoException, e )
  1160. {
  1161. sc = e.GetErrorCode();
  1162. eErrorClass = eIxssoError;
  1163. Win4Assert( !SUCCEEDED(sc) );
  1164. }
  1165. AND_CATCH( CParserException, e )
  1166. {
  1167. sc = e.GetParseError();
  1168. eErrorClass = eParseError;
  1169. Win4Assert( !SUCCEEDED(sc) );
  1170. }
  1171. AND_CATCH( CPostedOleDBException, e )
  1172. {
  1173. //
  1174. // When the execution error was detected, the Ole DB error
  1175. // info was retrieved and stored in the exception object.
  1176. // We retrieve that here and compose the error message.
  1177. //
  1178. sc = e.GetErrorCode();
  1179. Win4Assert( !SUCCEEDED(sc) );
  1180. XInterface <IErrorInfo> xErrorInfo(e.AcquireErrorInfo());
  1181. if (xErrorInfo.GetPointer())
  1182. {
  1183. BSTR bstrErrorDescription = 0;
  1184. xErrorInfo->GetDescription(&bstrErrorDescription);
  1185. if (bstrErrorDescription)
  1186. {
  1187. SetError( sc, OLESTR("CreateRecordset"), (WCHAR const *)bstrErrorDescription);
  1188. SysFreeString(bstrErrorDescription);
  1189. fSetErrorNeeded = FALSE;
  1190. }
  1191. else
  1192. eErrorClass = eDefaultError;
  1193. }
  1194. }
  1195. AND_CATCH( CException, e )
  1196. {
  1197. sc = e.GetErrorCode();
  1198. eErrorClass = eDefaultError;
  1199. Win4Assert( !SUCCEEDED(sc) );
  1200. }
  1201. END_CATCH
  1202. if (! SUCCEEDED(sc) && fSetErrorNeeded)
  1203. SetError( sc, OLESTR("CreateRecordset"), eErrorClass );
  1204. return sc;
  1205. }
  1206. //+---------------------------------------------------------------------------
  1207. //
  1208. // Member: CixssoQuery::ParseOptimizeFor - private static
  1209. //
  1210. // Synopsis: Parse the input string for the OptimizeFor property
  1211. //
  1212. // Arguments: [wcsOptString] - input string
  1213. // [eChoice] - OptimizeFor choice expressed in wcsOptString
  1214. //
  1215. // Returns: SCODE - status return
  1216. //
  1217. // History: 05 Mar 1997 Alanw Created
  1218. //
  1219. //----------------------------------------------------------------------------
  1220. SCODE CixssoQuery::ParseOptimizeFor( WCHAR const * wcsOptString,
  1221. DWORD & eChoice )
  1222. {
  1223. eChoice = eOptHitCount;
  1224. while (wcsOptString && *wcsOptString)
  1225. {
  1226. WCHAR * wcsNext = wcschr( wcsOptString, ',' );
  1227. ULONG cch = (wcsNext) ? CiPtrToUlong( wcsNext - wcsOptString ) :
  1228. wcslen( wcsOptString );
  1229. if ( 11 == cch && _wcsnicmp(wcsOptString, L"performance", 11) == 0)
  1230. {
  1231. eChoice |= eOptPerformance;
  1232. }
  1233. else if ( 6 == cch && _wcsnicmp(wcsOptString, L"recall", 6) == 0)
  1234. {
  1235. eChoice |= eOptRecall;
  1236. }
  1237. else if ( 8 == cch && _wcsnicmp(wcsOptString, L"hitcount", 8) == 0)
  1238. {
  1239. eChoice |= eOptHitCount;
  1240. }
  1241. else if ( 10 == cch && _wcsnicmp(wcsOptString, L"nohitcount", 10) == 0)
  1242. {
  1243. eChoice &= ~eOptHitCount;
  1244. }
  1245. else
  1246. return E_INVALIDARG;
  1247. wcsOptString = wcsNext;
  1248. if (wcsOptString)
  1249. {
  1250. wcsOptString++;
  1251. while (iswspace( *wcsOptString ))
  1252. wcsOptString++;
  1253. }
  1254. }
  1255. // 'performance' and 'recall' are mutually exclusive. Check if both
  1256. // were set.
  1257. if ( (eChoice & (eOptRecall | eOptPerformance)) ==
  1258. (eOptRecall | eOptPerformance) )
  1259. return E_INVALIDARG;
  1260. return S_OK;
  1261. }
  1262. //+---------------------------------------------------------------------------
  1263. //
  1264. // Member: CixssoQuery::ParseCiDepthFlag, private
  1265. //
  1266. // Synopsis: Parses the flags attribute
  1267. //
  1268. // Arguments: [bstrFlags] -- flags
  1269. //
  1270. // Returns: ULONG - query scope flags
  1271. //
  1272. // History: 96/Jan/03 DwightKr created
  1273. //
  1274. //----------------------------------------------------------------------------
  1275. ULONG CixssoQuery::ParseCiDepthFlag( BSTR bstrFlags )
  1276. {
  1277. if ( 0 == bstrFlags || 0 == SysStringLen(bstrFlags) )
  1278. {
  1279. return QUERY_DEEP;
  1280. }
  1281. ULONG ulFlags;
  1282. if ( _wcsicmp(bstrFlags, L"SHALLOW") == 0 )
  1283. {
  1284. ulFlags = QUERY_SHALLOW;
  1285. }
  1286. else if ( _wcsicmp(bstrFlags, L"DEEP") == 0 )
  1287. {
  1288. ulFlags = QUERY_DEEP;
  1289. }
  1290. else
  1291. {
  1292. THROW( CIxssoException(MSG_IXSSO_EXPECTING_SHALLOWDEEP, 0) );
  1293. }
  1294. return ulFlags;
  1295. }
  1296. //+---------------------------------------------------------------------------
  1297. //
  1298. // Member: CixssoQuery::SetLocaleString - private
  1299. //
  1300. // Synopsis: Parse the input string for a recognizable locale name
  1301. //
  1302. // Arguments: [bstrLocale] - input string
  1303. //
  1304. // Returns: SCODE - status return
  1305. //
  1306. // History: 13 Mar 1997 Alanw Created
  1307. //
  1308. //----------------------------------------------------------------------------
  1309. SCODE CixssoQuery::SetLocaleString(BSTR str)
  1310. {
  1311. LCID lcidTemp = GetLCIDFromString( str );
  1312. if (lcidTemp == -1)
  1313. {
  1314. return E_INVALIDARG;
  1315. }
  1316. _lcid = lcidTemp;
  1317. return S_OK;
  1318. }
  1319. //+---------------------------------------------------------------------------
  1320. //
  1321. // Function: ParseNumberVectorString - public
  1322. //
  1323. // Synopsis: Parses a string consisting of ',' separated numeric values
  1324. // into an array.
  1325. //
  1326. // Arguments: [pwszValue] - input string
  1327. // [aNum] - dynamic array where numbers are placed.
  1328. //
  1329. // History: 10 Jun 1997 Alanw Created
  1330. //
  1331. //----------------------------------------------------------------------------
  1332. void ParseNumberVectorString( WCHAR * pwszValue, CDynArrayInPlace<LONG> & aNum )
  1333. {
  1334. while (pwszValue)
  1335. {
  1336. LONG lNum = _wtoi( pwszValue );
  1337. aNum[aNum.Count()] = lNum;
  1338. pwszValue = wcschr(pwszValue, L',');
  1339. if (pwszValue)
  1340. pwszValue++;
  1341. }
  1342. }
  1343. void FormatLongVector( SAFEARRAY * psa, XGrowable<WCHAR> & awchBuf )
  1344. {
  1345. Win4Assert( SafeArrayGetDim( psa ) == 1 &&
  1346. SafeArrayGetElemsize( psa ) == sizeof (LONG) );
  1347. LONG iLBound = 0;
  1348. LONG iUBound = 0;
  1349. SCODE sc = SafeArrayGetLBound( psa, 1, &iLBound );
  1350. if (SUCCEEDED(sc))
  1351. sc = SafeArrayGetUBound( psa, 1, &iUBound );
  1352. unsigned cch = 0;
  1353. for (int i=iLBound; i<= iUBound; i++)
  1354. {
  1355. LONG lValue;
  1356. LONG ix[1];
  1357. ix[0] = i;
  1358. sc = SafeArrayGetElement( psa, ix, &lValue );
  1359. awchBuf.SetSize(cch + 20);
  1360. if (i != iLBound)
  1361. {
  1362. awchBuf[cch] = L',';
  1363. cch++;
  1364. }
  1365. _itow( lValue, &awchBuf[cch], 10 );
  1366. cch += wcslen( &awchBuf[cch] );
  1367. }
  1368. }
  1369. // CIXSSOPropertyList methods
  1370. //+-------------------------------------------------------------------------
  1371. //
  1372. // Member: CIXSSOPropertyList::CIXSSOPropertyList, public
  1373. //
  1374. // Synopsis: Constructs a property mapper for the ixsso's use.
  1375. //
  1376. // Parameters: [pDefaultList] -- The default column mapper.
  1377. //
  1378. // History: 26-Aug-97 KrishnaN Created
  1379. //
  1380. //--------------------------------------------------------------------------
  1381. CIXSSOPropertyList::CIXSSOPropertyList(ULONG ulCodePage)
  1382. : _cRefs( 1 ),
  1383. _ulCodePage( ulCodePage ),
  1384. _xDefaultList(0)
  1385. {
  1386. // default list is not known. Use SetDefaultList to set that
  1387. }
  1388. // Set the defualt list
  1389. void CIXSSOPropertyList::SetDefaultList(IColumnMapper *pDefaultList)
  1390. {
  1391. Win4Assert(pDefaultList);
  1392. _xDefaultList.Set(pDefaultList);
  1393. _xDefaultList->AddRef();
  1394. }
  1395. //+-------------------------------------------------------------------------
  1396. //
  1397. // Member: CIXSSOPropertyList::QueryInterface, public
  1398. //
  1399. // Arguments: [ifid] -- Interface id
  1400. // [ppiuk] -- Interface return pointer
  1401. //
  1402. // History: 26-Aug-97 KrishnaN Created
  1403. //
  1404. //--------------------------------------------------------------------------
  1405. STDMETHODIMP CIXSSOPropertyList::QueryInterface( REFIID ifid, void ** ppiuk )
  1406. {
  1407. if (0 == ppiuk)
  1408. return E_INVALIDARG;
  1409. if ( IID_IUnknown == ifid )
  1410. {
  1411. AddRef();
  1412. *ppiuk = (void *)((IUnknown *)this);
  1413. return S_OK;
  1414. }
  1415. else if (IID_IColumnMapper == ifid )
  1416. {
  1417. AddRef();
  1418. *ppiuk = (void *)((IColumnMapper *)this);
  1419. return S_OK;
  1420. }
  1421. else
  1422. {
  1423. *ppiuk = 0;
  1424. return E_NOINTERFACE;
  1425. }
  1426. }
  1427. //+-------------------------------------------------------------------------
  1428. //
  1429. // Member: CIXSSOPropertyList::AddRef, public
  1430. //
  1431. // Synopsis: Reference the virtual table.
  1432. //
  1433. // History: 26-Aug-97 KrishnaN Created
  1434. //
  1435. //--------------------------------------------------------------------------
  1436. STDMETHODIMP_(ULONG) CIXSSOPropertyList::AddRef(void)
  1437. {
  1438. InterlockedIncrement( &_cRefs );
  1439. return( _cRefs );
  1440. }
  1441. //+-------------------------------------------------------------------------
  1442. //
  1443. // Member: CIXSSOPropertyList::Release, public
  1444. //
  1445. // Synopsis: De-Reference the virtual table.
  1446. //
  1447. // Effects: If the ref count goes to 0 then the table is deleted.
  1448. //
  1449. // History: 26-Aug-97 KrishnaN Created
  1450. //
  1451. //--------------------------------------------------------------------------
  1452. STDMETHODIMP_(ULONG) CIXSSOPropertyList::Release(void)
  1453. {
  1454. unsigned long uTmp = InterlockedDecrement( &_cRefs );
  1455. if (0 == uTmp)
  1456. {
  1457. delete this;
  1458. }
  1459. return(uTmp);
  1460. }
  1461. //
  1462. // IColumnMapper methods
  1463. //
  1464. //+-------------------------------------------------------------------------
  1465. //
  1466. // Member: CIXSSOPropertyList::GetPropInfoFromName, public
  1467. //
  1468. // Synopsis: Get property info. from name.
  1469. //
  1470. // Parameters: [wcsPropName] -- Property name to look up.
  1471. // [ppPropId] -- Ptr to return Id of the property.
  1472. // [pPropType] -- Ptr to return type of the property.
  1473. // [puiWidth] -- Ptr to return property width.
  1474. //
  1475. // History: 26-Aug-97 KrishnaN Created
  1476. //
  1477. //--------------------------------------------------------------------------
  1478. SCODE CIXSSOPropertyList::GetPropInfoFromName(const WCHAR *wcsPropName,
  1479. DBID * *ppPropId,
  1480. DBTYPE *pPropType,
  1481. unsigned int *puiWidth)
  1482. {
  1483. //
  1484. // Callers can pass in 0 for pPropType and puiWidth if they
  1485. // don't care about them.
  1486. //
  1487. if (0 == wcsPropName || 0 == ppPropId)
  1488. return E_INVALIDARG;
  1489. Win4Assert(_xDefaultList.GetPointer());
  1490. //
  1491. // First check in the default list, then in the override list.
  1492. //
  1493. SCODE sc = _xDefaultList->GetPropInfoFromName(wcsPropName,
  1494. ppPropId,
  1495. pPropType,
  1496. puiWidth);
  1497. if (FAILED(sc) && 0 != _xOverrideList.GetPointer())
  1498. {
  1499. sc = _xOverrideList->GetPropInfoFromName(wcsPropName,
  1500. ppPropId,
  1501. pPropType,
  1502. puiWidth);
  1503. }
  1504. return sc;
  1505. }
  1506. //+-------------------------------------------------------------------------
  1507. //
  1508. // Member: CIXSSOPropertyList::GetPropInfoFromId, public
  1509. //
  1510. // Synopsis: Get property info. from dbid.
  1511. //
  1512. // Parameters: [pPropId] -- Ptr to prop to look up.
  1513. // [pwcsName] -- Ptr to return property name.
  1514. // [pPropType] -- Ptr to return type of the property.
  1515. // [puiWidth] -- Ptr to return property width.
  1516. //
  1517. // History: 26-Aug-97 KrishnaN Created
  1518. //
  1519. //--------------------------------------------------------------------------
  1520. SCODE CIXSSOPropertyList::GetPropInfoFromId(const DBID *pPropId,
  1521. WCHAR * *pwcsName,
  1522. DBTYPE *pPropType,
  1523. unsigned int *puiWidth)
  1524. {
  1525. Win4Assert(!"Not available!");
  1526. return E_NOTIMPL;
  1527. #if 0 // complete, working implementation, but not needed.
  1528. //
  1529. // Callers can pass in 0 for pPropType and puiWidth if they
  1530. // don't care about them.
  1531. //
  1532. if (0 == pwcsName || 0 == pPropId)
  1533. return E_INVALIDARG;
  1534. //
  1535. // First check in the default list, then in the override list.
  1536. //
  1537. SCODE sc = _xDefaultList->GetPropInfoFromId(pPropId,
  1538. pwcsName,
  1539. pPropType,
  1540. puiWidth);
  1541. if (FAILED(sc) && 0 != _xOverrideList.GetPointer())
  1542. {
  1543. sc = _xOverrideList->GetPropInfoFromId(pPropId,
  1544. pwcsName,
  1545. pPropType,
  1546. puiWidth);
  1547. }
  1548. return sc;
  1549. #endif // 0
  1550. }
  1551. //+-------------------------------------------------------------------------
  1552. //
  1553. // Member: CIXSSOPropertyList::EnumPropInfo, public
  1554. //
  1555. // Synopsis: Gets the i-th entry from the list of properties.
  1556. //
  1557. // Parameters: [iEntry] -- i-th entry to retrieve (0-based).
  1558. // [pwcsName] -- Ptr to return property name.
  1559. // [ppPropId] -- Ptr to return Id of the property.
  1560. // [pPropType] -- Ptr to return type of the property.
  1561. // [puiWidth] -- Ptr to return property width.
  1562. //
  1563. // History: 26-Aug-97 KrishnaN Created
  1564. //
  1565. //--------------------------------------------------------------------------
  1566. SCODE CIXSSOPropertyList::EnumPropInfo(ULONG iEntry,
  1567. const WCHAR * *pwcsName,
  1568. DBID * *ppPropId,
  1569. DBTYPE *pPropType,
  1570. unsigned int *puiWidth)
  1571. {
  1572. Win4Assert(!"Not available!");
  1573. return E_NOTIMPL;
  1574. }
  1575. //+-------------------------------------------------------------------------
  1576. //
  1577. // Member: CIXSSOPropertyList::IsMapUpToDate, public
  1578. //
  1579. // Synopsis: Indicates if the column map is up to date.
  1580. //
  1581. // History: 26-Aug-97 KrishnaN Created
  1582. //
  1583. //--------------------------------------------------------------------------
  1584. SCODE CIXSSOPropertyList::IsMapUpToDate()
  1585. {
  1586. Win4Assert(_xDefaultList.GetPointer());
  1587. // return the IsMapUpToDate of the default list.
  1588. // the override list is always considered to be
  1589. // upto date.
  1590. return _xDefaultList->IsMapUpToDate();
  1591. }
  1592. //+---------------------------------------------------------------------------
  1593. //
  1594. // Member: CIXSSOPropertyList::AddEntry, private
  1595. //
  1596. // Synopsis: Adds a CPropEntry to the overriding list. Verifies that the name
  1597. // isn't already in the default list or the overriding list.
  1598. //
  1599. // Arguments: [xPropEntry] -- CPropEntry to add. Acquired on success
  1600. // [iLine] -- line number we're parsing
  1601. //
  1602. // Returns: S_OK on success or S_
  1603. //
  1604. // History: 11-Sep-97 KrishnaN Created.
  1605. //
  1606. //----------------------------------------------------------------------------
  1607. SCODE CIXSSOPropertyList::AddEntry( XPtr<CPropEntry> & xPropEntry, int iLine )
  1608. {
  1609. Win4Assert(_xDefaultList.GetPointer());
  1610. SCODE sc = S_OK;
  1611. // protect _xOverrideList
  1612. CLock lock(_mtxAdd);
  1613. //
  1614. // We do not allow entries in the override list that have the same name
  1615. // as the default list.
  1616. //
  1617. DBID *pPropId;
  1618. DBTYPE PropType;
  1619. unsigned uWidth;
  1620. if ( S_OK == GetPropInfoFromName( xPropEntry->GetName(),
  1621. &pPropId,
  1622. &PropType,
  1623. &uWidth ))
  1624. {
  1625. if ( PropType != xPropEntry->GetPropType() ||
  1626. ( uWidth != xPropEntry->GetWidth() &&
  1627. xPropEntry->GetWidth() != PLIST_DEFAULT_WIDTH ) )
  1628. {
  1629. THROW( CPListException( QPLIST_E_DUPLICATE, iLine ) );
  1630. }
  1631. else
  1632. sc = QPLIST_S_DUPLICATE;
  1633. }
  1634. if ( S_OK == sc )
  1635. {
  1636. if (0 == _xOverrideList.GetPointer())
  1637. _xOverrideList.Set(new CPropertyList(_ulCodePage));
  1638. _xOverrideList->AddEntry( xPropEntry.GetPointer(), iLine);
  1639. xPropEntry.Acquire();
  1640. }
  1641. return sc;
  1642. } //AddEntry
  1643. #if 0
  1644. HRESULT CixssoQuery::GetInterfaceSafetyOptions(
  1645. REFIID riid,
  1646. DWORD * pdwSupportedOptions,
  1647. DWORD * pdwEnabledOptions )
  1648. {
  1649. if ( 0 == pdwSupportedOptions ||
  1650. 0 == pdwEnabledOptions )
  1651. return E_POINTER;
  1652. ixssoDebugOut(( DEB_ITRACE, "get safety options called...\n" ));
  1653. *pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER;
  1654. *pdwEnabledOptions = 0;
  1655. return S_OK;
  1656. } //GetInterfaceSafetyOptions
  1657. HRESULT CixssoQuery::SetInterfaceSafetyOptions(
  1658. REFIID riid,
  1659. DWORD dwOptionSetMask,
  1660. DWORD dwEnabledOptions )
  1661. {
  1662. ixssoDebugOut(( DEB_ITRACE, "set setmask: %#x\n", dwOptionSetMask ));
  1663. ixssoDebugOut(( DEB_ITRACE, "set enabled: %#x\n", dwEnabledOptions ));
  1664. _dwSafetyOptions = (dwEnabledOptions & dwOptionSetMask);
  1665. return S_OK;
  1666. } //SetInterfaceSafetyOptions
  1667. #endif
  1668. //+-------------------------------------------------------------------------
  1669. //
  1670. // Member: CixssoQuery::SetSite, public
  1671. //
  1672. // Synopsis: Sets the current site (if any). Called by containers of
  1673. // CixssoQuery like IE. Not called by other containers like
  1674. // ASP and CScript.
  1675. //
  1676. // Arguments: [pSite] -- The container of this query object
  1677. //
  1678. // Returns: HRESULT
  1679. //
  1680. // History: 09-Nov-00 dlee Created
  1681. //
  1682. //--------------------------------------------------------------------------
  1683. HRESULT CixssoQuery::SetSite( IUnknown * pSite )
  1684. {
  1685. _xSite.Free();
  1686. if ( 0 != pSite )
  1687. {
  1688. pSite->AddRef();
  1689. _xSite.Set( pSite );
  1690. }
  1691. ixssoDebugOut(( DEB_ITRACE, "setting site: %#x\n", pSite ));
  1692. return S_OK;
  1693. } //SetSite
  1694. //+-------------------------------------------------------------------------
  1695. //
  1696. // Member: CixssoQuery::GetSite, public
  1697. //
  1698. // Synopsis: Retrieves the current site (if any)
  1699. //
  1700. // Arguments: [riid] -- IID requested
  1701. // [ppvSite] -- Where the interface pointer is returned
  1702. //
  1703. // Returns: HRESULT like a QueryInterface()
  1704. //
  1705. // History: 09-Nov-00 dlee Created
  1706. //
  1707. //--------------------------------------------------------------------------
  1708. HRESULT CixssoQuery::GetSite(
  1709. REFIID riid,
  1710. void ** ppvSite )
  1711. {
  1712. ixssoDebugOut(( DEB_ITRACE, "getsite\n" ));
  1713. if ( 0 == ppvSite )
  1714. return E_POINTER;
  1715. *ppvSite = 0;
  1716. if ( _xSite.IsNull() )
  1717. return E_NOINTERFACE;
  1718. return _xSite->QueryInterface( riid, ppvSite );
  1719. } //GetSite
  1720. //+-------------------------------------------------------------------------
  1721. //
  1722. // Member: CixssoQuery::IsSafeForScripting, private
  1723. //
  1724. // Synopsis: Checks if it's ok to execute in the current context. Throws
  1725. // an exception if it's not safe or on error. It's not safe
  1726. // to execute script off a remote machine.
  1727. //
  1728. // History: 09-Nov-00 dlee Created
  1729. //
  1730. //--------------------------------------------------------------------------
  1731. void CixssoQuery::IsSafeForScripting()
  1732. {
  1733. XInterface<IServiceProvider> xServiceProvider;
  1734. SCODE sc = GetSite( IID_IServiceProvider,
  1735. xServiceProvider.GetQIPointer() );
  1736. //
  1737. // When queries are run in IIS the container does not call
  1738. // SetSite, so there is no site and we'll have E_NOINTERFACE
  1739. // at this point. Same for cscript.exe queries.
  1740. // If that ever changes, the check below for file:// URLs will
  1741. // fail and no IIS queries will ever work.
  1742. //
  1743. if ( E_NOINTERFACE == sc )
  1744. return;
  1745. if ( FAILED( sc ) )
  1746. THROW( CException( sc ) );
  1747. XInterface<IWebBrowser2> xWebBrowser;
  1748. sc = xServiceProvider->QueryService( SID_SWebBrowserApp,
  1749. IID_IWebBrowser2,
  1750. xWebBrowser.GetQIPointer() );
  1751. if ( E_NOINTERFACE == sc )
  1752. return;
  1753. if ( FAILED( sc ) )
  1754. THROW( CException( sc ) );
  1755. BSTR bstrURL;
  1756. sc = xWebBrowser->get_LocationURL( &bstrURL );
  1757. if ( FAILED( sc ) )
  1758. THROW( CException( sc ) );
  1759. XBStr xURL( bstrURL );
  1760. ixssoDebugOut(( DEB_ITRACE, "url: %ws\n", bstrURL ));
  1761. WCHAR buf[32];
  1762. URL_COMPONENTS uc;
  1763. RtlZeroMemory( &uc, sizeof uc );
  1764. uc.dwStructSize = sizeof uc;
  1765. uc.lpszScheme = buf;
  1766. uc.dwSchemeLength = sizeof buf / sizeof WCHAR;
  1767. INTERNET_SCHEME scheme = INTERNET_SCHEME_UNKNOWN;
  1768. if ( InternetCrackUrl( bstrURL, wcslen( bstrURL ), ICU_DECODE, &uc ) )
  1769. scheme = uc.nScheme;
  1770. // The URL has to be a file:/// URL or we won't allow it.
  1771. if ( INTERNET_SCHEME_FILE != scheme )
  1772. THROW( CException( E_ACCESSDENIED ) );
  1773. // OK, now it can't be a UNC path. Look for a drive letter and a colon
  1774. // file:///c: the length should at least be 10
  1775. if ( wcslen( bstrURL ) <= 9 )
  1776. THROW( CException( E_ACCESSDENIED ) );
  1777. WCHAR const * pwcPath = bstrURL + 8;
  1778. WCHAR const * pwcColon = wcschr( pwcPath, L':' );
  1779. ixssoDebugOut(( DEB_ITRACE, "Path is: %ws\n", pwcPath ));
  1780. if ( ( 0 == pwcColon ) ||
  1781. ( pwcColon > ( pwcPath + 1 ) ) )
  1782. THROW( CException( E_ACCESSDENIED ) );
  1783. WCHAR wcDrive = * ( pwcColon - 1 );
  1784. ixssoDebugOut(( DEB_ITRACE, "wcDrive is: %wc\n", wcDrive ));
  1785. wcDrive = towupper( wcDrive );
  1786. if ( ( wcDrive < L'A' ) || ( wcDrive > L'Z' ) )
  1787. THROW( CException( E_ACCESSDENIED ) );
  1788. } //IsSafeForScripting