Source code of Windows XP (NT5)
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.

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