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.

728 lines
14 KiB

  1. // TranxMgr.cpp: implementation for the CTranxMgr
  2. //
  3. // Copyright (c)1997-2001 Microsoft Corporation
  4. //
  5. //////////////////////////////////////////////////////////////////////
  6. #include "precomp.h"
  7. #include "XMLReader.h"
  8. /*
  9. Routine Description:
  10. Name:
  11. CXMLContent::CXMLContent
  12. Functionality:
  13. Trivial.
  14. Virtual:
  15. No.
  16. Arguments:
  17. None.
  18. Return Value:
  19. None as any constructor
  20. Notes:
  21. if you create any local members, think about initialize them here.
  22. */
  23. CXMLContent::CXMLContent ()
  24. : m_dwTotalElements(0),
  25. m_hOutFile(NULL),
  26. m_bFinished(false),
  27. m_bInSection(false),
  28. m_bSingleArea(true)
  29. {
  30. }
  31. /*
  32. Routine Description:
  33. Name:
  34. CXMLContent::~CXMLContent
  35. Functionality:
  36. Trivial.
  37. Virtual:
  38. Yes.
  39. Arguments:
  40. None.
  41. Return Value:
  42. None as any destructor
  43. Notes:
  44. if you create any local members, think about releasing them here.
  45. */
  46. CXMLContent::~CXMLContent()
  47. {
  48. if (m_hOutFile != NULL)
  49. {
  50. ::CloseHandle(m_hOutFile);
  51. }
  52. }
  53. /*
  54. Routine Description:
  55. Name:
  56. CXMLContent::startElement
  57. Functionality:
  58. Analyze the elements. If the element is what we are interested in,
  59. then we will cache the information.
  60. Virtual:
  61. Yes.
  62. Arguments:
  63. pwchNamespaceUri - The namespace URI.
  64. cchNamespaceUri - The length for the namespace URI.
  65. pwchLocalName - The local name string.
  66. cchLocalName - The length of the local name.
  67. pwchQName - The QName (with prefix) or, if QNames are not available, an empty string.
  68. cchQName - The length of the QName.
  69. pAttributes - COM interface to the attribute object.
  70. Return Value:
  71. Success:
  72. S_OK;
  73. Failure:
  74. E_FAIL (this causes the parser not to continue parsing).
  75. Notes:
  76. See MSDN ISAXContentHandler::startElement for detail. We must maintain our handler
  77. to stay compatible with MSDN's specification.
  78. */
  79. STDMETHODIMP
  80. CXMLContent::startElement (
  81. IN const wchar_t * pwchNamespaceUri,
  82. IN int cchNamespaceUri,
  83. IN const wchar_t * pwchLocalName,
  84. IN int cchLocalName,
  85. IN const wchar_t * pwchQName,
  86. IN int cchQName,
  87. IN ISAXAttributes * pAttributes
  88. )
  89. {
  90. //
  91. // If we have finished then we will stop here.
  92. //
  93. if ( m_bFinished )
  94. {
  95. return E_FAIL;
  96. }
  97. ++m_dwTotalElements;
  98. //
  99. // if we are not in our section, we will only need to carry out
  100. // further if this element is a Section element
  101. //
  102. if (m_bInSection == false && _wcsicmp(pwchQName, L"Section") == 0)
  103. {
  104. LPWSTR pArea = NULL;
  105. if (GetAttributeValue(pAttributes, L"Area", &pArea))
  106. {
  107. m_bInSection = (_wcsicmp(m_bstrSecArea, L"All") == 0 || _wcsicmp(pArea, m_bstrSecArea) == 0);
  108. //
  109. // $undone:shawnwu, put some header information, currently, hard coded for SCE's INF file
  110. //
  111. if (_wcsicmp(L"Sce_Core", pArea) == 0)
  112. {
  113. WriteContent(L"[Unicode]", NULL);
  114. WriteContent(L"Unicode", L"yes");
  115. WriteContent(L"[Version]", NULL);
  116. WriteContent(L"$CHICAGO$", NULL);
  117. WriteContent(L"Revision", L"1");
  118. WriteContent(L"\r\n", NULL);
  119. WriteContent(L"[System Access]", NULL);
  120. }
  121. WriteContent(L"\r\n", NULL);
  122. }
  123. delete [] pArea;
  124. }
  125. //
  126. // if not in our section, don't bother to continue
  127. //
  128. if (m_bInSection == false)
  129. {
  130. return S_OK;
  131. }
  132. if (m_bInElement == false && _wcsicmp(pwchQName, m_bstrElement) == 0)
  133. {
  134. m_bInElement = true;
  135. //
  136. // $undone:shawnwu, consider writing some element comments?
  137. //
  138. }
  139. if (m_bInElement == false)
  140. {
  141. return S_OK;
  142. }
  143. int iAttribCount = 0;
  144. pAttributes->getLength(&iAttribCount);
  145. LPWSTR pszPropName = NULL;
  146. LPWSTR pszPropValue = NULL;
  147. if (GetAttributeValue(pAttributes, L"Name", &pszPropName))
  148. {
  149. //
  150. // In real time, we will do something with the (name, value) pair
  151. // since we are just testing here, write it to the file
  152. //
  153. if (GetAttributeValue(pAttributes, L"Value", &pszPropValue))
  154. {
  155. WriteContent(pszPropName, pszPropValue);
  156. }
  157. delete [] pszPropName;
  158. pszPropName = NULL;
  159. delete [] pszPropValue;
  160. pszPropValue = NULL;
  161. }
  162. return S_OK;
  163. }
  164. /*
  165. Routine Description:
  166. Name:
  167. CXMLContent::endElement
  168. Functionality:
  169. Analyze the elements. We may decide that this is the end of our parsing need
  170. depending on our settings.
  171. Virtual:
  172. Yes.
  173. Arguments:
  174. pwchNamespaceUri - The namespace URI.
  175. cchNamespaceUri - The length for the namespace URI.
  176. pwchLocalName - The local name string.
  177. cchLocalName - The length of the local name.
  178. pwchQName - The QName (with prefix) or, if QNames are not available, an empty string.
  179. cchQName - The length of the QName.
  180. Return Value:
  181. Success:
  182. S_OK;
  183. Failure:
  184. E_FAIL (this causes the parser not to continue parsing).
  185. Notes:
  186. See MSDN ISAXContentHandler::endElement for detail. We must maintain our handler
  187. to stay compatible with MSDN's specification.
  188. */
  189. STDMETHODIMP
  190. CXMLContent::endElement (
  191. IN const wchar_t * pwchNamespaceUri,
  192. IN int cchNamespaceUri,
  193. IN const wchar_t * pwchLocalName,
  194. IN int cchLocalName,
  195. IN const wchar_t * pwchQName,
  196. IN int cchQName
  197. )
  198. {
  199. //
  200. // if we have seen the section ended, we are done.
  201. //
  202. if (m_bInSection && _wcsicmp(pwchQName, L"Section") == 0)
  203. {
  204. m_bFinished = m_bSingleArea;
  205. m_bInSection = false;
  206. }
  207. if (m_bInElement && _wcsicmp(pwchQName, m_bstrElement) == 0)
  208. {
  209. m_bInElement = false;
  210. }
  211. return S_OK;
  212. }
  213. STDMETHODIMP
  214. CXMLContent::startDocument()
  215. {
  216. m_bFinished = false;
  217. m_bInElement = false;
  218. m_bInSection = false;
  219. m_dwTotalElements = 0;
  220. return S_OK;
  221. }
  222. STDMETHODIMP
  223. CXMLContent::endDocument ()
  224. {
  225. LPCWSTR pszOutFile = m_bstrOutputFile;
  226. if (pszOutFile && *pszOutFile != L'\0')
  227. {
  228. //
  229. // testing code.
  230. //
  231. WCHAR pszValue[100];
  232. swprintf(pszValue, L"%d", m_dwTotalElements);
  233. WriteContent(L"\r\nTotal Elements parsed: ", pszValue);
  234. }
  235. return S_OK;
  236. }
  237. STDMETHODIMP
  238. CXMLContent::putDocumentLocator (
  239. IN ISAXLocator *pLocator
  240. )
  241. {
  242. return S_OK;
  243. }
  244. STDMETHODIMP
  245. CXMLContent::startPrefixMapping (
  246. IN const wchar_t * pwchPrefix,
  247. IN int cchPrefix,
  248. IN const wchar_t * pwchUri,
  249. IN int cchUri
  250. )
  251. {
  252. return S_OK;
  253. }
  254. STDMETHODIMP
  255. CXMLContent::endPrefixMapping (
  256. IN const wchar_t * pwchPrefix,
  257. IN int cchPrefix
  258. )
  259. {
  260. return S_OK;
  261. }
  262. STDMETHODIMP
  263. CXMLContent::characters (
  264. IN const wchar_t * pwchChars,
  265. IN int cchChars
  266. )
  267. {
  268. return S_OK;
  269. }
  270. STDMETHODIMP
  271. CXMLContent::ignorableWhitespace (
  272. IN const wchar_t * pwchChars,
  273. IN int cchChars
  274. )
  275. {
  276. return S_OK;
  277. }
  278. STDMETHODIMP
  279. CXMLContent::processingInstruction (
  280. IN const wchar_t * pwchTarget,
  281. IN int cchTarget,
  282. IN const wchar_t * pwchData,
  283. IN int cchData
  284. )
  285. {
  286. return S_OK;
  287. }
  288. STDMETHODIMP
  289. CXMLContent::skippedEntity (
  290. IN const wchar_t * pwchName,
  291. IN int cchName
  292. )
  293. {
  294. return S_OK;
  295. }
  296. /*
  297. Routine Description:
  298. Name:
  299. CXMLContent::GetAttributeValue
  300. Functionality:
  301. Private helper. Given the attribute's name, we will return the attribute's value.
  302. Virtual:
  303. No.
  304. Arguments:
  305. pAttributes - COM interface to the attribute object.
  306. pszTestName - The name of the attributes we want the value of.
  307. ppszAttrVal - Receives the attribute's value if found.
  308. Return Value:
  309. true if the named attribute is found;
  310. false otherwise.
  311. Notes:
  312. Caller is responsible for releasing the memory allocated to the
  313. out parameter.
  314. */
  315. bool
  316. CXMLContent::GetAttributeValue (
  317. IN ISAXAttributes * pAttributes,
  318. IN LPCWSTR pszAttrName,
  319. OUT LPWSTR * ppszAttrVal
  320. )
  321. {
  322. //
  323. // caller is responsible for passing valid parameters
  324. //
  325. *ppszAttrVal = NULL;
  326. int iAttribCount = 0;
  327. pAttributes->getLength(&iAttribCount);
  328. const wchar_t * pszName;
  329. const wchar_t * pszValue;
  330. int iNameLen;
  331. int iValLen;
  332. for ( int i = 0; i < iAttribCount; i++ )
  333. {
  334. HRESULT hr = pAttributes->getLocalName(i, &pszName, &iNameLen);
  335. if (SUCCEEDED(hr) && wcsncmp(pszAttrName, pszName, iNameLen) == 0)
  336. {
  337. hr = pAttributes->getValue(i, &pszValue, &iValLen);
  338. if (SUCCEEDED(hr))
  339. {
  340. *ppszAttrVal = new WCHAR[iValLen + 1];
  341. if (*ppszAttrVal != NULL)
  342. {
  343. wcscpy(*ppszAttrVal, pszValue);
  344. return true;
  345. }
  346. else
  347. {
  348. return false;
  349. }
  350. }
  351. }
  352. }
  353. return false;
  354. }
  355. /*
  356. Routine Description:
  357. Name:
  358. CXMLContent::GetAttributeValue
  359. Functionality:
  360. Private helper. Given the index, we will return the attribute's name and its value.
  361. Virtual:
  362. No.
  363. Arguments:
  364. pAttributes - COM interface to the attribute object.
  365. iIndex - The index of the attribute we want.
  366. ppszAttrName - Receives the name of the attributes we want.
  367. ppszAttrVal - Receives the attribute's value if found.
  368. Return Value:
  369. true if the named attribute is found;
  370. false otherwise.
  371. Notes:
  372. Caller is responsible for releasing the memory allocated to both
  373. out parameters.
  374. */
  375. bool
  376. CXMLContent::GetAttributeValue (
  377. IN ISAXAttributes * pAttributes,
  378. IN int iIndex,
  379. OUT LPWSTR * ppszAttrName,
  380. OUT LPWSTR * ppszAttrVal
  381. )
  382. {
  383. //
  384. // caller is responsible for passing valid parameters
  385. //
  386. *ppszAttrName = NULL;
  387. *ppszAttrVal = NULL;
  388. const wchar_t * pszName;
  389. const wchar_t * pszValue;
  390. int iNameLen;
  391. int iValLen;
  392. HRESULT hr = pAttributes->getLocalName(iIndex, &pszName, &iNameLen);
  393. if (SUCCEEDED(hr) && iNameLen > 0)
  394. {
  395. hr = pAttributes->getValue(iIndex, &pszValue, &iValLen);
  396. if (SUCCEEDED(hr) && iValLen > 0)
  397. {
  398. *ppszAttrName = new WCHAR[iNameLen + 1];
  399. *ppszAttrVal = new WCHAR[iValLen + 1];
  400. if (*ppszAttrName != NULL && *ppszAttrVal != NULL)
  401. {
  402. wcsncpy(*ppszAttrName, pszName, iNameLen);
  403. (*ppszAttrName)[iNameLen] = L'\0';
  404. wcsncpy(*ppszAttrVal, pszValue, iValLen);
  405. (*ppszAttrVal)[iValLen] = L'\0';
  406. return true;
  407. }
  408. else
  409. {
  410. return false;
  411. }
  412. }
  413. }
  414. return false;
  415. }
  416. /*
  417. Routine Description:
  418. Name:
  419. CXMLContent::WriteContent
  420. Functionality:
  421. Testing function. This determines which section area this
  422. reader is interested in and which element of the section
  423. this reader will process.
  424. Virtual:
  425. No.
  426. Arguments:
  427. pszSecArea - The Area attribute of the section the reader will process.
  428. pszElement - The name of the element the reader will process.
  429. bOneAreaOnly- Whether we will only process one area.
  430. Return Value:
  431. None.
  432. Notes:
  433. */
  434. void
  435. CXMLContent::SetSection (
  436. IN LPCWSTR pszSecArea,
  437. IN LPCWSTR pszElement,
  438. IN bool bOneAreaOnly
  439. )
  440. {
  441. m_bstrSecArea = pszSecArea;
  442. m_bstrElement = pszElement;
  443. m_bSingleArea = bOneAreaOnly;
  444. }
  445. /*
  446. Routine Description:
  447. Name:
  448. CXMLContent::WriteContent
  449. Functionality:
  450. Private helper for testing (for now).
  451. Given the name and value pair, we will write <name>=<value> into the output file.
  452. Virtual:
  453. No.
  454. Arguments:
  455. pszName - The name of the pair.
  456. pszValue - The value of the pair. Can be NULL. In that case, we will only
  457. write the pszName as a separate line.
  458. Return Value:
  459. None.
  460. Notes:
  461. */
  462. void
  463. CXMLContent::WriteContent (
  464. IN LPCWSTR pszName,
  465. IN LPCWSTR pszValue
  466. )
  467. {
  468. if (m_hOutFile == NULL)
  469. {
  470. m_hOutFile = ::CreateFile (m_bstrOutputFile,
  471. GENERIC_WRITE,
  472. FILE_SHARE_READ,
  473. NULL,
  474. OPEN_ALWAYS,
  475. FILE_ATTRIBUTE_NORMAL,
  476. NULL
  477. );
  478. }
  479. if (m_hOutFile != NULL)
  480. {
  481. DWORD dwBytesWritten = 0;
  482. ::WriteFile (m_hOutFile,
  483. (LPCVOID) pszName,
  484. wcslen(pszName) * sizeof(WCHAR),
  485. &dwBytesWritten,
  486. NULL
  487. );
  488. if (pszValue != NULL)
  489. {
  490. ::WriteFile (m_hOutFile,
  491. (LPCVOID) L"=",
  492. sizeof(WCHAR),
  493. &dwBytesWritten,
  494. NULL
  495. );
  496. ::WriteFile (m_hOutFile,
  497. (LPCVOID) pszValue,
  498. wcslen(pszValue) * sizeof(WCHAR),
  499. &dwBytesWritten,
  500. NULL
  501. );
  502. }
  503. //
  504. // a new line
  505. //
  506. ::WriteFile (m_hOutFile,
  507. (LPCVOID) L"\r\n",
  508. 2 * sizeof(WCHAR),
  509. &dwBytesWritten,
  510. NULL
  511. );
  512. }
  513. }