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.

566 lines
15 KiB

  1. //+------------------------------------------------------------------
  2. //
  3. // Copyright (C) 1991-1997 Microsoft Corporation.
  4. //
  5. // File: idxentry.cxx
  6. //
  7. // Contents: Document filter interface
  8. //
  9. // Classes: CIndexNotificationEntry
  10. //
  11. // History: 24-Feb-97 SitaramR Created
  12. //
  13. // Notes: The implementation uses the regular memory allocator,
  14. // and it makes a copy of every text string and property
  15. // that is added. A better approach may be to define a
  16. // custom memory allocator that allocates portions as
  17. // needed from say a 4K block of memory.
  18. //
  19. //-------------------------------------------------------------------
  20. #include <pch.cxx>
  21. #pragma hdrstop
  22. #include <cifrmcom.hxx>
  23. #include "idxentry.hxx"
  24. #include "cimanger.hxx"
  25. //+---------------------------------------------------------------------------
  26. //
  27. // Member: CChunkEntry::CChunkEntry
  28. //
  29. // Synopsis: Constructor
  30. //
  31. // Arguments: [pStatChunk] -- Pointer to stat chunk
  32. // [pwszText] -- Text
  33. //
  34. // History: 24-Feb-97 SitaramR Created
  35. //
  36. //----------------------------------------------------------------------------
  37. CChunkEntry::CChunkEntry( STAT_CHUNK const * pStatChunk, WCHAR const *pwszText )
  38. : _pChunkEntryNext( 0 )
  39. {
  40. _statChunk = *pStatChunk;
  41. XPtrST<WCHAR> xPropString;
  42. if ( _statChunk.attribute.psProperty.ulKind == PRSPEC_LPWSTR )
  43. {
  44. //
  45. // Make own copy of property string
  46. //
  47. ULONG cwcLen = wcslen( pStatChunk->attribute.psProperty.lpwstr ) + 1;
  48. _statChunk.attribute.psProperty.lpwstr = new WCHAR[cwcLen];
  49. RtlCopyMemory( _statChunk.attribute.psProperty.lpwstr,
  50. pStatChunk->attribute.psProperty.lpwstr,
  51. cwcLen * sizeof( WCHAR ) );
  52. xPropString.Set( _statChunk.attribute.psProperty.lpwstr );
  53. }
  54. ULONG cwcLen = wcslen( pwszText ) + 1;
  55. _pwszText = new WCHAR[cwcLen];
  56. RtlCopyMemory( _pwszText, pwszText, cwcLen * sizeof(WCHAR) );
  57. xPropString.Acquire(); // Pass ownership to CChunkEntry
  58. }
  59. //+---------------------------------------------------------------------------
  60. //
  61. // Member: CChunkEntry::CChunkEntry
  62. //
  63. // Synopsis: Constructor
  64. //
  65. // Arguments: [pStatChunk] -- Pointer to stat chunk
  66. // [pPropVar] -- Property
  67. //
  68. // History: 24-Feb-97 SitaramR Created
  69. //
  70. //----------------------------------------------------------------------------
  71. CChunkEntry::CChunkEntry( STAT_CHUNK const * pStatChunk, PROPVARIANT const * pPropVar )
  72. : _pChunkEntryNext( 0 )
  73. {
  74. _statChunk = *pStatChunk;
  75. XPtrST<WCHAR> xPropString;
  76. if ( _statChunk.attribute.psProperty.ulKind == PRSPEC_LPWSTR )
  77. {
  78. //
  79. // Make own copy of property string
  80. //
  81. ULONG cwcLen = wcslen( pStatChunk->attribute.psProperty.lpwstr ) + 1;
  82. _statChunk.attribute.psProperty.lpwstr = new WCHAR[cwcLen];
  83. RtlCopyMemory( _statChunk.attribute.psProperty.lpwstr,
  84. pStatChunk->attribute.psProperty.lpwstr,
  85. cwcLen * sizeof( WCHAR ) );
  86. xPropString.Set( _statChunk.attribute.psProperty.lpwstr );
  87. }
  88. _pStgVariant = new CStorageVariant( *(PROPVARIANT *)pPropVar );
  89. if ( _pStgVariant == 0 )
  90. THROW( CException( E_OUTOFMEMORY ) );
  91. xPropString.Acquire(); // Pass ownership to CChunkEntry
  92. }
  93. //+---------------------------------------------------------------------------
  94. //
  95. // Member: CChunkEntry::~CChunkEntry
  96. //
  97. // Synopsis: Destructor
  98. //
  99. // History: 24-Feb-97 SitaramR Created
  100. //
  101. //----------------------------------------------------------------------------
  102. CChunkEntry::~CChunkEntry()
  103. {
  104. if ( _statChunk.attribute.psProperty.ulKind == PRSPEC_LPWSTR )
  105. delete _statChunk.attribute.psProperty.lpwstr;
  106. if ( _statChunk.flags == CHUNK_TEXT )
  107. delete _pwszText;
  108. else
  109. delete _pStgVariant;
  110. }
  111. //+---------------------------------------------------------------------------
  112. //
  113. // Member: CIndexNotificationEntry::CIndexNotificationEntry
  114. //
  115. // Synopsis: Constructor
  116. //
  117. // History: 24-Feb-97 SitaramR Created
  118. //
  119. //----------------------------------------------------------------------------
  120. CIndexNotificationEntry::CIndexNotificationEntry(
  121. WORKID wid,
  122. CI_UPDATE_TYPE eUpdateType,
  123. XInterface<CIndexNotificationTable> & xNotifTable,
  124. XInterface<ICiCIndexNotificationStatus> & xNotifStatus,
  125. CCiManager * pCiManager,
  126. USN usn )
  127. : _xNotifTable( xNotifTable.Acquire() ),
  128. _xNotifStatus( xNotifStatus.Acquire() ),
  129. _pCiManager( pCiManager ),
  130. _wid( wid ),
  131. _eUpdateType( eUpdateType ),
  132. _fAddCompleted( FALSE ),
  133. _fShutdown( FALSE ),
  134. _fFilterDataPurged( FALSE ),
  135. _usn( usn ),
  136. _pChunkEntryHead( 0 ),
  137. _pChunkEntryTail( 0 ),
  138. _pChunkEntryIter( 0 ),
  139. _cRefs( 1 )
  140. {
  141. }
  142. //+---------------------------------------------------------------------------
  143. //
  144. // Member: CIndexNotificationEntry::~CIndexNotificationEntry
  145. //
  146. // Synopsis: Destructor
  147. //
  148. // History: 24-Feb-97 SitaramR Created
  149. //
  150. //----------------------------------------------------------------------------
  151. CIndexNotificationEntry::~CIndexNotificationEntry()
  152. {
  153. PurgeFilterData();
  154. }
  155. //+-------------------------------------------------------------------------
  156. //
  157. // Method: CIndexNotificationEntry::AddRef
  158. //
  159. // Synopsis: Increments refcount
  160. //
  161. // History: 24-Feb-1997 SitaramR Created
  162. //
  163. //--------------------------------------------------------------------------
  164. ULONG STDMETHODCALLTYPE CIndexNotificationEntry::AddRef()
  165. {
  166. return InterlockedIncrement( (long *) &_cRefs );
  167. }
  168. //+-------------------------------------------------------------------------
  169. //
  170. // Method: CIndexNotificationEntry::Release
  171. //
  172. // Synopsis: Decrement refcount. Delete if necessary.
  173. //
  174. // History: 24-Feb-1997 SitaramR Created
  175. //
  176. //--------------------------------------------------------------------------
  177. ULONG STDMETHODCALLTYPE CIndexNotificationEntry::Release()
  178. {
  179. Win4Assert( _cRefs > 0 );
  180. ULONG uTmp = InterlockedDecrement( (long *) &_cRefs );
  181. if ( 0 == uTmp )
  182. delete this;
  183. return uTmp;
  184. }
  185. //+-------------------------------------------------------------------------
  186. //
  187. // Method: CIndexNotificationEntry::QueryInterface
  188. //
  189. // Synopsis: Rebind to other interface
  190. //
  191. // Arguments: [riid] -- IID of new interface
  192. // [ppvObject] -- New interface * returned here
  193. //
  194. // Returns: S_OK if bind succeeded, E_NOINTERFACE if bind failed
  195. //
  196. // History: 24-Feb-1997 SitaramR Created
  197. //
  198. //--------------------------------------------------------------------------
  199. SCODE STDMETHODCALLTYPE CIndexNotificationEntry::QueryInterface( REFIID riid,
  200. void ** ppvObject)
  201. {
  202. Win4Assert( 0 != ppvObject );
  203. if ( riid == IID_ICiIndexNotificationEntry )
  204. *ppvObject = (void *)(ICiIndexNotificationEntry *) this;
  205. else if ( riid == IID_IUnknown )
  206. *ppvObject = (void *)(IUnknown *) this;
  207. else
  208. {
  209. *ppvObject = 0;
  210. return E_NOINTERFACE;
  211. }
  212. AddRef();
  213. return S_OK;
  214. }
  215. //+-------------------------------------------------------------------------
  216. //
  217. // Method: CIndexNotificationEntry::AddText
  218. //
  219. // Synopsis: Adds a text chunk
  220. //
  221. // Arguments: [pStatChunk] -- Pointer to stat chunk
  222. // [pwszText] -- Text
  223. //
  224. // History: 24-Feb-1997 SitaramR Created
  225. //
  226. //--------------------------------------------------------------------------
  227. SCODE STDMETHODCALLTYPE CIndexNotificationEntry::AddText( STAT_CHUNK const * pStatChunk,
  228. WCHAR const * pwszText )
  229. {
  230. if ( _fShutdown )
  231. return CI_E_SHUTDOWN;
  232. if ( _fAddCompleted )
  233. {
  234. Win4Assert( !"Adding text after AddCompleted was signalled" );
  235. return E_FAIL;
  236. }
  237. Win4Assert( pStatChunk->flags == CHUNK_TEXT );
  238. SCODE sc = S_OK;
  239. TRY
  240. {
  241. CChunkEntry *pEntry = new CChunkEntry( pStatChunk, pwszText );
  242. if ( _pChunkEntryTail )
  243. {
  244. _pChunkEntryTail->SetNextChunkEntry( pEntry ); // does not fail
  245. _pChunkEntryTail = pEntry;
  246. }
  247. else
  248. {
  249. _pChunkEntryTail = pEntry;
  250. _pChunkEntryHead = pEntry;
  251. }
  252. }
  253. CATCH( CException, e )
  254. {
  255. sc = e.GetErrorCode();
  256. ciDebugOut(( DEB_ERROR,
  257. "CIndexNotificationEntry::AddText - Exception caught 0x%x\n",
  258. sc ));
  259. }
  260. END_CATCH;
  261. return sc;
  262. }
  263. //+-------------------------------------------------------------------------
  264. //
  265. // Method: CIndexNotificationEntry::AddProperty
  266. //
  267. // Synopsis: Adds a property chunk
  268. //
  269. // Arguments: [pStatChunk] -- Pointer to stat chunk
  270. // [pPropVar] -- Property
  271. //
  272. // History: 24-Feb-1997 SitaramR Created
  273. //
  274. //--------------------------------------------------------------------------
  275. SCODE STDMETHODCALLTYPE CIndexNotificationEntry::AddProperty( STAT_CHUNK const * pStatChunk,
  276. PROPVARIANT const *pPropVar )
  277. {
  278. if ( _fShutdown )
  279. return CI_E_SHUTDOWN;
  280. if ( _fAddCompleted )
  281. {
  282. Win4Assert( !"Adding property after AddCompleted was signalled" );
  283. return E_FAIL;
  284. }
  285. Win4Assert( pStatChunk->flags == CHUNK_VALUE );
  286. SCODE sc = S_OK;
  287. TRY
  288. {
  289. CChunkEntry *pEntry = new CChunkEntry( pStatChunk, pPropVar );
  290. if ( _pChunkEntryTail )
  291. {
  292. _pChunkEntryTail->SetNextChunkEntry( pEntry ); // does not fail
  293. _pChunkEntryTail = pEntry;
  294. }
  295. else
  296. {
  297. _pChunkEntryTail = pEntry;
  298. _pChunkEntryHead = pEntry;
  299. }
  300. }
  301. CATCH( CException, e )
  302. {
  303. sc = e.GetErrorCode();
  304. ciDebugOut(( DEB_ERROR,
  305. "CIndexNotificationEntry::AddProperty - Exception caught 0x%x\n",
  306. sc ));
  307. }
  308. END_CATCH;
  309. return sc;
  310. }
  311. //+-------------------------------------------------------------------------
  312. //
  313. // Method: CIndexNotificationEntry::AddCompleted
  314. //
  315. // Synopsis: Signifies end of chunks. At this time the notification is
  316. // propagated to CCiManager.
  317. //
  318. // Arguments: [fAbort] -- If true, then the notification should not be
  319. // propagted to ICiManager. Also, all resources
  320. // need to be released
  321. //
  322. // History: 24-Feb-1997 SitaramR Created
  323. //
  324. //--------------------------------------------------------------------------
  325. SCODE STDMETHODCALLTYPE CIndexNotificationEntry::AddCompleted( ULONG fAbort )
  326. {
  327. if ( _fAddCompleted )
  328. {
  329. Win4Assert( !"AddCompleted being called for the second time" );
  330. return E_FAIL;
  331. }
  332. SCODE sc = S_OK;
  333. TRY
  334. {
  335. CIndexNotificationEntry *pNotifEntry;
  336. _fAddCompleted = TRUE;
  337. if ( fAbort || _fShutdown )
  338. {
  339. SCODE scode = _xNotifStatus->Abort();
  340. //
  341. // We don't have retry logic on failures
  342. //
  343. Win4Assert( SUCCEEDED( scode ) );
  344. //
  345. // Free entry from hash table, which should be ourself
  346. //
  347. XInterface<CIndexNotificationEntry> xIndexNotifEntry;
  348. _xNotifTable->Remove( _wid, xIndexNotifEntry );
  349. Win4Assert( this == xIndexNotifEntry.GetPointer() );
  350. //
  351. // xIndexNotifEntry is released when it goes out of scope
  352. //
  353. }
  354. else
  355. {
  356. CDocumentUpdateInfo info( _wid, CI_VOLID_USN_NOT_ENABLED, _usn, FALSE );
  357. sc = _pCiManager->UpdDocumentNoThrow( &info );
  358. if ( FAILED( sc ) )
  359. {
  360. SCODE scode = _xNotifStatus->Abort();
  361. //
  362. // We don't have retry logic on failures
  363. //
  364. Win4Assert( SUCCEEDED( scode ) );
  365. //
  366. // Free entry from hash table, which should be ourself
  367. //
  368. XInterface<CIndexNotificationEntry> xIndexNotifEntry;
  369. _xNotifTable->Remove( _wid, xIndexNotifEntry );
  370. Win4Assert( this == xIndexNotifEntry.GetPointer() );
  371. //
  372. // xIndexNotifEntry is released when it goes out of scope
  373. //
  374. }
  375. }
  376. }
  377. CATCH( CException, e )
  378. {
  379. sc = e.GetErrorCode();
  380. ciDebugOut(( DEB_ERROR,
  381. "CIndexNotificationEntry::AddCompleted - Exception caught 0x%x\n",
  382. sc ));
  383. //
  384. // Not clear why AddCompleted can ever fail
  385. //
  386. Win4Assert( !"AddCompleted failed" );
  387. }
  388. END_CATCH;
  389. return sc;
  390. }
  391. //+-------------------------------------------------------------------------
  392. //
  393. // Method: CIndexNotificationEntry::GetFirstChunk
  394. //
  395. // Synopsis: Returns first entry in list of chunks
  396. //
  397. // History: 24-Feb-1997 SitaramR Created
  398. //
  399. //--------------------------------------------------------------------------
  400. CChunkEntry *CIndexNotificationEntry::GetFirstChunk()
  401. {
  402. if ( _fFilterDataPurged )
  403. {
  404. Win4Assert( !"Re-filtering is not allowed in push filtering" );
  405. return 0;
  406. }
  407. _pChunkEntryIter = _pChunkEntryHead;
  408. return _pChunkEntryIter;
  409. }
  410. //+-------------------------------------------------------------------------
  411. //
  412. // Method: CIndexNotificationEntry::GetNextChunk
  413. //
  414. // Synopsis: Returns next entry in list of chunks. The state of iterator
  415. // is maintained in _pChunkEntryIter, which can be reset by
  416. // GetFirstChunk.
  417. //
  418. // History: 24-Feb-1997 SitaramR Created
  419. //
  420. //--------------------------------------------------------------------------
  421. CChunkEntry *CIndexNotificationEntry::GetNextChunk()
  422. {
  423. if ( _fFilterDataPurged )
  424. {
  425. Win4Assert( !"Re-filtering is not allowed in push filtering" );
  426. return 0;
  427. }
  428. if ( _pChunkEntryIter == 0 )
  429. return 0;
  430. else
  431. {
  432. _pChunkEntryIter = _pChunkEntryIter->GetNextChunkEntry();
  433. return _pChunkEntryIter;
  434. }
  435. }
  436. //+-------------------------------------------------------------------------
  437. //
  438. // Method: CIndexNotificationEntry::PurgeFilterData
  439. //
  440. // Synopsis: Deletes filter data, because wids are filtered only once
  441. // in push filtering.
  442. //
  443. // History: 17-Jun-1997 SitaramR Created
  444. //
  445. //--------------------------------------------------------------------------
  446. void CIndexNotificationEntry::PurgeFilterData()
  447. {
  448. _fFilterDataPurged = TRUE;
  449. //
  450. // Clean up all chunks
  451. //
  452. if ( _pChunkEntryHead != 0 )
  453. {
  454. CChunkEntry *pEntryPrev = _pChunkEntryHead;
  455. CChunkEntry *pEntryNext = pEntryPrev->GetNextChunkEntry();
  456. while ( pEntryNext != 0 )
  457. {
  458. delete pEntryPrev;
  459. pEntryPrev = pEntryNext;
  460. pEntryNext = pEntryNext->GetNextChunkEntry();
  461. }
  462. delete pEntryPrev;
  463. _pChunkEntryHead = 0;
  464. }
  465. }