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.

612 lines
16 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 2000.
  5. //
  6. // File: pidmap.cxx
  7. //
  8. // Contents: Maps pid <--> property name.
  9. //
  10. // History: 31-Jan-93 KyleP Created
  11. //
  12. //--------------------------------------------------------------------------
  13. #include <pch.cxx>
  14. #pragma hdrstop
  15. #include <pidremap.hxx>
  16. #include <coldesc.hxx>
  17. //+-------------------------------------------------------------------------
  18. //
  19. // Member: CPidRemapper::CPidRemapper, public
  20. //
  21. // Synopsis: Creates a prop id remapper. Translates input arguments
  22. // 'fake' propids to real propids.
  23. //
  24. // Arguments: [pidmap] - input prop ID mapping array
  25. // [xPropMapper] - property mapper for real pid lookup
  26. // [prst] - optional restriction, pids will be mapped
  27. // [pcol] - optional output columns, pids will be mapped
  28. // [pso] - optional sort specification, pids will be mapped
  29. //
  30. // History: 31-Jan-93 KyleP Created
  31. //
  32. //--------------------------------------------------------------------------
  33. CPidRemapper::CPidRemapper( const CPidMapper & pidmap,
  34. XInterface<IPropertyMapper> & xPropMapper,
  35. CRestriction * prst,
  36. CColumnSet * pcol,
  37. CSortSet * pso )
  38. : _xPropMapper( xPropMapper.Acquire() ),
  39. _fAnyStatProps( FALSE ),
  40. _fContentProp ( FALSE ),
  41. _fRankVectorProp( FALSE ),
  42. _cRefs( 1 )
  43. {
  44. _cpidReal = pidmap.Count();
  45. _xaPidReal.Set( _cpidReal, new PROPID[ _cpidReal ] );
  46. //
  47. // Iterate through the list
  48. //
  49. for ( unsigned i = 0; i < _cpidReal; i++ )
  50. {
  51. PROPID pid;
  52. FULLPROPSPEC const * pFullPropSpec = pidmap.Get(i)->CastToStruct();
  53. SCODE sc = _xPropMapper->PropertyToPropid( pFullPropSpec, TRUE, &pid );
  54. if ( FAILED( sc ) )
  55. THROW( CException( sc ) );
  56. _xaPidReal[i] = pid;
  57. if ( IsUserDefinedPid( _xaPidReal[i] ) )
  58. {
  59. //
  60. // Any user-defined property is a content property.
  61. // Note that the document characterization is a user-defined prop.
  62. //
  63. _fContentProp = TRUE;
  64. }
  65. else
  66. {
  67. if ( _xaPidReal[i] == pidContents )
  68. _fContentProp = TRUE;
  69. else
  70. _fAnyStatProps = TRUE;
  71. if ( _xaPidReal[i] == pidRankVector )
  72. _fRankVectorProp = TRUE;
  73. }
  74. #if CIDBG == 1
  75. if ( vqInfoLevel & DEB_ITRACE )
  76. {
  77. CFullPropSpec const & ps = *pidmap.Get(i);
  78. GUID const & guid = ps.GetPropSet();
  79. char szGuid[50];
  80. sprintf( szGuid,
  81. "%08lX-%04X-%04X-%02X%02X%02X%02X%02X%02X%02X%02X\\",
  82. guid.Data1,
  83. guid.Data2,
  84. guid.Data3,
  85. guid.Data4[0], guid.Data4[1],
  86. guid.Data4[2], guid.Data4[3],
  87. guid.Data4[4], guid.Data4[5],
  88. guid.Data4[6], guid.Data4[7] );
  89. vqDebugOut(( DEB_ITRACE, szGuid ));
  90. if ( ps.IsPropertyName() )
  91. vqDebugOut(( DEB_ITRACE | DEB_NOCOMPNAME,
  92. "%ws ",
  93. ps.GetPropertyName() ));
  94. else
  95. vqDebugOut(( DEB_ITRACE | DEB_NOCOMPNAME,
  96. "0x%x ",
  97. ps.GetPropertyPropid() ));
  98. vqDebugOut(( DEB_ITRACE | DEB_NOCOMPNAME, " --> pid 0x%x\n",
  99. _xaPidReal[i] ));
  100. }
  101. #endif // CIDBG == 1
  102. CFullPropSpec * ppsFull = new CFullPropSpec( *pidmap.Get(i) );
  103. XPtr<CFullPropSpec> xpps(ppsFull);
  104. if ( xpps.IsNull() || !xpps->IsValid() )
  105. {
  106. THROW( CException( STATUS_NO_MEMORY ) );
  107. }
  108. _propNames.Add( ppsFull, i );
  109. xpps.Acquire();
  110. Win4Assert( _xaPidReal[i] != pidInvalid );
  111. }
  112. if ( prst )
  113. RemapPropid( prst );
  114. if ( pcol )
  115. RemapPropid( pcol );
  116. if ( pso )
  117. RemapPropid( pso );
  118. }
  119. //+-------------------------------------------------------------------------
  120. //
  121. // Member: CPidRemapper::CPidRemapper, public
  122. //
  123. // Synopsis: Creates a prop id remapper.
  124. //
  125. // Arguments: [xPropMapper] - Property mapper for real pid lookup
  126. //
  127. // History: 12-Mar-95 DwightKr Created
  128. //
  129. //--------------------------------------------------------------------------
  130. CPidRemapper::CPidRemapper( XInterface<IPropertyMapper> & xPropMapper )
  131. : _xPropMapper( xPropMapper.Acquire() ),
  132. _cpidReal( 0 ),
  133. _cRefs( 1 )
  134. {
  135. }
  136. //+-------------------------------------------------------------------------
  137. //
  138. // Member: CPidRemapper::~CPidRemapper, public
  139. //
  140. // History: 15-Feb-93 KyleP Created
  141. //
  142. //--------------------------------------------------------------------------
  143. CPidRemapper::~CPidRemapper()
  144. {
  145. }
  146. //+-------------------------------------------------------------------------
  147. //
  148. // Member: CPidRemapper::RealToName, public
  149. //
  150. // Effects: Convert a PROPID to a propspec
  151. //
  152. // Arguments: [pid] - Given pid
  153. //
  154. // History: 22-Jan-97 SitaramR Added header
  155. //
  156. //--------------------------------------------------------------------------
  157. CFullPropSpec const * CPidRemapper::RealToName( PROPID pid ) const
  158. {
  159. Win4Assert( ! _xaPidReal.IsNull() );
  160. //
  161. // Just linear search
  162. //
  163. for ( unsigned i = 0;
  164. i < _cpidReal && _xaPidReal[i] != pid;
  165. i++
  166. )
  167. {
  168. continue;
  169. }
  170. Win4Assert( i < _cpidReal );
  171. //
  172. // This can happen if a hacker tries to munge query requests
  173. //
  174. if ( i == _cpidReal )
  175. THROW( CException( E_ABORT ) );
  176. return( _propNames.Get( i ) );
  177. }
  178. //+-------------------------------------------------------------------------
  179. //
  180. // Member: CPidRemapper::NameToReal, public
  181. //
  182. // Effects: Convert a property which is not necessarily in the pid map
  183. // to a PROPID.
  184. //
  185. // Arguments: [pProperty] - pointer to the propspec.
  186. //
  187. // Returns: PROPID - the mapped property ID or pidInvalid.
  188. //
  189. // History: 28 Jun 94 AlanW Created
  190. //
  191. //--------------------------------------------------------------------------
  192. PROPID CPidRemapper::NameToReal( CFullPropSpec const * pProperty )
  193. {
  194. for (unsigned i = 0; i < _cpidReal; i++)
  195. {
  196. if (*pProperty == *_propNames.Get(i))
  197. {
  198. return _xaPidReal[ i ];
  199. }
  200. }
  201. //
  202. // Property is not in the mapping array. Add it.
  203. //
  204. PROPID Prop;
  205. FULLPROPSPEC const * pFullPropSpec = pProperty->CastToStruct();
  206. SCODE sc = _xPropMapper->PropertyToPropid( pFullPropSpec, TRUE, &Prop );
  207. if ( FAILED( sc ) )
  208. THROW( CException( sc ) );
  209. if (Prop != pidInvalid)
  210. {
  211. PROPID *ppidReal = new PROPID[ _cpidReal+1 ];
  212. memcpy(ppidReal, _xaPidReal.GetPointer(), _cpidReal * sizeof (PROPID));
  213. //
  214. // No lock is needed here to prevent races with RealToName since in current
  215. // usage everything is added in the query path by a single thread before
  216. // reads happen from multiple threads.
  217. //
  218. PROPID *ppidTemp = _xaPidReal.Acquire();
  219. _xaPidReal.Set( _cpidReal+1, ppidReal );
  220. delete [] ppidTemp;
  221. CFullPropSpec * ppsFull = new CFullPropSpec( *pProperty );
  222. XPtr<CFullPropSpec> xpps(ppsFull);
  223. if ( xpps.IsNull() || !xpps->IsValid() )
  224. {
  225. THROW( CException( STATUS_NO_MEMORY ) );
  226. }
  227. _propNames.Add( ppsFull, _cpidReal );
  228. xpps.Acquire();
  229. Win4Assert(*_propNames.Get(_cpidReal) == *pProperty);
  230. _xaPidReal[_cpidReal] = Prop;
  231. _cpidReal++;
  232. }
  233. return Prop;
  234. }
  235. //+-------------------------------------------------------------------------
  236. //
  237. // Member: CPidRemapper::RemapPropid, public
  238. //
  239. // Effects: Traverses [pRst], converting 'fake' propid to 'real'
  240. //
  241. // Arguments: [pRst] -- Restriction
  242. //
  243. // History: 15-Feb-93 KyleP Created
  244. //
  245. //--------------------------------------------------------------------------
  246. void CPidRemapper::RemapPropid( CRestriction * pRst )
  247. {
  248. Win4Assert ( pRst != 0 );
  249. switch( pRst->Type() )
  250. {
  251. case RTInternalProp:
  252. {
  253. CInternalPropertyRestriction * pPropRst =
  254. (CInternalPropertyRestriction *)pRst;
  255. pPropRst->SetPid( FakeToReal( pPropRst->Pid() ) );
  256. if ( 0 != pPropRst->GetContentHelper() )
  257. RemapPropid( pPropRst->GetContentHelper() );
  258. break;
  259. }
  260. case RTWord:
  261. {
  262. CWordRestriction * pWordRst = (CWordRestriction *)pRst;
  263. pWordRst->SetPid( FakeToReal( pWordRst->Pid() ) );
  264. break;
  265. }
  266. case RTSynonym:
  267. {
  268. CSynRestriction * pSynRst = (CSynRestriction *)pRst;
  269. CKeyArray & keys = pSynRst->GetKeys();
  270. for ( int i = keys.Count() - 1; i >= 0; i-- )
  271. {
  272. CKey & key = keys.Get(i);
  273. key.SetPid( FakeToReal( key.Pid() ) );
  274. }
  275. break;
  276. }
  277. case RTNot:
  278. {
  279. CNotRestriction * pnrst = (CNotRestriction *)pRst;
  280. RemapPropid( pnrst->GetChild() );
  281. break;
  282. }
  283. case RTAnd:
  284. case RTOr:
  285. case RTVector:
  286. case RTProximity:
  287. case RTPhrase:
  288. {
  289. CNodeRestriction * pNodeRst = pRst->CastToNode();
  290. for ( int i = pNodeRst->Count() - 1; i >= 0; i-- )
  291. {
  292. RemapPropid( pNodeRst->GetChild( i ) );
  293. }
  294. break;
  295. }
  296. case RTRange:
  297. case RTNone: // probably a noise word in a vector query
  298. break;
  299. default:
  300. Win4Assert( !"RemapPropid: Unknown type." );
  301. break;
  302. }
  303. }
  304. //+-------------------------------------------------------------------------
  305. //
  306. // Member: CPidRemapper::RemapPropid, public
  307. //
  308. // Effects: Traverses [pColumns], converting 'fake' propid to 'real'
  309. //
  310. // Arguments: [pColumns] -- Output columns
  311. //
  312. // History: 22-Jun-93 KyleP Created
  313. //
  314. //--------------------------------------------------------------------------
  315. void CPidRemapper::RemapPropid( CColumnSet * pColumns )
  316. {
  317. for ( unsigned i = 0; i < pColumns->Count(); i++ )
  318. {
  319. pColumns->Get(i) = FakeToReal( pColumns->Get(i) );
  320. }
  321. }
  322. //+-------------------------------------------------------------------------
  323. //
  324. // Member: CPidRemapper::RemapPropid, public
  325. //
  326. // Effects: Traverses [pSort], converting 'fake' propid to 'real'
  327. //
  328. // Arguments: [pSort] -- Restriction
  329. //
  330. // History: 15-Feb-93 KyleP Created
  331. //
  332. //--------------------------------------------------------------------------
  333. void CPidRemapper::RemapPropid( CSortSet * pSort )
  334. {
  335. for ( unsigned i = 0; i < pSort->Count(); i++ )
  336. {
  337. pSort->Get(i).pidColumn = FakeToReal( pSort->Get(i).pidColumn );
  338. }
  339. }
  340. //+-------------------------------------------------------------------------
  341. //--------------------------------------------------------------------------
  342. void CPidRemapper::ReBuild( const CPidMapper & pidmap )
  343. {
  344. if ( _cpidReal < pidmap.Count() )
  345. {
  346. delete [] _xaPidReal.Acquire();
  347. _cpidReal = 0;
  348. _xaPidReal.Set( pidmap.Count(), new PROPID[ pidmap.Count() ] );
  349. }
  350. _cpidReal = pidmap.Count();
  351. //
  352. // Iterate through the list
  353. //
  354. for ( unsigned i = 0; i < _cpidReal; i++ )
  355. {
  356. PROPID pid;
  357. FULLPROPSPEC const * pFullPropSpec = pidmap.Get(i)->CastToStruct();
  358. SCODE sc = _xPropMapper->PropertyToPropid( pFullPropSpec, TRUE, &pid );
  359. if ( FAILED( sc ) )
  360. THROW( CException( sc ) );
  361. _xaPidReal[i] = pid;
  362. Win4Assert( _xaPidReal[i] != pidInvalid );
  363. }
  364. }
  365. //+-------------------------------------------------------------------------
  366. //--------------------------------------------------------------------------
  367. void CPidRemapper::Set( XArray<PROPID> & aPids )
  368. {
  369. delete [] _xaPidReal.Acquire();
  370. _cpidReal = aPids.Count();
  371. _xaPidReal.Set( _cpidReal, aPids.Acquire() );
  372. }
  373. //
  374. // This has to go somewhere...
  375. //
  376. UNICODECALLOUTS UnicodeCallouts = { WIN32_UNICODECALLOUTS };
  377. //+-------------------------------------------------------------------------
  378. //
  379. // Method: CPidRemapper::AddRef
  380. //
  381. // Synopsis: Increments refcount
  382. //
  383. // History: 22-Jan-1997 SitaramR Created
  384. //
  385. //--------------------------------------------------------------------------
  386. ULONG STDMETHODCALLTYPE CPidRemapper::AddRef()
  387. {
  388. return InterlockedIncrement( (long *) &_cRefs );
  389. }
  390. //+-------------------------------------------------------------------------
  391. //
  392. // Method: CPidRemapper::Release
  393. //
  394. // Synopsis: Decrement refcount. Delete if necessary.
  395. //
  396. // History: 22-Jan-1997 SitaramR Created
  397. //
  398. //--------------------------------------------------------------------------
  399. ULONG STDMETHODCALLTYPE CPidRemapper::Release()
  400. {
  401. Win4Assert( _cRefs > 0 );
  402. ULONG uTmp = InterlockedDecrement( (long *) &_cRefs );
  403. if ( 0 == uTmp )
  404. delete this;
  405. return(uTmp);
  406. }
  407. //+-------------------------------------------------------------------------
  408. //
  409. // Method: CPidRemapper::QueryInterface
  410. //
  411. // Synopsis: Rebind to other interface
  412. //
  413. // Arguments: [riid] -- IID of new interface
  414. // [ppvObject] -- New interface * returned here
  415. //
  416. // Returns: S_OK if bind succeeded, E_NOINTERFACE if bind failed
  417. //
  418. // History: 22-Jan-1997 SitaramR Created
  419. //
  420. //--------------------------------------------------------------------------
  421. SCODE STDMETHODCALLTYPE CPidRemapper::QueryInterface(
  422. REFIID riid,
  423. void ** ppvObject)
  424. {
  425. if ( IID_ICiQueryPropertyMapper == riid )
  426. *ppvObject = (ICiQueryPropertyMapper *)this;
  427. else if ( IID_IUnknown == riid )
  428. *ppvObject = (IUnknown *)this;
  429. else
  430. {
  431. *ppvObject = 0;
  432. return E_NOINTERFACE;
  433. }
  434. AddRef();
  435. return S_OK;
  436. }
  437. //+-------------------------------------------------------------------------
  438. //
  439. // Method: CPidRemapper::PropertyToPropid
  440. //
  441. // Synopsis: Convert propspec to pid
  442. //
  443. // Arguments: [pFullPropSpec] -- propspec to convert
  444. // [pPropId] -- pid returned here
  445. //
  446. // History: 22-Jan-1997 SitaramR Created
  447. //
  448. //--------------------------------------------------------------------------
  449. SCODE STDMETHODCALLTYPE CPidRemapper::PropertyToPropid( const FULLPROPSPEC *pFullPropSpec,
  450. PROPID *pPropId)
  451. {
  452. SCODE sc = S_OK;
  453. TRY
  454. {
  455. CFullPropSpec const * pProperty = (CFullPropSpec const *) pFullPropSpec;
  456. *pPropId = NameToReal( pProperty );
  457. }
  458. CATCH( CException, e )
  459. {
  460. sc = e.GetErrorCode();
  461. vqDebugOut(( DEB_ERROR,
  462. "CPidRemapper:PropertyToPropid - Exception caught 0x%x\n",
  463. sc ));
  464. }
  465. END_CATCH;
  466. return sc;
  467. }
  468. //+-------------------------------------------------------------------------
  469. //
  470. // Method: CPidRemapper::PropidToProperty
  471. //
  472. // Synopsis: Convert pid to propspec
  473. //
  474. // Arguments: [pPropId] -- pid to convert
  475. // [pFullPropSpec] -- propspec returned here
  476. //
  477. // Notes: *ppFullPropSpec is owned by CPidRemapper
  478. //
  479. // History: 22-Jan-1997 SitaramR Created
  480. //
  481. //--------------------------------------------------------------------------
  482. SCODE STDMETHODCALLTYPE CPidRemapper::PropidToProperty( PROPID propId,
  483. FULLPROPSPEC const **ppFullPropSpec )
  484. {
  485. SCODE sc = S_OK;
  486. TRY
  487. {
  488. *ppFullPropSpec = RealToName( propId )->CastToStruct();
  489. }
  490. CATCH( CException, e )
  491. {
  492. sc = e.GetErrorCode();
  493. vqDebugOut(( DEB_ERROR,
  494. "CPidRemapper:PropidToProperty - Exception caught 0x%x\n",
  495. sc ));
  496. }
  497. END_CATCH;
  498. return sc;
  499. }