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.

2470 lines
81 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996.
  5. //
  6. // File: filttest.cxx
  7. //
  8. // Contents: Definitions for CFiltTest methods
  9. //
  10. // Classes:
  11. //
  12. // Functions: methods of CFiltTest
  13. //
  14. // Coupling:
  15. //
  16. // Notes: Allocations: This function assumes that a newhandler has been
  17. // defined to handle failed allocations.
  18. //
  19. // History: 9-16-1996 ericne Created
  20. //
  21. //----------------------------------------------------------------------------
  22. #include "pch.cxx"
  23. #include "utility.hxx"
  24. #include "mydebug.hxx"
  25. #include "filttest.hxx"
  26. // added by t-shawnh 09/19/97
  27. #include "nlfilter.hxx"
  28. // t-shawnh
  29. // Must be compiled with the UNICODE flag
  30. #if ! defined( UNICODE ) && ! defined( _UNICODE )
  31. #error( "UNICODE must be defined" )
  32. #endif
  33. //+---------------------------------------------------------------------------
  34. //
  35. // Member: CFiltTest::CFiltTest
  36. //
  37. // Synopsis: Constructor for CFiltTest
  38. //
  39. // Arguments: [pwcFile] -- Wide character string containing file name
  40. //
  41. // Returns: none
  42. //
  43. // History: 9-19-1996 ericne Created
  44. //
  45. // Notes:
  46. //
  47. //----------------------------------------------------------------------------
  48. CFiltTest::CFiltTest( CLog * pLog )
  49. : m_pLog( pLog ),
  50. m_fIsText( FALSE ),
  51. m_pIFilter( NULL ),
  52. m_pDumpFile( NULL ),
  53. m_verbosity( HIGH ),
  54. m_fLegitOnly( FALSE ),
  55. m_ChunkStatsListHead(),
  56. m_pwcTextBuffer( NULL ),
  57. m_fIsInitialized( FALSE ),
  58. m_szInputFileName( NULL ),
  59. m_fSharedLog( NULL == pLog ? FALSE : TRUE )
  60. {
  61. } //CFiltTest::CFiltTest
  62. //+---------------------------------------------------------------------------
  63. //
  64. // Member: CFiltTest::~CFiltTest
  65. //
  66. // Synopsis: Destructor: cleans up dynamically allocated memory
  67. //
  68. // Arguments: (none)
  69. //
  70. // Returns: none
  71. //
  72. // History: 9-19-1996 ericne Created
  73. //
  74. // Notes:
  75. //
  76. //----------------------------------------------------------------------------
  77. CFiltTest::~CFiltTest()
  78. {
  79. if( NULL != m_pLog )
  80. {
  81. if( m_fSharedLog )
  82. {
  83. if( ! m_pLog->RemoveParticipant() )
  84. {
  85. _RPT1( _CRT_WARN,
  86. "Could not remote this thread as a participant of log for input file %ls\r\n",
  87. m_szInputFileName );
  88. }
  89. }
  90. else
  91. {
  92. m_pLog->ReportStats();
  93. if( ! m_pLog->RemoveParticipant() )
  94. {
  95. _RPT1( _CRT_WARN,
  96. "Could not remote this thread as a participant of log for input file %ls\r\n",
  97. m_szInputFileName );
  98. }
  99. delete m_pLog;
  100. }
  101. }
  102. if( NULL != m_szInputFileName )
  103. delete [] m_szInputFileName;
  104. if( NULL != m_pwcTextBuffer )
  105. delete [] m_pwcTextBuffer;
  106. if( NULL != m_pDumpFile && stdout != m_pDumpFile )
  107. fclose( m_pDumpFile );
  108. FlushList( );
  109. } //CFiltTest::~CFiltTest
  110. //+---------------------------------------------------------------------------
  111. //
  112. // Member: CFiltTest::Init
  113. //
  114. // Synopsis: Initialized the test
  115. //
  116. // Arguments: [szInputFileName] -- Name of the input file
  117. // [szLogFileName] -- Name of the file to log results
  118. // [szDumpFileName] -- Name of the file to dump text
  119. // [verbosity] -- Level of verbosity
  120. //
  121. // Returns: TRUE if init was successful
  122. // FALSE if init failed.
  123. //
  124. // History: 9-20-1996 ericne Created
  125. //
  126. // Notes:
  127. //
  128. //----------------------------------------------------------------------------
  129. BOOL CFiltTest::Init( const WCHAR * szInputFileName,
  130. const WCHAR * szLogFileName,
  131. const WCHAR * szDumpFileName,
  132. const WCHAR * szIniFileName,
  133. Verbosity verbosity,
  134. BOOL fLegitOnly )
  135. {
  136. WCHAR szIniPathName[ MAX_PATH ];
  137. // For use in writting the Unicode byte-order mark to the dump file
  138. WCHAR wcBOM = 0xFEFF;
  139. DWORD dwNbrBytes = 0;
  140. _ASSERT( NULL != szInputFileName );
  141. _ASSERT( NULL != szIniFileName );
  142. // Set the legit only flag
  143. m_fLegitOnly = fLegitOnly;
  144. // Allocate space for the filename
  145. m_szInputFileName = NEW WCHAR[ wcslen(szInputFileName) + 1 ];
  146. wcscpy( m_szInputFileName, szInputFileName );
  147. // Allocate space for the text returned by GetText
  148. m_pwcTextBuffer = NEW WCHAR[ BUFFER_SIZE + 1 ];
  149. // Set the verbosity
  150. m_verbosity = verbosity;
  151. // Create a log if necessary:
  152. if( NULL == m_pLog )
  153. m_pLog = NEW CLog;
  154. _ASSERT( NULL != m_pLog );
  155. // If logging is enabled, initialize the log
  156. if( NULL != szLogFileName )
  157. {
  158. if( ! m_fSharedLog )
  159. {
  160. if( ! m_pLog->InitLog( szLogFileName ) )
  161. {
  162. printf( "Could not open the log file %ls\r\n"
  163. "Could not initialize the test for file %ls\r\n",
  164. szLogFileName, szInputFileName );
  165. return( FALSE );
  166. }
  167. if( ! m_pLog->AddParticipant() )
  168. {
  169. printf( "Could not add this thread as a participant to"
  170. " the log file %ls.\r\n", szLogFileName );
  171. return( FALSE );
  172. }
  173. // Set the log threshold
  174. m_pLog->SetThreshold( VerbosityToLogStyle( verbosity ) );
  175. }
  176. else
  177. {
  178. // Otherwise, only add as a participant
  179. if( ! m_pLog->AddParticipant() )
  180. {
  181. printf( "Could not add this thread as a participant to"
  182. " the log file %ls.\r\n", szLogFileName );
  183. return( FALSE );
  184. }
  185. }
  186. // Send a message to the log file indicating which input file is
  187. // being filtered
  188. m_pLog->Log( TLS_TEST | TL_INFO, L"**** Input file : %ls",
  189. szInputFileName );
  190. }
  191. else
  192. {
  193. // Disable the log. Log messages will now be ignored
  194. m_pLog->Disable();
  195. }
  196. // If dumping is not enabled, leave m_pDumpFile == NULL
  197. // BUGBUG is there an easy way to redirect output to NUL?
  198. if( NULL != szDumpFileName )
  199. {
  200. // Fill in the dummping information
  201. if( NULL == szDumpFileName )
  202. {
  203. m_pDumpFile = stdout;
  204. }
  205. else
  206. {
  207. m_pDumpFile = _wfopen( szDumpFileName, L"wb" );
  208. // Write the Unicode byte-order mark to the file
  209. if( NULL != m_pDumpFile )
  210. {
  211. putwc( wcBOM, m_pDumpFile );
  212. }
  213. else
  214. {
  215. m_pLog->Log( TLS_TEST | TL_SEV1, L"Could not open the Dump file"
  216. L" %ls Could not initialize test for file %ls",
  217. szDumpFileName, szInputFileName );
  218. return( FALSE );
  219. }
  220. }
  221. }
  222. // Parse the input data file containing configuration information
  223. GetFullPathName( szIniFileName, MAX_PATH, szIniPathName, NULL );
  224. if( ! m_FiltParse.Init( szIniPathName ) )
  225. {
  226. m_pLog->Log( TLS_TEST | TL_SEV1, L"Could not parse the input file." );
  227. return( FALSE );
  228. }
  229. return( TRUE );
  230. } //CFiltTest::Init
  231. //+---------------------------------------------------------------------------
  232. //
  233. // Member: CFiltTest::FlushList
  234. //
  235. // Synopsis: Deletes all the nodes in the linked list
  236. //
  237. // Arguments: (none)
  238. //
  239. // Returns: none
  240. //
  241. // History: 9-19-1996 ericne Created
  242. //
  243. // Notes:
  244. //
  245. //----------------------------------------------------------------------------
  246. void CFiltTest::FlushList( )
  247. {
  248. // Clean up the memory allocated in the ChunkIDList
  249. CListNode *pListNode = m_ChunkStatsListHead.next;
  250. CListNode *pTempNode = NULL;
  251. while( NULL != pListNode )
  252. {
  253. pTempNode = pListNode;
  254. pListNode = pListNode->next;
  255. delete pTempNode; // Calls destructor for ChunkStats
  256. }
  257. m_ChunkStatsListHead.next = NULL;
  258. } //CFiltTest::FlushList
  259. BOOL CFiltTest::IsCurrentChunkContents()
  260. {
  261. static const GUID guidContents = PSGUID_STORAGE;
  262. if( CHUNK_TEXT == m_CurrentChunkStats.flags &&
  263. guidContents == m_CurrentChunkStats.attribute.guidPropSet &&
  264. PRSPEC_PROPID == m_CurrentChunkStats.attribute.psProperty.ulKind &&
  265. PID_STG_CONTENTS == m_CurrentChunkStats.attribute.psProperty.propid )
  266. {
  267. return TRUE;
  268. }
  269. return FALSE;
  270. }
  271. //+---------------------------------------------------------------------------
  272. //
  273. // Member: CFiltTest::ValidateChunkStats
  274. //
  275. // Synopsis: Checks the fields of m_CurrentChunkStats for sanity and adds
  276. // it to the end of the liked list
  277. //
  278. // Arguments: (none)
  279. //
  280. // Returns: void
  281. //
  282. // History: 9-19-1996 ericne Created
  283. //
  284. // Notes:
  285. //
  286. //----------------------------------------------------------------------------
  287. void CFiltTest::ValidateChunkStats( )
  288. {
  289. CListNode *pNewNode = NULL;
  290. CListNode *pLastNode = &m_ChunkStatsListHead;
  291. // Make sure nobody has messed with the head of the list
  292. _ASSERT( 0 == m_ChunkStatsListHead.ChunkStats.idChunk );
  293. // Check that the current chunk has a recognized value for the flags field
  294. if( CHUNK_VALUE != m_CurrentChunkStats.flags &&
  295. CHUNK_TEXT != m_CurrentChunkStats.flags )
  296. {
  297. m_pLog->Log( TLS_TEST | TL_SEV1, L"The current chunk has an illegal"
  298. L" value for the flags field. Legal values are 1 and 2." );
  299. LogChunkStats( m_CurrentChunkStats );
  300. }
  301. else
  302. {
  303. m_pLog->Log( TLS_TEST | TL_PASS, L"The current chunk has a legal value"
  304. L" for the flags field." );
  305. }
  306. // Check that the current chunk has a legal break yype
  307. if( CHUNK_NO_BREAK > m_CurrentChunkStats.breakType ||
  308. CHUNK_EOC < m_CurrentChunkStats.breakType )
  309. {
  310. m_pLog->Log( TLS_TEST | TL_SEV1, L"The current chunk has an illegal"
  311. L" value for breakType. Legal values are from 0 to 4." );
  312. LogChunkStats( m_CurrentChunkStats );
  313. }
  314. else
  315. {
  316. m_pLog->Log( TLS_TEST | TL_PASS, L"The current chunk has a legal value"
  317. L" for breakType." );
  318. }
  319. // The idChunkSource should not be larger than the id of the current chunk
  320. if( m_CurrentChunkStats.idChunkSource > m_CurrentChunkStats.idChunk )
  321. {
  322. m_pLog->Log( TLS_TEST | TL_WARN, L"For the current chunk, idChunkSource"
  323. L" is greater than idChunk." );
  324. LogChunkStats( m_CurrentChunkStats );
  325. }
  326. // If the idCunkSource is not equal to the idChunk, the chunk
  327. // cannot be a contents chunk
  328. if( m_CurrentChunkStats.idChunkSource != m_CurrentChunkStats.idChunk &&
  329. IsCurrentChunkContents() )
  330. {
  331. m_pLog->Log( TLS_TEST | TL_SEV1, L"ERROR: For the current chunk,"
  332. L" idChunkSource is not equal to idChunk and the chunk does"
  333. L" not contain a pseudo-property. This is not legal (see"
  334. L" IFilter spec for GetChunk)" );
  335. LogChunkStats( m_CurrentChunkStats );
  336. }
  337. // Check the propspec for validity
  338. ValidatePropspec( );
  339. // Step to the end of the list.
  340. while( NULL != pLastNode->next )
  341. {
  342. pLastNode = pLastNode->next;
  343. }
  344. // Before placing the chunk at the end of the list, verify that its ID
  345. // is in fact larger than that of the last chunk in the list
  346. if( m_CurrentChunkStats.idChunk <= pLastNode->ChunkStats.idChunk)
  347. {
  348. if( 0 == m_CurrentChunkStats.idChunk )
  349. {
  350. m_pLog->Log( TLS_TEST | TL_SEV1, L"Zero is an"
  351. L" illegal value for chunk id." );
  352. }
  353. if( pLastNode != &m_ChunkStatsListHead )
  354. {
  355. m_pLog->Log( TLS_TEST | TL_SEV1, L"The current chunk ID is not"
  356. L" greater than the previous." );
  357. }
  358. LogChunkStats( m_CurrentChunkStats );
  359. }
  360. else
  361. {
  362. m_pLog->Log( TLS_TEST | TL_PASS, L"The current chunk has a legal value"
  363. L" for chunk id." );
  364. }
  365. // Allocate space for a new CListNode:
  366. pNewNode = NEW CListNode;
  367. // Dump the chunk statistics:
  368. DisplayChunkStats( m_CurrentChunkStats, m_pDumpFile );
  369. // Add the data to the end of the list:
  370. pLastNode->next = pNewNode;
  371. pNewNode->next = NULL;
  372. // Fill in the ChunkStats field by using CStatChunk's overloaded
  373. // assignment operator:
  374. pNewNode->ChunkStats = m_CurrentChunkStats;
  375. } //CFiltTest::ValidateChunkStats
  376. //+---------------------------------------------------------------------------
  377. //
  378. // Member: CFiltTest::ValidatePropspec
  379. //
  380. // Synopsis: Validate that the current chunk should have been emitted, based
  381. // on the attributes specified in the filter configuration
  382. //
  383. // Arguments: (none)
  384. //
  385. // Returns: none
  386. //
  387. // History: 9-25-1996 ericne Created
  388. //
  389. // Notes:
  390. //
  391. //----------------------------------------------------------------------------
  392. void CFiltTest::ValidatePropspec( )
  393. {
  394. UINT uiLoop = 0;
  395. UINT uiLoopMax = 0;
  396. BOOL fIsLegalAttribute = FALSE;
  397. GUID psguid_storage = PSGUID_STORAGE;
  398. const GUID & guidPropSet = m_CurrentChunkStats.attribute.guidPropSet;
  399. const PROPSPEC & psProperty = m_CurrentChunkStats.attribute.psProperty;
  400. // Check to see if the ulKind field is OK
  401. if( PRSPEC_PROPID == psProperty.ulKind ||
  402. PRSPEC_LPWSTR == psProperty.ulKind )
  403. {
  404. m_pLog->Log( TLS_TEST | TL_PASS, L"The current chunk has a valid value"
  405. L" for the attribute.psProperty.ulKind field" );
  406. }
  407. else
  408. {
  409. m_pLog->Log( TLS_TEST | TL_SEV1, L"The current chunk has an invalid"
  410. L" value for the attribute.psProperty.ulKind field."
  411. L" Accepted values are 0 and 1." );
  412. // Nothing else we can do now, so return.
  413. return;
  414. }
  415. // If the PROPSPEC is a PROPID, make sure the value is not 0 or 1
  416. if( PRSPEC_PROPID == psProperty.ulKind &&
  417. ( 0 == psProperty.propid || 1 == psProperty.propid ) )
  418. {
  419. m_pLog->Log( TLS_TEST | TL_SEV1, L"The current chunk has an invalid"
  420. L" value for the attribute.psProperty.propid field."
  421. L" Illegal values are 0 and 1." );
  422. }
  423. else
  424. {
  425. m_pLog->Log( TLS_TEST | TL_PASS, L"The current chunk has a valid value"
  426. L" for the attribute.psProperty.propid field" );
  427. }
  428. // If some attributes were requested explicitly in aAttributes, only
  429. // look in aAttributes for a match
  430. if( 0 != m_CurrentConfig.cAttributes )
  431. {
  432. // Loop over the smaller of cAttributes and ulActNbrAttributes
  433. if( m_CurrentConfig.cAttributes < m_CurrentConfig.ulActNbrAttributes )
  434. uiLoopMax = m_CurrentConfig.cAttributes;
  435. else
  436. uiLoopMax = m_CurrentConfig.ulActNbrAttributes;
  437. // Loop over all attributes in the current configuration
  438. for( uiLoop = 0; uiLoop < uiLoopMax; uiLoop++ )
  439. {
  440. // If the properties are of different type, continue
  441. if( psProperty.ulKind !=
  442. m_CurrentConfig.aAttributes[ uiLoop ].psProperty.ulKind )
  443. continue;
  444. // If the guids don't match, continue
  445. if( guidPropSet !=
  446. m_CurrentConfig.aAttributes[ uiLoop ].guidPropSet )
  447. continue;
  448. // If propid, compare the id's. NOTE: If the first condition
  449. // eveluates to FALSE, the second is not eveluated at all.
  450. if( ( PRSPEC_PROPID == psProperty.ulKind ) &&
  451. ( psProperty.propid ==
  452. m_CurrentConfig.aAttributes[ uiLoop ].psProperty.propid ) )
  453. {
  454. fIsLegalAttribute = TRUE;
  455. break;
  456. }
  457. // If pwstr, compare the strings. NOTE: If the first condition
  458. // evaluates to FALSE, the second is not evaluated at all.
  459. if( ( PRSPEC_LPWSTR == psProperty.ulKind ) &&
  460. ( 0 == wcscmp( psProperty.lpwstr,
  461. m_CurrentConfig.aAttributes[ uiLoop ].psProperty.lpwstr ) ) )
  462. {
  463. fIsLegalAttribute = TRUE;
  464. break;
  465. }
  466. } // for
  467. }
  468. else if( m_CurrentConfig.grfFlags & IFILTER_INIT_APPLY_INDEX_ATTRIBUTES )
  469. {
  470. // The filter has been configured to emit everything
  471. fIsLegalAttribute = TRUE;
  472. // NOTE: The flag IFILTER_INIT_APPLY_OTHER_ATTRIBUTES has no meaning,
  473. // so I do not test for it.
  474. }
  475. else
  476. {
  477. // The filter should only be emitting contents
  478. if( PRSPEC_PROPID == psProperty.ulKind &&
  479. psguid_storage == guidPropSet &&
  480. PID_STG_CONTENTS == psProperty.propid )
  481. {
  482. fIsLegalAttribute = TRUE;
  483. }
  484. }
  485. // If this chunk has an unrequested attribute, display the error
  486. if( ! fIsLegalAttribute )
  487. {
  488. m_pLog->Log( TLS_TEST | TL_SEV1, L"The filter has emitted a chunk which"
  489. L" it was not requested to emit. Check the initialization"
  490. L" parameters in section %s of the initialization file.",
  491. m_CurrentConfig.szSectionName );
  492. // Write the offensive chunk stats to the log file for later inspection
  493. LogChunkStats( m_CurrentChunkStats );
  494. }
  495. else
  496. {
  497. m_pLog->Log( TLS_TEST | TL_PASS, L"The attribute of the current chunk"
  498. L" correctly matches the attributes specified in the"
  499. L" call to Init()." );
  500. }
  501. } //CFiltTest::ValidatePropspec
  502. //+---------------------------------------------------------------------------
  503. //
  504. // Member: CFiltTest::ExecuteTests
  505. //
  506. // Synopsis: Picks a configuration from the config list, binds the filter,
  507. // and initializes it with the configution. It then performs the
  508. // validation test. Then it re-initializes the filter and performs
  509. // the consistency test. Then it re-initialized the filter and
  510. // performs the invalid input test. Then it releases the filter,
  511. // picks a new configuration and repeats the whole process until
  512. // all the configurations have been tested.
  513. //
  514. // Arguments: (none)
  515. //
  516. // Returns: none
  517. //
  518. // History: 9-19-1996 ericne Created
  519. //
  520. // Notes:
  521. //
  522. //----------------------------------------------------------------------------
  523. void CFiltTest::ExecuteTests()
  524. {
  525. DWORD dwNbrBytes = 0;
  526. while( m_FiltParse.GetNextConfig( &m_CurrentConfig ) )
  527. {
  528. m_pLog->Log( TLS_TEST | TL_INFO, L"**** New configuration ****" );
  529. LogConfiguration( m_CurrentConfig );
  530. // Bind the filter:
  531. if( ! BindFilter( ) )
  532. {
  533. printf( "LoadIFilter failed before the Legitimacy Test. "
  534. "Test quitting.\r\n" );
  535. return;
  536. }
  537. // Initialize the filter
  538. if( ! InitializeFilter( m_CurrentConfig ) )
  539. {
  540. ReleaseFilter( );
  541. continue;
  542. }
  543. // Perform the validation test:
  544. LegitimacyTest( );
  545. // If the m_fLegitOnly member is TRUE, don't perform any more tests
  546. if( m_fLegitOnly )
  547. {
  548. ReleaseFilter( );
  549. FlushList( );
  550. continue;
  551. }
  552. // Only rebind the filter if IFILTER_INIT_INDEXING_ONLY flag is on:
  553. if( m_CurrentConfig.grfFlags & IFILTER_INIT_INDEXING_ONLY )
  554. {
  555. ReleaseFilter( );
  556. if( ! BindFilter( ) )
  557. {
  558. printf( "After successfully loading the filter for the "
  559. "Legitimacy Test,\r\nthe filter was released and "
  560. "LoadIFilter was called again.\r\nIt failed. "
  561. "Test quitting.\r\n" );
  562. return;
  563. }
  564. }
  565. // Initialize the filter
  566. if( ! InitializeFilter( m_CurrentConfig ) )
  567. {
  568. printf( "After successfully running the Legitimacy Test, a call"
  569. " to ::Init()\r\nto re-initialize the filter failed."
  570. " Test quitting.\r\n" );
  571. FlushList( );
  572. ReleaseFilter( );
  573. continue;
  574. }
  575. // Perform the consistency test test:
  576. ConsistencyTest( );
  577. // Only rebind the filter if IFILTER_INIT_INDEXING_ONLY flag is on:
  578. if( m_CurrentConfig.grfFlags & IFILTER_INIT_INDEXING_ONLY )
  579. {
  580. ReleaseFilter( );
  581. if( ! BindFilter( ) )
  582. {
  583. printf( "After successfully loading the filter for the "
  584. "Legitimacy Test\r\n and the Consistency Test, the "
  585. "filter was released and LoadIFilter\r\nwas called "
  586. "again. It failed. Test quitting.\r\n" );
  587. return;
  588. }
  589. }
  590. // Initialize the filter
  591. if( ! InitializeFilter( m_CurrentConfig ) )
  592. {
  593. printf( "After successfully running the Legitimacy Test and the "
  594. "Consistency Test,\r\na call to ::Init() to re-initialize"
  595. " the filter failed. Test quitting.\r\n" );
  596. FlushList( );
  597. ReleaseFilter( );
  598. continue;
  599. }
  600. // Perform the invalid input test:
  601. IllegitimacyTest( );
  602. // Flush the list:
  603. FlushList( );
  604. // Release the filter:
  605. ReleaseFilter( );
  606. }
  607. } //CFiltTest::ExecuteTests
  608. //+---------------------------------------------------------------------------
  609. //
  610. // Member: CFiltTest::BindFilter
  611. //
  612. // Synopsis: Bind the filter to m_pIFilter using LoadIFilter
  613. //
  614. // Arguments: (none)
  615. //
  616. // Returns: TRUE if successful, FALSE otherwise
  617. //
  618. // History: 9-19-1996 ericne Created
  619. //
  620. // Notes:
  621. //
  622. //----------------------------------------------------------------------------
  623. BOOL CFiltTest::BindFilter( )
  624. {
  625. SCODE sc = S_OK;
  626. _ASSERT( ! m_fIsInitialized );
  627. // Bind the filter:
  628. // added by t-shawnh 09/19/97
  629. sc = NLLoadIFilter( m_szInputFileName, (IUnknown*)0, (void**) &m_pIFilter );
  630. if (FAILED(sc))
  631. {
  632. sc = LoadIFilter( m_szInputFileName, (IUnknown*)0, (void**) &m_pIFilter );
  633. }
  634. // t-shawnh
  635. if( FAILED( sc ) )
  636. {
  637. m_pLog->Log( TLS_TEST | TL_SEV1, L"Unable to bind filter to file %ls"
  638. L" Return code is 0x%08x", m_szInputFileName, sc );
  639. return( FALSE );
  640. }
  641. m_pLog->Log( TLS_TEST | TL_INFO, L"Successfully bound filter." );
  642. return( TRUE );
  643. } //CFiltTest::BindFilter
  644. //+---------------------------------------------------------------------------
  645. //
  646. // Member: CFiltTest::InitializeFilter
  647. //
  648. // Synopsis: Initializes the filter with the configuration specified
  649. //
  650. // Arguments: [Configuration] -- structure which contains all the parameters
  651. // needed to initialize a filter
  652. //
  653. // Returns: TRUE if successful, FALSE otherwise
  654. //
  655. // History: 9-19-1996 ericne Created
  656. //
  657. // Notes:
  658. //
  659. //----------------------------------------------------------------------------
  660. BOOL CFiltTest::InitializeFilter( const CONFIG & Configuration )
  661. {
  662. // Initialize the filter
  663. SCODE sc = S_OK;
  664. _ASSERT( NULL != Configuration.pdwFlags );
  665. // Set *pdwFlags equal to an illegal value to make sure Init sets it
  666. // correctly
  667. *Configuration.pdwFlags = -1;
  668. __try
  669. {
  670. sc = m_pIFilter->Init( Configuration.grfFlags,
  671. Configuration.cAttributes,
  672. Configuration.aAttributes,
  673. Configuration.pdwFlags );
  674. }
  675. __except( EXCEPTION_EXECUTE_HANDLER )
  676. {
  677. m_pLog->Log( TLS_TEST | TL_SEV1, L"Exception 0x%08X occured in IFilter"
  678. L"::Init() The filter is bound to %ls Below are the"
  679. L" parameters which led to the exception.",
  680. GetExceptionCode(), m_szInputFileName );
  681. LogConfiguration( Configuration );
  682. return( FALSE );
  683. }
  684. // Check to see if Init failed
  685. if( FAILED( sc ) )
  686. {
  687. // It is legal for Init to return FILTER_E_PASSWORD or FILTER_E_ACCESS
  688. if( FILTER_E_PASSWORD == sc )
  689. {
  690. m_pLog->Log( TLS_TEST | TL_PASS, L"IFilter::Init returned"
  691. L" FILTER_E_PASSWORD. The filter is bound to %ls."
  692. L" The test cannot continue.", m_szInputFileName );
  693. }
  694. else if( FILTER_E_ACCESS == sc )
  695. {
  696. m_pLog->Log( TLS_TEST | TL_PASS, L"IFilter::Init returned"
  697. L" FILTER_E_ACCESS. The filter is bound to %ls."
  698. L" The test cannot continue.", m_szInputFileName );
  699. }
  700. else
  701. {
  702. // Log a message if init failed. It is ok to fail if cAttributes
  703. // is > 0 and aAttributes is NULL
  704. if( ( 0 == Configuration.cAttributes ) ||
  705. ( NULL != Configuration.aAttributes ) )
  706. {
  707. m_pLog->Log( TLS_TEST | TL_SEV1, L"Tried to initialize filer. "
  708. L" Expecting a return code of S_OK. Return code was"
  709. L" 0x%08x Filter is bound to %ls. Below are the"
  710. L" parameters which led to the failure.", sc,
  711. m_szInputFileName );
  712. LogConfiguration( Configuration );
  713. }
  714. else
  715. {
  716. m_pLog->Log( TLS_TEST | TL_PASS, L"Passed invalid parameters to"
  717. L" Init. cAttributes > 0 and aAttributes == NULL. "
  718. L" Return code is 0x%08x", sc );
  719. }
  720. }
  721. return( FALSE );
  722. }
  723. // If the call succeeded and the parameters were bad, something is wrong
  724. if( ( 0 < Configuration.cAttributes ) &&
  725. ( NULL == Configuration.aAttributes ) )
  726. {
  727. m_pLog->Log( TLS_TEST | TL_SEV1, L"Passed invalid parameters to Init. "
  728. L" cAttributes > 0 and aAttributes == NULL. Expecting call"
  729. L" to fail. Return code is 0x%08x. The filter is bound to"
  730. L" %ls", sc, m_szInputFileName );
  731. return( FALSE );
  732. }
  733. // Check the pdwFlags return value for legitimacy
  734. if( 0 != *Configuration.pdwFlags &&
  735. IFILTER_FLAGS_OLE_PROPERTIES != *Configuration.pdwFlags )
  736. {
  737. m_pLog->Log( TLS_TEST | TL_SEV1, L"Init() returned an invalid value for"
  738. L" pdwFlags. Acceptable values are 0 and IFILTER_FLAGS_OLE"
  739. L"_PROPERTIES. Returned value is %d",
  740. *Configuration.pdwFlags );
  741. return( FALSE );
  742. }
  743. else
  744. {
  745. m_pLog->Log( TLS_TEST | TL_PASS, L"Init() returned a valid value for"
  746. L" pdwFlags." );
  747. }
  748. // Set the initialized flag:
  749. m_fIsInitialized = TRUE;
  750. m_pLog->Log( TLS_TEST | TL_INFO, L"Successfully initialized filter." );
  751. return( TRUE );
  752. } //CFiltTest::InitializeFilter
  753. //+---------------------------------------------------------------------------
  754. //
  755. // Member: CFiltTest::ReleaseFilter
  756. //
  757. // Synopsis: Releases the filter
  758. //
  759. // Arguments: (none)
  760. //
  761. // Returns: none
  762. //
  763. // History: 9-19-1996 ericne Created
  764. //
  765. // Notes: This is necessary because Release() lowers the reference count
  766. // on the filter object and allows it to be deleted by the system
  767. //
  768. //----------------------------------------------------------------------------
  769. void CFiltTest::ReleaseFilter()
  770. {
  771. // Turn off the Initialized flag:
  772. m_fIsInitialized = FALSE;
  773. // Release the filter:
  774. if( 0 != m_pIFilter->Release() )
  775. {
  776. m_pLog->Log( TLS_TEST | TL_SEV1, L"The return value of IFilter::Release()"
  777. L" is not zero. This indicates that there is a resource"
  778. L" leak in the filter" );
  779. }
  780. m_pLog->Log( TLS_TEST | TL_INFO, L"Released filter" );
  781. } //CFiltTest::ReleaseFilter
  782. //+---------------------------------------------------------------------------
  783. //
  784. // Member: CFiltTest::LegitimacyTest
  785. //
  786. // Synopsis: Get all the chunks from the object, validate them, add them to
  787. // the list of chunks, and call GetTextFromTextChunk() or
  788. // GetValueFromValueChunk(). This is the "sane" test, intended
  789. // to validate that the ifilter is in minimum working condition.
  790. //
  791. // Arguments: (none)
  792. //
  793. // Returns: none
  794. //
  795. // History: 9-19-1996 ericne Created
  796. //
  797. // Notes:
  798. //
  799. //----------------------------------------------------------------------------
  800. void CFiltTest::LegitimacyTest( )
  801. {
  802. SCODE sc = S_OK;
  803. //STAT_CHUNK OldChunkStats = m_ChunkStatsListHead.ChunkStats;
  804. _ASSERT( m_fIsInitialized );
  805. m_pLog->Log( TLS_TEST | TL_INFO, L"Performing validation test."
  806. L" In this part of the test, the chunks structures returned"
  807. L" by the filter are checked for correctness, and the return"
  808. L" values of the filter calls are checked." );
  809. // Break out of this loop when GetChunk returns FILTER_E_END_OF_CHUNKS
  810. while( 1 )
  811. {
  812. __try
  813. {
  814. sc = m_pIFilter->GetChunk( &m_CurrentChunkStats );
  815. }
  816. __except( EXCEPTION_EXECUTE_HANDLER )
  817. {
  818. m_pLog->Log( TLS_TEST | TL_SEV1, L"Exception 0x%08X occured in"
  819. L" GetChunk(). The filter is bound to %ls Legitimacy"
  820. L" Test is quitting.", GetExceptionCode(),
  821. m_szInputFileName );
  822. return;
  823. }
  824. // Break if we are at the end of the chunks
  825. if( FILTER_E_END_OF_CHUNKS == sc )
  826. break;
  827. if( FILTER_E_EMBEDDING_UNAVAILABLE == sc )
  828. {
  829. m_pLog->Log( TLS_TEST | TL_INFO, L"Encountered an embedding for"
  830. L" which a filter is not available." );
  831. continue;
  832. }
  833. if( FILTER_E_LINK_UNAVAILABLE == sc)
  834. {
  835. m_pLog->Log( TLS_TEST | TL_INFO, L"Encountered a link for which a"
  836. L" filter is not available." );
  837. continue;
  838. }
  839. if( FILTER_E_PASSWORD == sc )
  840. {
  841. m_pLog->Log( TLS_TEST | TL_INFO, L"Access failure: GetChunk()"
  842. L" returned FILTER_E_PASSWORD." );
  843. continue;
  844. }
  845. if( FILTER_E_ACCESS == sc )
  846. {
  847. m_pLog->Log( TLS_TEST | TL_INFO, L"Access failure: GetChunk()"
  848. L" returned FILTER_E_ACCESS." );
  849. break;
  850. }
  851. if( FAILED( sc ) )
  852. {
  853. m_pLog->Log( TLS_TEST | TL_SEV1, L"GetChunk() failed for unknown"
  854. L" reason. The return code is 0x%08x", sc );
  855. return;
  856. }
  857. else
  858. {
  859. m_pLog->Log( TLS_TEST | TL_PASS, L"GetChunk() succeeded." );
  860. }
  861. // Otherwise, we have a valid chunk.
  862. // Validate the chunk statistics
  863. ValidateChunkStats( );
  864. // Set the m_fIsText field:
  865. if( CHUNK_VALUE == m_CurrentChunkStats.flags )
  866. m_fIsText = FALSE;
  867. else
  868. m_fIsText = TRUE;
  869. // Get the text or value from chunk
  870. if( m_fIsText )
  871. GetTextFromTextChunk( );
  872. else
  873. GetValueFromValueChunk( );
  874. // Save the old chunk stats for future comparison
  875. //OldChunkStats = m_CurrentChunkStats;
  876. }
  877. // Last call to GetChunk() should not change m_CurrentChunkStats
  878. //if( OldChunkStats != m_CurrentChunkStats )
  879. //{
  880. // m_pLog->Log( TLS_TEST | TL_WARN, L"Final call to GetChunk() modified"
  881. // L" the STAT_CHUNK structure." );
  882. //}
  883. } //CFiltTest::LegitimacyTest
  884. //+---------------------------------------------------------------------------
  885. //
  886. // Member: CFiltTest::GetTextFromTextChunk
  887. //
  888. // Synopsis: Call GetText() until all the text has been returned. Validate
  889. // all return codes.
  890. //
  891. // Arguments: (none)
  892. //
  893. // Returns:
  894. //
  895. // History: 9-19-1996 ericne Created
  896. //
  897. // Notes:
  898. //
  899. //----------------------------------------------------------------------------
  900. void CFiltTest::GetTextFromTextChunk( )
  901. {
  902. BOOL fNoMoreText = FALSE;
  903. BOOL fIsFirstTime = TRUE;
  904. SCODE sc = S_OK;
  905. ULONG ulBufferCount = BUFFER_SIZE;
  906. _ASSERT( m_fIsText );
  907. _ASSERT( m_fIsInitialized );
  908. // Try-finally block to simplify clean-up
  909. __try
  910. {
  911. if( NULL != m_pDumpFile )
  912. fwprintf( m_pDumpFile, L"\r\n" );
  913. while( 1 )
  914. {
  915. // Reset ulBufferCount
  916. ulBufferCount = BUFFER_SIZE;
  917. __try
  918. {
  919. sc = m_pIFilter->GetText( &ulBufferCount, m_pwcTextBuffer );
  920. }
  921. __except( EXCEPTION_EXECUTE_HANDLER )
  922. {
  923. m_pLog->Log( TLS_TEST | TL_SEV1, L"Calling GetText() on a text"
  924. L" chunk produced exception 0x%08X",
  925. GetExceptionCode() );
  926. LogChunkStats( m_CurrentChunkStats );
  927. __leave;
  928. }
  929. // Break if we have reached the end of the text:
  930. if ( FILTER_E_NO_MORE_TEXT == sc )
  931. {
  932. // If this is the first loop through, display a warning
  933. // if( fIsFirstTime )
  934. // {
  935. // m_pLog->Log( TLS_TEST | TL_WARN, L"First call to GetText()"
  936. // L" on the chunk with chunk id %d returned"
  937. // L" FILTER_E_NO_MORE_TEXT.",
  938. // m_CurrentChunkStats.idChunk );
  939. // }
  940. break;
  941. }
  942. // Set the "first time" flag
  943. fIsFirstTime = FALSE;
  944. // If this evaluates to true, there is a problem:
  945. if( fNoMoreText )
  946. {
  947. m_pLog->Log( TLS_TEST | TL_SEV1, L"Previous call to GetText()"
  948. L" returned FILTER_S_LAST_TEXT. Expected next"
  949. L" call to return FILTER_E_END_OF_TEXT."
  950. L" GetText() returned 0x%08x", sc );
  951. fNoMoreText = FALSE;
  952. }
  953. else
  954. {
  955. // No need to display any message here
  956. }
  957. // Check for failure
  958. if( FAILED( sc ) )
  959. {
  960. m_pLog->Log( TLS_TEST | TL_SEV1, L"Call to GetText() failed for "
  961. L"unknown reason. The return code is 0x%08x", sc );
  962. __leave;
  963. }
  964. else
  965. {
  966. m_pLog->Log( TLS_TEST | TL_PASS, L"Call to GetText() succeeded.");
  967. }
  968. // Make sure ulBufferCount is <= what it was before the call
  969. if( ulBufferCount > BUFFER_SIZE )
  970. {
  971. m_pLog->Log( TLS_TEST | TL_SEV1, L"Called GetText() and checked"
  972. L" value of *pcwcBuffer. Expected: *pcwcBuffer"
  973. L" <= value prior to call. Found: *pcwcBuffer"
  974. L" > value prior to call." );
  975. }
  976. else
  977. {
  978. m_pLog->Log( TLS_TEST | TL_PASS, L"After call to GetText(), *pcwc"
  979. L"Buffer is <= its value prior to the call" );
  980. }
  981. // BUGBUG: Maybe I should save the text in the List for future
  982. // comparison.
  983. // Before dumping the text, make sure it's null-terminated
  984. m_pwcTextBuffer[ ulBufferCount ] = L'\0';
  985. // Dump the text
  986. DisplayText( m_pwcTextBuffer, m_pDumpFile );
  987. // Set the fNoMoreChunks field if necessary.
  988. if( FILTER_S_LAST_TEXT == sc )
  989. {
  990. // Next GetText() call should return FILTER_E_NO_MORE_TEXT
  991. fNoMoreText = TRUE;
  992. }
  993. }
  994. // output some blank lines to keep the dump file looking neat
  995. if( NULL != m_pDumpFile )
  996. fwprintf( m_pDumpFile, L"\r\n\r\n" );
  997. // BUGBUG make sure last call to GetText() didn't change m_pwcTextBuffer
  998. //if( BUFFER_SIZE != ulBufferCount )
  999. //{
  1000. // m_pLog->Log( TLS_TEST | TL_WARN, L"Final call to GetText()"
  1001. // L" modified ulBufferCount." );
  1002. //}
  1003. }
  1004. __finally
  1005. {
  1006. // Make sure no unhandled exceptions occured in the try block
  1007. _ASSERT( ! AbnormalTermination() );
  1008. // Any clean up code goes here
  1009. }
  1010. } //CFiltTest::GetTextFromTextChunk
  1011. //+---------------------------------------------------------------------------
  1012. //
  1013. // Member: CFiltTest::GetValueFromValueChunk
  1014. //
  1015. // Synopsis: Call GetValue on chunk containing a value until all values
  1016. // are returned. There should only be one value. Verify the
  1017. // return codes
  1018. //
  1019. // Arguments: (none)
  1020. //
  1021. // Returns: none
  1022. //
  1023. // History: 9-19-1996 ericne Created
  1024. //
  1025. // Notes:
  1026. //
  1027. //----------------------------------------------------------------------------
  1028. void CFiltTest::GetValueFromValueChunk( )
  1029. {
  1030. int iNbrChars = 0;
  1031. SCODE sc = S_OK;
  1032. DWORD dwByteCount = 0;
  1033. PROPVARIANT *pPropValue = NULL;
  1034. // Only in the debug version
  1035. _ASSERT( ! m_fIsText );
  1036. _ASSERT( m_fIsInitialized );
  1037. // Try-finally block to simplify clean-up
  1038. __try
  1039. {
  1040. // First call to GetValue should not return FILTER_E_NO_MORE_VALUES
  1041. __try
  1042. {
  1043. sc = m_pIFilter->GetValue( &pPropValue );
  1044. }
  1045. __except( EXCEPTION_EXECUTE_HANDLER )
  1046. {
  1047. m_pLog->Log( TLS_TEST | TL_SEV1, L"Exception 0x%08X occured in"
  1048. L" GetValue()", GetExceptionCode() );
  1049. __leave;
  1050. }
  1051. if( FILTER_E_NO_MORE_VALUES == sc )
  1052. {
  1053. m_pLog->Log( TLS_TEST | TL_WARN, L"First call to GetValue() returned"
  1054. L" FILTER_E_NO_MORE_VALUES." );
  1055. __leave;
  1056. }
  1057. // Check for a failure
  1058. if( FAILED( sc ) )
  1059. {
  1060. m_pLog->Log( TLS_TEST | TL_SEV1, L"GetValue() failed for unknown"
  1061. L" reason Return value is 0x%08x", sc );
  1062. __leave;
  1063. }
  1064. else
  1065. {
  1066. m_pLog->Log( TLS_TEST | TL_PASS, L"GetValue() succeeded" );
  1067. }
  1068. // Make sure we have a PROPSPEC structure
  1069. if( NULL == pPropValue )
  1070. {
  1071. m_pLog->Log( TLS_TEST | TL_SEV1, L"GetValue() misbehaved by not"
  1072. L" returning a valid PROPVARIANT structure." );
  1073. LogChunkStats( m_CurrentChunkStats );
  1074. __leave;
  1075. }
  1076. else
  1077. {
  1078. m_pLog->Log( TLS_TEST | TL_PASS, L"GetValue() returned a valid "
  1079. L"PROPVARIANT" );
  1080. }
  1081. // BUGBUG Think about storing the property for later validation
  1082. DisplayValue( pPropValue, m_pDumpFile );
  1083. } // __try
  1084. __finally
  1085. {
  1086. // Make sure no unhandled exception occured
  1087. _ASSERT( ! AbnormalTermination() );
  1088. // Free the memory allocated by GetValue()
  1089. if( pPropValue )
  1090. FreePropVariant( pPropValue );
  1091. }
  1092. } //CFiltTest::GetValueFromValueChunk
  1093. //+---------------------------------------------------------------------------
  1094. //
  1095. // Member: CFiltTest::ConsistencyTest
  1096. //
  1097. // Synopsis: Called by ExecuteTests() after reinitializing the filter.
  1098. // Call GetChunk() and make sure the STAT_CHUNK's returned
  1099. // are exactly equal to those stored in the list. This function
  1100. // should be called only after the validation test has completed.
  1101. //
  1102. // Arguments: (none)
  1103. //
  1104. // Returns: none
  1105. //
  1106. // History: 9-19-1996 ericne Created
  1107. //
  1108. // Notes:
  1109. //
  1110. //----------------------------------------------------------------------------
  1111. void CFiltTest::ConsistencyTest( )
  1112. {
  1113. // This function is called after the filter has been reinitialized.
  1114. // It runs through the entire document and checks that the chunks
  1115. // returned are identical to those returned previously.
  1116. SCODE sc = S_OK;
  1117. CListNode *CurrentListNode = m_ChunkStatsListHead.next;
  1118. // Only in debug version
  1119. _ASSERT( m_fIsInitialized );
  1120. m_pLog->Log( TLS_TEST | TL_INFO, L"Performing consistency test."
  1121. L" The filter has been reinitialized and the test will now"
  1122. L" validate that the chunks emitted are the same as those"
  1123. L" that were emitted previously, including Chunk ID's." );
  1124. // Break out of this loop when GetChunk() returns FILTER_E_END_OF_CHUNKS
  1125. while( 1 )
  1126. {
  1127. // Try to get a chunk
  1128. __try
  1129. {
  1130. sc = m_pIFilter->GetChunk( &m_CurrentChunkStats );
  1131. }
  1132. __except( EXCEPTION_EXECUTE_HANDLER )
  1133. {
  1134. m_pLog->Log( TLS_TEST | TL_SEV1, L"Exception 0x%08X occured in"
  1135. L" GetChunk(). Consistency Test is quitting.",
  1136. GetExceptionCode() );
  1137. return;
  1138. }
  1139. // Break if sc is FILTER_E_END_OF_CHUNKS
  1140. if( FILTER_E_END_OF_CHUNKS == sc )
  1141. break;
  1142. if( FILTER_E_EMBEDDING_UNAVAILABLE == sc )
  1143. continue;
  1144. if( FILTER_E_LINK_UNAVAILABLE == sc)
  1145. continue;
  1146. if( FILTER_E_PASSWORD == sc )
  1147. continue;
  1148. if( FILTER_E_ACCESS == sc )
  1149. break;
  1150. if( FAILED( sc ) )
  1151. {
  1152. m_pLog->Log( TLS_TEST | TL_SEV1, L"GetChunk() failed for unknown"
  1153. L" reason. The return code is 0x%08x", sc );
  1154. return;
  1155. }
  1156. else
  1157. {
  1158. m_pLog->Log( TLS_TEST | TL_PASS, L"GetChunk() succeeded after "
  1159. L"reinitialization" );
  1160. }
  1161. // Otherwise, we have a valid chunk.
  1162. // See if we have more nodes in the list to compare to:
  1163. if( NULL == CurrentListNode )
  1164. {
  1165. m_pLog->Log( TLS_TEST | TL_SEV1, L"Upon reinitialization of the"
  1166. L" filter, an extra chunk has been emitted that was"
  1167. L" not emitted previously." );
  1168. m_pLog->Log( TLS_TEST | TL_INFO, L"Chunk structure found:" );
  1169. LogChunkStats( m_CurrentChunkStats );
  1170. continue;
  1171. }
  1172. else
  1173. {
  1174. // No message needs to be displayed here
  1175. }
  1176. // Make sure the Current chunk statistics are the same as those
  1177. // in the list. Here I am using the != operator overloaded for
  1178. // CStatChunk
  1179. if( CurrentListNode->ChunkStats != m_CurrentChunkStats )
  1180. {
  1181. m_pLog->Log( TLS_TEST | TL_SEV1, L"Upon reinitialization of the"
  1182. L" filter, a chunk has been emitted that does not"
  1183. L" exactly match the corresponding chunk emitted"
  1184. L" previously." );
  1185. m_pLog->Log( TLS_TEST | TL_INFO, L"Chunk structure expected:" );
  1186. LogChunkStats( CurrentListNode->ChunkStats );
  1187. m_pLog->Log( TLS_TEST | TL_INFO, L"Chunk structure found:" );
  1188. LogChunkStats( m_CurrentChunkStats );
  1189. }
  1190. else
  1191. {
  1192. m_pLog->Log( TLS_TEST | TL_PASS, L"Upon reinitialization of the"
  1193. L" filter, the chunk structure returned exactly matches"
  1194. L" the chunk structure returned earlier." );
  1195. }
  1196. // Advance the CurrentListNode pointer
  1197. CurrentListNode = CurrentListNode->next;
  1198. }
  1199. // BUGBUG Final call to GetChunk should not change m_CurrentChunkStats
  1200. // No more chunks will be emitted.
  1201. // Make sure we are at the end of of the list:
  1202. if( NULL != CurrentListNode )
  1203. {
  1204. m_pLog->Log( TLS_TEST | TL_SEV1, L"Upon reinitialization of the filter,"
  1205. L" fewer chunks were emitted than were emitted"
  1206. L" previously." );
  1207. while( NULL != CurrentListNode )
  1208. {
  1209. m_pLog->Log( TLS_TEST | TL_INFO, L"Chunk structure expected:" );
  1210. LogChunkStats( CurrentListNode->ChunkStats );
  1211. CurrentListNode = CurrentListNode->next;
  1212. }
  1213. }
  1214. else
  1215. {
  1216. m_pLog->Log( TLS_TEST | TL_PASS, L"Upon reinitialization of the filter,"
  1217. L" the same number of chunks were emitted than were"
  1218. L" emmitted previously." );
  1219. }
  1220. } //CFiltTest::ConsistencyTest
  1221. //+---------------------------------------------------------------------------
  1222. //
  1223. // Member: CFiltTest::IllegitimacyTest
  1224. //
  1225. // Synopsis: Called from ExecuteTests() after reinitializing the filter.
  1226. // Call GetChunk(), validate the chunk structures again, then
  1227. // call GetTextfromValueChunk() and GetValueFromTextChunk() to
  1228. // make sure the filter is well-behaved.
  1229. //
  1230. // Arguments: (none)
  1231. //
  1232. // Returns: none
  1233. //
  1234. // History: 9-19-1996 ericne Created
  1235. //
  1236. // Notes:
  1237. //
  1238. //----------------------------------------------------------------------------
  1239. void CFiltTest::IllegitimacyTest( )
  1240. {
  1241. // This function does unexpected things to the filter and checks
  1242. // return codes for compliance with the IFilter spec.
  1243. SCODE sc = S_OK;
  1244. CListNode *CurrentListNode = m_ChunkStatsListHead.next;
  1245. // Debug version only
  1246. _ASSERT( m_fIsInitialized );
  1247. m_pLog->Log( TLS_TEST | TL_INFO, L"Performing the invalid input test."
  1248. L" The filter has been reinitialized and the test will now"
  1249. L" make inappropriate IFilter method calls and verify the"
  1250. L" return codes. In addition, it will double-check the"
  1251. L" chunk structures returned by GetChunk()." );
  1252. // Break out of this loop when GetChunk() returns FILTER_E_END_OF_CHUNKS
  1253. while( 1 )
  1254. {
  1255. // Try to get a chunk
  1256. __try
  1257. {
  1258. sc = m_pIFilter->GetChunk( &m_CurrentChunkStats );
  1259. }
  1260. __except( EXCEPTION_EXECUTE_HANDLER )
  1261. {
  1262. m_pLog->Log( TLS_TEST | TL_SEV1, L"Exception 0x%08X occured in"
  1263. L" GetChunk(). Invalid Input Test is quitting.",
  1264. GetExceptionCode() );
  1265. return;
  1266. }
  1267. // Break if sc is FILTER_E_END_OF_CHUNKS
  1268. if( FILTER_E_END_OF_CHUNKS == sc )
  1269. break;
  1270. if( FILTER_E_EMBEDDING_UNAVAILABLE == sc )
  1271. continue;
  1272. if( FILTER_E_LINK_UNAVAILABLE == sc)
  1273. continue;
  1274. if( FILTER_E_PASSWORD == sc )
  1275. continue;
  1276. if( FILTER_E_ACCESS == sc )
  1277. break;
  1278. if( FAILED( sc ) )
  1279. {
  1280. m_pLog->Log( TLS_TEST | TL_SEV1, L"GetChunk() failed for unknown"
  1281. L" reason. The return code is 0x%08x", sc );
  1282. return;
  1283. }
  1284. else
  1285. {
  1286. m_pLog->Log( TLS_TEST | TL_PASS, L"Upon reinitilization of the"
  1287. L" filter,GetChunk() succeeded." );
  1288. }
  1289. // Otherwise, we have a valid chunk.
  1290. // See if we have more nodes in the list to compare to:
  1291. if( NULL == CurrentListNode )
  1292. {
  1293. m_pLog->Log( TLS_TEST | TL_SEV1, L"Upon reinitialization of the"
  1294. L" filter, an extra chunk has been emitted that was"
  1295. L" not emitted previously." );
  1296. m_pLog->Log( TLS_TEST | TL_INFO, L"Chunk structure found:" );
  1297. LogChunkStats( m_CurrentChunkStats );
  1298. continue;
  1299. }
  1300. else
  1301. {
  1302. // No message needs to be displayed here
  1303. }
  1304. // Make sure the Current chunk statistics are the same as those
  1305. // in the list. Here I am using the != operator overloaded for
  1306. // CStatChunk
  1307. if( CurrentListNode->ChunkStats != m_CurrentChunkStats )
  1308. {
  1309. m_pLog->Log( TLS_TEST | TL_SEV1, L"Upon reinitialization of the filt"
  1310. L"er, a chunk has been emitted that does not exactly"
  1311. L" match the corresponding chunk emitted previously." );
  1312. m_pLog->Log( TLS_TEST | TL_INFO, L"Chunk structure expected:" );
  1313. LogChunkStats( CurrentListNode->ChunkStats );
  1314. m_pLog->Log( TLS_TEST | TL_INFO, L"Chunk structure found:" );
  1315. LogChunkStats( m_CurrentChunkStats );
  1316. }
  1317. else
  1318. {
  1319. m_pLog->Log( TLS_TEST | TL_PASS, L"Upon reinitilization of the filter"
  1320. L", the chunk structure returned by GetChunk() exactly"
  1321. L" matches the chunk structure returned earlier." );
  1322. }
  1323. // Advance the CurrentListNode pointer
  1324. CurrentListNode = CurrentListNode->next;
  1325. // See if we have text or a property
  1326. if( CHUNK_VALUE == m_CurrentChunkStats.flags )
  1327. m_fIsText = FALSE;
  1328. else
  1329. m_fIsText = TRUE;
  1330. // Call the appropriate functions:
  1331. if( m_fIsText )
  1332. GetValueFromTextChunk( );
  1333. else
  1334. GetTextFromValueChunk( );
  1335. }
  1336. // BUGBUG Final call to GetChunk should not change m_CurrentChunkStats
  1337. // No more chunks will be emitted.
  1338. // Make sure we are at the end of of the list:
  1339. if( NULL != CurrentListNode )
  1340. {
  1341. m_pLog->Log( TLS_TEST | TL_SEV1, L"Upon reinitialization of the filter,"
  1342. L" fewer chunks were emitted than were emitted previously.");
  1343. while( NULL != CurrentListNode )
  1344. {
  1345. m_pLog->Log( TLS_TEST | TL_INFO, L"Chunk structure expected:" );
  1346. LogChunkStats( CurrentListNode->ChunkStats );
  1347. CurrentListNode = CurrentListNode->next;
  1348. }
  1349. }
  1350. else
  1351. {
  1352. m_pLog->Log( TLS_TEST | TL_PASS, L"Upon reinitialization of the filter,"
  1353. L" the same number of chunks were emitted as were emitted"
  1354. L" previously." );
  1355. }
  1356. // Make another call to GetChunk() to make sure it still returns
  1357. // FILTER_E_END_OF_CHUNKS
  1358. __try
  1359. {
  1360. sc = m_pIFilter->GetChunk( &m_CurrentChunkStats );
  1361. }
  1362. __except( EXCEPTION_EXECUTE_HANDLER )
  1363. {
  1364. m_pLog->Log( TLS_TEST | TL_SEV1, L"Exception 0x%08X occured in GetChunk()"
  1365. L" Consistency Test is quitting.", GetExceptionCode() );
  1366. return;
  1367. }
  1368. if( FILTER_E_END_OF_CHUNKS != sc )
  1369. {
  1370. m_pLog->Log( TLS_TEST | TL_SEV1, L"Called GetChunk() one extra time"
  1371. L" after end of chunks. Expected FILTER_E_END_OF_CHUNKS."
  1372. L" Return code is 0x%08x", sc );
  1373. }
  1374. else
  1375. {
  1376. m_pLog->Log( TLS_TEST | TL_PASS, L"Calling GetChunk() after end of"
  1377. L" chunks returned FILTER_E_END_OF_CHUNKS." );
  1378. }
  1379. // BUGBUG Final call to GetChunk should not change m_CurrentChunkStats
  1380. } //CFiltTest::IllegitimacyTest
  1381. //+---------------------------------------------------------------------------
  1382. //
  1383. // Member: CFiltTest::GetValueFromTextChunk
  1384. //
  1385. // Synopsis: Called from IllegitimacyTest() to see if anything unexpected
  1386. // happens when we try to get a value from a chunk that contains
  1387. // text.
  1388. //
  1389. // Arguments: (none)
  1390. //
  1391. // Returns:
  1392. //
  1393. // History: 9-19-1996 ericne Created
  1394. //
  1395. // Notes:
  1396. //
  1397. //----------------------------------------------------------------------------
  1398. void CFiltTest::GetValueFromTextChunk( )
  1399. {
  1400. // This function is used by the illegitimacy function to verify
  1401. // that unexpected things don't happen when GetValue() is called
  1402. // on a chunk containing text
  1403. BOOL fIsFirstTime = FALSE;
  1404. SCODE sc = S_OK;
  1405. ULONG ulBufferCount = BUFFER_SIZE;
  1406. PROPVARIANT *pPropValue = NULL;
  1407. // Debug version only
  1408. _ASSERT( m_fIsText );
  1409. _ASSERT( m_fIsInitialized );
  1410. // try-finally block to simplify clean-up
  1411. __try
  1412. {
  1413. // Try to get a value
  1414. __try
  1415. {
  1416. sc = m_pIFilter->GetValue( &pPropValue );
  1417. }
  1418. __except( EXCEPTION_EXECUTE_HANDLER )
  1419. {
  1420. m_pLog->Log( TLS_TEST | TL_SEV1, L"Exception 0x%08X occured in"
  1421. L" GetValue().", GetExceptionCode() );
  1422. __leave;
  1423. }
  1424. // Make sure we got the correct return code
  1425. if( FILTER_E_NO_VALUES != sc )
  1426. {
  1427. m_pLog->Log( TLS_TEST | TL_SEV1, L"Called GetValue() on a text"
  1428. L" chunk. Expected FILTER_E_NO_VALUES to be returned."
  1429. L" Return value is 0x%08x", sc );
  1430. LogChunkStats( m_CurrentChunkStats );
  1431. }
  1432. else
  1433. {
  1434. m_pLog->Log( TLS_TEST | TL_PASS, L"GetValue() on a text chunk"
  1435. L" returned FILTER_E_NO_VALUES." );
  1436. }
  1437. // Make sure a PROPVARIANT was not allocated
  1438. if( pPropValue )
  1439. {
  1440. m_pLog->Log( TLS_TEST | TL_SEV1, L"Called GetValue() on a text chunk."
  1441. L" GetValue() erroneously allocated a PROPVARIANT." );
  1442. LogChunkStats( m_CurrentChunkStats );
  1443. FreePropVariant( pPropValue );
  1444. pPropValue = NULL;
  1445. }
  1446. else
  1447. {
  1448. m_pLog->Log( TLS_TEST | TL_PASS, L"GetValue() on a text chunk did"
  1449. L" not allocate a PROPVARIANT." );
  1450. }
  1451. // Make sure calls to GetText() will now succeed
  1452. // Break when GetText() returns FILTER_E_NO_MORE_TEXT
  1453. while( 1 )
  1454. {
  1455. // Reset ulBufferCount
  1456. ulBufferCount = BUFFER_SIZE;
  1457. // First call to GetText() should not return FILTER_E_NO_MORE_TEXT
  1458. __try
  1459. {
  1460. sc = m_pIFilter->GetText( &ulBufferCount, m_pwcTextBuffer );
  1461. }
  1462. __except( EXCEPTION_EXECUTE_HANDLER )
  1463. {
  1464. m_pLog->Log( TLS_TEST | TL_SEV1, L"After calling GetValue() on"
  1465. L" a text chunk, a call to GetText() produced"
  1466. L" exception 0x%08X", GetExceptionCode() );
  1467. __leave;
  1468. }
  1469. // If no more text, break
  1470. if( FILTER_E_NO_MORE_TEXT == sc )
  1471. {
  1472. // If this is the first time through loop, display warning
  1473. // if( fIsFirstTime )
  1474. // {
  1475. // m_pLog->Log( TLS_TEST | TL_WARN, L"First call to GetText()"
  1476. // L" after calling GetValue() on a text chunk"
  1477. // L" returned FILTER_E_NO_MORE_TEXT." );
  1478. // }
  1479. break;
  1480. }
  1481. // Set the "fisrt time" flag
  1482. fIsFirstTime = FALSE;
  1483. // See if the call failed
  1484. if( FAILED( sc ) )
  1485. {
  1486. m_pLog->Log( TLS_TEST | TL_SEV1, L"After calling GetValue() on a"
  1487. L" text chunk, the call to GetText() failed."
  1488. L" The return value is 0x%08x", sc );
  1489. __leave;
  1490. }
  1491. else
  1492. {
  1493. m_pLog->Log( TLS_TEST | TL_PASS, L"After calling GetValue() on a"
  1494. L" text chunk, the call to GetText() succeeded." );
  1495. }
  1496. // Make sure ulBufferCount is <= what it was before the call
  1497. if( ulBufferCount > BUFFER_SIZE )
  1498. {
  1499. m_pLog->Log( TLS_TEST | TL_SEV1, L"After calling GetValue() on a"
  1500. L" text chunk, I called GetText() and checked the"
  1501. L" value of *pcwcBuffer. Expected: *pcwcBuffer <="
  1502. L" value prior to call. Found: *pcwcBuffer > value"
  1503. L" prior to call." );
  1504. }
  1505. else
  1506. {
  1507. m_pLog->Log( TLS_TEST | TL_PASS, L"After call to GetText(), *pcwc"
  1508. L"Buffer is <= its value prior to the call" );
  1509. }
  1510. }
  1511. // BUGBUG Check to make sure the last call to GetText() didn't change
  1512. // ulBufferCount or m_pwcTextBuffer
  1513. // Call GetText() one more time to make sure it does the right thing
  1514. __try
  1515. {
  1516. sc = m_pIFilter->GetText( &ulBufferCount, m_pwcTextBuffer );
  1517. }
  1518. __except( EXCEPTION_EXECUTE_HANDLER )
  1519. {
  1520. m_pLog->Log( TLS_TEST | TL_SEV1, L"Calling GetText() after it"
  1521. L" returned FILTER_E_NO_MORE_TEXT resulted in"
  1522. L" exception 0x%08X", GetExceptionCode() );
  1523. __leave;
  1524. }
  1525. if( FILTER_E_NO_MORE_TEXT == sc )
  1526. {
  1527. m_pLog->Log( TLS_TEST | TL_PASS, L"After GetText() returned"
  1528. L" FILTER_E_NO_MORE_TEXT, another call to GetText()"
  1529. L" still returned FILTER_E_NO_MORE_TEXT." );
  1530. }
  1531. else if( E_INVALIDARG == sc )
  1532. {
  1533. m_pLog->Log( TLS_TEST | TL_PASS, L"After GetText() returned"
  1534. L" FILTER_E_NO_MORE_TEXT, another call to GetText()"
  1535. L" returned E_INVALIDARG", sc );
  1536. }
  1537. else
  1538. {
  1539. m_pLog->Log( TLS_TEST | TL_SEV1, L"After GetText() returned"
  1540. L" FILTER_E_NO_MORE_TEXT, another call to GetText()"
  1541. L" returned 0x%08x", sc );
  1542. }
  1543. // BUGBUG Check to make sure the last call to GetText() didn't change
  1544. // ulBufferCount or m_pwcTextBuffer
  1545. }
  1546. __finally
  1547. {
  1548. // Make sure there were no unhandled exceptions in the try block.
  1549. _ASSERT( ! AbnormalTermination() );
  1550. // Clean up the heap
  1551. if( pPropValue )
  1552. FreePropVariant( pPropValue );
  1553. }
  1554. } //CFiltTest::GetValueFromTextChunk
  1555. //+---------------------------------------------------------------------------
  1556. //
  1557. // Member: CFiltTest::GetTextFromValueChunk
  1558. //
  1559. // Synopsis: Called from IllegitimacyTest() to see if anything unexpected
  1560. // happens when we try to get text from a chunk that contains a
  1561. // value.
  1562. //
  1563. // Arguments: (none)
  1564. //
  1565. // Returns:
  1566. //
  1567. // History: 9-19-1996 ericne Created
  1568. //
  1569. // Notes:
  1570. //
  1571. //----------------------------------------------------------------------------
  1572. void CFiltTest::GetTextFromValueChunk( )
  1573. {
  1574. // This function is used by the illegitimacy test to verify
  1575. // that unexpected behavior does not occur when GetText is called
  1576. // on a chunk that contains a value
  1577. SCODE sc = S_OK;
  1578. WCHAR *pwcTempBuffer = NULL;
  1579. ULONG ulBufferCount = BUFFER_SIZE;
  1580. PROPVARIANT *pPropValue = NULL;
  1581. // Debug version only
  1582. _ASSERT( ! m_fIsText );
  1583. _ASSERT( m_fIsInitialized );
  1584. // Try-finally block to simplify clean-up
  1585. __try
  1586. {
  1587. // Allocate space for the temp buffer
  1588. pwcTempBuffer = NEW WCHAR[ BUFFER_SIZE ];
  1589. // Fill the temp buffer with a known garbage value
  1590. memset( (void*) pwcTempBuffer, (int)0xCC, BUFFER_SIZE * sizeof(WCHAR) );
  1591. // Copy the contents of the temp buffer into the TextBuffer
  1592. memcpy( (void*) m_pwcTextBuffer, (void*) pwcTempBuffer,
  1593. BUFFER_SIZE * sizeof(WCHAR) );
  1594. // Call GetText on the value chunk
  1595. __try
  1596. {
  1597. sc = m_pIFilter->GetText( &ulBufferCount, m_pwcTextBuffer );
  1598. }
  1599. __except( EXCEPTION_EXECUTE_HANDLER )
  1600. {
  1601. m_pLog->Log( TLS_TEST | TL_SEV1, L"Called GetText() on a chunk"
  1602. L" containing a value. Exception 0x%08X occured in"
  1603. L" GetText().", GetExceptionCode() );
  1604. __leave;
  1605. }
  1606. // Make sure we got the correct return value
  1607. if( FILTER_E_NO_TEXT != sc )
  1608. {
  1609. m_pLog->Log( TLS_TEST | TL_SEV1, L"Called GetText() on a value"
  1610. L" chunk. Expected FILTER_E_NO_TEXT to be returned."
  1611. L" Return value is 0x%08x", sc );
  1612. LogChunkStats( m_CurrentChunkStats );
  1613. }
  1614. else
  1615. {
  1616. m_pLog->Log( TLS_TEST | TL_PASS, L"Called GetText() on a value"
  1617. L" chunk. FILTER_E_NO_TEXT was returned." );
  1618. }
  1619. // Make sure ulBufferCount was not modified
  1620. if( BUFFER_SIZE != ulBufferCount )
  1621. {
  1622. m_pLog->Log( TLS_TEST | TL_WARN, L"Called GetText() on a chunk"
  1623. L" containing a value. GetText() erroneously"
  1624. L" modified pcwcBuffer." );
  1625. }
  1626. // Make sure the Buffer was not modified
  1627. if( 0 != memcmp( (void*) m_pwcTextBuffer, (void*) pwcTempBuffer,
  1628. BUFFER_SIZE * sizeof(WCHAR) ) )
  1629. {
  1630. m_pLog->Log( TLS_TEST | TL_WARN, L"Called GetText() on a chunk"
  1631. L" containing a value. GetText() erroneously"
  1632. L" modified awcBuffer." );
  1633. }
  1634. // Try to get a value
  1635. __try
  1636. {
  1637. sc = m_pIFilter->GetValue( &pPropValue );
  1638. }
  1639. __except( EXCEPTION_EXECUTE_HANDLER )
  1640. {
  1641. m_pLog->Log( TLS_TEST | TL_SEV1, L"After calling GetText() on a"
  1642. L" chunk containing a value, a call to GetValue()"
  1643. L" procuced exception 0x%08X", GetExceptionCode() );
  1644. __leave;
  1645. }
  1646. // First call to GetValue() should not return FILTER_E_NO_MORE_VALUES
  1647. if( FILTER_E_NO_MORE_VALUES == sc )
  1648. {
  1649. m_pLog->Log( TLS_TEST | TL_WARN, L"First call to GetValue() after"
  1650. L" calling GetText() on a value chunk returned"
  1651. L" FILTER_E_NO_MORE_VALUES." );
  1652. __leave;
  1653. }
  1654. // The call should have succeeded
  1655. if( FAILED( sc ) )
  1656. {
  1657. m_pLog->Log( TLS_TEST | TL_SEV1, L"After calling GetText() on a chunk"
  1658. L" containing a value, a call to GetValue() failed."
  1659. L" The return code is 0x%08x", sc );
  1660. __leave;
  1661. }
  1662. else
  1663. {
  1664. m_pLog->Log( TLS_TEST | TL_PASS, L"After calling GetText() on a chunk"
  1665. L" containing a value, calling GetValue() succeeded." );
  1666. }
  1667. // Make sure we have a valid PROPVARIANT
  1668. if( NULL == pPropValue )
  1669. {
  1670. m_pLog->Log( TLS_TEST | TL_SEV1, L"After calling GetText() on a chunk"
  1671. L" containing a value, GetValue() failed to allocate"
  1672. L" a PROPVARIANT." );
  1673. }
  1674. else
  1675. {
  1676. m_pLog->Log( TLS_TEST | TL_PASS, L"After calling GetText() on a chunk"
  1677. L" containing a value, GetValue() successfully"
  1678. L" allocated a PROPVARIANT." );
  1679. // free the memory, since we will be calling GetValue again
  1680. FreePropVariant( pPropValue );
  1681. pPropValue = NULL;
  1682. }
  1683. // Another call to GetValue() should return FILTER_E_NO_MORE_VALUES
  1684. __try
  1685. {
  1686. sc = m_pIFilter->GetValue( &pPropValue );
  1687. }
  1688. __except( EXCEPTION_EXECUTE_HANDLER )
  1689. {
  1690. m_pLog->Log( TLS_TEST | TL_SEV1, L"I called GetText() on a value"
  1691. L" chunk. I then called GetValue() twice. The second"
  1692. L" call produced exception 0x%08X", GetExceptionCode() );
  1693. __leave;
  1694. }
  1695. if( FILTER_E_NO_MORE_VALUES != sc )
  1696. {
  1697. m_pLog->Log( TLS_TEST | TL_WARN, L"I called GetText() on a value"
  1698. L" chunk. Then, I called GetValue() twice, expecting"
  1699. L" FILTER_E_NO_MORE_VALUES. GetValue() returned 0x%08x",
  1700. sc );
  1701. }
  1702. // Check that GetValue() did not allocate a pPropValue
  1703. if( pPropValue )
  1704. {
  1705. m_pLog->Log( TLS_TEST | TL_WARN, L"I called GetText() on a value"
  1706. L" chunk. Then, I called GetValue() twice, expecting"
  1707. L" FILTER_E_NO_MORE_VALUES. In the second call, a"
  1708. L" PROPVARIANT was erroneously allocated." );
  1709. FreePropVariant( pPropValue );
  1710. pPropValue = NULL;
  1711. }
  1712. } // try
  1713. __finally
  1714. {
  1715. // Make sure no unhandled exceptions occured in the try block
  1716. _ASSERT( ! AbnormalTermination() );
  1717. // Clean up the heap
  1718. if( pPropValue )
  1719. FreePropVariant( pPropValue );
  1720. if( pwcTempBuffer )
  1721. delete [] pwcTempBuffer;
  1722. }
  1723. } //CFiltTest::GetTextFromValueChunk
  1724. //+---------------------------------------------------------------------------
  1725. //
  1726. // Member: CFiltTest::LogConfiguration
  1727. //
  1728. // Synopsis: Displays the configuration to pFileStream in ANSI
  1729. //
  1730. // Arguments: [config] -- the configuration to be displayed
  1731. // [pFileStream] - FILE* to which the output is directed
  1732. //
  1733. // Returns: none
  1734. //
  1735. // History: 9-25-1996 ericne Created
  1736. //
  1737. // Notes:
  1738. //
  1739. //----------------------------------------------------------------------------
  1740. void CFiltTest::LogConfiguration( const CONFIG & config )
  1741. {
  1742. TCHAR szGuidBuffer[ GuidBufferSize ];
  1743. UINT uiLoop = 0;
  1744. m_pLog->Log( TLS_TEST | TL_INFO, L"Section name : %s", config.szSectionName);
  1745. // display grfFlags
  1746. m_pLog->Log( TLS_TEST | TL_INFO, L"grfFlags : %d", config.grfFlags );
  1747. // display the attribute count
  1748. m_pLog->Log( TLS_TEST | TL_INFO, L"cAttributes : %d", config.cAttributes );
  1749. // If there are no atributes, say so
  1750. if( 0 == config.ulActNbrAttributes )
  1751. {
  1752. m_pLog->Log( TLS_TEST | TL_INFO, L"aAttributes : NONE" );
  1753. }
  1754. // Otherwise, display all the attributes
  1755. for( uiLoop = 0; uiLoop < config.ulActNbrAttributes; uiLoop++ )
  1756. {
  1757. m_pLog->Log( TLS_TEST | TL_INFO, L"Attribute %d:", uiLoop + 1 );
  1758. GetStringFromCLSID( config.aAttributes[ uiLoop ].guidPropSet,
  1759. szGuidBuffer, GuidBufferSize );
  1760. m_pLog->Log( TLS_TEST | TL_INFO, L"\tGUID : %s", szGuidBuffer );
  1761. if( PRSPEC_PROPID == config.aAttributes[ uiLoop ].psProperty.ulKind )
  1762. {
  1763. m_pLog->Log( TLS_TEST | TL_INFO, L"\tPROPID : 0x%08x",
  1764. config.aAttributes[ uiLoop ].psProperty.propid );
  1765. }
  1766. else
  1767. {
  1768. // Display the lpwstr
  1769. m_pLog->Log( TLS_TEST | TL_INFO, L"\tLPWSTR : %ls",
  1770. config.aAttributes[ uiLoop ].psProperty.lpwstr );
  1771. }
  1772. }
  1773. // display pdwFlags
  1774. m_pLog->Log( TLS_TEST | TL_INFO, L"pdwFlags : %d", *config.pdwFlags );
  1775. } //CFiltTest::LogConfiguration
  1776. //+---------------------------------------------------------------------------
  1777. //
  1778. // Member: CFiltTest::DisplayChunkStats
  1779. //
  1780. // Synopsis: Displays the structure of the chunk passed in ChunkStats
  1781. //
  1782. // Arguments: [ChunkStats] -- STAT_CHUNK containing the information for
  1783. // the chunk to be displayed.
  1784. // [pFileStream] - FILE* to which the output is directed
  1785. //
  1786. // Returns: none
  1787. //
  1788. // History: 9-19-1996 ericne Created
  1789. //
  1790. // Notes:
  1791. //
  1792. //----------------------------------------------------------------------------
  1793. void CFiltTest::DisplayChunkStats( const STAT_CHUNK &ChunkStats,
  1794. FILE * pFileStream )
  1795. {
  1796. TCHAR szGuidBuffer[ GuidBufferSize ];
  1797. // Only print the chunk state if the verbosity is HIGH
  1798. if( HIGH > m_verbosity || NULL == pFileStream )
  1799. return;
  1800. // Insert a blank line
  1801. fwprintf( pFileStream, L"\r\nChunk statistics:\r\n" );
  1802. // Print the chunk id
  1803. fwprintf( pFileStream, L"Chunk ID: ........... %d\r\n", ChunkStats.idChunk);
  1804. // Print the break type (in English if possible)
  1805. if( CHUNK_NO_BREAK > ChunkStats.breakType ||
  1806. CHUNK_EOC < ChunkStats.breakType ) // not legal
  1807. {
  1808. fwprintf( pFileStream, L"Illegal Break Type: . %d\r\n",
  1809. ChunkStats.breakType );
  1810. }
  1811. else
  1812. {
  1813. fwprintf( pFileStream, L"Chunk Break Type: ... %ls\r\n",
  1814. BreakType[ ChunkStats.breakType ] );
  1815. }
  1816. // Print the Chunk state (in English if possible)
  1817. if( CHUNK_TEXT == ChunkStats.flags || CHUNK_VALUE == ChunkStats.flags)
  1818. {
  1819. fwprintf( pFileStream, L"Chunk State: ........ %ls\r\n",
  1820. ChunkState[ ChunkStats.flags - 1 ] );
  1821. }
  1822. else
  1823. {
  1824. fwprintf( pFileStream, L"Bad Chunk State: .... %d\r\n",
  1825. ChunkStats.flags );
  1826. }
  1827. // Print the locale
  1828. fwprintf( pFileStream, L"Chunk Locale: ....... 0x%08x\r\n",
  1829. ChunkStats.locale );
  1830. // Print the Chunk id source
  1831. fwprintf( pFileStream, L"Chunk Source ID: .... %d\r\n",
  1832. ChunkStats.idChunkSource );
  1833. // Print the start source
  1834. fwprintf( pFileStream, L"Chunk Start Source .. 0x%08x\r\n",
  1835. ChunkStats.cwcStartSource );
  1836. // Print the length source
  1837. fwprintf( pFileStream, L"Chunk Length Source . 0x%08x\r\n",
  1838. ChunkStats.cwcLenSource );
  1839. // Display the guid
  1840. GetStringFromCLSID( ChunkStats.attribute.guidPropSet, szGuidBuffer,
  1841. GuidBufferSize );
  1842. _ftprintf( pFileStream, _T("GUID ................ %s\r\n"), szGuidBuffer );
  1843. // Display the contents of the PROPSPEC field (careful of the union)
  1844. if( PRSPEC_LPWSTR == ChunkStats.attribute.psProperty.ulKind )
  1845. {
  1846. fwprintf( pFileStream, L"Property name ....... %ls\r\n",
  1847. ChunkStats.attribute.psProperty.lpwstr );
  1848. }
  1849. else if( PRSPEC_PROPID == ChunkStats.attribute.psProperty.ulKind )
  1850. {
  1851. fwprintf( pFileStream, L"Property ID ......... 0x%08x\r\n",
  1852. ChunkStats.attribute.psProperty.propid );
  1853. }
  1854. else
  1855. {
  1856. fwprintf( pFileStream, L"Bad ulKind field .... %d\r\n",
  1857. ChunkStats.attribute.psProperty.ulKind );
  1858. }
  1859. // Insert a blank line
  1860. fwprintf( pFileStream, L"\r\n" );
  1861. } //CFiltTest::DisplayChunkStats
  1862. //+---------------------------------------------------------------------------
  1863. //
  1864. // Member: CFiltTest::LogChunkStats
  1865. //
  1866. // Synopsis:
  1867. //
  1868. // Arguments: [ChunkStats] --
  1869. //
  1870. // Returns:
  1871. //
  1872. // History: 2-03-1997 ericne Created
  1873. //
  1874. // Notes:
  1875. //
  1876. //----------------------------------------------------------------------------
  1877. void CFiltTest::LogChunkStats( const STAT_CHUNK & ChunkStats )
  1878. {
  1879. TCHAR szGuidBuffer[ GuidBufferSize ];
  1880. // Insert a blank line
  1881. m_pLog->Log( TLS_TEST | TL_INFO, L"Chunk statistics:" );
  1882. // Print the chunk id
  1883. m_pLog->Log( TLS_TEST | TL_INFO, L"Chunk ID: ........... %d",
  1884. ChunkStats.idChunk);
  1885. // Print the break type (in English if possible)
  1886. if( CHUNK_NO_BREAK > ChunkStats.breakType ||
  1887. CHUNK_EOC < ChunkStats.breakType ) // not legal
  1888. {
  1889. m_pLog->Log( TLS_TEST | TL_INFO, L"Illegal Break Type: . %d",
  1890. ChunkStats.breakType );
  1891. }
  1892. else
  1893. {
  1894. m_pLog->Log( TLS_TEST | TL_INFO, L"Chunk Break Type: ... %ls",
  1895. BreakType[ ChunkStats.breakType ] );
  1896. }
  1897. // Print the Chunk state (in English if possible)
  1898. if( CHUNK_TEXT == ChunkStats.flags || CHUNK_VALUE == ChunkStats.flags)
  1899. {
  1900. m_pLog->Log( TLS_TEST | TL_INFO, L"Chunk State: ........ %ls",
  1901. ChunkState[ ChunkStats.flags - 1 ] );
  1902. }
  1903. else
  1904. {
  1905. m_pLog->Log( TLS_TEST | TL_INFO, L"Bad Chunk State: .... %d",
  1906. ChunkStats.flags );
  1907. }
  1908. // Print the locale
  1909. m_pLog->Log( TLS_TEST | TL_INFO, L"Chunk Locale: ....... 0x%08x",
  1910. ChunkStats.locale );
  1911. // Print the Chunk id source
  1912. m_pLog->Log( TLS_TEST | TL_INFO, L"Chunk Source ID: .... %d",
  1913. ChunkStats.idChunkSource );
  1914. // Print the start source
  1915. m_pLog->Log( TLS_TEST | TL_INFO, L"Chunk Start Source .. 0x%08x",
  1916. ChunkStats.cwcStartSource );
  1917. // Print the length source
  1918. m_pLog->Log( TLS_TEST | TL_INFO, L"Chunk Length Source . 0x%08x",
  1919. ChunkStats.cwcLenSource );
  1920. // Display the guid
  1921. GetStringFromCLSID( ChunkStats.attribute.guidPropSet, szGuidBuffer,
  1922. GuidBufferSize );
  1923. m_pLog->Log( TLS_TEST | TL_INFO, L"GUID ................ %s",
  1924. szGuidBuffer );
  1925. // Display the contents of the PROPSPEC field (careful of the union)
  1926. if( PRSPEC_LPWSTR == ChunkStats.attribute.psProperty.ulKind )
  1927. {
  1928. m_pLog->Log( TLS_TEST | TL_INFO, L"Property name ....... %ls",
  1929. ChunkStats.attribute.psProperty.lpwstr );
  1930. }
  1931. else if( PRSPEC_PROPID == ChunkStats.attribute.psProperty.ulKind )
  1932. {
  1933. m_pLog->Log( TLS_TEST | TL_INFO, L"Property ID ......... 0x%08x",
  1934. ChunkStats.attribute.psProperty.propid );
  1935. }
  1936. else
  1937. {
  1938. m_pLog->Log( TLS_TEST | TL_INFO, L"Bad ulKind field .... %d",
  1939. ChunkStats.attribute.psProperty.ulKind );
  1940. }
  1941. } //CFiltTest::LogChunkStats
  1942. //+---------------------------------------------------------------------------
  1943. //
  1944. // Member: CFiltTest::DisplayText
  1945. //
  1946. // Synopsis: Either dumps the text to a Unicode file, or converts the text
  1947. // to ASCII and displays dumps it to the console
  1948. //
  1949. // Arguments: [pwcTextBuffer] -- Wide character buffer storing the text
  1950. // [pFileStream] ---- FILE* to which the output is directed
  1951. //
  1952. // Returns: none
  1953. //
  1954. // History: 9-20-1996 ericne Created
  1955. //
  1956. // Notes:
  1957. //
  1958. //----------------------------------------------------------------------------
  1959. void CFiltTest::DisplayText( const WCHAR * pwcTextBuffer,
  1960. FILE * pFileStream )
  1961. {
  1962. int iLoop = 0;
  1963. if( NULL == pFileStream )
  1964. return;
  1965. for( iLoop = 0; pwcTextBuffer[ iLoop ]; iLoop++ )
  1966. {
  1967. // Handle the return characters correctly
  1968. if( 0x000A == pwcTextBuffer[ iLoop ] )
  1969. fwprintf( pFileStream, L"\r\n" );
  1970. else
  1971. fputwc( pwcTextBuffer[ iLoop ], pFileStream );
  1972. }
  1973. //fwprintf( pFileStream, L"\r\n\r\n" );
  1974. } //CFiltTest::DisplayText
  1975. //+---------------------------------------------------------------------------
  1976. //
  1977. // Member: CFiltTest::DisplayValue
  1978. //
  1979. // Synopsis: Dumps the value to the screen or to the log file
  1980. //
  1981. // Arguments: [pPropValue] -- PROPVARIANT structure
  1982. // [pFileStream] - FILE* to which the output is directed
  1983. //
  1984. // Returns: void
  1985. //
  1986. // History: 9-20-1996 ericne Created
  1987. //
  1988. // Notes:
  1989. //
  1990. //----------------------------------------------------------------------------
  1991. void CFiltTest::DisplayValue( const PROPVARIANT * pPropValue,
  1992. FILE * pFileStream )
  1993. {
  1994. ULONG ul=0; // Loop counter for VT_ARRAY values
  1995. if( NULL == pFileStream )
  1996. return;
  1997. // Display the property
  1998. fwprintf( pFileStream, L"\r\n" );
  1999. switch( pPropValue->vt )
  2000. {
  2001. case VT_EMPTY:
  2002. case VT_NULL:
  2003. case VT_ILLEGAL:
  2004. m_pLog->Log( TLS_TEST | TL_SEV1, L"GetValue() returned a PROPVARIANT"
  2005. L" with an invalid vt field. The value of the"
  2006. L" field is 0x%08x", pPropValue->vt );
  2007. break;
  2008. // Here are some non-vector cases
  2009. case VT_UI1:
  2010. fwprintf( pFileStream, L"0x%02hx\r\n", (USHORT)pPropValue->bVal );
  2011. break;
  2012. case VT_I2:
  2013. fwprintf( pFileStream, L"0x%04hx\r\n", pPropValue->iVal );
  2014. break;
  2015. case VT_UI2:
  2016. fwprintf( pFileStream, L"0x%04hx\r\n", pPropValue->uiVal );
  2017. break;
  2018. case VT_I4:
  2019. fwprintf( pFileStream, L"0x%08x\r\n", pPropValue->lVal );
  2020. break;
  2021. case VT_UI4:
  2022. fwprintf( pFileStream, L"0x%08x\r\n", pPropValue->ulVal );
  2023. break;
  2024. case VT_I8:
  2025. fwprintf( pFileStream, L"0x%016I64x\r\n", pPropValue->hVal );
  2026. break;
  2027. case VT_UI8:
  2028. fwprintf( pFileStream, L"0x%016I64x\r\n", pPropValue->uhVal );
  2029. break;
  2030. case VT_R4:
  2031. fwprintf( pFileStream, L"%g\r\n", (double)pPropValue->fltVal );
  2032. break;
  2033. case VT_R8:
  2034. fwprintf( pFileStream, L"%g\r\n", pPropValue->dblVal );
  2035. break;
  2036. case VT_LPWSTR:
  2037. fwprintf( pFileStream, L"%ls\r\n", pPropValue->pwszVal );
  2038. break;
  2039. case VT_LPSTR:
  2040. fwprintf( pFileStream, L"%hs\r\n", pPropValue->pszVal );
  2041. break;
  2042. case VT_BSTR:
  2043. fwprintf( pFileStream, L"%ls\r\n", pPropValue->bstrVal );
  2044. break;
  2045. // Here are the vector cases:
  2046. case VT_VECTOR | VT_UI1:
  2047. for( ul=0; ul<pPropValue->caub.cElems; ul++ )
  2048. fwprintf( pFileStream, L"0x%02hx\r\n",
  2049. (USHORT)pPropValue->caub.pElems[ul] );
  2050. break;
  2051. case VT_VECTOR | VT_I2:
  2052. for( ul=0; ul<pPropValue->cai.cElems; ul++ )
  2053. fwprintf( pFileStream, L"0x%04hx\r\n",
  2054. pPropValue->cai.pElems[ul] );
  2055. break;
  2056. case VT_VECTOR | VT_UI2:
  2057. for( ul=0; ul<pPropValue->caui.cElems; ul++ )
  2058. fwprintf( pFileStream, L"0x%04hx\r\n",
  2059. pPropValue->caui.pElems[ul] );
  2060. break;
  2061. case VT_VECTOR | VT_I4:
  2062. for( ul=0; ul<pPropValue->cal.cElems; ul++ )
  2063. fwprintf( pFileStream, L"0x%08x\r\n",
  2064. pPropValue->cal.pElems[ul] );
  2065. break;
  2066. case VT_VECTOR | VT_UI4:
  2067. for( ul=0; ul<pPropValue->caul.cElems; ul++ )
  2068. fwprintf( pFileStream, L"0x%08x\r\n",
  2069. pPropValue->caul.pElems[ul] );
  2070. break;
  2071. case VT_VECTOR | VT_I8:
  2072. for( ul=0; ul<pPropValue->cah.cElems; ul++ )
  2073. fwprintf( pFileStream, L"0x%016I64x\r\n",
  2074. pPropValue->cah.pElems[ul] );
  2075. break;
  2076. case VT_VECTOR | VT_UI8:
  2077. for( ul=0; ul<pPropValue->cauh.cElems; ul++ )
  2078. fwprintf( pFileStream, L"0x%016I64x\r\n",
  2079. pPropValue->cauh.pElems[ul] );
  2080. break;
  2081. case VT_VECTOR | VT_R4:
  2082. for( ul=0; ul<pPropValue->caflt.cElems; ul++ )
  2083. fwprintf( pFileStream, L"%g\r\n",
  2084. (double)pPropValue->caflt.pElems[ul] );
  2085. break;
  2086. case VT_VECTOR | VT_R8:
  2087. for( ul=0; ul<pPropValue->cadbl.cElems; ul++ )
  2088. fwprintf( pFileStream, L"%g\r\n",
  2089. pPropValue->cadbl.pElems[ul] );
  2090. break;
  2091. case VT_VECTOR | VT_LPWSTR:
  2092. for( ul=0; ul<pPropValue->calpwstr.cElems; ul++ )
  2093. fwprintf( pFileStream, L"%ls\r\n",
  2094. pPropValue->calpwstr.pElems[ul] );
  2095. break;
  2096. case VT_VECTOR | VT_LPSTR:
  2097. for( ul=0; ul<pPropValue->calpstr.cElems; ul++ )
  2098. fwprintf( pFileStream, L"%hs\r\n",
  2099. pPropValue->calpstr.pElems[ul] );
  2100. break;
  2101. case VT_VECTOR | VT_BSTR:
  2102. for( ul=0; ul<pPropValue->cabstr.cElems; ul++ )
  2103. fwprintf( pFileStream, L"%ls\r\n",
  2104. pPropValue->cabstr.pElems[ul] );
  2105. break;
  2106. default:
  2107. // BUGBUG Lots of other cases to handle.
  2108. m_pLog->Log( TLS_TEST | TL_INFO, L"0x%08x: This property cannot be"
  2109. L" displayed at this time.", pPropValue->vt );
  2110. break;
  2111. }
  2112. // Insert a blank line
  2113. fwprintf( pFileStream, L"\r\n" );
  2114. } //CFiltTest::DisplayValue