Leaked source code of windows server 2003
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.

640 lines
18 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1991 - 2000.
  5. //
  6. // File: CXXFLT.CXX
  7. //
  8. // Contents: C and Cxx Filter
  9. //
  10. // History: 07-Oct-93 AmyA Created
  11. //
  12. //----------------------------------------------------------------------------
  13. #include <pch.cxx>
  14. #pragma hdrstop
  15. extern "C" GUID CLSID_CxxIFilter;
  16. GUID guidCPlusPlus = { 0x8DEE0300, \
  17. 0x16C2, 0x101B, \
  18. 0xB1, 0x21, 0x08, 0x00, 0x2B, 0x2E, 0xCD, 0xA9 };
  19. //+---------------------------------------------------------------------------
  20. //
  21. // Member: CxxIFilter::CxxIFilter, public
  22. //
  23. // Synopsis: Constructor
  24. //
  25. // History: 07-Oct-93 AmyA Created.
  26. //
  27. //----------------------------------------------------------------------------
  28. CxxIFilter::CxxIFilter()
  29. : _state(FilterDone),
  30. _ulLastTextChunkID(0),
  31. _ulChunkID(0),
  32. _pTextFilt(0),
  33. _pPersFile(0),
  34. _pPersStream(0),
  35. _cAttrib(0),
  36. _pAttrib(0),
  37. _pTextStream(0),
  38. _locale(0) // the default locale
  39. {
  40. }
  41. const FULLPROPSPEC fpsContents = { PSGUID_STORAGE, PRSPEC_PROPID, PID_STG_CONTENTS };
  42. BOOL IsContents( FULLPROPSPEC const & fps )
  43. {
  44. return ( !memcmp( &fps, &fpsContents, sizeof fpsContents ) );
  45. } //IsContents
  46. BOOL FPSMatch( FULLPROPSPEC const & fpsA, FULLPROPSPEC const & fpsB )
  47. {
  48. if ( fpsA.guidPropSet != fpsB.guidPropSet )
  49. return FALSE;
  50. if ( fpsA.psProperty.ulKind != fpsB.psProperty.ulKind )
  51. return FALSE;
  52. if ( PRSPEC_PROPID == fpsA.psProperty.ulKind )
  53. return ( fpsA.psProperty.propid == fpsB.psProperty.propid );
  54. if ( PRSPEC_LPWSTR != fpsA.psProperty.ulKind )
  55. return FALSE;
  56. return ( !wcscmp( fpsA.psProperty.lpwstr,
  57. fpsB.psProperty.lpwstr ) );
  58. } //FPSMatch
  59. void FPSCopy( FULLPROPSPEC & fpsTo, FULLPROPSPEC const & fpsFrom )
  60. {
  61. fpsTo.guidPropSet = fpsFrom.guidPropSet;
  62. fpsTo.psProperty.ulKind = fpsFrom.psProperty.ulKind;
  63. if ( PRSPEC_PROPID == fpsFrom.psProperty.ulKind )
  64. {
  65. fpsTo.psProperty.propid = fpsFrom.psProperty.propid;
  66. return;
  67. }
  68. if ( PRSPEC_LPWSTR == fpsFrom.psProperty.ulKind )
  69. {
  70. unsigned cwc = 1 + wcslen( fpsFrom.psProperty.lpwstr );
  71. fpsTo.psProperty.lpwstr = (LPWSTR) CoTaskMemAlloc( cwc );
  72. wcscpy( fpsTo.psProperty.lpwstr, fpsFrom.psProperty.lpwstr );
  73. }
  74. } //FPSCopy
  75. void FPSFree( FULLPROPSPEC &fps )
  76. {
  77. if ( ( PRSPEC_LPWSTR == fps.psProperty.ulKind ) &&
  78. ( 0 != fps.psProperty.lpwstr ) )
  79. {
  80. CoTaskMemFree( fps.psProperty.lpwstr );
  81. fps.psProperty.lpwstr = 0;
  82. }
  83. } //FPSFree
  84. //+---------------------------------------------------------------------------
  85. //
  86. // Member: CxxIFilter::~CxxIFilter, public
  87. //
  88. // Synopsis: Destructor
  89. //
  90. // History: 07-Oct-93 AmyA Created.
  91. //
  92. //----------------------------------------------------------------------------
  93. CxxIFilter::~CxxIFilter()
  94. {
  95. delete [] _pAttrib;
  96. if ( _pTextFilt )
  97. _pTextFilt->Release();
  98. if ( _pPersFile )
  99. _pPersFile->Release();
  100. if ( _pPersStream )
  101. _pPersStream->Release();
  102. delete _pTextStream;
  103. }
  104. //+---------------------------------------------------------------------------
  105. //
  106. // Member: CxxIFilter::Init, public
  107. //
  108. // Synopsis: Initializes instance of text filter
  109. //
  110. // Arguments: [grfFlags] -- flags for filter behavior
  111. // [cAttributes] -- number of attributes in array aAttributes
  112. // [aAttributes] -- array of attributes
  113. // [pfBulkyObject] -- indicates whether this object is a
  114. // bulky object
  115. //
  116. // History: 07-Oct-93 AmyA Created.
  117. //
  118. //----------------------------------------------------------------------------
  119. SCODE STDMETHODCALLTYPE CxxIFilter::Init( ULONG grfFlags,
  120. ULONG cAttributes,
  121. FULLPROPSPEC const * aAttributes,
  122. ULONG * pFlags )
  123. {
  124. CTranslateSystemExceptions translate;
  125. SCODE sc = S_OK;
  126. TRY
  127. {
  128. _ulLastTextChunkID = 0;
  129. _ulChunkID = 0;
  130. if( cAttributes > 0 )
  131. {
  132. if ( 0 == aAttributes )
  133. return E_INVALIDARG;
  134. _state = FilterProp;
  135. _cAttrib = cAttributes;
  136. if ( 0 != _pAttrib )
  137. {
  138. delete [] _pAttrib;
  139. _pAttrib = 0;
  140. }
  141. _pAttrib = new CFps [_cAttrib];
  142. for ( ULONG i = 0; i < cAttributes; i++ )
  143. {
  144. if ( _state != FilterContents && IsContents( aAttributes[i] ) )
  145. _state = FilterContents;
  146. _pAttrib[i].Copy( aAttributes[i] );
  147. }
  148. }
  149. else if ( 0 == grfFlags || (grfFlags & IFILTER_INIT_APPLY_INDEX_ATTRIBUTES) )
  150. {
  151. _state = FilterContents;
  152. }
  153. else
  154. {
  155. _state = FilterDone;
  156. }
  157. }
  158. CATCH(CException, e)
  159. {
  160. sc = e.GetErrorCode();
  161. }
  162. END_CATCH;
  163. if ( FAILED( sc ) )
  164. return sc;
  165. return _pTextFilt->Init( 0,
  166. 1,
  167. &fpsContents,
  168. pFlags );
  169. } //Init
  170. //+---------------------------------------------------------------------------
  171. //
  172. // Member: CxxIFilter::GetChunk, public
  173. //
  174. // Synopsis: Gets the next chunk and returns chunk information in pStat
  175. //
  176. // Arguments: [pStat] -- for chunk information
  177. //
  178. // History: 07-Oct-93 AmyA Created.
  179. //
  180. //----------------------------------------------------------------------------
  181. SCODE STDMETHODCALLTYPE CxxIFilter::GetChunk( STAT_CHUNK * pStat )
  182. {
  183. SCODE sc = S_OK;
  184. CTranslateSystemExceptions translate;
  185. TRY
  186. {
  187. if (_state == FilterNextProp)
  188. {
  189. _state = FilterProp;
  190. }
  191. //
  192. // All chunks of plain text come first.
  193. //
  194. if ( _state == FilterContents )
  195. {
  196. sc = _pTextFilt->GetChunk( pStat );
  197. if ( SUCCEEDED(sc) )
  198. {
  199. pStat->locale = 0; // use the default word breaker
  200. _locale = 0;
  201. _ulLastTextChunkID = pStat->idChunk;
  202. }
  203. else if ( sc == FILTER_E_END_OF_CHUNKS )
  204. {
  205. _ulChunkID = _ulLastTextChunkID;
  206. ULONG Flags;
  207. sc = _pTextFilt->Init( 0,
  208. 1,
  209. &fpsContents,
  210. &Flags );
  211. if ( SUCCEEDED(sc) )
  212. {
  213. delete _pTextStream;
  214. _pTextStream = new CFilterTextStream (_pTextFilt);
  215. if (SUCCEEDED (_pTextStream->GetStatus()))
  216. {
  217. _cxxParse.Init( _pTextStream );
  218. _state = FilterProp;
  219. }
  220. else
  221. _state = FilterDone;
  222. }
  223. else
  224. _state = FilterDone;
  225. }
  226. }
  227. if ( _state == FilterProp && SUCCEEDED(sc) )
  228. {
  229. while ( TRUE )
  230. {
  231. if (_cxxParse.Parse())
  232. {
  233. pStat->attribute.guidPropSet = guidCPlusPlus;
  234. pStat->attribute.psProperty = _cxxParse.GetAttribute();
  235. for ( unsigned i = 0; i < _cAttrib; i++ )
  236. if ( _pAttrib[i].IsMatch( pStat->attribute ) )
  237. break;
  238. if ( _cAttrib == 0 || i < _cAttrib ) // Property should be returned
  239. {
  240. pStat->idChunk = ++_ulChunkID;
  241. pStat->breakType = CHUNK_EOS;
  242. pStat->flags = CHUNK_TEXT;
  243. pStat->locale = _locale;
  244. FILTERREGION regionSource;
  245. // what's the source of this derived property?
  246. _cxxParse.GetRegion ( regionSource );
  247. pStat->idChunkSource = regionSource.idChunk;
  248. pStat->cwcStartSource = regionSource.cwcStart;
  249. pStat->cwcLenSource = regionSource.cwcExtent;
  250. sc = S_OK;
  251. break;
  252. }
  253. }
  254. else
  255. {
  256. _state = FilterValue;
  257. break;
  258. }
  259. }
  260. }
  261. if ( _state == FilterNextValue )
  262. {
  263. _cxxParse.SkipValue();
  264. _state = FilterValue;
  265. }
  266. if ( _state == FilterValue )
  267. {
  268. while ( TRUE )
  269. {
  270. if ( _cxxParse.GetValueAttribute( pStat->attribute.psProperty ) )
  271. {
  272. pStat->attribute.guidPropSet = guidCPlusPlus;
  273. for ( unsigned i = 0; i < _cAttrib; i++ )
  274. if ( _pAttrib[i].IsMatch( pStat->attribute ) )
  275. break;
  276. if ( _cAttrib == 0 || i < _cAttrib ) // Property should be returned
  277. {
  278. pStat->flags = CHUNK_VALUE;
  279. pStat->locale = _locale;
  280. _state = FilterNextValue;
  281. sc = S_OK;
  282. break;
  283. }
  284. else
  285. _cxxParse.SkipValue();
  286. }
  287. else
  288. {
  289. _state = FilterDone;
  290. break;
  291. }
  292. }
  293. }
  294. if (_state == FilterDone || !SUCCEEDED(sc))
  295. {
  296. sc = FILTER_E_END_OF_CHUNKS;
  297. _state = FilterDone;
  298. }
  299. }
  300. CATCH(CException, e)
  301. {
  302. sc = e.GetErrorCode();
  303. }
  304. END_CATCH;
  305. return sc;
  306. }
  307. //+---------------------------------------------------------------------------
  308. //
  309. // Member: CxxIFilter::GetText, public
  310. //
  311. // Synopsis: Retrieves text from current chunk
  312. //
  313. // Arguments: [pcwcBuffer] -- count of characters in buffer
  314. // [awcBuffer] -- buffer for text
  315. //
  316. // History: 07-Oct-93 AmyA Created.
  317. //
  318. //----------------------------------------------------------------------------
  319. SCODE STDMETHODCALLTYPE CxxIFilter::GetText( ULONG * pcwcBuffer,
  320. WCHAR * awcBuffer )
  321. {
  322. if ( _state == FilterValue || _state == FilterNextValue )
  323. return FILTER_E_NO_TEXT;
  324. if ( _state == FilterContents )
  325. {
  326. return _pTextFilt->GetText( pcwcBuffer, awcBuffer );
  327. }
  328. else if ( _state == FilterProp )
  329. {
  330. if ( _cxxParse.GetTokens( pcwcBuffer, awcBuffer ))
  331. {
  332. _state = FilterNextProp;
  333. return FILTER_S_LAST_TEXT;
  334. }
  335. else
  336. return S_OK;
  337. }
  338. else if ( _state == FilterNextProp )
  339. {
  340. return FILTER_E_NO_MORE_TEXT;
  341. }
  342. else
  343. {
  344. Win4Assert ( _state == FilterDone );
  345. return FILTER_E_NO_MORE_TEXT;
  346. }
  347. }
  348. //+---------------------------------------------------------------------------
  349. //
  350. // Member: CxxIFilter::GetValue, public
  351. //
  352. // Synopsis: Not implemented for the text filter
  353. //
  354. // History: 07-Oct-93 AmyA Created.
  355. //
  356. //----------------------------------------------------------------------------
  357. SCODE STDMETHODCALLTYPE CxxIFilter::GetValue( PROPVARIANT ** ppPropValue )
  358. {
  359. if ( _state == FilterContents )
  360. return _pTextFilt->GetValue( ppPropValue );
  361. if ( _state == FilterDone )
  362. return FILTER_E_NO_MORE_VALUES;
  363. if ( _state != FilterNextValue )
  364. return FILTER_E_NO_VALUES;
  365. *ppPropValue = _cxxParse.GetValue();
  366. _state = FilterValue;
  367. if ( 0 == *ppPropValue )
  368. return FILTER_E_NO_MORE_VALUES;
  369. else
  370. return S_OK;
  371. }
  372. //+---------------------------------------------------------------------------
  373. //
  374. // Member: CxxIFilter::BindRegion, public
  375. //
  376. // Synopsis: Creates moniker or other interface for text indicated
  377. //
  378. // Arguments: [origPos] -- location of text
  379. // [riid] -- Interface Id
  380. // [ppunk] -- returned interface
  381. //
  382. // History: 07-Oct-93 AmyA Created.
  383. //
  384. //----------------------------------------------------------------------------
  385. SCODE STDMETHODCALLTYPE CxxIFilter::BindRegion( FILTERREGION origPos,
  386. REFIID riid,
  387. void ** ppunk )
  388. {
  389. return _pTextFilt->BindRegion( origPos, riid, ppunk );
  390. }
  391. //+---------------------------------------------------------------------------
  392. //
  393. // Member: CxxIFilter::GetClassID, public
  394. //
  395. // Synopsis: Returns the class id of this class.
  396. //
  397. // Arguments: [pClassID] -- the class id
  398. //
  399. // History: 07-Oct-93 AmyA Created.
  400. //
  401. //----------------------------------------------------------------------------
  402. SCODE STDMETHODCALLTYPE CxxIFilter::GetClassID( CLSID * pClassID )
  403. {
  404. *pClassID = CLSID_CxxIFilter;
  405. return S_OK;
  406. }
  407. //+---------------------------------------------------------------------------
  408. //
  409. // Member: CxxIFilter::IsDirty, public
  410. //
  411. // Synopsis: Always returns S_FALSE since this class is read-only.
  412. //
  413. // History: 07-Oct-93 AmyA Created.
  414. //
  415. //----------------------------------------------------------------------------
  416. SCODE STDMETHODCALLTYPE CxxIFilter::IsDirty()
  417. {
  418. return S_FALSE; // Since the filter is read-only, there will never be
  419. // changes to the file.
  420. }
  421. typedef HRESULT (__stdcall * PFnLoadTextFilter)( WCHAR const * pwcPath,
  422. IFilter ** ppIFilter );
  423. PFnLoadTextFilter g_pLoadTextFilter = 0;
  424. SCODE MyLoadTextFilter( WCHAR const *pwc, IFilter **ppFilter )
  425. {
  426. if ( 0 == g_pLoadTextFilter )
  427. {
  428. // Dummy call to CIState to force query.dll to be always loaded
  429. CIState( 0, 0, 0 );
  430. g_pLoadTextFilter = (PFnLoadTextFilter) GetProcAddress( GetModuleHandle( L"query.dll" ), "LoadTextFilter" );
  431. if ( 0 == g_pLoadTextFilter )
  432. return HRESULT_FROM_WIN32( GetLastError() );
  433. }
  434. return g_pLoadTextFilter( pwc, ppFilter );
  435. }
  436. //+---------------------------------------------------------------------------
  437. //
  438. // Member: CxxIFilter::Load, public
  439. //
  440. // Synopsis: Loads the indicated file
  441. //
  442. // Arguments: [pszFileName] -- the file name
  443. // [dwMode] -- the mode to load the file in
  444. //
  445. // History: 07-Oct-93 AmyA Created.
  446. //
  447. // Notes: dwMode must be either 0 or STGM_READ.
  448. //
  449. //----------------------------------------------------------------------------
  450. SCODE STDMETHODCALLTYPE CxxIFilter::Load(LPCWSTR pszFileName, DWORD dwMode)
  451. {
  452. if ( 0 != _pTextFilt )
  453. {
  454. _pTextFilt->Release();
  455. _pTextFilt = 0;
  456. }
  457. if ( 0 != _pPersFile )
  458. {
  459. _pPersFile->Release();
  460. _pPersFile = 0;
  461. }
  462. if ( 0 != _pPersStream )
  463. {
  464. _pPersStream->Release();
  465. _pPersStream = 0;
  466. }
  467. SCODE sc = MyLoadTextFilter( pszFileName, &_pTextFilt );
  468. if ( SUCCEEDED(sc) )
  469. {
  470. // Load file
  471. sc = _pTextFilt->QueryInterface( IID_IPersistFile, (void **) &_pPersFile );
  472. if ( SUCCEEDED(sc) )
  473. {
  474. sc = _pPersFile->Load( pszFileName, dwMode );
  475. }
  476. else
  477. {
  478. _pTextFilt->Release();
  479. _pTextFilt = 0;
  480. }
  481. }
  482. return sc;
  483. } //Load
  484. SCODE STDMETHODCALLTYPE CxxIFilter::Load( IStream * pStm )
  485. {
  486. SCODE sc = MyLoadTextFilter( 0, &_pTextFilt );
  487. if ( SUCCEEDED(sc) )
  488. {
  489. // Load file
  490. sc = _pTextFilt->QueryInterface( IID_IPersistStream, (void **) &_pPersStream );
  491. if ( SUCCEEDED(sc) )
  492. {
  493. sc = _pPersStream->Load( pStm );
  494. }
  495. else
  496. {
  497. _pTextFilt->Release();
  498. _pTextFilt = 0;
  499. }
  500. }
  501. return sc;
  502. } //Load
  503. //+---------------------------------------------------------------------------
  504. //
  505. // Member: CxxIFilter::Save, public
  506. //
  507. // Synopsis: Always returns E_FAIL, since the file is opened read-only
  508. //
  509. // History: 16-Jul-93 AmyA Created.
  510. //
  511. //----------------------------------------------------------------------------
  512. SCODE STDMETHODCALLTYPE CxxIFilter::Save(LPCWSTR pszFileName, BOOL fRemember)
  513. {
  514. return E_FAIL; // cannot be saved since it is read-only
  515. }
  516. //+---------------------------------------------------------------------------
  517. //
  518. // Member: CxxIFilter::SaveCompleted, public
  519. //
  520. // Synopsis: Always returns S_OK since the file is opened read-only
  521. //
  522. // History: 16-Jul-93 AmyA Created.
  523. //
  524. //----------------------------------------------------------------------------
  525. SCODE STDMETHODCALLTYPE CxxIFilter::SaveCompleted(LPCWSTR pszFileName)
  526. {
  527. return E_FAIL;
  528. }
  529. //+---------------------------------------------------------------------------
  530. //
  531. // Member: CxxIFilter::GetCurFile, public
  532. //
  533. // Synopsis: Returns a copy of the current file name
  534. //
  535. // Arguments: [ppszFileName] -- where the copied string is returned.
  536. //
  537. // History: 09-Aug-93 AmyA Created.
  538. //
  539. //----------------------------------------------------------------------------
  540. SCODE STDMETHODCALLTYPE CxxIFilter::GetCurFile(LPWSTR * ppszFileName)
  541. {
  542. return _pPersFile->GetCurFile( ppszFileName );
  543. }