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.

991 lines
27 KiB

  1. //----------------------------------------------------------------------------
  2. // Microsoft OLE DB Implementation For Index Server
  3. // (C) Copyright 1997 By Microsoft Corporation.
  4. //
  5. // @doc
  6. //
  7. // @module PTPROPS.CPP |
  8. //
  9. // @rev 1 | 10-13-97 | Briants | Created
  10. //
  11. // Includes ------------------------------------------------------------------
  12. #pragma hdrstop
  13. #include "msidxtr.h"
  14. // Constants and Static Struct -----------------------------------------------
  15. #define CALC_CCH_MINUS_NULL(p1) (sizeof(p1) / sizeof(*(p1))) - 1
  16. // Code ----------------------------------------------------------------------
  17. // CScopeData::CScopeData ---------------------------------------------------
  18. //
  19. // @mfunc Constructor
  20. //
  21. CScopeData::CScopeData()
  22. {
  23. m_cRef = 1;
  24. m_cScope = 0;
  25. m_cMaxScope = 0;
  26. m_cbData = 0;
  27. m_cbMaxData = 0;
  28. m_rgbData = NULL;
  29. m_rgulDepths = NULL;
  30. m_rgCatalogOffset = NULL;
  31. m_rgScopeOffset = NULL;
  32. m_rgMachineOffset = NULL;
  33. }
  34. // CScopeData::~CScopeData ---------------------------------------------------
  35. //
  36. // @mfunc Destructor
  37. //
  38. CScopeData::~CScopeData()
  39. {
  40. delete m_rgulDepths;
  41. delete m_rgCatalogOffset;
  42. delete m_rgScopeOffset;
  43. delete m_rgMachineOffset;
  44. delete m_rgbData;
  45. }
  46. // CScopeData::Reset ---------------------------------------------------------
  47. //
  48. // @mfunc Reset the scope count and offsets back to initial state.
  49. //
  50. // @rdesc HRESULT | status of methods success / failure
  51. // @flags OTHER | from called methods
  52. //
  53. HRESULT CScopeData::Reset(void)
  54. {
  55. // Reset the offsets to unused
  56. for (ULONG i = 0; i<m_cMaxScope; i++)
  57. {
  58. m_rgScopeOffset[i] = UNUSED_OFFSET;
  59. m_rgCatalogOffset[i] = UNUSED_OFFSET;
  60. m_rgMachineOffset[i] = UNUSED_OFFSET;
  61. }
  62. // Set Scope Index Back to 0
  63. m_cScope = 0;
  64. return S_OK;
  65. }
  66. // CScopeData::FInit ---------------------------------------------------------
  67. //
  68. // @mfunc Initialize the Constructed Object
  69. //
  70. // @rdesc HRESULT | status of methods success / failure
  71. // @flags OTHER | from called methods
  72. //
  73. HRESULT CScopeData::FInit
  74. (
  75. LPCWSTR pwszMachine // @param IN | current default machine
  76. )
  77. {
  78. HRESULT hr;
  79. // Allocate Scope buffers
  80. // @devnote: IncrementScopeCount() has special logic for the first
  81. // allocation, thus the m_cScope will remain 0 after this call
  82. if( SUCCEEDED(hr = IncrementScopeCount()) )
  83. {
  84. assert( m_cScope == 0 );
  85. // Initialize the machine
  86. hr = SetTemporaryMachine((LPWSTR)pwszMachine, CALC_CCH_MINUS_NULL(L"."));
  87. }
  88. return hr;
  89. }
  90. // CScopeData::AddRef ------------------------------------------
  91. //
  92. // @mfunc Increments a persistence count for the object
  93. //
  94. // @rdesc Current reference count
  95. //
  96. ULONG CScopeData::AddRef (void)
  97. {
  98. return InterlockedIncrement( (long*) &m_cRef);
  99. }
  100. // CScopeData::Release -----------------------------------------
  101. //
  102. // @mfunc Decrements a persistence count for the object and if
  103. // persistence count is 0, the object destroys itself.
  104. //
  105. // @rdesc Current reference count
  106. //
  107. ULONG CScopeData::Release (void)
  108. {
  109. assert( m_cRef > 0 );
  110. ULONG cRef = InterlockedDecrement( (long *) &m_cRef );
  111. if( 0 == cRef )
  112. {
  113. delete this;
  114. return 0;
  115. }
  116. return cRef;
  117. }
  118. // CScopeData::GetData -------------------------------------------------------
  119. //
  120. // @mfunc Copies the current value of our scope data into the passed in
  121. // variant
  122. //
  123. // @rdesc HRESULT | status of methods success / failure
  124. // @flags S_OK | retrieved the scope data
  125. // @flags E_INVALIDARG | Unknown PropId requested
  126. // @flags OTHER | from called methods
  127. //
  128. HRESULT CScopeData::GetData(
  129. ULONG uPropId, //@parm IN | id of scope data to return
  130. VARIANT* pvValue, //@parm INOUT | Variant to return data in
  131. LPCWSTR pcwszCatalog
  132. )
  133. {
  134. assert( pvValue );
  135. HRESULT hr;
  136. ULONG ul;
  137. SAFEARRAYBOUND rgsabound[1];
  138. SAFEARRAY FAR* psa = NULL;
  139. rgsabound[0].lLbound = 0;
  140. rgsabound[0].cElements = m_cScope;
  141. // Make sure that we free any memory that may be held by the variant.
  142. VariantClear(pvValue);
  143. switch( uPropId )
  144. {
  145. LONG rgIx[1];
  146. case PTPROPS_SCOPE:
  147. {
  148. // Create a 1 dim safe array of type BSTR
  149. psa = SafeArrayCreate(VT_BSTR, 1, rgsabound);
  150. if( psa )
  151. {
  152. for(ul=0; ul<m_cScope; ul++)
  153. {
  154. rgIx[0] = ul;
  155. BSTR bstrVal = SysAllocString((LPWSTR)(m_rgbData + m_rgScopeOffset[ul]));
  156. if( bstrVal )
  157. {
  158. hr = SafeArrayPutElement(psa, rgIx, bstrVal);
  159. SysFreeString(bstrVal);
  160. if( FAILED(hr) )
  161. goto error_delete;
  162. }
  163. else
  164. {
  165. hr = ResultFromScode(E_OUTOFMEMORY);
  166. goto error_delete;
  167. }
  168. }
  169. V_VT(pvValue) = VT_BSTR | VT_ARRAY;
  170. V_ARRAY(pvValue) = psa;
  171. psa = NULL;
  172. }
  173. else
  174. return ResultFromScode(E_OUTOFMEMORY);
  175. }
  176. break;
  177. case PTPROPS_DEPTH:
  178. {
  179. // Create a 1 dim safe array of type I4
  180. psa = SafeArrayCreate(VT_I4, 1, rgsabound);
  181. if( psa )
  182. {
  183. for(ul=0; ul<m_cScope; ul++)
  184. {
  185. rgIx[0] = ul;
  186. hr = SafeArrayPutElement(psa, rgIx, (void*)&m_rgulDepths[ul]);
  187. if( FAILED(hr) )
  188. goto error_delete;
  189. }
  190. V_VT(pvValue) = VT_I4 | VT_ARRAY;
  191. V_ARRAY(pvValue) = psa;
  192. psa = NULL;
  193. }
  194. else
  195. return ResultFromScode(E_OUTOFMEMORY);
  196. }
  197. break;
  198. case PTPROPS_CATALOG:
  199. {
  200. assert( pcwszCatalog );
  201. // Create a 1 dim safe array of type BSTR
  202. psa = SafeArrayCreate(VT_BSTR, 1, rgsabound);
  203. if( psa )
  204. {
  205. for(ul=0; ul<m_cScope; ul++)
  206. {
  207. rgIx[0] = ul;
  208. BSTR bstrVal;
  209. // Check to see if the catalog value has been cached, if not
  210. //
  211. if( m_rgCatalogOffset[ul] != UNUSED_OFFSET )
  212. {
  213. bstrVal = SysAllocString((LPWSTR)(m_rgbData + m_rgCatalogOffset[ul]));
  214. }
  215. else
  216. {
  217. bstrVal = SysAllocString(pcwszCatalog);
  218. }
  219. if( bstrVal )
  220. {
  221. hr = SafeArrayPutElement(psa, rgIx, bstrVal);
  222. SysFreeString(bstrVal);
  223. if( FAILED(hr) )
  224. goto error_delete;
  225. }
  226. else
  227. {
  228. hr = ResultFromScode(E_OUTOFMEMORY);
  229. goto error_delete;
  230. }
  231. }
  232. V_VT(pvValue) = VT_BSTR | VT_ARRAY;
  233. V_ARRAY(pvValue) = psa;
  234. psa = NULL;
  235. }
  236. else
  237. return ResultFromScode(E_OUTOFMEMORY);
  238. }
  239. break;
  240. case PTPROPS_MACHINE:
  241. {
  242. // Create a 1 dim safe array of type BSTR
  243. psa = SafeArrayCreate(VT_BSTR, 1, rgsabound);
  244. if( psa )
  245. {
  246. for(ul=0; ul<m_cScope; ul++)
  247. {
  248. rgIx[0] = ul;
  249. BSTR bstrVal = SysAllocString((LPWSTR)(m_rgbData + m_rgMachineOffset[ul]));
  250. if( bstrVal )
  251. {
  252. hr = SafeArrayPutElement(psa, rgIx, bstrVal);
  253. SysFreeString(bstrVal);
  254. if( FAILED(hr) )
  255. goto error_delete;
  256. }
  257. else
  258. {
  259. hr = ResultFromScode(E_OUTOFMEMORY);
  260. goto error_delete;
  261. }
  262. }
  263. V_VT(pvValue) = VT_BSTR | VT_ARRAY;
  264. V_ARRAY(pvValue) = psa;
  265. psa = NULL;
  266. }
  267. else
  268. return ResultFromScode(E_OUTOFMEMORY);
  269. }
  270. break;
  271. default:
  272. return ResultFromScode(E_INVALIDARG);
  273. break;
  274. }
  275. hr = S_OK;
  276. error_delete:
  277. if( psa )
  278. SafeArrayDestroy(psa);
  279. return hr;
  280. }
  281. // CScopeData::CacheData -----------------------------------------------------
  282. //
  283. // @mfunc Manages storing data values in our buffer
  284. //
  285. // @rdesc HRESULT | status of methods success / failure
  286. // @flags S_OK | Data value stored at returned offset.
  287. // @flags E_OUTOFMEMORY | Could not allocate resources.
  288. //
  289. HRESULT CScopeData::CacheData(
  290. LPVOID pData,
  291. ULONG cb,
  292. ULONG* pulOffset
  293. )
  294. {
  295. SCODE sc = S_OK;
  296. TRY
  297. {
  298. assert( pData && pulOffset && cb > 0 );
  299. // Check to see if there is room in the Data buffer, if not
  300. // reallocate data buffer
  301. if( m_cbData + cb > m_cbMaxData )
  302. {
  303. ULONG cbTempMax = m_cbMaxData + ( (cb < CB_SCOPE_DATA_BUFFER_INC) ?
  304. (CB_SCOPE_DATA_BUFFER_INC) :
  305. (cb + CB_SCOPE_DATA_BUFFER_INC) );
  306. m_rgbData = renewx( m_rgbData, m_cbMaxData, cbTempMax );
  307. m_cbMaxData = cbTempMax;
  308. }
  309. // copy data and terminator
  310. RtlCopyMemory( (m_rgbData + m_cbData), pData, cb );
  311. // Set the offset where the new value can be found
  312. *pulOffset = m_cbData;
  313. // Adjust offset to start on an 8 Byte boundary.
  314. assert( (m_cbData % 8) == 0 );
  315. // @devnote: After this calculation, m_cchData may actually be larger
  316. // than m_cchMaxData. This is OK, because FindOffsetBuffer will re-alloc
  317. // the next time around.
  318. m_cbData += cb + (8 - (cb % 8));
  319. }
  320. CATCH( CException, e )
  321. {
  322. sc = e.GetErrorCode();
  323. }
  324. END_CATCH
  325. return sc;
  326. }
  327. // CScopeData::SetTemporaryMachine -------------------------------------------
  328. //
  329. // @mfunc Stores the machine name used for setting machine properties
  330. // in the compiler environment.
  331. //
  332. // @rdesc HRESULT | status of methods success / failure
  333. // @flags OTHER | from called methods
  334. //
  335. HRESULT CScopeData::SetTemporaryMachine
  336. (
  337. LPWSTR pwszMachine, // @parm IN | machine to store
  338. ULONG cch // @parm IN | count of characters for new scope, exclude terminator
  339. )
  340. {
  341. HRESULT hr;
  342. ULONG ulOffset;
  343. assert( pwszMachine );
  344. assert( wcslen(pwszMachine) == cch );
  345. // Increment count of characters to include null terminator
  346. cch++;
  347. hr = CacheData(pwszMachine, (cch * sizeof(WCHAR)), &ulOffset);
  348. if( SUCCEEDED(hr) )
  349. {
  350. m_rgMachineOffset[m_cScope] = ulOffset;
  351. }
  352. return hr;
  353. }
  354. // CScopeData::SetTemporaryCatalog -------------------------------------------
  355. //
  356. // @mfunc Stores the catalog name used for setting scope properties
  357. // in the compiler environment.
  358. //
  359. // @rdesc HRESULT | status of methods success / failure
  360. // @flags S_OK | Data value stored at returned offset.
  361. // @flags OTHER | from called methods
  362. //
  363. HRESULT CScopeData::SetTemporaryCatalog
  364. (
  365. LPWSTR pwszCatalog, // @parm IN | catalog name
  366. ULONG cch
  367. )
  368. {
  369. assert( pwszCatalog );
  370. assert( wcslen(pwszCatalog) == cch );
  371. ULONG ulOffset;
  372. // Increment count of characters to include null terminator
  373. cch++;
  374. // Store the catalog value
  375. HRESULT hr = CacheData( pwszCatalog, (cch * sizeof(WCHAR)), &ulOffset );
  376. if( SUCCEEDED(hr) )
  377. m_rgCatalogOffset[m_cScope] = ulOffset;
  378. return hr;
  379. }
  380. // CScopeData::SetTemporaryScope ---------------------------------------------
  381. //
  382. // @mfunc Stores the scope name used for setting scope properties
  383. // in the compiler environment.
  384. //
  385. // @rdesc HRESULT | status of methods success / failure
  386. // @flags OTHER | from called methods
  387. //
  388. HRESULT CScopeData::SetTemporaryScope
  389. (
  390. LPWSTR pwszScope, // @parm IN | scope to store
  391. ULONG cch // @parm IN | count of characters for new scope, exclude terminator
  392. )
  393. {
  394. HRESULT hr;
  395. ULONG ulOffset;
  396. assert( pwszScope );
  397. assert( wcslen(pwszScope) == cch );
  398. // Increment count of characters to include null terminator
  399. cch++;
  400. hr = CacheData(pwszScope, (cch * sizeof(WCHAR)), &ulOffset);
  401. if( SUCCEEDED(hr) )
  402. {
  403. m_rgScopeOffset[m_cScope] = ulOffset;
  404. // @devnote: Fixup for '/' being in the scope, Index Server requires
  405. // this to rewritten.
  406. for (WCHAR *wcsLetter = (WCHAR*)(m_rgbData + ulOffset); *wcsLetter != L'\0'; wcsLetter++)
  407. if (L'/' == *wcsLetter)
  408. *wcsLetter = L'\\'; // path names needs backslashes, not forward slashes
  409. }
  410. return hr;
  411. }
  412. // CScopeData::IncrementScopeCount -------------------------------------------
  413. //
  414. // @mfunc Increments the number of temporary scopes defined. It also
  415. // copies the depth values to the next scope in case multiple
  416. // scopes are defined with the same traversal depth.
  417. //
  418. // @rdesc HRESULT | status of methods success / failure
  419. // @flags S_OK | Activated next scope arrays element
  420. // @flags E_OUTOFMEMORY | could allocate enough resources to do this.
  421. //
  422. HRESULT CScopeData::IncrementScopeCount()
  423. {
  424. SCODE sc = S_OK;
  425. TRY
  426. {
  427. ULONG cCurScope = m_cScope + 1;
  428. // Check if re-alloc must be done.
  429. if( cCurScope >= m_cMaxScope )
  430. {
  431. ULONG cNewMaxScope = m_cMaxScope + SCOPE_BUFFERS_INCREMENT;
  432. m_rgulDepths = renewx( m_rgulDepths, m_cMaxScope, cNewMaxScope );
  433. m_rgScopeOffset = renewx( m_rgScopeOffset, m_cMaxScope, cNewMaxScope );
  434. m_rgCatalogOffset = renewx( m_rgCatalogOffset, m_cMaxScope, cNewMaxScope );
  435. m_rgMachineOffset = renewx( m_rgMachineOffset, m_cMaxScope, cNewMaxScope );
  436. // If the is the initial Allocation, then make our current scope
  437. // equal to 0
  438. if( m_cMaxScope == 0 )
  439. cCurScope = 0;
  440. // Initialize new elements
  441. for (ULONG i = cCurScope; i<cNewMaxScope; i++)
  442. {
  443. m_rgScopeOffset[i] = UNUSED_OFFSET;
  444. m_rgCatalogOffset[i] = UNUSED_OFFSET;
  445. m_rgMachineOffset[i] = UNUSED_OFFSET;
  446. }
  447. // Save new Max Elements.
  448. m_cMaxScope = cNewMaxScope;
  449. }
  450. // Transfer Depth from previous node
  451. if( m_rgulDepths[m_cScope] & QUERY_SHALLOW )
  452. m_rgulDepths[cCurScope] = QUERY_SHALLOW;
  453. else
  454. m_rgulDepths[cCurScope] = QUERY_DEEP;
  455. // Transfer Machine and Catalog from previous node
  456. m_rgCatalogOffset[cCurScope] = m_rgCatalogOffset[m_cScope];
  457. m_rgMachineOffset[cCurScope] = m_rgMachineOffset[m_cScope];
  458. // Set the current # of used scopes to our new node.
  459. m_cScope = cCurScope;
  460. }
  461. CATCH( CException, e )
  462. {
  463. sc = e.GetErrorCode();
  464. }
  465. END_CATCH
  466. return sc;
  467. }
  468. //============================================================================
  469. //=
  470. //= CImpIParserTreeProperties
  471. //=
  472. //============================================================================
  473. // CImpIParserTreeProperties::CImpIParserTreeProperties ------------------------
  474. //
  475. // @mfunc Constructor
  476. //
  477. // @rdesc None
  478. //
  479. CImpIParserTreeProperties::CImpIParserTreeProperties()
  480. {
  481. // Reference count.
  482. m_cRef = 1;
  483. m_LastHR = S_OK;
  484. m_iErrOrd = 0;
  485. m_cErrParams = 0;
  486. m_dbType = 0;
  487. m_fDesc = QUERY_SORTASCEND;
  488. m_pctContainsColumn = NULL;
  489. m_pCScopeData = NULL;
  490. m_pwszCatalog = NULL;
  491. // initialize the CiRestriction data
  492. m_rgwchCiColumn[0] = L' '; // First character to a <space>
  493. m_rgwchCiColumn[1] = L'\0'; // Second is Null Term
  494. m_cchMaxRestriction = 0;
  495. m_cchRestriction = 0;
  496. m_pwszRestriction = NULL;
  497. m_pwszRestrictionAppendPtr = NULL;
  498. m_fLeftParen = false;
  499. }
  500. // CImpIParserTreeProperties::~CImpIParserTreeProperties -----------------------
  501. //
  502. // @mfunc Destructor
  503. //
  504. // @rdesc None
  505. //
  506. CImpIParserTreeProperties::~CImpIParserTreeProperties()
  507. {
  508. FreeErrorDescriptions();
  509. delete [] m_pwszRestriction;
  510. delete [] m_pwszCatalog;
  511. if( 0 != m_pCScopeData )
  512. m_pCScopeData->Release();
  513. }
  514. // CImpIParserTreeProperties::FInit -------------------------------
  515. //
  516. // @mfunc Initialize class
  517. //
  518. // @rdesc HResult indicating the status of the method
  519. // @flag S_OK | Init'd
  520. //
  521. HRESULT CImpIParserTreeProperties::FInit(
  522. LPCWSTR pcwszCatalog, //@parm IN | Current Catalog
  523. LPCWSTR pcwszMachine ) //@parm IN | Current Machine
  524. {
  525. SCODE sc = S_OK;
  526. TRY
  527. {
  528. Win4Assert( 0 != pcwszCatalog );
  529. Win4Assert( 0 == m_pwszCatalog );
  530. XPtrST<WCHAR> xCatalog( CopyString(pcwszCatalog) );
  531. sc = CreateNewScopeDataObject( pcwszMachine );
  532. if (SUCCEEDED(sc) )
  533. m_pwszCatalog = xCatalog.Acquire();
  534. }
  535. CATCH( CException, e )
  536. {
  537. sc = e.GetErrorCode();
  538. }
  539. END_CATCH
  540. return sc;
  541. }
  542. // CImpIParserTreeProperties::GetTreeProperties -------------------------------
  543. //
  544. // @mfunc Allows retrieval of properties
  545. //
  546. // @rdesc HResult indicating the status of the method
  547. // @flag S_OK | Property Value retrieved
  548. //
  549. STDMETHODIMP CImpIParserTreeProperties::GetProperties(
  550. ULONG eParseProp, //@parm IN | property to return value for
  551. VARIANT* vParseProp //@parm IN | Value of property
  552. )
  553. {
  554. // Require a buffer
  555. assert( vParseProp );
  556. //@TODO should we have to do this, or assume it is clean.
  557. VariantClear(vParseProp);
  558. switch( eParseProp )
  559. {
  560. case PTPROPS_SCOPE:
  561. case PTPROPS_DEPTH:
  562. case PTPROPS_MACHINE:
  563. return m_pCScopeData->GetData(eParseProp, vParseProp);
  564. break;
  565. case PTPROPS_CATALOG:
  566. return m_pCScopeData->GetData(eParseProp, vParseProp, m_pwszCatalog);
  567. break;
  568. case PTPROPS_CIRESTRICTION:
  569. V_BSTR(vParseProp) = SysAllocString(m_pwszRestriction);
  570. V_VT(vParseProp) = VT_BSTR;
  571. break;
  572. case PTPROPS_ERR_IDS:
  573. V_I4(vParseProp) = m_iErrOrd;
  574. V_VT(vParseProp) = VT_I4;
  575. break;
  576. case PTPROPS_ERR_HR:
  577. V_I4(vParseProp) = m_LastHR;
  578. V_VT(vParseProp) = VT_I4;
  579. break;
  580. case PTPROPS_ERR_DISPPARAM:
  581. {
  582. HRESULT hr = NOERROR;
  583. SAFEARRAYBOUND rgsabound[1];
  584. V_VT(vParseProp) = VT_BSTR | VT_ARRAY;
  585. V_ARRAY(vParseProp) = NULL;
  586. rgsabound[0].lLbound = 0;
  587. rgsabound[0].cElements = m_cErrParams;
  588. // Create a 1 dim safe array of type BSTR
  589. SAFEARRAY FAR* psa = SafeArrayCreate(VT_BSTR, 1, rgsabound);
  590. if( psa )
  591. {
  592. LONG rgIx[1];
  593. for(ULONG ul=0; ul<m_cErrParams; ul++)
  594. {
  595. rgIx[0] = ul;
  596. BSTR bstrVal = SysAllocString(m_pwszErrParams[ul]);
  597. if( bstrVal )
  598. {
  599. hr = SafeArrayPutElement(psa, rgIx, bstrVal);
  600. SysFreeString(bstrVal);
  601. if( FAILED(hr) )
  602. break;
  603. }
  604. else
  605. {
  606. hr = ResultFromScode(E_OUTOFMEMORY);
  607. break;
  608. }
  609. }
  610. if( SUCCEEDED(hr) )
  611. V_ARRAY(vParseProp) = psa;
  612. else
  613. SafeArrayDestroy(psa);
  614. }
  615. }
  616. break;
  617. default:
  618. return ResultFromScode(E_INVALIDARG);
  619. break;
  620. }
  621. return S_OK;
  622. }
  623. // CImpIParserTreeProperties::QueryInterface ----------------------------------
  624. //
  625. // @mfunc Returns a pointer to a specified interface. Callers use
  626. // QueryInterface to determine which interfaces the called object
  627. // supports.
  628. //
  629. // @rdesc HResult indicating the status of the method
  630. // @flag S_OK | Interface is supported and ppvObject is set.
  631. // @flag E_NOINTERFACE | Interface is not supported by the object
  632. // @flag E_INVALIDARG | One or more arguments are invalid.
  633. //
  634. STDMETHODIMP CImpIParserTreeProperties::QueryInterface
  635. (
  636. REFIID riid, //@parm IN | Interface ID of the interface being queried for.
  637. LPVOID * ppv //@parm OUT | Pointer to interface that was instantiated
  638. )
  639. {
  640. if( ppv == NULL )
  641. return ResultFromScode(E_INVALIDARG);
  642. if( (riid == IID_IUnknown) ||
  643. (riid == IID_IParserTreeProperties) )
  644. *ppv = (LPVOID)this;
  645. else
  646. *ppv = NULL;
  647. // If we're going to return an interface, AddRef it first
  648. if( *ppv )
  649. {
  650. ((LPUNKNOWN)*ppv)->AddRef();
  651. return NOERROR;
  652. }
  653. return ResultFromScode(E_NOINTERFACE);
  654. }
  655. // CImpIParserTreeProperties::AddRef ------------------------------------------
  656. //
  657. // @mfunc Increments a persistence count for the object
  658. //
  659. // @rdesc Current reference count
  660. //
  661. STDMETHODIMP_(ULONG) CImpIParserTreeProperties::AddRef (void)
  662. {
  663. return InterlockedIncrement( (long*) &m_cRef);
  664. }
  665. // CImpIParserTreeProperties::Release -----------------------------------------
  666. //
  667. // @mfunc Decrements a persistence count for the object and if
  668. // persistence count is 0, the object destroys itself.
  669. //
  670. // @rdesc Current reference count
  671. //
  672. STDMETHODIMP_(ULONG) CImpIParserTreeProperties::Release (void)
  673. {
  674. assert( m_cRef > 0 );
  675. ULONG cRef = InterlockedDecrement( (long *) &m_cRef );
  676. if( 0 == cRef )
  677. {
  678. delete this;
  679. return 0;
  680. }
  681. return cRef;
  682. }
  683. // CImpIParserTreeProperties::SetCiColumn -------------------------------------
  684. //
  685. // @mfunc Store the current column name to be applied to the
  686. // restriction later
  687. //
  688. // @rdesc None
  689. //
  690. void CImpIParserTreeProperties::SetCiColumn
  691. (
  692. LPWSTR pwszColumn // @parm IN | column name for this portion of restriction
  693. )
  694. {
  695. // Should alway remain a <space>
  696. assert( *m_rgwchCiColumn == L' ' );
  697. assert( wcslen(pwszColumn) <= MAX_CCH_COLUMNNAME );
  698. // Copy column name into buffer.
  699. wcscpy(&m_rgwchCiColumn[1], pwszColumn);
  700. }
  701. // CImpIParserTreeProperties::AppendCiRestriction -----------------------------
  702. //
  703. // @mfunc Appends the given string to the end of the contructed CiRestriction.
  704. //
  705. // @rdesc HRESULT | status of methods success / failure
  706. // @flags S_OK
  707. // @flags E_OUTOFMEMORY
  708. //
  709. HRESULT CImpIParserTreeProperties::AppendCiRestriction
  710. (
  711. LPWSTR pwsz, // @parm IN | latest addition to the generated CiRestriction
  712. ULONG cch // @parm IN | count of characters for new token, exclude terminator
  713. )
  714. {
  715. SCODE sc = S_OK;
  716. TRY
  717. {
  718. assert( 0 != pwsz && 0 != cch );
  719. assert( wcslen(pwsz) == cch ); // cch should NOT include space for terminator
  720. // Determine if buffer is large enough or needs to be expanded.
  721. if( m_cchRestriction + cch > m_cchMaxRestriction )
  722. {
  723. ULONG cchNew = m_cchRestriction + ( (cch >= CCH_CIRESTRICTION_INCREMENT) ?
  724. (CCH_CIRESTRICTION_INCREMENT + cch) :
  725. CCH_CIRESTRICTION_INCREMENT);
  726. LPWSTR pwszTemp = renewx( m_pwszRestriction, m_cchMaxRestriction, cchNew );
  727. if ( 0 != pwszTemp )
  728. {
  729. // First allocation Processing
  730. if( 0 == m_cchMaxRestriction )
  731. {
  732. *pwszTemp = L'\0';
  733. m_cchRestriction = 1;
  734. }
  735. // Recalculate Append Pointer
  736. m_pwszRestrictionAppendPtr = pwszTemp + (m_pwszRestrictionAppendPtr - m_pwszRestriction);
  737. // Set member variable to new buffer.
  738. m_pwszRestriction = pwszTemp;
  739. // Set Max number of character slots
  740. m_cchMaxRestriction = cchNew;
  741. }
  742. else
  743. return E_OUTOFMEMORY;
  744. }
  745. assert( m_pwszRestriction );
  746. assert( *m_pwszRestrictionAppendPtr == L'\0' ); //Should always be on Null Terminator
  747. wcscpy( m_pwszRestrictionAppendPtr, pwsz );
  748. m_cchRestriction += cch;
  749. m_pwszRestrictionAppendPtr += cch;
  750. }
  751. CATCH( CException, e )
  752. {
  753. sc = e.GetErrorCode();
  754. }
  755. END_CATCH
  756. return sc;
  757. }
  758. // CImpIParserTreeProperties::UseCiColumn -------------------------------------
  759. //
  760. // @mfunc Copies the current CiRestriction column name to the CiRestriction
  761. //
  762. // @rdesc HRESULT | status of methods success / failure
  763. // @flags S_OK
  764. // @flags OTHER | from called methods
  765. //
  766. HRESULT CImpIParserTreeProperties::UseCiColumn
  767. (
  768. WCHAR wch // @parm IN | prefix for column access
  769. )
  770. {
  771. SCODE sc = S_OK;
  772. // Do we have a column name stored
  773. if( m_rgwchCiColumn[1] != L'\0' )
  774. {
  775. m_rgwchCiColumn[0] = wch;
  776. sc = AppendCiRestriction( m_rgwchCiColumn, wcslen(m_rgwchCiColumn) );
  777. if( SUCCEEDED(sc) )
  778. {
  779. if( true == m_fLeftParen )
  780. {
  781. sc = AppendCiRestriction(L" (", CALC_CCH_MINUS_NULL(L" ("));
  782. m_fLeftParen = false;
  783. }
  784. else
  785. {
  786. sc = AppendCiRestriction(L" ", CALC_CCH_MINUS_NULL(L" "));
  787. }
  788. }
  789. m_rgwchCiColumn[0] = L' ';
  790. }
  791. return sc;
  792. }
  793. // CImpIParserTreeProperties::CreateNewScopeDataObject -------------------------
  794. //
  795. // @mfunc Creates a new ScopeData container
  796. //
  797. // @rdesc HRESULT | status of methods success / failure
  798. // @flags S_OK
  799. // @flags E_FAIL | FInit failed
  800. // @flags E_OUTOFMEMORY
  801. //
  802. HRESULT CImpIParserTreeProperties::CreateNewScopeDataObject
  803. (
  804. LPCWSTR pcwszMachine // @param IN | the current default machine
  805. )
  806. {
  807. Assert( 0 != pcwszMachine );
  808. SCODE sc = S_OK;
  809. TRY
  810. {
  811. // Allocate ScopeData container
  812. // @devnote: After this allocation has succeeded, all
  813. // deletions of this object should be done through refcounts
  814. XInterface<CScopeData> xpScopeData( new CScopeData() );
  815. sc = xpScopeData->FInit( pcwszMachine );
  816. if( SUCCEEDED(sc) )
  817. {
  818. if ( m_pCScopeData )
  819. m_pCScopeData->Release();
  820. m_pCScopeData = xpScopeData.Acquire();
  821. }
  822. }
  823. CATCH( CException, e )
  824. {
  825. sc = e.GetErrorCode();
  826. }
  827. END_CATCH
  828. return sc;
  829. }
  830. // CImpIParserTreeProperties::ReplaceScopeDataPtr -------------------------
  831. //
  832. // @mfunc Take ownership of the ScopeData
  833. //
  834. // @rdesc void
  835. //
  836. void CImpIParserTreeProperties::ReplaceScopeDataPtr(CScopeData* pCScopeData)
  837. {
  838. assert( pCScopeData );
  839. if( m_pCScopeData )
  840. {
  841. ULONG ulRef = m_pCScopeData->Release();
  842. assert( ulRef == 0 );
  843. }
  844. m_pCScopeData = pCScopeData;
  845. m_pCScopeData->AddRef();
  846. }