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.

663 lines
20 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 2000.
  5. //
  6. // File: cmdprutl.cxx
  7. //
  8. // Contents: A wrapper for scope properties around ICommand
  9. //
  10. // History: 5-10-97 mohamedn created
  11. //
  12. //----------------------------------------------------------------------------
  13. #include <pch.cxx>
  14. #pragma hdrstop
  15. #include <cmdprutl.hxx>
  16. #include <fsciclnt.h>
  17. #include <guidutil.hxx>
  18. static GUID const guidQueryCorePropset = DBPROPSET_CIFRMWRKCORE_EXT;
  19. static GUID const guidCiFsExt = DBPROPSET_FSCIFRMWRK_EXT;
  20. static const cFsCiProps = 4;
  21. static const cInitProps = 2;
  22. static const cScopePropSets = 2;
  23. //
  24. // utility functions
  25. //
  26. extern WCHAR **GetWCharFromVariant ( DBPROP & dbProp, ULONG *cElements );
  27. extern DWORD * GetDepthsFromVariant( DBPROP & dbProp, ULONG *cElements, ULONG mask );
  28. //+---------------------------------------------------------------------------
  29. //
  30. // Member: CGetCmdProps::CGetCmdProps
  31. //
  32. // Synopsis: Constructor - Initializes all, calls GetProperties().
  33. //
  34. // History: 5-10-97 mohamedn created
  35. //
  36. //----------------------------------------------------------------------------
  37. CGetCmdProps::CGetCmdProps( ICommand * pICommand )
  38. :_fGuidValid(FALSE),
  39. _aDepths(0),
  40. _aPaths(0),
  41. _aCatalogs(0),
  42. _aMachines(0),
  43. _cDepths(0),
  44. _cScopes(0),
  45. _cCatalogs(0),
  46. _cMachines(0),
  47. _cGuids(0),
  48. _type(CiNormal),
  49. _cPropertySets(0),
  50. _cCardinality(0xffffffff)
  51. {
  52. RtlZeroMemory( &_clientGuid, sizeof GUID );
  53. SCODE sc = pICommand->QueryInterface( IID_ICommandProperties,
  54. _xICmdProp.GetQIPointer() );
  55. if ( FAILED(sc) )
  56. THROW( CException(sc) );
  57. //
  58. // Populate our internal data structs
  59. //
  60. GetProperties();
  61. SetCardinalityValue();
  62. }
  63. //+---------------------------------------------------------------------------
  64. //
  65. // Member: CGetCmdProps::GetProperties
  66. //
  67. // Synopsis: Retrieves all the properties from ICommandProperties interface.
  68. //
  69. // Arguments: none
  70. //
  71. // Returns: Throws upon failure.
  72. //
  73. // History: 5-10-97 mohamedn created
  74. //
  75. //----------------------------------------------------------------------------
  76. //
  77. // Hack #214: IID_ICommandProperties is intercepted by service layers, which
  78. // don't like us passing in the magic code to fetch hidden scope
  79. // properties. But the controlling unknown doesn't recognize
  80. // IID_IKyleProp and sends it right to us. Implementation is
  81. // identical to ICommandProperties.
  82. //
  83. GUID IID_IKyleProp = { 0xb4237bc2, 0xe09f, 0x11d1, 0x80, 0xc0, 0x00, 0xc0, 0x4f, 0xa3, 0x54, 0xba };
  84. void CGetCmdProps::GetProperties()
  85. {
  86. // get all properties including scope props
  87. XInterface<ICommandProperties> xTemp;
  88. SCODE sc = _xICmdProp->QueryInterface( IID_IKyleProp,
  89. xTemp.GetQIPointer() );
  90. const ULONG cPropIdSets = 3141592653;
  91. DBPROPSET * pDbPropSet;
  92. ULONG cPropertySets;
  93. if ( SUCCEEDED(sc) )
  94. sc = xTemp->GetProperties( cPropIdSets,
  95. 0,
  96. &cPropertySets,
  97. &pDbPropSet );
  98. if ( FAILED(sc) )
  99. {
  100. // On this failure, you have to free the properties returned!
  101. Win4Assert( DB_E_ERRORSOCCURRED != sc );
  102. ciDebugOut(( DEB_ERROR, "Failed to do GetProperties (0x%X)\n", sc ));
  103. THROW( CException( sc ) );
  104. }
  105. _xPropSet.Set( cPropertySets, (CDbPropSet *) pDbPropSet );
  106. _cPropertySets = cPropertySets;
  107. for ( ULONG i = 0; i < cPropertySets; i++ )
  108. ProcessPropSet( pDbPropSet[i] );
  109. } //GetProperties
  110. //+---------------------------------------------------------------------------
  111. //
  112. // Member: CGetCmdProps::SetCardinalityValue
  113. //
  114. // Synopsis: validates and sets the Cardinality value
  115. //
  116. // Arguments: none
  117. //
  118. // Returns: none - throws upon failure.
  119. //
  120. // History: 5-12-97 mohamedn moved from CQuerySpec
  121. //
  122. //----------------------------------------------------------------------------
  123. void CGetCmdProps::SetCardinalityValue()
  124. {
  125. //
  126. // Final cardinality check...
  127. //
  128. if ( _cDepths != _cScopes ||
  129. (_cScopes != _cCatalogs && _cCatalogs != 1) ||
  130. _cCatalogs != _cMachines )
  131. {
  132. ciDebugOut(( DEB_ERROR, "CQuerySpec::QueryInternalQuery -- Cardinality mismatch\n" ));
  133. THROW( CException( CI_E_CARDINALITY_MISMATCH ) );
  134. }
  135. // The query is distributed if multiple machines or multiple catalogs
  136. // are present. Multiple scopes on one catalog/machine are handled
  137. // by a non-distributed query.
  138. BOOL fDistributed = FALSE;
  139. if (_cCatalogs > 1)
  140. {
  141. for ( unsigned i = 0; !fDistributed && i < _cScopes-1; i++ )
  142. {
  143. if ( ( _wcsicmp( _aMachines[i], _aMachines[i+1] ) ) ||
  144. ( _wcsicmp( _aCatalogs[i], _aCatalogs[i+1] ) ) )
  145. {
  146. fDistributed = TRUE;
  147. }
  148. }
  149. }
  150. // Win4Assert( !" Break here to set single/distributed query" );
  151. if ( fDistributed )
  152. {
  153. Win4Assert( _cCatalogs > 1 );
  154. _cCardinality = _cCatalogs; // distributed case
  155. }
  156. else if ( 0 == _cCatalogs )
  157. {
  158. _cCardinality = 0; // local case
  159. }
  160. else
  161. {
  162. _cCardinality = 1; // single machine case.
  163. }
  164. }
  165. //+---------------------------------------------------------------------------
  166. //
  167. // Member: CGetCmdProps::PopulateDbProps
  168. //
  169. // Synopsis: Creates a new IDBProperties using ICommand properties
  170. //
  171. // Arguments: [pIDBProperties] -- IDBProperties interface
  172. // [iElement] -- specifies which of the distributed properties to use
  173. //
  174. // Returns: none - thorws upon failure.
  175. //
  176. // History: 5-12-97 mohamedn created
  177. //
  178. //----------------------------------------------------------------------------
  179. void CGetCmdProps::PopulateDbProps(IDBProperties *pIDBProperties, ULONG iElement )
  180. {
  181. Win4Assert( !_xICmdProp.IsNull() ); // src
  182. Win4Assert( pIDBProperties != 0 ); // destination
  183. Win4Assert( _cPropertySets != 0 ); // at least one property set exist.
  184. Win4Assert( _xPropSet.GetPointer() != 0 );
  185. DBPROPSET * pPropSet = 0;
  186. ULONG cPropSets = 0;
  187. XArrayOLEInPlace<CDbPropSet> xPropSet;
  188. CreateNewPropSet(&cPropSets, &pPropSet, iElement);
  189. Win4Assert( pPropSet != 0 );
  190. Win4Assert( cPropSets != 0 );
  191. xPropSet.Set(cPropSets,(CDbPropSet *)pPropSet);
  192. SCODE sc = pIDBProperties->SetProperties( cPropSets, xPropSet.GetPointer());
  193. if ( FAILED(sc) )
  194. THROW( CException(sc) );
  195. }
  196. //+---------------------------------------------------------------------------
  197. //
  198. // Member: CGetCmdProps::CreateNewPropSet, private
  199. //
  200. // Synopsis: Creates new property sets on IDBProperties from ICommand properties.
  201. //
  202. // Arguments: [cPropSets] -- count of property sets
  203. // [ppPropSet] -- to return new property sets
  204. // [index] -- specifies which of the distributed properties to use
  205. //
  206. // Returns: none - throws upon failure.
  207. //
  208. // History: 05-12-97 mohamedn created
  209. //
  210. //----------------------------------------------------------------------------
  211. void CGetCmdProps::CreateNewPropSet(ULONG *cPropSets, DBPROPSET **ppPropSet, ULONG index)
  212. {
  213. XArrayOLEInPlace<CDbPropSet> xPropSet(_cPropertySets);
  214. ULONG cPropSetsCopied = 0;
  215. for ( unsigned i = 0; i < _cPropertySets; i++ )
  216. {
  217. if ( _xPropSet[i].guidPropertySet == guidQueryCorePropset )
  218. {
  219. CopyPropertySet( xPropSet[cPropSetsCopied], _xPropSet[i], index );
  220. cPropSetsCopied++;
  221. }
  222. else if ( _xPropSet[i].guidPropertySet == guidCiFsExt )
  223. {
  224. CopyPropertySet( xPropSet[cPropSetsCopied], _xPropSet[i], index );
  225. cPropSetsCopied++;
  226. }
  227. else
  228. {
  229. //
  230. // Other property sets just get copied verbatim (e.g. index == 0)
  231. //
  232. CopyPropertySet( xPropSet[cPropSetsCopied], _xPropSet[i], 0 );
  233. cPropSetsCopied++;
  234. }
  235. }
  236. *cPropSets = cPropSetsCopied;
  237. *ppPropSet = xPropSet.Acquire();
  238. }
  239. //+---------------------------------------------------------------------------
  240. //
  241. // Member: CGetCmdProps::CopyPropertySet, private
  242. //
  243. // Synopsis: Copies srcPropSet to destPropSet - using index for distributed props.
  244. //
  245. // Arguments: [destPropSet] -- destination prop set
  246. // [srcPropSet] -- source prop set
  247. // [index] -- specifies which of the distributed properties to use
  248. //
  249. // Returns: none - throws upon failure.
  250. //
  251. // History: 05-12-97 mohamedn created
  252. //
  253. //----------------------------------------------------------------------------
  254. void CGetCmdProps::CopyPropertySet( CDbPropSet &destPropSet, CDbPropSet &srcPropSet, ULONG index )
  255. {
  256. RtlZeroMemory( &destPropSet, sizeof (CDbPropSet) );
  257. RtlCopyMemory( &destPropSet.guidPropertySet, &srcPropSet.guidPropertySet, sizeof GUID );
  258. XArrayOLEInPlace<CDbProp> xDestDbPrp(srcPropSet.cProperties);
  259. //
  260. // copy all the properties from the src property set
  261. //
  262. for ( unsigned i = 0; i < srcPropSet.cProperties; i++ )
  263. {
  264. CDbProp & destProp = xDestDbPrp[i];
  265. CDbProp & srcProp = (CDbProp &)srcPropSet.rgProperties[i];
  266. RtlZeroMemory(&destProp, sizeof (CDbProp) );
  267. if ( srcProp.dwStatus != DBPROPSTATUS_OK )
  268. {
  269. destProp.dwPropertyID = srcPropSet.rgProperties[i].dwPropertyID;
  270. destProp.dwStatus = DBPROPSTATUS_NOTSET;
  271. destProp.vValue.vt = VT_EMPTY;
  272. ciDebugOut(( DEB_TRACE, "PropID: %x, dwStatus: %x\n",
  273. srcPropSet.rgProperties[i].dwPropertyID, srcProp.dwStatus ));
  274. continue;
  275. }
  276. if ( destPropSet.guidPropertySet == guidQueryCorePropset )
  277. {
  278. switch (srcProp.dwPropertyID)
  279. {
  280. case DBPROP_MACHINE:
  281. CopyDbProp(destProp, srcProp, index);
  282. break;
  283. default:
  284. if ( !destProp.Copy( srcProp ) )
  285. THROW( CException(E_OUTOFMEMORY) );
  286. }
  287. }
  288. else if ( destPropSet.guidPropertySet == guidCiFsExt )
  289. {
  290. switch (srcProp.dwPropertyID)
  291. {
  292. case DBPROP_CI_INCLUDE_SCOPES:
  293. case DBPROP_CI_DEPTHS:
  294. //
  295. // in none-distributed case, Scope and Depth cardinality can be > 1
  296. //
  297. if ( _cCardinality <= 1 )
  298. {
  299. if ( !destProp.Copy( srcProp ) )
  300. THROW( CException(E_OUTOFMEMORY) );
  301. }
  302. else
  303. {
  304. // distributed case.
  305. CopyDbProp(destProp, srcProp, index);
  306. }
  307. break;
  308. case DBPROP_CI_CATALOG_NAME:
  309. CopyDbProp(destProp, srcProp, index);
  310. break;
  311. default:
  312. if ( !destProp.Copy( srcProp ) )
  313. THROW( CException(E_OUTOFMEMORY) );
  314. }
  315. } // if-else-if
  316. else
  317. {
  318. if ( !destProp.Copy( srcProp ) )
  319. THROW( CException(E_OUTOFMEMORY) );
  320. }
  321. } // for
  322. destPropSet.rgProperties = xDestDbPrp.Acquire();
  323. destPropSet.cProperties = srcPropSet.cProperties;
  324. } //CopyPropertySet
  325. //+---------------------------------------------------------------------------
  326. //
  327. // Member: CGetCmdProps::CopyDbProp
  328. //
  329. // Synopsis: copies source dbprop to the dest dbprop.
  330. //
  331. // Arguments: [destProp] -- destination dbProp
  332. // [srcProp] -- source dbprop
  333. // [index] -- specifies which property to copy
  334. //
  335. // Returns: None - throws upon failure.
  336. //
  337. // History: 05-12-97 mohamedn created
  338. //
  339. //----------------------------------------------------------------------------
  340. void CGetCmdProps::CopyDbProp(CDbProp &destProp, CDbProp &srcProp, ULONG index)
  341. {
  342. RtlCopyMemory(&destProp,&srcProp,sizeof(CDbProp));
  343. VARIANT & srcVar = srcProp.vValue;
  344. VARIANT & destVar= destProp.vValue;
  345. RtlZeroMemory( &destVar, sizeof (VARIANT) );
  346. //
  347. // index must be 0 if variant is not a safearray
  348. //
  349. if ( !(srcVar.vt & VT_ARRAY) && (0 != index) )
  350. {
  351. ciDebugOut(( DEB_ERROR, "index must be zero if not using VT_ARRAY, Index: %x\n", index));
  352. THROW( CException( STATUS_INVALID_PARAMETER ) );
  353. }
  354. else if ( (srcVar.vt & VT_ARRAY) && (index >= srcVar.parray->rgsabound[0].cElements) )
  355. {
  356. ciDebugOut(( DEB_ERROR, "index value out of range: %x\n", index ));
  357. THROW( CException( STATUS_INVALID_PARAMETER ) );
  358. }
  359. //
  360. // copy dbprop
  361. //
  362. switch (srcVar.vt)
  363. {
  364. case VT_ARRAY|VT_BSTR:
  365. {
  366. SAFEARRAY & sa = *srcVar.parray;
  367. BSTR * pBstr = (BSTR *)sa.pvData;
  368. if ( sa.cDims != 1 )
  369. THROW( CException( STATUS_INVALID_PARAMETER ) );
  370. destVar.vt = VT_BSTR;
  371. destVar.bstrVal = SysAllocString(pBstr[index]);
  372. if ( 0 == destVar.bstrVal )
  373. THROW( CException(E_OUTOFMEMORY) );
  374. }
  375. break;
  376. case VT_BSTR:
  377. {
  378. destVar.vt = VT_BSTR;
  379. destVar.bstrVal = SysAllocString(srcVar.bstrVal);
  380. if ( 0 == destVar.bstrVal )
  381. THROW( CException(E_OUTOFMEMORY) );
  382. }
  383. break;
  384. case VT_ARRAY|VT_I4:
  385. case VT_ARRAY|VT_UI4:
  386. {
  387. SAFEARRAY & sa = *srcVar.parray;
  388. DWORD * pdwDepths = (DWORD *)sa.pvData;
  389. if ( sa.cDims != 1 )
  390. THROW( CException( STATUS_INVALID_PARAMETER ) );
  391. destVar.vt = VT_I4;
  392. destVar.lVal = pdwDepths[index];
  393. }
  394. break;
  395. case VT_I4:
  396. case VT_UI4:
  397. {
  398. destVar.vt = VT_I4;
  399. destVar.lVal = srcVar.lVal;
  400. }
  401. break;
  402. default:
  403. ciDebugOut(( DEB_ERROR,"Invalid VARIANT type: %x\n",destVar.vt));
  404. THROW( CException( STATUS_INVALID_PARAMETER ) );
  405. }
  406. }
  407. //+---------------------------------------------------------------------------
  408. //
  409. // Member: CGetDbProps::ProcessDbInitPropSet
  410. //
  411. // Synopsis: Processes the DBPROPSET_INIT property set.
  412. //
  413. // Arguments: [propSet] - The property set to process.
  414. //
  415. // Returns: none - throws upon failure.
  416. //
  417. // History: 1-13-97 srikants Created
  418. // 5-12-97 mohamedn fs/core prop set splits.
  419. //
  420. //----------------------------------------------------------------------------
  421. void CGetCmdProps::ProcessDbInitPropSet( DBPROPSET & propSet )
  422. {
  423. CDbPropSet * pDbPropSet = (CDbPropSet *) &propSet;
  424. for ( ULONG i = 0; i < propSet.cProperties; i++ )
  425. {
  426. CDbProp * pDbProp = pDbPropSet->GetProperty(i);
  427. if ( DBPROPSTATUS_OK != pDbProp->dwStatus )
  428. {
  429. ciDebugOut(( DEB_TRACE, "DbProp.dwPropertyID: %x has dwStatus= %x\n",
  430. pDbProp->dwPropertyID,pDbProp->dwStatus));
  431. continue;
  432. }
  433. switch ( pDbProp->dwPropertyID )
  434. {
  435. case DBPROP_MACHINE:
  436. // machine count can be greater than 1
  437. _aMachines = GetWCharFromVariant(*pDbProp, &_cMachines);
  438. Win4Assert( 0 != _aMachines );
  439. break;
  440. case DBPROP_CLIENT_CLSID:
  441. {
  442. WCHAR **apGuids = GetWCharFromVariant(*pDbProp, &_cGuids);
  443. if ( _cGuids == 1 )
  444. {
  445. CGuidUtil::StringToGuid( apGuids[0], _clientGuid );
  446. _fGuidValid = TRUE;
  447. }
  448. else
  449. {
  450. ciDebugOut(( DEB_ERROR, "Invalid value for PropertyID(%x)\n",
  451. pDbProp->dwPropertyID ));
  452. THROW( CException(STATUS_INVALID_PARAMETER) );
  453. }
  454. }
  455. break;
  456. default:
  457. ciDebugOut(( DEB_ERROR, "InvalidPropertyID(%x)\n",
  458. pDbProp->dwPropertyID ));
  459. THROW( CException(STATUS_INVALID_PARAMETER) );
  460. }
  461. }
  462. } //ProcessDbInitPropSet
  463. //+---------------------------------------------------------------------------
  464. //
  465. // Member: CGetCmdProps::ProcessCiFsExtPropSet
  466. //
  467. // Synopsis: Processes the FSCI extension property set.
  468. //
  469. // Arguments: [propSet] - The propety set to process.
  470. // Returns: none - throws upon failure.
  471. //
  472. // History: 1-13-97 srikants Created
  473. // 5-12-97 mohamedn fs/core prop set splits.
  474. //
  475. //----------------------------------------------------------------------------
  476. void CGetCmdProps::ProcessCiFsExtPropSet( DBPROPSET & propSet )
  477. {
  478. CDbPropSet * pDbPropSet = (CDbPropSet *) &propSet;
  479. for ( ULONG i = 0; i < propSet.cProperties; i++ )
  480. {
  481. CDbProp * pDbProp = pDbPropSet->GetProperty(i);
  482. if ( pDbProp->dwStatus != DBPROPSTATUS_OK )
  483. {
  484. ciDebugOut(( DEB_TRACE, "PropStatus (0x%X) for (%d) th property\n",
  485. pDbProp->dwStatus, i ));
  486. continue;
  487. }
  488. switch ( pDbProp->dwPropertyID )
  489. {
  490. case DBPROP_CI_CATALOG_NAME:
  491. _aCatalogs = GetWCharFromVariant(*pDbProp,&_cCatalogs);
  492. break;
  493. case DBPROP_CI_DEPTHS:
  494. _aDepths = GetDepthsFromVariant(*pDbProp, &_cDepths,
  495. (ULONG)~( QUERY_SHALLOW |
  496. QUERY_DEEP |
  497. QUERY_PHYSICAL_PATH |
  498. QUERY_VIRTUAL_PATH ) );
  499. break;
  500. case DBPROP_CI_INCLUDE_SCOPES:
  501. _aPaths = GetWCharFromVariant(*pDbProp, &_cScopes);
  502. break;
  503. case DBPROP_CI_QUERY_TYPE:
  504. switch ( pDbProp->vValue.vt)
  505. {
  506. case VT_I4:
  507. case VT_UI4:
  508. _type = (CiMetaData) pDbProp->vValue.ulVal;
  509. break;
  510. default:
  511. ciDebugOut(( DEB_ERROR, "DBPROP_CI_QUERY_TYPE: invalid variant type: %x\n",
  512. pDbProp->vValue.vt ));
  513. THROW( CException(STATUS_INVALID_PARAMETER) );
  514. }
  515. break;
  516. default:
  517. {
  518. //
  519. // skip extra properties
  520. //
  521. ciDebugOut(( DEB_TRACE, "non-Native PropID(%x)\n",
  522. pDbProp->dwPropertyID ));
  523. }
  524. }
  525. }
  526. }
  527. //+---------------------------------------------------------------------------
  528. //
  529. // Member: CGetCmdProps::ProcessPropSet
  530. //
  531. // Synopsis: Processes the given property set.
  532. //
  533. // Arguments: [propSet] -
  534. //
  535. // History: 1-13-97 srikants Created
  536. //
  537. //----------------------------------------------------------------------------
  538. void CGetCmdProps::ProcessPropSet( DBPROPSET & propSet )
  539. {
  540. if ( propSet.guidPropertySet == guidCiFsExt )
  541. {
  542. ProcessCiFsExtPropSet( propSet );
  543. }
  544. else if ( propSet.guidPropertySet == guidQueryCorePropset )
  545. {
  546. ProcessDbInitPropSet( propSet );
  547. }
  548. else
  549. {
  550. //
  551. // skip other property sets -- not needed for Indexing Service.
  552. //
  553. }
  554. }