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.

542 lines
17 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1996.
  5. //
  6. // File: filtpars.cxx
  7. //
  8. // Contents: Definitions of the CFiltParse methods
  9. //
  10. // Classes:
  11. //
  12. // Functions: CFiltParse, ~CFiltParse, Init, GetNextConfig,
  13. // ParseFlags, GetAttributes
  14. //
  15. // Coupling:
  16. //
  17. // Notes:
  18. //
  19. // History: 9-21-1996 ericne Created
  20. //
  21. //----------------------------------------------------------------------------
  22. #include "pch.cxx"
  23. #include <ctype.h>
  24. #include "utility.hxx"
  25. #include "mydebug.hxx"
  26. #include "filtpars.hxx"
  27. //+---------------------------------------------------------------------------
  28. //
  29. // Member: CFiltParse::CFiltParse
  30. //
  31. // Synopsis: Constructor. Default initialization
  32. //
  33. // Arguments: (none)
  34. //
  35. // Returns:
  36. //
  37. // History: 9-21-1996 ericne Created
  38. //
  39. // Notes:
  40. //
  41. //----------------------------------------------------------------------------
  42. CFiltParse::CFiltParse( )
  43. : m_pNextListNode( NULL )
  44. {
  45. // Zero all the fields of m_FirstListNode (this makes the "next" field 0)
  46. memset( (void*) &m_FirstListNode, (int)0, sizeof( ListNode ) );
  47. } //CFiltParse::CFiltParse
  48. //+---------------------------------------------------------------------------
  49. //
  50. // Member: CFiltParse::~CFiltParse
  51. //
  52. // Synopsis: Destructor. Cleans up the heap
  53. //
  54. // Arguments: (none)
  55. //
  56. // Returns:
  57. //
  58. // History: 9-21-1996 ericne Created
  59. //
  60. // Notes:
  61. //
  62. //----------------------------------------------------------------------------
  63. CFiltParse::~CFiltParse( )
  64. {
  65. ListNode *pCurrentNode = m_FirstListNode.next;
  66. ListNode *pTempNode = NULL;
  67. ULONG ul = 0;
  68. while( NULL != pCurrentNode )
  69. {
  70. pTempNode = pCurrentNode;
  71. pCurrentNode = pCurrentNode->next;
  72. // If there are any attributes, delete any lpwstr's
  73. for( ul=0; ul < pTempNode->Configuration.ulActNbrAttributes; ul++ )
  74. {
  75. if( PRSPEC_LPWSTR ==
  76. pTempNode->Configuration.aAttributes[ ul ].psProperty.ulKind )
  77. {
  78. delete [] pTempNode->Configuration.aAttributes[ ul ].
  79. psProperty.lpwstr;
  80. }
  81. }
  82. if( pTempNode->Configuration.aAttributes )
  83. delete [] pTempNode->Configuration.aAttributes;
  84. delete pTempNode->Configuration.pdwFlags;
  85. delete [] pTempNode->Configuration.szSectionName;
  86. delete pTempNode;
  87. }
  88. } //CFiltParse::~CFiltParse
  89. //+---------------------------------------------------------------------------
  90. //
  91. // Member: CFiltParse::Init
  92. //
  93. // Synopsis: Parses the contents of the .ini file
  94. //
  95. // Arguments: [pcFileName] -- name of data file
  96. //
  97. // Returns: TRUE if file was parsed successfully, FALSE otherwise
  98. //
  99. // History: 9-22-1996 ericne Created
  100. //
  101. // Notes: The full path to the *.ini file must be specified
  102. //
  103. //----------------------------------------------------------------------------
  104. BOOL CFiltParse::Init( LPCTSTR szFileName )
  105. {
  106. int iFlags = 0;
  107. int iSectionIndex = 0;
  108. TCHAR szFlags[ MAX_LINE_SIZE ];
  109. TCHAR szSectionNames[ MAX_SECTION_NAMES_SIZE ];
  110. UINT uiAttributeCount = 0;
  111. DWORD dwNbrChars = 0;
  112. DWORD dwFileAttributes = 0;
  113. ULONG ulNbrAttributes = 0;
  114. ListNode *pNewNode = NULL;
  115. ListNode *pLastListNode = &m_FirstListNode;
  116. FULLPROPSPEC *pAttributes = NULL;
  117. // Check to see if the ini file exists:
  118. dwFileAttributes = GetFileAttributes( szFileName );
  119. // If the file doesn't exist, create a default configuration
  120. if( 0xFFFFFFFF == dwFileAttributes )
  121. {
  122. _tprintf( _T("WARNING: Initialization file %s not found. Using a")
  123. _T(" default configuration.\r\n"), szFileName );
  124. pNewNode = new ListNode;
  125. pNewNode->Configuration.grfFlags = IFILTER_INIT_APPLY_INDEX_ATTRIBUTES;
  126. pNewNode->Configuration.cAttributes = 0;
  127. pNewNode->Configuration.aAttributes = NULL;
  128. pNewNode->Configuration.pdwFlags = new DWORD(0);
  129. pNewNode->Configuration.ulActNbrAttributes = 0;
  130. pNewNode->Configuration.szSectionName =
  131. new TCHAR[ _tcslen( szDefaultSectionName ) + 1 ];
  132. _tcscpy( pNewNode->Configuration.szSectionName, szDefaultSectionName );
  133. pNewNode->next = NULL;
  134. m_pNextListNode = m_FirstListNode.next = pNewNode;
  135. return( TRUE );
  136. }
  137. // Get the Section names from the *.ini file
  138. dwNbrChars = GetPrivateProfileString( NULL,
  139. NULL,
  140. _T(""),
  141. szSectionNames,
  142. MAX_SECTION_NAMES_SIZE,
  143. szFileName );
  144. // Make sure we got some section names
  145. if( 0 == dwNbrChars )
  146. {
  147. _tprintf( _T("Parsing error: no sections found in %s\r\n"),
  148. szFileName );
  149. return( FALSE );
  150. }
  151. // Make sure we didn't fill the buffer
  152. if( MAX_SECTION_NAMES_SIZE - 2 == dwNbrChars )
  153. {
  154. _tprintf( _T("Parsing error: too many section names were found in ")
  155. _T("%s\r\n"), szFileName );
  156. return( FALSE );
  157. }
  158. while( szSectionNames[ iSectionIndex ] )
  159. {
  160. dwNbrChars =
  161. GetPrivateProfileString( &szSectionNames[ iSectionIndex ],
  162. _T("Flags"),
  163. _T(""),
  164. szFlags,
  165. MAX_LINE_SIZE,
  166. szFileName );
  167. // Parse the flags
  168. if( ! ParseFlags( szFlags, &iFlags ) )
  169. return( FALSE );
  170. // Get the number of attributes
  171. uiAttributeCount =
  172. GetPrivateProfileInt( &szSectionNames[ iSectionIndex ],
  173. _T("cAttributes"),
  174. 0,
  175. szFileName );
  176. // Get the attributes listed in this section
  177. if( ! GetAttributes( &szSectionNames[ iSectionIndex ],
  178. szFileName,
  179. pAttributes,
  180. ulNbrAttributes ) )
  181. {
  182. return( FALSE );
  183. }
  184. // Create a new ListNode
  185. pNewNode = new ListNode;
  186. // Fill in the Configuration information
  187. pNewNode->Configuration.grfFlags = iFlags;
  188. pNewNode->Configuration.cAttributes = uiAttributeCount;
  189. pNewNode->Configuration.aAttributes = pAttributes;
  190. pNewNode->Configuration.ulActNbrAttributes = ulNbrAttributes;
  191. // Create a new dword for the pdwFlags
  192. pNewNode->Configuration.pdwFlags = new DWORD( 0 );
  193. // Save the secion name in the CONFIG structure
  194. pNewNode->Configuration.szSectionName =
  195. new TCHAR[ _tcslen( &szSectionNames[ iSectionIndex ] ) + 1 ];
  196. _tcscpy( pNewNode->Configuration.szSectionName,
  197. &szSectionNames[ iSectionIndex ] );
  198. // Put the node at the end of the list
  199. pLastListNode->next = pNewNode;
  200. pLastListNode = pNewNode;
  201. pNewNode->next = NULL;
  202. // Increment the section index past the current section name
  203. while( szSectionNames[ iSectionIndex++ ] )
  204. {
  205. ( (void)0 ); // No work needs to be done here
  206. }
  207. }
  208. // Initialize the next node pointer
  209. m_pNextListNode = m_FirstListNode.next;
  210. // Successfully parsed the file:
  211. return( TRUE );
  212. } //CFiltParse::Init
  213. //+---------------------------------------------------------------------------
  214. //
  215. // Member: CFiltParse::GetNextConfig
  216. //
  217. // Synopsis: extracts the next configuration from the list
  218. //
  219. // Arguments: [pConfiguration] -- pointer to the configuration structure
  220. //
  221. // Returns: TRUE if successful, FALSE if there are no more configurations
  222. //
  223. // History: 9-22-1996 ericne Created
  224. //
  225. // Notes: This function performs a bit-wise copy of the config structure
  226. // which contains pointers. This is intentional. All pointers
  227. // to dynamically allocated memory are stored in the linked list
  228. // and are cleaned up in the destructor. The client is not
  229. // responsible for deleting the memory, and shouldn't.
  230. //
  231. //----------------------------------------------------------------------------
  232. BOOL CFiltParse::GetNextConfig( CONFIG *pConfiguration )
  233. {
  234. // If we are at the end of the list, return.
  235. if( NULL == m_pNextListNode )
  236. return( FALSE );
  237. // Bit-wise copy the CONFIG structure, pointers included.
  238. memcpy( (void*) pConfiguration,
  239. (void*) &(m_pNextListNode->Configuration),
  240. sizeof( CONFIG ) );
  241. // Advance the current node pointer
  242. m_pNextListNode = m_pNextListNode->next;
  243. return( TRUE );
  244. } //CFiltParse::GetNextConfig
  245. //+---------------------------------------------------------------------------
  246. //
  247. // Member: CFiltParse::ParseFlags
  248. //
  249. // Synopsis: Makes extensive use of streams to extract individual tokens
  250. // from a single line of the data file. The tokens should
  251. // correspont to IFilter Init flags. Their values are bit-wise
  252. // ORed together and stored in m_Flags
  253. //
  254. // Arguments: (none)
  255. //
  256. // Returns: TRUE if successful
  257. // FALSE if an error occurs
  258. //
  259. // History: 9-22-1996 ericne Created
  260. //
  261. // Notes:
  262. //
  263. //----------------------------------------------------------------------------
  264. BOOL CFiltParse::ParseFlags( LPTSTR szFlags, int * piFlags )
  265. {
  266. BOOL fIsLegalToken = FALSE;
  267. LPCTSTR szTokenBuffer = _tcstok( szFlags, _T(" \t") );
  268. // initialize *piFlags
  269. *piFlags = 0;
  270. // While there are more tokens in szFlags:
  271. while( NULL != szTokenBuffer )
  272. {
  273. // Assume the token is not legal
  274. fIsLegalToken = FALSE;
  275. // Try to find a match for this token
  276. for( int iCount = 0; iCount < 8; iCount++ )
  277. {
  278. if( 0 == _tcsicmp( szTokenBuffer, strInitFlags[ iCount ] ) )
  279. {
  280. // Bitwise-or of *piFlags with 1 left-shifted by iCount
  281. *piFlags |= ( 1 << iCount );
  282. fIsLegalToken = TRUE;
  283. break;
  284. }
  285. }
  286. // If no match was found
  287. if( ! fIsLegalToken )
  288. {
  289. _tprintf( _T("Parsing error: Illegal Init flag: %s\r\n"),
  290. szTokenBuffer );
  291. return( FALSE );
  292. }
  293. // Get the next token
  294. szTokenBuffer = _tcstok( NULL, _T(" \t") );
  295. }
  296. return( TRUE );
  297. } //CFiltParse::GetFlags
  298. //+---------------------------------------------------------------------------
  299. //
  300. // Member: CFiltParse::GetAttributes
  301. //
  302. // Synopsis: Gets the correct number of attributes from the data file
  303. //
  304. // Arguments: (none)
  305. //
  306. // Returns: TRUE if successful,
  307. // FALSE if an error occurs or the end of file is reached
  308. //
  309. // History: 9-22-1996 ericne Created
  310. //
  311. // Notes:
  312. //
  313. //----------------------------------------------------------------------------
  314. BOOL CFiltParse::GetAttributes( const TCHAR *szSectionName,
  315. const TCHAR *szFileName,
  316. FULLPROPSPEC *&pFullPropspec,
  317. ULONG &ulNbrAttributes )
  318. {
  319. TCHAR szAttributeString[ MAX_LINE_SIZE ];
  320. LPTSTR szGuidBuffer = NULL;
  321. LPTSTR szPropspecBuffer = NULL;
  322. LPTSTR szTestBuffer = NULL;
  323. TCHAR szKeyNames[ MAX_KEY_NAMES_SIZE ];
  324. UINT uiKeyIndex = 0;
  325. UINT uiAttributeIndex = 0;
  326. BOOL fSuccessful = FALSE;
  327. DWORD dwNbrChars = 0;
  328. // Initialize m_Attributes field
  329. pFullPropspec = NULL;
  330. ulNbrAttributes = 0;
  331. // Enumerate all the Key names in this section:
  332. dwNbrChars = GetPrivateProfileString( szSectionName,
  333. NULL,
  334. _T(""),
  335. szKeyNames,
  336. MAX_KEY_NAMES_SIZE,
  337. szFileName );
  338. // Make sure we had enough room:
  339. if( MAX_KEY_NAMES_SIZE - 2 == dwNbrChars )
  340. {
  341. _tprintf( _T("Parse error: too many keys found in section %s ")
  342. _T("in file %s\r\n"), szSectionName, szFileName );
  343. return( FALSE );
  344. }
  345. // Find out how many attributes are specified:
  346. while( szKeyNames[ uiKeyIndex ] )
  347. {
  348. if( &szKeyNames[ uiKeyIndex ] ==
  349. _tcsstr( &szKeyNames[ uiKeyIndex ], _T("aAttributes") ) )
  350. {
  351. ++ulNbrAttributes;
  352. }
  353. while( szKeyNames[ uiKeyIndex++ ] )
  354. {
  355. ( (void)0 );
  356. }
  357. }
  358. // If no attributes are specified, return TRUE (we're done)
  359. if( 0 == ulNbrAttributes )
  360. return( TRUE );
  361. // Allocate the correct number of attributes
  362. pFullPropspec = new FULLPROPSPEC[ ulNbrAttributes ];
  363. // Reset the Key index
  364. uiKeyIndex = 0;
  365. // try-finally block simplifies clean-up
  366. __try
  367. {
  368. // Loop over all the key names:
  369. // The (dis)advantage of this approach is that it allows a user to
  370. // specify a number of attributes in cAttributes, but then allocate a
  371. // different number of attributes, to see how the filter handles this
  372. while( szKeyNames[ uiKeyIndex ] )
  373. {
  374. // Assert that I don't overwrite the Attribute array
  375. // (Debug version only)
  376. _ASSERT( uiAttributeIndex < ulNbrAttributes );
  377. // If this key is not specifying an attribute, continue
  378. if( &szKeyNames[ uiKeyIndex ] !=
  379. _tcsstr( &szKeyNames[ uiKeyIndex ], _T("aAttributes") ) )
  380. {
  381. while( szKeyNames[ uiKeyIndex++ ] )
  382. {
  383. ( (void)0 );
  384. }
  385. continue;
  386. }
  387. // Get the attribute string
  388. dwNbrChars = GetPrivateProfileString( szSectionName,
  389. &szKeyNames[ uiKeyIndex ],
  390. _T(""),
  391. szAttributeString,
  392. MAX_LINE_SIZE,
  393. szFileName );
  394. // Pull out the guid token:
  395. if( NULL ==
  396. ( szGuidBuffer = _tcstok( szAttributeString, _T(" \t") ) ) )
  397. {
  398. _tprintf( _T("Parsing error: Expecting guid.\r\n") );
  399. __leave;
  400. }
  401. // Pull out the Propid
  402. if( NULL == ( szPropspecBuffer = _tcstok( NULL, _T(" \t") ) ) )
  403. {
  404. _tprintf( _T("Parsing error: Expecting propspec.\r\n") );
  405. __leave;
  406. }
  407. // Make sure the string stream is empty now
  408. if( NULL != ( szTestBuffer = _tcstok( NULL, _T(" \t") ) ) )
  409. {
  410. _tprintf( _T("Parsing error: %s was unexpected at this")
  411. _T(" time.\r\n"), szTestBuffer );
  412. __leave;
  413. }
  414. // Convert the guid string to a guid
  415. if( ! StrToGuid( szGuidBuffer,
  416. &pFullPropspec[ uiAttributeIndex ].guidPropSet ) )
  417. {
  418. _tprintf( _T("Parsing error: could not convert %s to")
  419. _T(" a GUID\r\n"), szGuidBuffer );
  420. __leave;
  421. }
  422. if( ! StrToPropspec( szPropspecBuffer,
  423. &pFullPropspec[ uiAttributeIndex ].psProperty ) )
  424. {
  425. _tprintf( _T("Parsing error: could not convert %s to a")
  426. _T(" PROPSPEC\r\n"), szPropspecBuffer );
  427. __leave;
  428. }
  429. // Advanve the Attribute index
  430. ++uiAttributeIndex;
  431. // Advance uiKeyIndex
  432. while( szKeyNames[ uiKeyIndex++ ] )
  433. {
  434. ( (void)0 );
  435. }
  436. }
  437. // Assert that I copied exactly the correct number of attributes
  438. // (Debug version only)
  439. _ASSERT( uiAttributeIndex == ulNbrAttributes );
  440. // Set the success flag
  441. fSuccessful = TRUE;
  442. }
  443. __finally
  444. {
  445. // If not successful, clean the heap and reset return values
  446. if( ! fSuccessful )
  447. {
  448. if( pFullPropspec )
  449. {
  450. delete [] pFullPropspec;
  451. pFullPropspec = NULL;
  452. }
  453. ulNbrAttributes = 0;
  454. }
  455. }
  456. return fSuccessful;
  457. } //CFiltParse::GetAttributes