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.

3174 lines
88 KiB

  1. ////////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // File: read.cpp
  4. //
  5. // History: 16-Nov-00 markder Created.
  6. // 15-Jan-02 jdoherty Modified code to add ID to additional tags.
  7. //
  8. // Desc: This file contains all code needed to manipulate the MSXML
  9. // COM object, walk the document object model (DOM) for an XML
  10. // file, and populate the SdbDatabase internal C++ object.
  11. //
  12. ////////////////////////////////////////////////////////////////////////////////////
  13. #include "StdAfx.h"
  14. #include "xml.h"
  15. #include "make.h"
  16. #include "typeinfo.h"
  17. typedef struct tagAttrStringTableEntry {
  18. LPCTSTR pszName;
  19. DWORD dwValue;
  20. } ATTRSTRINGTABLEENTRY, *PATTRSTRINGTABLEENTRY;
  21. ATTRSTRINGTABLEENTRY g_rgStringSeverity[] = {
  22. { _T("HARDBLOCK" ), SDB_APPHELP_HARDBLOCK},
  23. { _T("MINORPROBLEM"), SDB_APPHELP_MINORPROBLEM},
  24. { _T("NOBLOCK" ), SDB_APPHELP_NOBLOCK},
  25. { _T("REINSTALL" ), SDB_APPHELP_REINSTALL},
  26. { _T("SHIM" ), SDB_APPHELP_SHIM},
  27. { _T("VERSIONSUB" ), SDB_APPHELP_VERSIONSUB},
  28. { _T("NONE" ), SDB_APPHELP_NONE}
  29. };
  30. ATTRSTRINGTABLEENTRY g_rgStringModuleType[] = {
  31. { _T("NONE"), MT_UNKNOWN_MODULE},
  32. { _T("UNKNOWN"), MT_UNKNOWN_MODULE},
  33. { _T("WIN16"), MT_W16_MODULE},
  34. { _T("WIN32"), MT_W32_MODULE},
  35. { _T("DOS"), MT_DOS_MODULE},
  36. };
  37. ATTRSTRINGTABLEENTRY g_rgStringYesNo[] = {
  38. { _T("YES"), TRUE},
  39. { _T("NO"), FALSE}
  40. };
  41. ATTRSTRINGTABLEENTRY g_rgStringDataType[] = {
  42. { _T("DWORD"), eValueDWORD},
  43. { _T("QWORD"), eValueQWORD},
  44. { _T("STRING"), eValueString},
  45. { _T("BINARY"), eValueBinary},
  46. { _T("NONE"), eValueNone}
  47. };
  48. ATTRSTRINGTABLEENTRY g_rgStringOSSKUType[] = {
  49. { _T("PER"), OS_SKU_PER},
  50. { _T("PRO"), OS_SKU_PRO},
  51. { _T("SRV"), OS_SKU_SRV},
  52. { _T("ADS"), OS_SKU_ADS},
  53. { _T("DTC"), OS_SKU_DTC},
  54. { _T("BLA"), OS_SKU_BLA},
  55. { _T("TAB"), OS_SKU_TAB},
  56. { _T("MED"), OS_SKU_MED},
  57. { _T("SBS"), OS_SKU_SBS},
  58. };
  59. ATTRSTRINGTABLEENTRY g_rgStringOSPlatform[] = {
  60. { _T("I386"), OS_PLATFORM_I386},
  61. { _T("IA64"), OS_PLATFORM_IA64}
  62. };
  63. ATTRSTRINGTABLEENTRY g_rgStringRuntimePlatformType[] = {
  64. { _T("X86"), PROCESSOR_ARCHITECTURE_INTEL}, // x86
  65. { _T("IA64"), PROCESSOR_ARCHITECTURE_IA64}, // ia64
  66. { _T("AMD64"), PROCESSOR_ARCHITECTURE_AMD64}, // amd64
  67. { _T("IA3264"), PROCESSOR_ARCHITECTURE_IA32_ON_WIN64} // this means running in wow on ia64
  68. };
  69. ATTRSTRINGTABLEENTRY g_rgStringFilter[] = {
  70. { _T("FIX"), SDB_FILTER_FIX},
  71. { _T("APPHELP"), SDB_FILTER_APPHELP},
  72. { _T("MSI"), SDB_FILTER_MSI},
  73. { _T("DRIVER"), SDB_FILTER_DRIVER},
  74. { _T("NTCOMPAT"), SDB_FILTER_NTCOMPAT},
  75. { _T("CUSTOM"), SDB_FILTER_INCLUDE_ALL}
  76. };
  77. ATTRSTRINGTABLEENTRY g_rgStringOutputType[] = {
  78. { _T("SDB"), SDB_OUTPUT_TYPE_SDB},
  79. { _T("HTMLHELP"), SDB_OUTPUT_TYPE_HTMLHELP},
  80. { _T("MIGDB_INX"), SDB_OUTPUT_TYPE_MIGDB_INX},
  81. { _T("MIGDB_TXT"), SDB_OUTPUT_TYPE_MIGDB_TXT},
  82. { _T("WIN2K_REGISTRY"), SDB_OUTPUT_TYPE_WIN2K_REGISTRY},
  83. { _T("REDIR_MAP"), SDB_OUTPUT_TYPE_REDIR_MAP},
  84. { _T("NTCOMPAT_INF"), SDB_OUTPUT_TYPE_NTCOMPAT_INF},
  85. { _T("NTCOMPAT_MESSAGE_INF"), SDB_OUTPUT_TYPE_NTCOMPAT_MESSAGE_INF},
  86. { _T("APPHELP_REPORT"), SDB_OUTPUT_TYPE_APPHELP_REPORT}
  87. };
  88. ATTRSTRINGTABLEENTRY g_rgStringMatchModeType[] = {
  89. { _T("NORMAL"), MATCHMODE_NORMAL_SHIMDBC },
  90. { _T("EXCLUSIVE"), MATCHMODE_EXCLUSIVE_SHIMDBC },
  91. { _T("ADDITIVE"), MATCHMODE_ADDITIVE_SHIMDBC }
  92. };
  93. LPCTSTR EncodeStringAttribute(
  94. DWORD dwValue,
  95. PATTRSTRINGTABLEENTRY pTable,
  96. int nSize)
  97. {
  98. static LPCTSTR pszUnknown = _T("UNKNOWN");
  99. int i;
  100. for (i = 0; i < nSize; ++i, ++pTable) {
  101. if (dwValue == pTable->dwValue) {
  102. return(pTable->pszName);
  103. }
  104. }
  105. return pszUnknown;
  106. }
  107. BOOL DecodeStringAttribute(
  108. LPCTSTR lpszAttribute,
  109. PATTRSTRINGTABLEENTRY pTable,
  110. int nSize,
  111. DWORD* pdwValue)
  112. {
  113. int i;
  114. //
  115. // Find the indicator and return the flag
  116. //
  117. for (i = 0; i < nSize; ++i, ++pTable) {
  118. if (0 == _tcsicmp(lpszAttribute, pTable->pszName)) {
  119. if (NULL != pdwValue) {
  120. *pdwValue = pTable->dwValue;
  121. }
  122. break;
  123. }
  124. }
  125. return i < nSize;
  126. }
  127. LPCTSTR SeverityIndicatorToStr(SdbAppHelpType Severity)
  128. {
  129. return(EncodeStringAttribute((DWORD)Severity, g_rgStringSeverity, ARRAYSIZE(g_rgStringSeverity)));
  130. }
  131. LPCTSTR ModuleTypeIndicatorToStr(DWORD ModuleType)
  132. {
  133. return(EncodeStringAttribute(ModuleType, g_rgStringModuleType, ARRAYSIZE(g_rgStringModuleType)));
  134. }
  135. #define GetSeverityIndicator(lpszSeverity, pSeverity) \
  136. DecodeStringAttribute(lpszSeverity, g_rgStringSeverity, ARRAYSIZE(g_rgStringSeverity), (DWORD*)pSeverity)
  137. #define GetModuleTypeIndicator(lpszModuleType, pModuleType) \
  138. DecodeStringAttribute(lpszModuleType, g_rgStringModuleType, ARRAYSIZE(g_rgStringModuleType), pModuleType)
  139. #define GetVersionSubIndicator(lpszVersionSub, pVersionSub) \
  140. DecodeStringAttribute(lpszVersionSub, g_rgStringVersionSub, ARRAYSIZE(g_rgStringVersionSub), pVersionSub)
  141. #define GetYesNoIndicator(lpszYesNo, pYesNo) \
  142. DecodeStringAttribute(lpszYesNo, g_rgStringYesNo, ARRAYSIZE(g_rgStringYesNo), pYesNo)
  143. #define GetDataTypeIndicator(lpszDataType, pDataType) \
  144. DecodeStringAttribute(lpszDataType, g_rgStringDataType, ARRAYSIZE(g_rgStringDataType), pDataType)
  145. DWORD GetOSSKUType(LPCTSTR szOSSKUType)
  146. {
  147. DWORD dwReturn = OS_SKU_NONE;
  148. DecodeStringAttribute(szOSSKUType, g_rgStringOSSKUType, ARRAYSIZE(g_rgStringOSSKUType), &dwReturn);
  149. return dwReturn;
  150. }
  151. DWORD GetOSPlatform(LPCTSTR szOSPlatform)
  152. {
  153. DWORD dwReturn = OS_PLATFORM_NONE;
  154. DecodeStringAttribute(szOSPlatform, g_rgStringOSPlatform, ARRAYSIZE(g_rgStringOSPlatform), &dwReturn);
  155. return dwReturn;
  156. }
  157. DWORD GetRuntimePlatformType(LPCTSTR szPlatformType)
  158. {
  159. DWORD dwReturn = PROCESSOR_ARCHITECTURE_UNKNOWN;
  160. DecodeStringAttribute(szPlatformType, g_rgStringRuntimePlatformType, ARRAYSIZE(g_rgStringRuntimePlatformType), &dwReturn);
  161. return dwReturn;
  162. }
  163. DWORD GetFilter(LPCTSTR szFilter)
  164. {
  165. DWORD dwReturn = SDB_FILTER_EXCLUDE_ALL;
  166. CString csFilter(szFilter);
  167. CString csFilterBit;
  168. DWORD dwFilterBit = 0;
  169. long i;
  170. for (i = 0; i <= csFilter.GetLength(); i++) {
  171. switch (csFilter.GetAt(i)) {
  172. case _T(' '):
  173. break;
  174. case _T('|'):
  175. case _T('\0'):
  176. DecodeStringAttribute(csFilterBit, g_rgStringFilter, ARRAYSIZE(g_rgStringFilter), &dwFilterBit);
  177. dwReturn |= dwFilterBit;
  178. csFilterBit.Empty();
  179. break;
  180. default:
  181. csFilterBit += csFilter.GetAt(i);
  182. break;
  183. }
  184. }
  185. return dwReturn;
  186. }
  187. SdbOutputType GetOutputType(LPCTSTR szOutputType)
  188. {
  189. DWORD dwReturn = SDB_OUTPUT_TYPE_UNKNOWN;
  190. DecodeStringAttribute(szOutputType, g_rgStringOutputType, ARRAYSIZE(g_rgStringOutputType), &dwReturn);
  191. return (SdbOutputType) dwReturn;
  192. }
  193. //////////////////////////////////////////////////////////////////////////////////////
  194. //
  195. // ProcureGuidIDAttribute
  196. //
  197. // retrieve Guid "ID" attribute for a given node, possibly update the source and
  198. // generate the attribute if it was not found
  199. //
  200. BOOL ProcureGuidIDAttribute(
  201. SdbDatabase* pDB,
  202. IXMLDOMNode* pNode,
  203. GUID* pGuid,
  204. CString* pcsGUID
  205. )
  206. {
  207. CString csID;
  208. BOOL bSuccess = FALSE;
  209. if (!GetAttribute(_T("ID"), pNode, &csID)) {
  210. if (!GenerateIDAttribute(pNode, &csID, pGuid)) {
  211. SDBERROR_FORMAT((_T("Error generating ID attribute for the node\n%s\n"),
  212. GetXML(pNode)));
  213. goto eh;
  214. }
  215. pDB->m_pCurrentInputFile->m_bSourceUpdated = TRUE;
  216. } else {
  217. if (!GUIDFromString(csID, pGuid)) {
  218. //
  219. // This is the case when we cannot parse the guid and it appears to be
  220. // an invalid guid.
  221. //
  222. SDBERROR_FORMAT((_T("ID attribute is not a valid GUID\n%s\n"), csID));
  223. goto eh;
  224. }
  225. }
  226. if (pcsGUID != NULL) {
  227. *pcsGUID = csID;
  228. }
  229. bSuccess = TRUE;
  230. eh:
  231. return bSuccess;
  232. }
  233. ////////////////////////////////////////////////////////////////////////////////////
  234. //
  235. // Func: GetNextSequentialID
  236. //
  237. // Desc: Determines the next available sequential to be generated.
  238. //
  239. DWORD SdbDatabase::GetNextSequentialID(CString csType)
  240. {
  241. CString csMaxID, csID;
  242. IXMLDOMNodePtr cpXMLAppHelp;
  243. DWORD dwMaxID = 0;
  244. DWORD dwMaxReportedID = 0;
  245. DWORD dwMaxEmpiricalID = 0;
  246. XMLNodeList XQL;
  247. long i;
  248. //
  249. // Determine largest ID
  250. //
  251. if (GetAttribute(_T("MAX_") + csType,
  252. m_cpCurrentDatabaseNode,
  253. &csMaxID)) {
  254. dwMaxReportedID = _ttol(csMaxID);
  255. }
  256. DWORD dwID = 0;
  257. if (!XQL.Query(m_cpCurrentDatabaseNode, _T("//@") + csType)) {
  258. SDBERROR_PROPOGATE();
  259. goto eh;
  260. }
  261. for (i = 0; i < XQL.GetSize(); i++) {
  262. if (!XQL.GetItem(i, &cpXMLAppHelp)) {
  263. SDBERROR_PROPOGATE();
  264. goto eh;
  265. }
  266. csID = GetText(cpXMLAppHelp);
  267. if (csID.GetLength()) {
  268. dwID = _ttol(csID);
  269. if (dwID > dwMaxEmpiricalID) {
  270. dwMaxEmpiricalID = dwID;
  271. }
  272. }
  273. cpXMLAppHelp.Release();
  274. }
  275. if (dwMaxEmpiricalID > dwMaxReportedID) {
  276. dwMaxID = dwMaxEmpiricalID;
  277. } else {
  278. dwMaxID = dwMaxReportedID;
  279. }
  280. dwMaxID++;
  281. csMaxID.Format(_T("%d"), dwMaxID);
  282. if (!AddAttribute(m_cpCurrentDatabaseNode,
  283. _T("MAX_") + csType, csMaxID)) {
  284. }
  285. m_pCurrentInputFile->m_bSourceUpdated = TRUE;
  286. eh:
  287. return dwMaxID;
  288. }
  289. ////////////////////////////////////////////////////////////////////////////////////
  290. //
  291. // Func: ReadDatabase
  292. //
  293. // Desc: Opens an XML file and calls read on the database object.
  294. //
  295. BOOL ReadDatabase(
  296. SdbInputFile* pInputFile,
  297. SdbDatabase* pDatabase)
  298. {
  299. BOOL bSuccess = FALSE;
  300. IXMLDOMNodePtr cpRootNode;
  301. IXMLDOMNodePtr cpDatabase;
  302. XMLNodeList XQL;
  303. if (!OpenXML(pInputFile->m_csName, &cpRootNode)) {
  304. SDBERROR_PROPOGATE();
  305. goto eh;
  306. }
  307. if (!GetChild(_T("DATABASE"), cpRootNode, &cpDatabase)) {
  308. SDBERROR(_T("<DATABASE> object not found"));
  309. goto eh;
  310. }
  311. pDatabase->m_cpCurrentDatabaseNode = cpDatabase;
  312. if (!pDatabase->ReadFromXML(cpDatabase, pDatabase)) {
  313. SDBERROR_PROPOGATE();
  314. goto eh;
  315. }
  316. if (pInputFile->m_bSourceUpdated) {
  317. //
  318. // We need to modify original XML file
  319. //
  320. if (!SaveXMLFile(pInputFile->m_csName, cpDatabase)) {
  321. SDBERROR_PROPOGATE();
  322. goto eh;
  323. }
  324. }
  325. bSuccess = TRUE;
  326. eh:
  327. pDatabase->m_cpCurrentDatabaseNode = NULL;
  328. return bSuccess;
  329. }
  330. ////////////////////////////////////////////////////////////////////////////////////
  331. //
  332. // Func: ReadCallers
  333. //
  334. // Desc: Reads in all <INCLUDE> and <EXCLUDE> child tags on node pNode and
  335. // adds them as SdbCaller objects to the array pointed to by prgCallers.
  336. //
  337. BOOL ReadCallers(
  338. SdbArray<SdbCaller>* prgCallers,
  339. SdbDatabase* pDB,
  340. IXMLDOMNode* pNode)
  341. {
  342. USES_CONVERSION;
  343. BOOL bSuccess = FALSE;
  344. long nIndex = 0;
  345. long nListLength = 0;
  346. IXMLDOMNodePtr cpCallerNode;
  347. XMLNodeList NodeList;
  348. SdbCaller* pSdbCaller = NULL;
  349. CString csNodeName, csTemp;
  350. if (!NodeList.GetChildNodes(pNode)) {
  351. //
  352. // No child nodes -- that's fine, return success.
  353. //
  354. bSuccess = TRUE;
  355. goto eh;
  356. }
  357. for (nIndex = 0; nIndex < NodeList.GetSize(); nIndex++) {
  358. if (!NodeList.GetItem(nIndex, &cpCallerNode)) {
  359. SDBERROR(_T("Could not retrieve INCLUDE/EXCLUDE item"));
  360. goto eh;
  361. }
  362. if (GetNodeName(cpCallerNode) == _T("INCLUDE") ||
  363. GetNodeName(cpCallerNode) == _T("EXCLUDE")) {
  364. pSdbCaller = new SdbCaller();
  365. if (pSdbCaller == NULL) {
  366. SDBERROR(_T("Error allocating SdbCaller object"));
  367. goto eh;
  368. }
  369. if (!pSdbCaller->ReadFromXML(cpCallerNode, pDB)) {
  370. SDBERROR_PROPOGATE();
  371. delete pSdbCaller;
  372. pSdbCaller = NULL;
  373. goto eh;
  374. }
  375. //
  376. // Add in reverse order to help the Shim engine's logic
  377. // building code
  378. //
  379. prgCallers->InsertAt(0, pSdbCaller);
  380. pSdbCaller = NULL;
  381. }
  382. cpCallerNode.Release();
  383. }
  384. bSuccess = TRUE;
  385. eh:
  386. return bSuccess;
  387. }
  388. BOOL ReadLocalizedNames(
  389. SdbArray<SdbLocalizedString>* prgNames,
  390. CString csTag,
  391. SdbDatabase* pDB,
  392. IXMLDOMNode* pNode)
  393. {
  394. BOOL bSuccess = FALSE;
  395. IXMLDOMNodePtr cpTag;
  396. XMLNodeList XQL;
  397. CString csTemp, csLangID, csName;
  398. SdbLocalizedString* pLocString = NULL;
  399. long i;
  400. if (!XQL.Query(pNode, csTag)) {
  401. SDBERROR_PROPOGATE();
  402. goto eh;
  403. }
  404. for (i = 0; i < XQL.GetSize(); i++) {
  405. CString csID;
  406. GUID ID = GUID_NULL;
  407. if (!XQL.GetItem(i, &cpTag)) {
  408. SDBERROR_PROPOGATE();
  409. goto eh;
  410. }
  411. if (!GetAttribute(_T("LANGID"), cpTag, &csLangID)) {
  412. if (!pDB->m_csCurrentLangID.GetLength())
  413. {
  414. SDBERROR_FORMAT((
  415. _T("LOCALIZED_NAME tag requires LANGID attribute if there is no LANGID on the DATABASE node\n%s\n"),
  416. GetXML(cpTag)));
  417. goto eh;
  418. }
  419. csLangID = pDB->m_csCurrentLangID;
  420. }
  421. if (!ProcureGuidIDAttribute(pDB, cpTag, &ID, &csID)) {
  422. SDBERROR_PROPOGATE();
  423. goto eh;
  424. }
  425. if (!GetAttribute(_T("NAME"), cpTag, &csName)) {
  426. SDBERROR_FORMAT((
  427. _T("LOCALIZED_NAME tag requires NAME attribute:\n%s\n"),
  428. GetXML(cpTag)));
  429. goto eh;
  430. }
  431. pLocString = new SdbLocalizedString();
  432. pLocString->m_csName = csName;
  433. pLocString->m_csLangID = csLangID;
  434. pLocString->m_csValue = GetInnerXML(cpTag);
  435. prgNames->Add(pLocString);
  436. }
  437. bSuccess = TRUE;
  438. eh:
  439. return bSuccess;
  440. }
  441. BOOL SdbDatabase::ReadFromXML(
  442. IXMLDOMNode* pNode,
  443. SdbDatabase* pDB)
  444. {
  445. BOOL bSuccess = FALSE;
  446. long i;
  447. long nListCount = 0;
  448. IXMLDOMNodePtr cpXMLLibrary;
  449. IXMLDOMNodePtr cpXMLAppHelp;
  450. IXMLDOMNodePtr cpXMLA;
  451. IXMLDOMNodePtr cpXMLHTMLHELPTemplate;
  452. IXMLDOMNodePtr cpXMLHTMLHELPFirstScreen;
  453. CString csHTMLHELPID, csXQL, csHistoryClause;
  454. CString csID, csRedirID, csRedirURL, csOSVersion;
  455. CString csTemplateName;
  456. DWORD dwHTMLHELPID = 0;
  457. XMLNodeList XQL;
  458. SdbLocalizedString* pRedir = NULL;
  459. SdbLocalizedString* pHTMLHelpTemplate = NULL;
  460. SdbLocalizedString* pHTMLHelpFirstScreen = NULL;
  461. //
  462. // Read the name of the database
  463. //
  464. ReadName(pNode, &m_csName);
  465. //
  466. // Read the LangID for this database file
  467. //
  468. m_csCurrentLangID = _T("---");
  469. GetAttribute(_T("LANGID"), pNode, &m_csCurrentLangID);
  470. //
  471. // Read the default ID
  472. //
  473. if (!GetAttribute(_T("ID"), pNode, &csID)) {
  474. //
  475. // Guid was not found. We need to generate it.
  476. //
  477. if (!GenerateIDAttribute(pNode, &csID, &m_ID)) {
  478. SDBERROR_FORMAT((_T("Error generating ID attribute for the node\n%s\n"),
  479. GetXML(pNode)));
  480. goto eh;
  481. }
  482. pDB->m_pCurrentInputFile->m_bSourceUpdated = TRUE;
  483. } else if (!GUIDFromString(csID, &m_ID)) {
  484. //
  485. // This is the case when we cannot parse the guid and it appears to be
  486. // an invalid guid.
  487. //
  488. SDBERROR_FORMAT((_T("ID attribute is not a valid GUID\n%s\n"), csID));
  489. goto eh;
  490. }
  491. //
  492. // Add REDIR_IDs to <A> tags if necessary
  493. //
  494. if (!XQL.Query(pNode, _T("//A"))) {
  495. SDBERROR_PROPOGATE();
  496. goto eh;
  497. }
  498. for (i = 0; i < XQL.GetSize(); i++) {
  499. if (!XQL.GetItem(i, &cpXMLA)) {
  500. SDBERROR_PROPOGATE();
  501. goto eh;
  502. }
  503. if (!GetAttribute(_T("REDIR_ID"), cpXMLA, &csRedirID)) {
  504. //
  505. // Not there, generate it.
  506. //
  507. csRedirID.Format(_T("%d"), GetNextSequentialID(_T("REDIR_ID")));
  508. if (!AddAttribute(cpXMLA, _T("REDIR_ID"), csRedirID)) {
  509. SDBERROR_PROPOGATE();
  510. goto eh;
  511. }
  512. }
  513. if (!GetAttribute(_T("HREF"), cpXMLA, &csRedirURL)) {
  514. //
  515. // No HREF attribute. Take the link from the display name.
  516. //
  517. csRedirURL = GetText(cpXMLA);
  518. }
  519. pRedir = (SdbLocalizedString *) m_rgRedirs.LookupName(csRedirID, m_csCurrentLangID);
  520. if (pRedir) {
  521. SDBERROR_FORMAT((_T("Non-unique REDIR_ID:\n%s\n"), GetXML(cpXMLA)));
  522. goto eh;
  523. }
  524. pRedir = new SdbLocalizedString();
  525. pRedir->m_csName = csRedirID;
  526. pRedir->m_csLangID = m_csCurrentLangID;
  527. pRedir->m_csValue = csRedirURL;
  528. m_rgRedirs.Add(pRedir);
  529. cpXMLA = NULL;
  530. }
  531. //
  532. // Read HTMLHELP_TEMPLATE
  533. //
  534. if (!XQL.Query(pNode, _T("HTMLHELP_TEMPLATE"))) {
  535. SDBERROR_PROPOGATE();
  536. goto eh;
  537. }
  538. for (i = 0; i < XQL.GetSize(); i++) {
  539. if (!XQL.GetItem(i, &cpXMLHTMLHELPTemplate)) {
  540. SDBERROR_PROPOGATE();
  541. goto eh;
  542. }
  543. if (!GetAttribute(_T("NAME"), cpXMLHTMLHELPTemplate, &csTemplateName)) {
  544. SDBERROR_FORMAT((_T("HTMLHELP_TEMPLATE requires NAME attribute:\n%s\n"),
  545. GetXML(cpXMLHTMLHELPTemplate)));
  546. goto eh;
  547. }
  548. pHTMLHelpTemplate = new SdbLocalizedString();
  549. pHTMLHelpTemplate->m_csName = csTemplateName;
  550. pHTMLHelpTemplate->m_csLangID = m_csCurrentLangID;
  551. pHTMLHelpTemplate->m_csValue = GetInnerXML(cpXMLHTMLHELPTemplate);
  552. m_rgHTMLHelpTemplates.Add(pHTMLHelpTemplate);
  553. }
  554. //
  555. // Read HTMLHELP_FIRST_SCREEN
  556. //
  557. if (!XQL.Query(pNode, _T("HTMLHELP_FIRST_SCREEN"))) {
  558. SDBERROR_PROPOGATE();
  559. goto eh;
  560. }
  561. if (XQL.GetSize() > 1) {
  562. SDBERROR(_T("More than one HTMLHELP_FIRST_SCREEN tags found:\n%s\n"));
  563. goto eh;
  564. }
  565. if (XQL.GetSize() == 1) {
  566. if (!XQL.GetItem(0, &cpXMLHTMLHELPFirstScreen)) {
  567. SDBERROR_PROPOGATE();
  568. goto eh;
  569. }
  570. pHTMLHelpFirstScreen = new SdbLocalizedString();
  571. pHTMLHelpFirstScreen->m_csName = _T("HTMLHELP_FIRST_SCREEN");
  572. pHTMLHelpFirstScreen->m_csLangID = m_csCurrentLangID;
  573. pHTMLHelpFirstScreen->m_csValue = GetInnerXML(cpXMLHTMLHELPFirstScreen);
  574. m_rgHTMLHelpFirstScreens.Add(pHTMLHelpFirstScreen);
  575. }
  576. //
  577. // Read Library
  578. //
  579. if (!XQL.Query(pNode, _T("LIBRARY"))) {
  580. SDBERROR_PROPOGATE();
  581. goto eh;
  582. }
  583. for (i = 0; i < XQL.GetSize(); i++) {
  584. if (!XQL.GetItem(i, &cpXMLLibrary)) {
  585. SDBERROR_PROPOGATE();
  586. goto eh;
  587. }
  588. if (!m_Library.ReadFromXML(cpXMLLibrary, this)) {
  589. SDBERROR_PROPOGATE();
  590. goto eh;
  591. }
  592. cpXMLLibrary.Release();
  593. }
  594. //
  595. // Action tags
  596. //
  597. if (!m_rgAction.ReadFromXML(_T("ACTION"), pDB, pNode, NULL)) {
  598. SDBERROR_PROPOGATE();
  599. goto eh;
  600. }
  601. //
  602. // Construct XQL from m_prgHistoryKeywords
  603. //
  604. if (m_pCurrentMakefile->m_rgHistoryKeywords.GetSize() > 0) {
  605. for (i = 0; i < m_pCurrentMakefile->m_rgHistoryKeywords.GetSize(); i++) {
  606. if (i > 0) {
  607. csHistoryClause += _T(" or ");
  608. }
  609. csHistoryClause = _T("KEYWORD/@NAME = '") +
  610. m_pCurrentMakefile->m_rgHistoryKeywords.GetAt(i) + _T("'");
  611. }
  612. csXQL = _T("APP[") + csHistoryClause + _T("]");
  613. csXQL += _T(" | DRIVER[") + csHistoryClause + _T("]");
  614. } else {
  615. csXQL = _T("APP | DRIVER");
  616. }
  617. if (!m_rgApps.ReadFromXML(csXQL, pDB, pNode)) {
  618. SDBERROR_PROPOGATE();
  619. goto eh;
  620. }
  621. m_pDB = this;
  622. bSuccess = TRUE;
  623. eh:
  624. return bSuccess;
  625. }
  626. BOOL SdbLibrary::ReadFromXML(
  627. IXMLDOMNode* pNode,
  628. SdbDatabase* pDB)
  629. {
  630. BOOL bSuccess = FALSE;
  631. if (!m_rgFiles.ReadFromXML(_T(".//FILE"), pDB, pNode)) {
  632. SDBERROR_PROPOGATE();
  633. goto eh;
  634. }
  635. if (!m_rgShims.ReadFromXML(_T("SHIM"), pDB, pNode)) {
  636. SDBERROR_PROPOGATE();
  637. goto eh;
  638. }
  639. if (!m_rgPatches.ReadFromXML(_T("PATCH"), pDB, pNode)) {
  640. SDBERROR_PROPOGATE();
  641. goto eh;
  642. }
  643. if (!m_rgFlags.ReadFromXML(_T("FLAG"), pDB, pNode)) {
  644. SDBERROR_PROPOGATE();
  645. goto eh;
  646. }
  647. if (!m_rgLayers.ReadFromXML(_T("LAYER"), pDB, pNode)) {
  648. SDBERROR_PROPOGATE();
  649. goto eh;
  650. }
  651. if (!m_rgMsiTransforms.ReadFromXML(_T("MSI_TRANSFORM"), pDB, pNode)) {
  652. SDBERROR_PROPOGATE();
  653. goto eh;
  654. }
  655. if (!pDB->m_rgContactInfo.ReadFromXML(_T("CONTACT_INFO"), pDB, pNode, NULL, FALSE, _T("VENDOR"))) {
  656. SDBERROR_PROPOGATE();
  657. goto eh;
  658. }
  659. if (!pDB->m_rgMessageTemplates.ReadFromXML(_T("TEMPLATE"), pDB, pNode)) {
  660. SDBERROR_PROPOGATE();
  661. goto eh;
  662. }
  663. if (!pDB->m_rgMessages.ReadFromXML(_T("MESSAGE"), pDB, pNode)) {
  664. SDBERROR_PROPOGATE();
  665. goto eh;
  666. }
  667. if (!ReadCallers(&m_rgCallers, pDB, pNode)) {
  668. SDBERROR_PROPOGATE();
  669. goto eh;
  670. }
  671. if (!ReadLocalizedNames(
  672. &(pDB->m_rgLocalizedAppNames), _T("LOCALIZED_APP_NAME"), pDB, pNode)) {
  673. SDBERROR_PROPOGATE();
  674. goto eh;
  675. }
  676. if (!ReadLocalizedNames(
  677. &(pDB->m_rgLocalizedVendorNames), _T("LOCALIZED_VENDOR_NAME"), pDB, pNode)) {
  678. SDBERROR_PROPOGATE();
  679. goto eh;
  680. }
  681. m_pDB = pDB;
  682. bSuccess = TRUE;
  683. eh:
  684. return bSuccess;
  685. }
  686. BOOL SdbFile::ReadFromXML(
  687. IXMLDOMNode* pNode,
  688. SdbDatabase* pDB)
  689. {
  690. BOOL bSuccess = FALSE;
  691. CString csFilter;
  692. if (!ReadName(pNode, &m_csName)) {
  693. SDBERROR_PROPOGATE();
  694. goto eh;
  695. }
  696. if (GetAttribute(_T("FILTER"), pNode, &csFilter)) {
  697. m_dwFilter = GetFilter(csFilter) | SDB_FILTER_OVERRIDE;
  698. }
  699. m_pDB = pDB;
  700. bSuccess = TRUE;
  701. eh:
  702. return bSuccess;
  703. }
  704. BOOL SdbShim::ReadFromXML(
  705. IXMLDOMNode* pNode,
  706. SdbDatabase* pDB)
  707. {
  708. BOOL bSuccess = FALSE;
  709. long i;
  710. CString csTemp, csID;
  711. IXMLDOMNodePtr cpDesc;
  712. if (!ReadName(pNode, &m_csName)) {
  713. SDBERROR_PROPOGATE();
  714. goto eh;
  715. }
  716. if (!GetAttribute(_T("FILE"), pNode, &m_csDllFile) && g_bStrict) {
  717. SDBERROR_FORMAT((_T("<SHIM> requires FILE attribute:\n%s\n\n"),
  718. GetXML(pNode)));
  719. goto eh;
  720. }
  721. if (!ProcureGuidIDAttribute(pDB, pNode, &m_ID, &csID)) {
  722. SDBERROR_PROPOGATE();
  723. goto eh;
  724. }
  725. if (GetChild(_T("DESCRIPTION"), pNode, &cpDesc)) {
  726. m_csDesc = GetText(cpDesc);
  727. }
  728. csTemp.Empty();
  729. if (GetAttribute(_T("PURPOSE"), pNode, &csTemp)) {
  730. if (csTemp == _T("GENERAL")) {
  731. m_Purpose = SDB_PURPOSE_GENERAL;
  732. } else {
  733. m_Purpose = SDB_PURPOSE_SPECIFIC;
  734. }
  735. }
  736. //
  737. // Check what OS PLATFORM this entry is meant for
  738. //
  739. csTemp.Empty();
  740. if (GetAttribute(_T("OS_PLATFORM"), pNode, &csTemp)) {
  741. //
  742. // Decode it. This string is a semi-colon delimited set
  743. // of OS PLATFORMs.
  744. //
  745. if (!DecodeString(csTemp, &m_dwOSPlatform, GetOSPlatform)) {
  746. SDBERROR_FORMAT((_T("OS_PLATFORM attribute syntax error: %s"), csTemp));
  747. goto eh;
  748. }
  749. }
  750. csTemp.Empty();
  751. if (GetAttribute(_T("APPLY_ALL_SHIMS"), pNode, &csTemp)) {
  752. if (csTemp == _T("YES")) {
  753. m_bApplyAllShims = TRUE;
  754. }
  755. }
  756. if (!ReadCallers(&m_rgCallers, pDB, pNode)) {
  757. SDBERROR(_T("Could not read INCLUDE/EXCLUDE info of <SHIM> tag"));
  758. goto eh;
  759. }
  760. m_pDB = pDB;
  761. bSuccess = TRUE;
  762. eh:
  763. return bSuccess;
  764. }
  765. BOOL SdbShimRef::ReadFromXML(
  766. IXMLDOMNode* pNode,
  767. SdbDatabase* pDB)
  768. {
  769. BOOL bSuccess = FALSE;
  770. if (!ReadName(pNode, &m_csName)) {
  771. SDBERROR_PROPOGATE();
  772. goto eh;
  773. }
  774. m_pShim = (SdbShim *) pDB->m_Library.m_rgShims.LookupName(m_csName);
  775. if (m_pShim == NULL && g_bStrict) {
  776. SDBERROR_FORMAT((_T("SHIM \"%s\" not found in library:\n%s\n\n"),
  777. m_csName, GetXML(pNode)));
  778. goto eh;
  779. }
  780. GetAttribute(_T("COMMAND_LINE"), pNode, &m_csCommandLine);
  781. if (!ReadCallers(&m_rgCallers, pDB, pNode)) {
  782. SDBERROR(_T("Could not read INCLUDE/EXCLUDE info of <SHIM> tag"));
  783. goto eh;
  784. }
  785. // finally, read all the child data elements
  786. if (!m_rgData.ReadFromXML(_T("DATA"), pDB, pNode)) {
  787. SDBERROR_PROPOGATE();
  788. goto eh;
  789. }
  790. m_pDB = pDB;
  791. bSuccess = TRUE;
  792. eh:
  793. return bSuccess;
  794. }
  795. BOOL SdbPatch::ReadFromXML(
  796. IXMLDOMNode* pNode,
  797. SdbDatabase* pDB)
  798. {
  799. BOOL bSuccess = FALSE;
  800. PATCHOP PatchOp;
  801. PATCHWRITEDATA PatchWriteData;
  802. PATCHMATCHDATA PatchMatchData;
  803. XMLNodeList NodeList;
  804. IXMLDOMNodePtr cpOpNode;
  805. long i;
  806. CString csNodeName, csError;
  807. CString csModule, csOffset;
  808. CString csID;
  809. DWORD dwByteCount = 0;
  810. BYTE* pBytes = NULL;
  811. if (!ReadName(pNode, &m_csName)) {
  812. SDBERROR_PROPOGATE();
  813. goto eh;
  814. }
  815. if (!ProcureGuidIDAttribute(pDB, pNode, &m_ID, &csID)) {
  816. SDBERROR_PROPOGATE();
  817. goto eh;
  818. }
  819. //
  820. // NOTE: We don't write the patch description in the binary database
  821. // so there's no point reading it either.
  822. //
  823. NodeList.GetChildNodes(pNode);
  824. for (i = 0; i < NodeList.GetSize(); i++) {
  825. if (!NodeList.GetItem(i, &cpOpNode)) {
  826. SDBERROR(_T("Could not retrieve PATCH instructions"));
  827. goto eh;
  828. }
  829. csNodeName = GetNodeName(cpOpNode);
  830. if (csNodeName == _T("MATCH_BYTES")) {
  831. if (!GetAttribute(_T("MODULE"), cpOpNode, &csModule)) {
  832. csError.Format(_T("<MATCH_BYTES> requires MODULE attribute:\n%s\n"),
  833. GetXML(cpOpNode));
  834. SDBERROR(csError);
  835. goto eh;
  836. }
  837. if (!GetAttribute(_T("OFFSET"), cpOpNode, &csOffset)) {
  838. csError.Format(_T("<MATCH_BYTES> requires OFFSET attribute:\n%s\n"),
  839. GetXML(cpOpNode));
  840. SDBERROR(csError);
  841. goto eh;
  842. }
  843. PatchOp.dwOpcode = PMAT;
  844. PatchMatchData.rva.address = StringToDword(csOffset);
  845. if (csModule.GetLength() >= sizeof(PatchMatchData.rva.moduleName)) {
  846. csError.Format(_T("MODULE attribute greater than %d characters:\n%s\n"),
  847. sizeof(PatchMatchData.rva.moduleName) - 1,
  848. GetXML(cpOpNode));
  849. SDBERROR(csError);
  850. goto eh;
  851. }
  852. dwByteCount = GetByteStringSize(GetText(cpOpNode));
  853. if (dwByteCount == 0xFFFFFFFF) {
  854. csError.Format(_T("Bad byte string for patch operation:\n%s\n"),
  855. GetXML(cpOpNode));
  856. SDBERROR(csError);
  857. goto eh;
  858. }
  859. PatchMatchData.dwSizeData = dwByteCount;
  860. if (csModule == _T("%EXE%")) {
  861. PatchMatchData.rva.moduleName[0] = _T('\0');
  862. } else {
  863. StringCchCopy(PatchMatchData.rva.moduleName,
  864. ARRAYSIZE(PatchMatchData.rva.moduleName),
  865. csModule);
  866. }
  867. pBytes = (BYTE*) new BYTE[dwByteCount];
  868. if (pBytes == NULL) {
  869. SDBERROR(_T("Error allocating memory for <PATCH> block."));
  870. goto eh;
  871. }
  872. if (GetBytesFromString(GetText(cpOpNode), pBytes, dwByteCount) == 0xFFFFFFFF) {
  873. csError.Format(_T("Bad byte string for patch operation:\n%s\n"),
  874. GetXML(cpOpNode));
  875. SDBERROR(csError);
  876. goto eh;
  877. }
  878. PatchOp.dwNextOpcode = sizeof(DWORD) * 3
  879. + sizeof(RELATIVE_MODULE_ADDRESS)
  880. + dwByteCount;
  881. AddBlobBytes(&PatchOp, sizeof(DWORD) * 2);
  882. AddBlobBytes(&PatchMatchData, sizeof(DWORD) + sizeof(RELATIVE_MODULE_ADDRESS));
  883. AddBlobBytes(pBytes, dwByteCount);
  884. delete [] pBytes;
  885. pBytes = NULL;
  886. } else if (csNodeName == _T("WRITE_BYTES")) {
  887. if (!GetAttribute(_T("MODULE"), cpOpNode, &csModule)) {
  888. csError.Format(_T("<WRITE_BYTES> requires MODULE attribute:\n%s\n"),
  889. GetXML(cpOpNode));
  890. SDBERROR(csError);
  891. goto eh;
  892. }
  893. if (!GetAttribute(_T("OFFSET"), cpOpNode, &csOffset)) {
  894. csError.Format(_T("<WRITE_BYTES> requires OFFSET attribute:\n%s\n"),
  895. GetXML(cpOpNode));
  896. SDBERROR(csError);
  897. goto eh;
  898. }
  899. PatchOp.dwOpcode = PWD;
  900. PatchWriteData.rva.address = StringToDword(csOffset);
  901. if (csModule.GetLength() >= sizeof(PatchWriteData.rva.moduleName)) {
  902. csError.Format(_T("MODULE attribute greater than %d characters:\n%s\n"),
  903. sizeof(PatchWriteData.rva.moduleName) - 1,
  904. GetXML(cpOpNode));
  905. SDBERROR(csError);
  906. goto eh;
  907. }
  908. dwByteCount = GetByteStringSize(GetText(cpOpNode));
  909. if (dwByteCount == 0xFFFFFFFF) {
  910. csError.Format(_T("Bad byte string for patch operation:\n%s\n"),
  911. GetXML(cpOpNode));
  912. SDBERROR(csError);
  913. goto eh;
  914. }
  915. PatchWriteData.dwSizeData = dwByteCount;
  916. if (csModule == _T("%EXE%")) {
  917. PatchWriteData.rva.moduleName[0] = _T('\0');
  918. } else {
  919. StringCchCopy(PatchWriteData.rva.moduleName,
  920. ARRAYSIZE(PatchWriteData.rva.moduleName),
  921. csModule);
  922. }
  923. pBytes = (BYTE*) new BYTE[dwByteCount];
  924. if (pBytes == NULL) {
  925. SDBERROR(_T("Error allocating memory for <PATCH> block."));
  926. goto eh;
  927. }
  928. if (GetBytesFromString(GetText(cpOpNode), pBytes, dwByteCount) == 0xFFFFFFFF) {
  929. csError.Format(_T("Bad byte string for patch operation:\n%s\n"),
  930. GetXML(cpOpNode));
  931. SDBERROR(csError);
  932. goto eh;
  933. }
  934. PatchOp.dwNextOpcode = sizeof(DWORD) * 3
  935. + sizeof(RELATIVE_MODULE_ADDRESS)
  936. + dwByteCount;
  937. AddBlobBytes(&PatchOp, sizeof(DWORD) * 2);
  938. AddBlobBytes(&PatchWriteData, sizeof(DWORD) + sizeof(RELATIVE_MODULE_ADDRESS));
  939. AddBlobBytes(pBytes, dwByteCount);
  940. delete [] pBytes;
  941. pBytes = NULL;
  942. }
  943. cpOpNode.Release();
  944. }
  945. //
  946. // Add terminating NULL bytes
  947. //
  948. ZeroMemory(&PatchOp, sizeof(DWORD) * 2);
  949. AddBlobBytes(&PatchOp, sizeof(DWORD) * 2);
  950. m_pDB = pDB;
  951. bSuccess = TRUE;
  952. eh:
  953. return bSuccess;
  954. }
  955. BOOL SdbLayer::ReadFromXML(
  956. IXMLDOMNode* pNode,
  957. SdbDatabase* pDB)
  958. {
  959. BOOL bSuccess = FALSE;
  960. CString csID;
  961. CString csTemp;
  962. IXMLDOMNodePtr cpDesc;
  963. if (!ReadName(pNode, &m_csName)) {
  964. SDBERROR_PROPOGATE();
  965. goto eh;
  966. }
  967. if (GetChild(_T("DESCRIPTION"), pNode, &cpDesc)) {
  968. m_csDesc = GetText(cpDesc);
  969. }
  970. //
  971. // Check what OS PLATFORM this entry is meant for
  972. //
  973. if (GetAttribute(_T("OS_PLATFORM"), pNode, &csTemp)) {
  974. //
  975. // Decode it. This string is a semi-colon delimited set
  976. // of OS PLATFORMs.
  977. //
  978. if (!DecodeString(csTemp, &m_dwOSPlatform, GetOSPlatform)) {
  979. SDBERROR_FORMAT((_T("OS_PLATFORM attribute syntax error: %s"), csTemp));
  980. goto eh;
  981. }
  982. }
  983. if (!m_rgShimRefs.ReadFromXML(_T("SHIM"), pDB, pNode)) {
  984. SDBERROR_PROPOGATE();
  985. goto eh;
  986. }
  987. if (!m_rgFlagRefs.ReadFromXML(_T("FLAG"), pDB, pNode)) {
  988. SDBERROR_PROPOGATE();
  989. goto eh;
  990. }
  991. if (!ProcureGuidIDAttribute(pDB, pNode, &m_ID, &csID)) {
  992. SDBERROR_PROPOGATE();
  993. goto eh;
  994. }
  995. GetAttribute(_T("DISPLAY_NAME"), pNode, &m_csDisplayName);
  996. m_pDB = pDB;
  997. bSuccess = TRUE;
  998. eh:
  999. return bSuccess;
  1000. }
  1001. BOOL SdbLayerRef::ReadFromXML(
  1002. IXMLDOMNode* pNode,
  1003. SdbDatabase* pDB)
  1004. {
  1005. BOOL bSuccess = FALSE;
  1006. if (!ReadName(pNode, &m_csName)) {
  1007. SDBERROR_PROPOGATE();
  1008. goto eh;
  1009. }
  1010. m_pLayer = (SdbLayer*) pDB->m_Library.m_rgLayers.LookupName(m_csName);
  1011. //
  1012. // finally, read all the child data elements
  1013. //
  1014. if (!m_rgData.ReadFromXML(_T("DATA"), pDB, pNode)) {
  1015. SDBERROR_PROPOGATE();
  1016. goto eh;
  1017. }
  1018. m_pDB = pDB;
  1019. bSuccess = TRUE;
  1020. eh:
  1021. return bSuccess;
  1022. }
  1023. BOOL SdbCaller::ReadFromXML(
  1024. IXMLDOMNode* pNode,
  1025. SdbDatabase* pDB)
  1026. {
  1027. BOOL bSuccess = FALSE;
  1028. CString csNodeName, csTemp;
  1029. csNodeName = GetNodeName(pNode);
  1030. if (csNodeName == _T("INCLUDE")) {
  1031. m_CallerType = SDB_CALLER_INCLUDE;
  1032. } else if (csNodeName == _T("EXCLUDE")) {
  1033. m_CallerType = SDB_CALLER_EXCLUDE;
  1034. }
  1035. if (!GetAttribute(_T("MODULE"), pNode, &csTemp)) {
  1036. SDBERROR_FORMAT((_T("<INCLUDE> or <EXCLUDE> requires MODULE attribute:\n%s\n"),
  1037. GetXML(pNode)));
  1038. goto eh;
  1039. }
  1040. //
  1041. // Convert %EXE% keyword to $ for optimization
  1042. //
  1043. if (csTemp.CompareNoCase(_T("%EXE%")) == 0) {
  1044. csTemp = _T("$");
  1045. }
  1046. m_csModule = csTemp;
  1047. m_pDB = pDB;
  1048. bSuccess = TRUE;
  1049. eh:
  1050. return bSuccess;
  1051. }
  1052. BOOL SdbFlag::ReadFromXML(
  1053. IXMLDOMNode* pNode,
  1054. SdbDatabase* pDB)
  1055. {
  1056. BOOL bSuccess = FALSE;
  1057. CString csMask;
  1058. CString csType;
  1059. CString csTemp;
  1060. CString csID;
  1061. IXMLDOMNodePtr cpDesc;
  1062. if (!ReadName(pNode, &m_csName)) {
  1063. SDBERROR_PROPOGATE();
  1064. goto eh;
  1065. }
  1066. if (!ProcureGuidIDAttribute(pDB, pNode, &m_ID, &csID)) {
  1067. SDBERROR_PROPOGATE();
  1068. goto eh;
  1069. }
  1070. if (GetChild(_T("DESCRIPTION"), pNode, &cpDesc)) {
  1071. m_csDesc = GetText(cpDesc);
  1072. }
  1073. if (!GetAttribute(_T("TYPE"), pNode, &csType)) {
  1074. //
  1075. // By default the apphacks are for kernel.
  1076. //
  1077. SDBERROR_FORMAT((_T("<FLAG> requires TYPE attribute:\n%s\n"),
  1078. GetXML(pNode)));
  1079. goto eh;
  1080. }
  1081. csTemp.Empty();
  1082. if (GetAttribute(_T("PURPOSE"), pNode, &csTemp)) {
  1083. if (csTemp == _T("GENERAL")) {
  1084. m_Purpose = SDB_PURPOSE_GENERAL;
  1085. } else {
  1086. m_Purpose = SDB_PURPOSE_SPECIFIC;
  1087. }
  1088. }
  1089. if (!SetType(csType)) {
  1090. SDBERROR_FORMAT((_T("<FLAG> bad TYPE attribute:\n%s\n"),
  1091. GetXML(pNode)));
  1092. goto eh;
  1093. }
  1094. if (!GetAttribute(_T("MASK"), pNode, &csMask)) {
  1095. SDBERROR_FORMAT((_T("<FLAG> requires MASK attribute:\n%s\n"),
  1096. GetXML(pNode)));
  1097. goto eh;
  1098. }
  1099. m_ullMask = StringToQword(csMask);
  1100. m_pDB = pDB;
  1101. bSuccess = TRUE;
  1102. eh:
  1103. return bSuccess;
  1104. }
  1105. BOOL SdbFlagRef::ReadFromXML(
  1106. IXMLDOMNode* pNode,
  1107. SdbDatabase* pDB)
  1108. {
  1109. BOOL bSuccess = FALSE;
  1110. if (!ReadName(pNode, &m_csName)) {
  1111. SDBERROR_PROPOGATE();
  1112. goto eh;
  1113. }
  1114. m_pFlag = (SdbFlag *) pDB->m_Library.m_rgFlags.LookupName(m_csName);
  1115. if (m_pFlag == NULL && g_bStrict) {
  1116. SDBERROR_FORMAT((_T("SHIM \"%s\" not found in library:\n%s\n\n"),
  1117. m_csName, GetXML(pNode)));
  1118. goto eh;
  1119. }
  1120. //
  1121. // see if we have cmd line, applicable mostly to ntvdm flags
  1122. //
  1123. GetAttribute(_T("COMMAND_LINE"), pNode, &m_csCommandLine);
  1124. m_pDB = pDB;
  1125. bSuccess = TRUE;
  1126. eh:
  1127. return bSuccess;
  1128. }
  1129. BOOL SdbApp::ReadFromXML(
  1130. IXMLDOMNode* pNode,
  1131. SdbDatabase* pDB)
  1132. {
  1133. BOOL bSuccess = FALSE;
  1134. XMLNodeList XQL;
  1135. IXMLDOMNodePtr cpHistoryNode;
  1136. IXMLDOMNodePtr cpAppHelpNode;
  1137. SdbAppHelpRef* pAppHelpRef1 = NULL;
  1138. SdbAppHelpRef* pAppHelpRef2 = NULL;
  1139. long i, j;
  1140. CString csTemp, csTemp2, csTemp3, csID;
  1141. COleDateTime odtLastRevision, odtCandidate;
  1142. if (!ReadName(pNode, &m_csName)) {
  1143. SDBERROR_PROPOGATE();
  1144. goto eh;
  1145. }
  1146. GetAttribute(_T("VENDOR"), pNode, &m_csVendor);
  1147. GetAttribute(_T("VENDOR"), pNode, &m_csVendorXML, TRUE);
  1148. GetAttribute(_T("VERSION"), pNode, &m_csVersion);
  1149. if (!ProcureGuidIDAttribute(pDB, pNode, &m_ID, &csID)) {
  1150. SDBERROR_PROPOGATE();
  1151. goto eh;
  1152. }
  1153. if (!XQL.Query(pNode, _T("HISTORY"))) {
  1154. SDBERROR_PROPOGATE();
  1155. goto eh;
  1156. }
  1157. //
  1158. // Set the default modified date to 01/01/2000
  1159. //
  1160. odtLastRevision.ParseDateTime(_T("01/01/2001"), 0, 0x0409);
  1161. for (i = 0; i < XQL.GetSize(); i++) {
  1162. if (!XQL.GetItem(i, &cpHistoryNode)) {
  1163. SDBERROR_PROPOGATE();
  1164. goto eh;
  1165. }
  1166. if (GetAttribute(_T("DATE"), cpHistoryNode, &csTemp)) {
  1167. //
  1168. // Validate format. It's important that the date format is
  1169. // consistent to provide easy text searches.
  1170. //
  1171. if (!(_istdigit(csTemp[0]) && _istdigit(csTemp[1]) &&
  1172. csTemp[2] == _T('/') && _istdigit(csTemp[3]) &&
  1173. _istdigit(csTemp[4]) && csTemp[5] == _T('/') &&
  1174. _istdigit(csTemp[6]) && _istdigit(csTemp[7]) &&
  1175. _istdigit(csTemp[8]) && _istdigit(csTemp[9]) &&
  1176. csTemp[10] == _T('\0'))) {
  1177. SDBERROR_FORMAT((_T("HISTORY DATE is not in format MM/DD/YYYY: \"%s\"\nFor app: \"%s\""),
  1178. csTemp, m_csName));
  1179. goto eh;
  1180. }
  1181. if (!odtCandidate.ParseDateTime(csTemp, 0, 0x0409))
  1182. {
  1183. SDBERROR_FORMAT((_T("HISTORY DATE is not in format MM/DD/YYYY: \"%s\"\nFor app: \"%s\""),
  1184. csTemp, m_csName));
  1185. goto eh;
  1186. }
  1187. if (odtCandidate > odtLastRevision)
  1188. {
  1189. odtLastRevision = odtCandidate;
  1190. }
  1191. }
  1192. if (GetAttribute(_T("KEYWORDS"), cpHistoryNode, &csTemp)) {
  1193. m_csKeywords += csTemp;
  1194. m_csKeywords += _T(";");
  1195. }
  1196. cpHistoryNode.Release();
  1197. }
  1198. m_dtLastRevision = odtLastRevision.m_dt;
  1199. //
  1200. // Set m_pCurrentApp so that new SdbExe objects can grab their m_pApp pointer
  1201. //
  1202. pDB->m_pCurrentApp = this;
  1203. //
  1204. // Add the EXEs as in an "ordered" fashion
  1205. //
  1206. // SYS is the driver XML version of EXE
  1207. //
  1208. if (!m_rgExes.ReadFromXML(_T("EXE | SYS"), pDB, pNode, NULL, TRUE)) {
  1209. SDBERROR_PROPOGATE();
  1210. goto eh;
  1211. }
  1212. //
  1213. // Add the WIN9X_MIGRATION entries
  1214. //
  1215. if (!m_rgWin9xMigEntries.ReadFromXML(_T("WIN9X_MIGRATION"), pDB, pNode, NULL, FALSE, NULL)) {
  1216. SDBERROR_PROPOGATE();
  1217. goto eh;
  1218. }
  1219. //
  1220. // Add the WINNT_UPGRADE entries
  1221. //
  1222. if (!m_rgWinNTUpgradeEntries.ReadFromXML(_T("WINNT_UPGRADE"), pDB, pNode, NULL, FALSE, NULL)) {
  1223. SDBERROR_PROPOGATE();
  1224. goto eh;
  1225. }
  1226. //
  1227. // Read MSI_PACKAGE tags, owner is this one (hence the NULL), add them ordered
  1228. //
  1229. if (!m_rgMsiPackages.ReadFromXML(_T("MSI_PACKAGE"), pDB, pNode, NULL, TRUE)) {
  1230. SDBERROR_PROPOGATE();
  1231. goto eh;
  1232. }
  1233. //
  1234. // Run through the AppHelpRefs to make sure
  1235. // they all have HTMLHELPIDs
  1236. //
  1237. for (i = 0; i < m_rgAppHelpRefs.GetSize(); i++) {
  1238. pAppHelpRef1 = (SdbAppHelpRef *) m_rgAppHelpRefs[i];
  1239. if (pAppHelpRef1->m_cpNode) {
  1240. if (!pAppHelpRef1->ReadFromXML(pAppHelpRef1->m_cpNode,
  1241. pDB)) {
  1242. SDBERROR_PROPOGATE();
  1243. goto eh;
  1244. }
  1245. pAppHelpRef1->m_cpNode = NULL;
  1246. }
  1247. }
  1248. if (g_bStrict) {
  1249. for (i = 0; i < m_rgAppHelpRefs.GetSize(); i++) {
  1250. pAppHelpRef1 = (SdbAppHelpRef *) m_rgAppHelpRefs[i];
  1251. for (j = 0; j < m_rgAppHelpRefs.GetSize(); j++) {
  1252. pAppHelpRef2 = (SdbAppHelpRef *) m_rgAppHelpRefs[j];
  1253. if (pAppHelpRef1->m_pAppHelp->m_csName != pAppHelpRef2->m_pAppHelp->m_csName &&
  1254. pAppHelpRef1->m_pAppHelp->m_csMessage == pAppHelpRef2->m_pAppHelp->m_csMessage &&
  1255. pAppHelpRef1->m_pAppHelp->m_Type == pAppHelpRef2->m_pAppHelp->m_Type &&
  1256. pAppHelpRef1->m_pAppHelp->m_bBlockUpgrade == pAppHelpRef2->m_pAppHelp->m_bBlockUpgrade &&
  1257. pAppHelpRef1->m_pAppHelp->m_csURL == pAppHelpRef2->m_pAppHelp->m_csURL &&
  1258. pAppHelpRef1->m_pAppHelp->m_csParameter1 == pAppHelpRef2->m_pAppHelp->m_csParameter1) {
  1259. SDBERROR_FORMAT((_T("Different HTMLHELPIDs for same <APPHELP MESSAGE BLOCK BLOCK_UPGRADE DETAILS_URL and PARAMETER1>:\n%s\n"),
  1260. GetXML(pNode)));
  1261. goto eh;
  1262. }
  1263. }
  1264. }
  1265. }
  1266. //
  1267. // Set m_dtLastRevision for important children.
  1268. //
  1269. for (i = 0; i < m_rgExes.GetSize(); i++)
  1270. {
  1271. ((SdbArrayElement *) m_rgExes.GetAt(i))->m_dtLastRevision = m_dtLastRevision;
  1272. }
  1273. for (i = 0; i < this->m_rgAppHelpRefs.GetSize(); i++)
  1274. {
  1275. ((SdbAppHelpRef *) m_rgAppHelpRefs.GetAt(i))->m_pAppHelp->m_dtLastRevision = m_dtLastRevision;
  1276. }
  1277. for (i = 0; i < m_rgMsiPackages.GetSize(); i++)
  1278. {
  1279. ((SdbArrayElement *) m_rgMsiPackages.GetAt(i))->m_dtLastRevision = m_dtLastRevision;
  1280. }
  1281. for (i = 0; i < m_rgWin9xMigEntries.GetSize(); i++)
  1282. {
  1283. ((SdbArrayElement *) m_rgWin9xMigEntries.GetAt(i))->m_dtLastRevision = m_dtLastRevision;
  1284. }
  1285. for (i = 0; i < m_rgWinNTUpgradeEntries.GetSize(); i++)
  1286. {
  1287. ((SdbArrayElement *) m_rgWinNTUpgradeEntries.GetAt(i))->m_dtLastRevision = m_dtLastRevision;
  1288. }
  1289. m_pDB = pDB;
  1290. bSuccess = TRUE;
  1291. eh:
  1292. pDB->m_pCurrentApp = NULL;
  1293. return bSuccess;
  1294. }
  1295. BOOL
  1296. CheckExeID(
  1297. SdbDatabase* pDB,
  1298. SdbArrayElement* pElement,
  1299. LPCTSTR lpszID
  1300. )
  1301. {
  1302. SdbArrayElement* pOtherExe = NULL;
  1303. LPCTSTR pszName = NULL;
  1304. LPCTSTR pszTag = NULL;
  1305. if (pDB->m_mapExeIDtoExe.Lookup(lpszID, (PVOID&)pOtherExe)) {
  1306. //
  1307. // see what kind of an object we caught with this duplicate id
  1308. //
  1309. const type_info& TypeInfoObj = typeid(*pOtherExe);
  1310. if (typeid(SdbMsiPackage) == TypeInfoObj) {
  1311. pszName = ((SdbMsiPackage*)pOtherExe)->m_pApp->m_csName;
  1312. pszTag = _T("<MSI_PACKAGE NAME=");
  1313. } else if (typeid(SdbExe) == TypeInfoObj) {
  1314. pszName = ((SdbExe*)pOtherExe)->m_pApp->m_csName;
  1315. pszTag = _T("<EXE NAME=");
  1316. } else {
  1317. // deep poop - we don't know what this is
  1318. pszName = _T("???");
  1319. pszTag = _T("<???");
  1320. }
  1321. SDBERROR_FORMAT((_T("EXE ID %s is not unique\n")
  1322. _T("\tNested within <APP NAME=\"%s\">\n\tAnd also within %s\"%s\">\r\n"),
  1323. lpszID, pszName, pszTag, pElement->m_csName));
  1324. return FALSE;
  1325. }
  1326. pDB->m_mapExeIDtoExe.SetAt(lpszID, pElement);
  1327. return TRUE;
  1328. }
  1329. BOOL SdbExe::ReadFromXML(
  1330. IXMLDOMNode* pNode,
  1331. SdbDatabase* pDB)
  1332. {
  1333. BOOL bSuccess = FALSE;
  1334. long i;
  1335. CString csID, csTemp;
  1336. BOOL bGenerateWinNTUpgrade = FALSE;
  1337. XMLNodeList XQL;
  1338. IXMLDOMNodePtr cpSXS;
  1339. IXMLDOMNodePtr cpMessage;
  1340. SdbMatchingFile* pMFile = NULL;
  1341. SdbData* pData = NULL;
  1342. SdbData* pPolicy = NULL;
  1343. SdbWinNTUpgrade* pNTUpg = NULL;
  1344. VARIANT vType;
  1345. VARIANT vValue;
  1346. IXMLDOMDocumentPtr cpDocument;
  1347. IXMLDOMNodePtr cpNewNode;
  1348. IXMLDOMNodePtr cpXMLNSNode;
  1349. IXMLDOMNodeListPtr cpNodeList;
  1350. IXMLDOMNamedNodeMapPtr cpAttrs;
  1351. VariantInit(&vType);
  1352. VariantInit(&vValue);
  1353. m_pApp = pDB->m_pCurrentApp;
  1354. if (!GetAttribute(_T("NAME"), pNode, &m_csName)) {
  1355. if (GetAttribute(_T("MODULE_NAME"), pNode, &m_csName)) {
  1356. m_bMatchOnModule = TRUE;
  1357. } else {
  1358. SDBERROR_FORMAT((_T("NAME or MODULE_NAME attribute required:\n%s\n\n"),
  1359. GetXML(pNode)));
  1360. goto eh;
  1361. }
  1362. }
  1363. if (!ProcureGuidIDAttribute(pDB, pNode, &m_ID, &csID)) {
  1364. SDBERROR_PROPOGATE();
  1365. goto eh;
  1366. }
  1367. if (g_bStrict) {
  1368. if (!CheckExeID(pDB, this, csID)) {
  1369. SDBERROR_PROPOGATE();
  1370. goto eh;
  1371. }
  1372. }
  1373. //
  1374. // Look for a match mode entry
  1375. //
  1376. if (GetAttribute(_T("MATCH_MODE"), pNode, &csTemp)) {
  1377. if (!DecodeStringAttribute(csTemp,
  1378. g_rgStringMatchModeType,
  1379. ARRAYSIZE(g_rgStringMatchModeType),
  1380. &m_dwMatchMode)) {
  1381. //
  1382. // try to decode using the hex (direct) format
  1383. //
  1384. if (!StringToMask(&m_dwMatchMode, csTemp)) {
  1385. SDBERROR_FORMAT((_T("MATCH_MODE attribute is invalid\n%s\n"),
  1386. GetXML(pNode)));
  1387. goto eh;
  1388. }
  1389. }
  1390. }
  1391. if (GetAttribute(_T("RUNTIME_PLATFORM"), pNode, &csTemp)) {
  1392. if (!DecodeRuntimePlatformString(csTemp, &m_dwRuntimePlatform)) {
  1393. SDBERROR_FORMAT((_T("RUNTIME_PLATFORM no in recognized format: \"%s\"\n%s\n"),
  1394. (LPCTSTR)csTemp, GetXML(pNode)));
  1395. goto eh;
  1396. }
  1397. }
  1398. GetAttribute(_T("OS_VERSION"), pNode, &m_csOSVersionSpec);
  1399. //
  1400. // Check what OS SKU this entry is meant for
  1401. //
  1402. if (GetAttribute(_T("OS_SKU"), pNode, &csTemp)) {
  1403. //
  1404. // Decode it. This string is a semi-colon delimited set
  1405. // of OS SKUs.
  1406. //
  1407. if (!DecodeString(csTemp, &m_dwOSSKU, GetOSSKUType)) {
  1408. SDBERROR_FORMAT((_T("OS_SKU attribute syntax error: %s"), csTemp));
  1409. goto eh;
  1410. }
  1411. }
  1412. //
  1413. // Check what OS PLATFORM this entry is meant for
  1414. //
  1415. if (GetAttribute(_T("OS_PLATFORM"), pNode, &csTemp)) {
  1416. //
  1417. // Decode it. This string is a semi-colon delimited set
  1418. // of OS PLATFORMs.
  1419. //
  1420. if (!DecodeString(csTemp, &m_dwOSPlatform, GetOSPlatform)) {
  1421. SDBERROR_FORMAT((_T("OS_PLATFORM attribute syntax error: %s"), csTemp));
  1422. goto eh;
  1423. }
  1424. }
  1425. //
  1426. // Add EXE as matching file
  1427. //
  1428. pMFile = new SdbMatchingFile();
  1429. if (pMFile == NULL) {
  1430. SDBERROR(_T("Error allocating SdbMatchingFile object"));
  1431. goto eh;
  1432. }
  1433. m_rgMatchingFiles.Add(pMFile, pDB);
  1434. if (!pMFile->ReadFromXML(pNode, pDB)) {
  1435. SDBERROR_PROPOGATE();
  1436. goto eh;
  1437. }
  1438. //
  1439. // Change name to "*" -- that is the alias for the EXE. This is done
  1440. // to allow matching on a wildcard executable name.
  1441. //
  1442. pMFile->m_csName = _T("*");
  1443. if (!m_rgMatchingFiles.ReadFromXML(_T("MATCHING_FILE"), pDB, pNode)) {
  1444. SDBERROR_PROPOGATE();
  1445. goto eh;
  1446. }
  1447. if (!m_rgShimRefs.ReadFromXML(_T("SHIM"), pDB, pNode)) {
  1448. SDBERROR_PROPOGATE();
  1449. goto eh;
  1450. }
  1451. if (!m_rgLayerRefs.ReadFromXML(_T("LAYER"), pDB, pNode)) {
  1452. SDBERROR_PROPOGATE();
  1453. goto eh;
  1454. }
  1455. if (!m_rgPatches.ReadFromXML(_T("PATCH"), pDB, pNode, &(pDB->m_Library.m_rgPatches))) {
  1456. SDBERROR_PROPOGATE();
  1457. goto eh;
  1458. }
  1459. if (!m_rgFlagRefs.ReadFromXML(_T("FLAG"), pDB, pNode)) {
  1460. SDBERROR_PROPOGATE();
  1461. goto eh;
  1462. }
  1463. //
  1464. // Data tags
  1465. //
  1466. if (!m_rgData.ReadFromXML(_T("(DATA | DRIVER_POLICY)"), pDB, pNode, NULL)) {
  1467. SDBERROR_PROPOGATE();
  1468. goto eh;
  1469. }
  1470. //
  1471. // Driver database 'hack': We look for CRITICAL="NO" on the SYS tag
  1472. // and add a Policy = 0x1 <DATA> element if found. This is to help
  1473. // readability.
  1474. //
  1475. //
  1476. // Check if policy already exists
  1477. //
  1478. for (i = 0; i < m_rgData.GetSize(); i++) {
  1479. pData = (SdbData *) m_rgData.GetAt(i);
  1480. if (pData->m_csName.CompareNoCase(_T("Policy")) == 0) {
  1481. pPolicy = pData;
  1482. break;
  1483. }
  1484. }
  1485. if (GetAttribute(_T("CRITICAL"), pNode, &csTemp)) {
  1486. if (csTemp.CompareNoCase(_T("NO")) == 0) {
  1487. if (pPolicy == NULL) {
  1488. pPolicy = new SdbData;
  1489. pPolicy->m_csName = _T("Policy");
  1490. pPolicy->SetValue(eValueDWORD, _T("0x0"));
  1491. m_rgData.Add(pPolicy, pDB);
  1492. }
  1493. pPolicy->m_dwValue |= 1;
  1494. }
  1495. }
  1496. if (GetAttribute(_T("USER_MODE_BLOCK"), pNode, &csTemp)) {
  1497. if (csTemp.CompareNoCase(_T("NO")) == 0) {
  1498. if (pPolicy == NULL) {
  1499. pPolicy = new SdbData;
  1500. pPolicy->m_csName = _T("Policy");
  1501. pPolicy->SetValue(eValueDWORD, _T("0x0"));
  1502. m_rgData.Add(pPolicy, pDB);
  1503. }
  1504. pPolicy->m_dwValue |= 2;
  1505. }
  1506. }
  1507. //
  1508. // Action tags
  1509. //
  1510. if (!m_rgAction.ReadFromXML(_T("ACTION"), pDB, pNode, NULL)) {
  1511. SDBERROR_PROPOGATE();
  1512. goto eh;
  1513. }
  1514. //
  1515. // Read APPHELP refs
  1516. //
  1517. if (!XQL.Query(pNode, _T("APPHELP"))) {
  1518. SDBERROR_PROPOGATE();
  1519. goto eh;
  1520. }
  1521. if (XQL.GetSize() > 1) {
  1522. SDBERROR_FORMAT((_T("Multiple <APPHELP> tags per <EXE> not allowed\n%s\n"),
  1523. GetXML(pNode)));
  1524. goto eh;
  1525. }
  1526. if (XQL.GetSize() == 1) {
  1527. if (!XQL.GetItem(0, &cpMessage)) {
  1528. SDBERROR_PROPOGATE();
  1529. goto eh;
  1530. }
  1531. if (!m_AppHelpRef.ReadFromXML(cpMessage, pDB)) {
  1532. SDBERROR_PROPOGATE();
  1533. goto eh;
  1534. }
  1535. if (m_rgShimRefs.GetSize() == 0 &&
  1536. m_rgPatches.GetSize() == 0 &&
  1537. m_rgFlagRefs.GetSize() == 0 &&
  1538. m_rgLayerRefs.GetSize() == 0) {
  1539. m_AppHelpRef.m_bApphelpOnly = TRUE;
  1540. }
  1541. //
  1542. // <SYS> entries automatically get an <WINNT_UPGRADE> entry
  1543. //
  1544. if (GetNodeName(pNode) == _T("SYS")) {
  1545. bGenerateWinNTUpgrade = TRUE;
  1546. if (GetAttribute(_T("GENERATE_UPGRADE_REPORT_ENTRY"), pNode, &csTemp)) {
  1547. if (0 == csTemp.CompareNoCase(_T("NO"))) {
  1548. bGenerateWinNTUpgrade = FALSE;
  1549. }
  1550. }
  1551. if (bGenerateWinNTUpgrade) {
  1552. pNTUpg = new SdbWinNTUpgrade;
  1553. pNTUpg->m_pDB = pDB;
  1554. pNTUpg->m_pApp = pDB->m_pCurrentApp;
  1555. if (!pNTUpg->m_AppHelpRef.ReadFromXML(cpMessage, pDB)) {
  1556. SDBERROR_PROPOGATE();
  1557. goto eh;
  1558. }
  1559. csTemp = m_csName;
  1560. ReplaceStringNoCase(csTemp, _T(".SYS"), _T(""));
  1561. pNTUpg->m_MatchingFile.m_csServiceName = csTemp;
  1562. pNTUpg->m_MatchingFile.m_csName.Format(_T("%%SystemRoot%%\\System32\\Drivers\\%s"), m_csName);
  1563. pNTUpg->m_MatchingFile.m_dwMask = pMFile->m_dwMask;
  1564. pNTUpg->m_MatchingFile.m_ullBinProductVersion = pMFile->m_ullBinProductVersion;
  1565. pNTUpg->m_MatchingFile.m_ullUpToBinProductVersion = pMFile->m_ullUpToBinProductVersion;
  1566. pNTUpg->m_MatchingFile.m_timeLinkDate = pMFile->m_timeLinkDate;
  1567. pNTUpg->m_MatchingFile.m_timeUpToLinkDate = pMFile->m_timeUpToLinkDate;
  1568. m_pApp->m_rgWinNTUpgradeEntries.Add(pNTUpg, pDB);
  1569. pDB->m_rgWinNTUpgradeEntries.Add(pNTUpg, pDB);
  1570. }
  1571. }
  1572. }
  1573. //
  1574. // Read SXS manifest
  1575. //
  1576. if (!XQL.Query(pNode, _T("SXS"))) {
  1577. SDBERROR_PROPOGATE();
  1578. goto eh;
  1579. }
  1580. if (XQL.GetSize() > 1) {
  1581. SDBERROR_FORMAT((_T("Multiple <SXS> tags per <EXE> not allowed\n%s\n"),
  1582. GetXML(pNode)));
  1583. goto eh;
  1584. }
  1585. if (XQL.GetSize() == 1) {
  1586. if (!XQL.GetItem(0, &cpSXS)) {
  1587. SDBERROR_PROPOGATE();
  1588. goto eh;
  1589. }
  1590. m_csSXSManifest = TrimParagraph(GetInnerXML(cpSXS));
  1591. if (m_csSXSManifest.IsEmpty()) {
  1592. SDBERROR_FORMAT((_T("Failed to read SXS manifest:\n%s\n"),
  1593. GetXML(cpSXS)));
  1594. goto eh;
  1595. }
  1596. }
  1597. //
  1598. // Check whether the EXE name contains a wildcard
  1599. //
  1600. m_bWildcardInName = (0 <= m_csName.FindOneOf(_T("*?")));
  1601. //
  1602. // Differentiate between driver.xml entries and dbu.xml
  1603. //
  1604. if (GetNodeName(pNode) == _T("SYS")) {
  1605. //
  1606. // Set filter
  1607. //
  1608. m_dwFilter = SDB_FILTER_DRIVER | SDB_FILTER_OVERRIDE;
  1609. if (m_bWildcardInName) {
  1610. SDBERROR_FORMAT((_T("Wildcards not allowed in SYS entries:\n%s\n"),
  1611. GetXML(pNode)));
  1612. goto eh;
  1613. } else {
  1614. pDB->m_rgExes.Add(this, pDB, TRUE);
  1615. }
  1616. } else {
  1617. //
  1618. // Check if we're compiling for Win2k and make
  1619. // sure Win2k supports all the matching operations.
  1620. //
  1621. if (g_bStrict) {
  1622. if (!IsValidForWin2k(GetXML(pNode))) {
  1623. if (GetAttribute(_T("OS_VERSION"), pNode, &csTemp)) {
  1624. SDBERROR_PROPOGATE();
  1625. goto eh;
  1626. }
  1627. if (!AddAttribute(pNode, _T("OS_VERSION"), _T("gte5.1"))) {
  1628. SDBERROR_PROPOGATE();
  1629. goto eh;
  1630. }
  1631. SDBERROR_CLEAR();
  1632. pDB->m_pCurrentInputFile->m_bSourceUpdated = TRUE;
  1633. }
  1634. }
  1635. if (m_bWildcardInName) {
  1636. pDB->m_rgWildcardExes.Add(this, pDB, TRUE);
  1637. } else if (m_bMatchOnModule) {
  1638. pDB->m_rgModuleExes.Add(this, pDB, TRUE);
  1639. } else {
  1640. pDB->m_rgExes.Add(this, pDB, TRUE);
  1641. }
  1642. }
  1643. m_AppHelpRef.m_pDB = pDB;
  1644. m_pDB = pDB;
  1645. bSuccess = TRUE;
  1646. eh:
  1647. VariantClear(&vType);
  1648. VariantClear(&vValue);
  1649. return bSuccess;
  1650. }
  1651. ////////////////////////////////////////////////////////////////////////
  1652. //
  1653. // Read in MSI Package tag
  1654. // <MSI_PACKAGE NAME="my msi package" ID="{xxxxx}">
  1655. // <DATA NAME="Additional Data" VALUETYPE="DWORD" VALUE="0x233"/>
  1656. // <MSI_TRANSFORM NAME="Apply Me for a fix"/>
  1657. // </MSI_PACKAGE>
  1658. //
  1659. SdbDatabase* CastDatabaseToFixDatabase(SdbDatabase* pDB)
  1660. {
  1661. const type_info& TypeInfoFixDB = typeid(SdbDatabase);
  1662. const type_info& TypeInfoDB = typeid(*pDB);
  1663. if (TypeInfoDB == TypeInfoFixDB) {
  1664. return (SdbDatabase*)pDB;
  1665. }
  1666. //
  1667. // bad error
  1668. //
  1669. SDBERROR_FORMAT((_T("Internal Compiler Error: Bad cast operation on Database object\n")));
  1670. return NULL;
  1671. }
  1672. BOOL SdbMsiPackage::ReadFromXML(
  1673. IXMLDOMNode* pNode,
  1674. SdbDatabase* pDB)
  1675. {
  1676. BOOL bSuccess = FALSE;
  1677. CString csID;
  1678. CString csTemp;
  1679. XMLNodeList XQL;
  1680. IXMLDOMNodePtr cpMessage;
  1681. SdbDatabase* pFixDB = CastDatabaseToFixDatabase(pDB);
  1682. if (pFixDB == NULL) {
  1683. SDBERROR_PROPOGATE();
  1684. goto eh;
  1685. }
  1686. m_pApp = pFixDB->m_pCurrentApp;
  1687. if (!ReadName(pNode, &m_csName)) {
  1688. SDBERROR_PROPOGATE();
  1689. goto eh;
  1690. }
  1691. if (!ProcureGuidIDAttribute(pDB, pNode, &m_ID, &csID)) {
  1692. SDBERROR_PROPOGATE();
  1693. goto eh;
  1694. }
  1695. if (g_bStrict) {
  1696. if (!CheckExeID(pDB, this, csID)) {
  1697. SDBERROR_PROPOGATE();
  1698. goto eh;
  1699. }
  1700. }
  1701. if (!GetAttribute(_T("PRODUCT_CODE"), pNode, &csID)) {
  1702. //
  1703. // Guid was not found. We do not generate ids for packages -- they are
  1704. // statically defined attributes provided to identify the package
  1705. //
  1706. SDBERROR_FORMAT((_T("MSI_PACKAGE requires PRODUCT_CODE attribute\n%s\n"),
  1707. GetXML(pNode)));
  1708. goto eh;
  1709. }
  1710. if (!GUIDFromString(csID, &m_MsiPackageID)) {
  1711. //
  1712. // This is the case when we cannot parse the guid and it appears to be
  1713. // an invalid guid.
  1714. //
  1715. SDBERROR_FORMAT((_T("ID attribute is not a valid GUID\n%s\n"), csID));
  1716. goto eh;
  1717. }
  1718. //
  1719. // procure RUNTIME_PLATFORM attribute
  1720. //
  1721. if (GetAttribute(_T("RUNTIME_PLATFORM"), pNode, &csTemp)) {
  1722. if (!DecodeRuntimePlatformString(csTemp, &m_dwRuntimePlatform)) {
  1723. SDBERROR_FORMAT((_T("RUNTIME_PLATFORM no in recognized format: \"%s\"\n%s\n"),
  1724. (LPCTSTR)csTemp, GetXML(pNode)));
  1725. goto eh;
  1726. }
  1727. }
  1728. //
  1729. // Check what OS SKU this entry is meant for
  1730. //
  1731. if (GetAttribute(_T("OS_SKU"), pNode, &csTemp)) {
  1732. //
  1733. // Decode it. This string is a semi-colon delimited set
  1734. // of OS SKUs.
  1735. //
  1736. if (!DecodeString(csTemp, &m_dwOSSKU, GetOSSKUType)) {
  1737. SDBERROR_FORMAT((_T("OS_SKU attribute syntax error: %s"), csTemp));
  1738. goto eh;
  1739. }
  1740. }
  1741. //
  1742. // read supplemental data for this object
  1743. //
  1744. if (!m_rgData.ReadFromXML(_T("DATA"), pDB, pNode)) {
  1745. SDBERROR_PROPOGATE();
  1746. goto eh;
  1747. }
  1748. //
  1749. // we have name, guid(id) and supplemental data, read fixes for this package
  1750. //
  1751. if (!m_rgMsiTransformRefs.ReadFromXML(_T("MSI_TRANSFORM"), pDB, pNode)) {
  1752. SDBERROR_PROPOGATE();
  1753. goto eh;
  1754. }
  1755. if (!m_rgCustomActions.ReadFromXML(_T("CUSTOM_ACTION"), pDB, pNode)) {
  1756. SDBERROR_PROPOGATE();
  1757. goto eh;
  1758. }
  1759. //
  1760. // Read APPHELP refs
  1761. //
  1762. if (!XQL.Query(pNode, _T("APPHELP"))) {
  1763. SDBERROR_PROPOGATE();
  1764. goto eh;
  1765. }
  1766. if (XQL.GetSize() > 1) {
  1767. SDBERROR_FORMAT((_T("Multiple <APPHELP> tags per <MSI_PACKAGE> not allowed\n%s\n"),
  1768. GetXML(pNode)));
  1769. goto eh;
  1770. }
  1771. if (XQL.GetSize() == 1) {
  1772. if (!XQL.GetItem(0, &cpMessage)) {
  1773. SDBERROR_PROPOGATE();
  1774. goto eh;
  1775. }
  1776. if (!m_AppHelpRef.ReadFromXML(cpMessage, pDB)) {
  1777. SDBERROR_PROPOGATE();
  1778. goto eh;
  1779. }
  1780. }
  1781. pDB->m_rgMsiPackages.Add(this, pDB, TRUE);
  1782. m_AppHelpRef.m_pDB = pDB;
  1783. m_pDB = pDB;
  1784. bSuccess = TRUE;
  1785. eh:
  1786. return bSuccess;
  1787. }
  1788. BOOL
  1789. SdbMsiCustomAction::ReadFromXML(
  1790. IXMLDOMNode* pNode,
  1791. SdbDatabase* pDB
  1792. )
  1793. {
  1794. BOOL bSuccess = FALSE;
  1795. if (!GetAttribute(_T("NAME"), pNode, &m_csName)) {
  1796. SDBERROR_FORMAT((_T("<CUSTOM_ACTION> requires NAME attribute:\n%s\n\n"),
  1797. GetXML(pNode)));
  1798. goto eh;
  1799. }
  1800. if (!m_rgShimRefs.ReadFromXML(_T("SHIM"), pDB, pNode)) {
  1801. SDBERROR_PROPOGATE();
  1802. goto eh;
  1803. }
  1804. if (!m_rgLayerRefs.ReadFromXML(_T("LAYER"), pDB, pNode)) {
  1805. SDBERROR_PROPOGATE();
  1806. goto eh;
  1807. }
  1808. m_pDB = pDB;
  1809. bSuccess = TRUE;
  1810. eh:
  1811. return bSuccess;
  1812. }
  1813. /////////////////////////////////////////////////////////////////////////////////////////////////
  1814. //
  1815. // Read in MSI_TRANSFORM tag
  1816. // <MSI_TRANSFORM NAME="This is transform name" FILE="This is filename.foo">
  1817. // <DESCRIPTION>
  1818. // blah blah blah
  1819. // </DESCRIPTION>
  1820. // </MSI_TRANSFORM>
  1821. //
  1822. BOOL SdbMsiTransform::ReadFromXML(
  1823. IXMLDOMNode* pNode,
  1824. SdbDatabase* pDB)
  1825. {
  1826. BOOL bSuccess = FALSE;
  1827. IXMLDOMNodePtr cpDesc, cpFile;
  1828. XMLNodeList XQL;
  1829. SdbDatabase* pFixDB = CastDatabaseToFixDatabase(pDB);
  1830. if (pFixDB == NULL) {
  1831. SDBERROR_PROPOGATE();
  1832. goto eh;
  1833. }
  1834. // read msi Transform from the library
  1835. if (!ReadName(pNode, &m_csName)) {
  1836. SDBERROR_PROPOGATE();
  1837. goto eh;
  1838. }
  1839. if (!XQL.Query(pNode, _T("FILE"))) {
  1840. SDBERROR_PROPOGATE();
  1841. goto eh;
  1842. }
  1843. if (XQL.GetSize() == 0 ||
  1844. XQL.GetSize() > 1) {
  1845. SDBERROR_FORMAT((_T("<MSI_TRANSFORM> requires one and only one <FILE> child:\n%s\n\n"),
  1846. GetXML(pNode)));
  1847. goto eh;
  1848. }
  1849. if (!XQL.GetItem(0, &cpFile)) {
  1850. SDBERROR_PROPOGATE();
  1851. goto eh;
  1852. }
  1853. if (!GetAttribute(_T("NAME"), cpFile, &m_csMsiTransformFile)) {
  1854. SDBERROR_FORMAT((_T("<FILE> requires NAME attribute:\n%s\n\n"),
  1855. GetXML(pNode)));
  1856. goto eh;
  1857. }
  1858. if (GetChild(_T("DESCRIPTION"), pNode, &cpDesc)) {
  1859. GetNodeText(cpDesc, m_csDesc);
  1860. }
  1861. //
  1862. // name should be unique for each of thesee transforms, enforce
  1863. //
  1864. if (pFixDB->m_Library.m_rgMsiTransforms.LookupName(m_csName) != NULL) {
  1865. SDBERROR_FORMAT((_T("MSI_TRANSFORM NAME attribute is not unique\n%s\n\n"),
  1866. GetXML(pNode)));
  1867. goto eh;
  1868. }
  1869. //
  1870. // find corresponding file object
  1871. //
  1872. if (m_csMsiTransformFile.GetLength()) {
  1873. m_pSdbFile = (SdbFile*)pFixDB->m_Library.m_rgFiles.LookupName(m_csMsiTransformFile);
  1874. if (g_bStrict && m_pSdbFile == NULL) {
  1875. SDBERROR_FORMAT((_T("<MSI_TRANSFORM specifies FILE which is not available in the library\n%s\n\n"),
  1876. GetXML(pNode)));
  1877. goto eh;
  1878. }
  1879. }
  1880. bSuccess = TRUE;
  1881. eh:
  1882. return bSuccess;
  1883. }
  1884. /////////////////////////////////////////////////////////////////////////////////////////////////
  1885. //
  1886. // Read the reference to the transform object
  1887. // <MSI_TRANSFORM NAME="name-reference-to the transform in library"/>
  1888. //
  1889. BOOL SdbMsiTransformRef::ReadFromXML(
  1890. IXMLDOMNode* pNode,
  1891. SdbDatabase* pDB)
  1892. {
  1893. BOOL bSuccess = FALSE;
  1894. SdbDatabase* pFixDB = NULL;
  1895. if (!ReadName(pNode, &m_csName)) {
  1896. SDBERROR_PROPOGATE();
  1897. goto eh;
  1898. }
  1899. pFixDB = CastDatabaseToFixDatabase(pDB);
  1900. if (pFixDB == NULL) {
  1901. SDBERROR_PROPOGATE();
  1902. goto eh;
  1903. }
  1904. m_pMsiTransform = (SdbMsiTransform *) pFixDB->m_Library.m_rgMsiTransforms.LookupName(m_csName);
  1905. if (m_pMsiTransform == NULL && g_bStrict) {
  1906. SDBERROR_FORMAT((_T("MSI_TRANSFORM \"%s\" not found in library:\n%s\n\n"),
  1907. m_csName, GetXML(pNode)));
  1908. goto eh;
  1909. }
  1910. m_pDB = pDB; // set the root db pointer (why???)
  1911. bSuccess = TRUE;
  1912. eh:
  1913. return bSuccess;
  1914. }
  1915. /////////////////////////////////////////////////////////////////////////////////////////////////
  1916. BOOL SdbMatchingFile::ReadFromXML(
  1917. IXMLDOMNode* pNode,
  1918. SdbDatabase* pDB)
  1919. {
  1920. BOOL bSuccess = FALSE;
  1921. CString csTemp;
  1922. GetAttribute(_T("SERVICE_NAME"), pNode, &m_csServiceName);
  1923. if (!GetAttribute(_T("NAME"), pNode, &m_csName)) {
  1924. if (GetNodeName(pNode) == _T("EXE")) {
  1925. m_csName = _T("*");
  1926. } else if (m_csServiceName.IsEmpty()) {
  1927. SDBERROR_FORMAT((_T("NAME attribute required:\n%s\n\n"),
  1928. GetXML(pNode)));
  1929. goto eh;
  1930. }
  1931. }
  1932. if (GetParentNodeName(pNode) == _T("WIN9X_MIGRATION") ||
  1933. GetNodeName(pNode) == _T("MATCH_ANY") ||
  1934. GetNodeName(pNode) == _T("MATCH_ALL")) {
  1935. if (-1 != m_csName.Find(_T("\\"))) {
  1936. SDBERROR_FORMAT((_T("<MATCHING_FILE> inside <WIN9X_MIGRATION> cannot contain relative paths:\n%s\n"),
  1937. GetXML(pNode)));
  1938. goto eh;
  1939. }
  1940. }
  1941. m_dwMask = 0;
  1942. if (GetAttribute(_T("SIZE"), pNode, &csTemp)) {
  1943. m_dwSize = StringToDword(csTemp);
  1944. m_dwMask |= SDB_MATCHINGINFO_SIZE;
  1945. } else {
  1946. m_dwSize = 0;
  1947. }
  1948. if (GetAttribute(_T("CHECKSUM"), pNode, &csTemp)) {
  1949. m_dwChecksum = StringToDword(csTemp);
  1950. m_dwMask |= SDB_MATCHINGINFO_CHECKSUM;
  1951. } else
  1952. m_dwChecksum = 0;
  1953. if (GetAttribute(_T("COMPANY_NAME"), pNode, &(m_csCompanyName))) {
  1954. m_dwMask |= SDB_MATCHINGINFO_COMPANY_NAME;
  1955. }
  1956. if (GetAttribute(_T("PRODUCT_NAME"), pNode, &(m_csProductName))) {
  1957. m_dwMask |= SDB_MATCHINGINFO_PRODUCT_NAME;
  1958. }
  1959. if (GetAttribute(_T("PRODUCT_VERSION"), pNode, &(m_csProductVersion))) {
  1960. m_dwMask |= SDB_MATCHINGINFO_PRODUCT_VERSION;
  1961. }
  1962. if (GetAttribute(_T("FILE_DESCRIPTION"), pNode, &(m_csFileDescription))) {
  1963. m_dwMask |= SDB_MATCHINGINFO_FILE_DESCRIPTION;
  1964. }
  1965. if (GetAttribute(_T("BIN_FILE_VERSION"), pNode, &csTemp)) {
  1966. if (!VersionToQword(csTemp, &m_ullBinFileVersion)) {
  1967. SDBERROR_FORMAT((_T("Bad BIN_FILE_VERSION attribute:\n\n%s\n"), GetXML(pNode)));
  1968. goto eh;
  1969. }
  1970. m_dwMask |= SDB_MATCHINGINFO_BIN_FILE_VERSION;
  1971. }
  1972. if (GetAttribute(_T("BIN_PRODUCT_VERSION"), pNode, &csTemp)) {
  1973. if (!VersionToQword(csTemp, &m_ullBinProductVersion)) {
  1974. SDBERROR_FORMAT((_T("Bad BIN_PRODUCT_VERSION attribute:\n\n%s\n"), GetXML(pNode)));
  1975. goto eh;
  1976. }
  1977. m_dwMask |= SDB_MATCHINGINFO_BIN_PRODUCT_VERSION;
  1978. }
  1979. if (GetAttribute(_T("MODULE_TYPE"), pNode, &csTemp)) {
  1980. if (!GetModuleTypeIndicator(csTemp, &m_dwModuleType)) {
  1981. SDBERROR_FORMAT((_T("<MATCHING_FILE> MODULE_TYPE attribute unrecognized:\n%s\n"),
  1982. GetXML(pNode)));
  1983. goto eh;
  1984. }
  1985. m_dwMask |= SDB_MATCHINGINFO_MODULE_TYPE;
  1986. }
  1987. if (GetAttribute(_T("VERFILEDATELO"), pNode, &csTemp)) {
  1988. m_dwFileDateLS = StringToDword(csTemp);
  1989. m_dwMask |= SDB_MATCHINGINFO_VERFILEDATELO;
  1990. }
  1991. if (GetAttribute(_T("VERFILEDATEHI"), pNode, &csTemp)) {
  1992. m_dwFileDateMS = StringToDword(csTemp);
  1993. m_dwMask |= SDB_MATCHINGINFO_VERFILEDATEHI;
  1994. }
  1995. if (GetAttribute(_T("VERFILEOS"), pNode, &csTemp)) {
  1996. m_dwFileOS = StringToDword(csTemp);
  1997. m_dwMask |= SDB_MATCHINGINFO_VERFILEOS;
  1998. }
  1999. if (GetAttribute(_T("VERFILETYPE"), pNode, &csTemp)) {
  2000. m_dwFileType = StringToDword(csTemp);
  2001. m_dwMask |= SDB_MATCHINGINFO_VERFILETYPE;
  2002. }
  2003. if (GetAttribute(_T("PE_CHECKSUM"), pNode, &csTemp)) {
  2004. m_ulPECheckSum = StringToULong(csTemp);
  2005. m_dwMask |= SDB_MATCHINGINFO_PE_CHECKSUM;
  2006. }
  2007. if (GetAttribute(_T("LINKER_VERSION"), pNode, &csTemp)) {
  2008. m_dwLinkerVersion = StringToDword(csTemp);
  2009. m_dwMask |= SDB_MATCHINGINFO_LINKER_VERSION;
  2010. }
  2011. if (GetAttribute(_T("FILE_VERSION"), pNode, &m_csFileVersion)) {
  2012. m_dwMask |= SDB_MATCHINGINFO_FILE_VERSION;
  2013. }
  2014. if (GetAttribute(_T("ORIGINAL_FILENAME"), pNode, &m_csOriginalFileName)) {
  2015. m_dwMask |= SDB_MATCHINGINFO_ORIGINAL_FILENAME;
  2016. }
  2017. if (GetAttribute(_T("INTERNAL_NAME"), pNode, &m_csInternalName)) {
  2018. m_dwMask |= SDB_MATCHINGINFO_INTERNAL_NAME;
  2019. }
  2020. if (GetAttribute(_T("LEGAL_COPYRIGHT"), pNode, &m_csLegalCopyright)) {
  2021. m_dwMask |= SDB_MATCHINGINFO_LEGAL_COPYRIGHT;
  2022. }
  2023. if (GetAttribute(_T("S16BIT_DESCRIPTION"), pNode, &m_cs16BitDescription)) {
  2024. m_dwMask |= SDB_MATCHINGINFO_16BIT_DESCRIPTION;
  2025. }
  2026. if (GetAttribute(_T("S16BIT_MODULE_NAME"), pNode, &m_cs16BitModuleName)) {
  2027. m_dwMask |= SDB_MATCHINGINFO_16BIT_MODULE_NAME;
  2028. }
  2029. if (GetAttribute(_T("UPTO_BIN_PRODUCT_VERSION"), pNode, &csTemp)) {
  2030. if (!VersionToQword(csTemp, &m_ullUpToBinProductVersion)) {
  2031. SDBERROR_FORMAT((_T("Bad UPTO_BIN_PRODUCT_VERSION attribute:\n\n%s\n"), GetXML(pNode)));
  2032. goto eh;
  2033. }
  2034. m_dwMask |= SDB_MATCHINGINFO_UPTO_BIN_PRODUCT_VERSION;
  2035. }
  2036. if (GetAttribute(_T("UPTO_BIN_FILE_VERSION"), pNode, &csTemp)) {
  2037. if (!VersionToQword(csTemp, &m_ullUpToBinFileVersion)) {
  2038. SDBERROR_FORMAT((_T("Bad UPTO_BIN_FILE_VERSION attribute:\n\n%s\n"), GetXML(pNode)));
  2039. goto eh;
  2040. }
  2041. m_dwMask |= SDB_MATCHINGINFO_UPTO_BIN_FILE_VERSION;
  2042. }
  2043. if (GetAttribute(_T("PREVOSMAJORVERSION"), pNode, &csTemp)) {
  2044. m_dwPrevOSMajorVersion = StringToDword(csTemp);
  2045. m_dwMask |= SDB_MATCHINGINFO_PREVOSMAJORVERSION;
  2046. }
  2047. if (GetAttribute(_T("PREVOSMINORVERSION"), pNode, &csTemp)) {
  2048. m_dwPrevOSMinorVersion = StringToDword(csTemp);
  2049. m_dwMask |= SDB_MATCHINGINFO_PREVOSMINORVERSION;
  2050. }
  2051. if (GetAttribute(_T("PREVOSPLATFORMID"), pNode, &csTemp)) {
  2052. m_dwPrevOSPlatformID = StringToDword(csTemp);
  2053. m_dwMask |= SDB_MATCHINGINFO_PREVOSPLATFORMID;
  2054. }
  2055. if (GetAttribute(_T("PREVOSBUILDNO"), pNode, &csTemp)) {
  2056. m_dwPrevOSBuildNo = StringToDword(csTemp);
  2057. m_dwMask |= SDB_MATCHINGINFO_PREVOSBUILDNO;
  2058. }
  2059. if (GetAttribute(_T("LINK_DATE"), pNode, &csTemp)) {
  2060. if (!MakeUTCTime(csTemp, &m_timeLinkDate)) {
  2061. SDBERROR_FORMAT((_T("LINK_DATE not in recognized time format: \"%s\"\n%s\n"),
  2062. csTemp,
  2063. GetXML(pNode)));
  2064. goto eh;
  2065. }
  2066. m_dwMask |= SDB_MATCHINGINFO_LINK_DATE;
  2067. }
  2068. if (GetAttribute(_T("UPTO_LINK_DATE"), pNode, &csTemp)) {
  2069. if (!MakeUTCTime(csTemp, &m_timeUpToLinkDate)) {
  2070. SDBERROR_FORMAT((_T("UPTO_LINK_DATE not in recognized time format: \"%s\"\n%s\n"),
  2071. csTemp,
  2072. GetXML(pNode)));
  2073. goto eh;
  2074. }
  2075. m_dwMask |= SDB_MATCHINGINFO_UPTO_LINK_DATE;
  2076. }
  2077. if (GetAttribute(_T("VER_LANGUAGE"), pNode, &csTemp)) {
  2078. if (!ParseLanguageID(csTemp, &m_dwVerLanguage)) {
  2079. SDBERROR_FORMAT((_T("VER_LANGUAGE not in recognized format: \"%s\"\n%s\n"),
  2080. (LPCTSTR)csTemp,
  2081. GetXML(pNode)));
  2082. goto eh;
  2083. }
  2084. m_dwMask |= SDB_MATCHINGINFO_VER_LANGUAGE;
  2085. }
  2086. if (GetAttribute(_T("REGISTRY_ENTRY"), pNode, &m_csRegistryEntry)) {
  2087. m_dwMask |= SDB_MATCHINGINFO_REGISTRY_ENTRY;
  2088. }
  2089. if (GetAttribute(_T("LOGIC"), pNode, &csTemp)) {
  2090. if (0 == csTemp.CompareNoCase(_T("NOT"))) {
  2091. m_bMatchLogicNot = TRUE;
  2092. }
  2093. }
  2094. m_pDB = pDB;
  2095. bSuccess = TRUE;
  2096. eh:
  2097. return bSuccess;
  2098. }
  2099. BOOL SdbMatchingRegistryEntry::ReadFromXML(
  2100. IXMLDOMNode* pNode,
  2101. SdbDatabase* pDB)
  2102. {
  2103. BOOL bSuccess = FALSE;
  2104. CString csTemp;
  2105. if (!GetAttribute(_T("KEY"), pNode, &m_csName)) {
  2106. SDBERROR_FORMAT((_T("<MATCHING_REGISTRY_ENTRY> requires KEY attribute:\n%s\n\n"),
  2107. GetXML(pNode)));
  2108. goto eh;
  2109. }
  2110. GetAttribute(_T("VALUE_NAME"), pNode, &m_csValueName);
  2111. GetAttribute(_T("VALUE"), pNode, &m_csValue);
  2112. m_pDB = pDB;
  2113. bSuccess = TRUE;
  2114. eh:
  2115. return bSuccess;
  2116. }
  2117. BOOL SdbAppHelpRef::ReadFromXML(
  2118. IXMLDOMNode* pNode,
  2119. SdbDatabase* pDB)
  2120. {
  2121. BOOL bSuccess = FALSE;
  2122. SdbMessage* pMessage = NULL;
  2123. SdbAppHelpRef* pAppHelpRef = NULL;
  2124. BOOL bBlockUpgrade = FALSE;
  2125. long i;
  2126. CString csHTMLHELPID, csType, csURL, csMessage, csParameter1;
  2127. IXMLDOMNodePtr cpParentNode;
  2128. SdbAppHelpType Type = SDB_APPHELP_NOBLOCK;
  2129. if (FAILED(pNode->get_parentNode(&cpParentNode))) {
  2130. SDBERROR_FORMAT((_T("Error retrieving parent node of APPHELP: %s\n"),
  2131. GetXML(pNode)));
  2132. goto eh;
  2133. }
  2134. if (!GetAttribute(_T("MESSAGE"), pNode, &csMessage)) {
  2135. SDBERROR_FORMAT((_T("<APPHELP> requires MESSAGE attribute:\n%s\n"),
  2136. GetXML(pNode)));
  2137. goto eh;
  2138. }
  2139. //
  2140. // get a custom URL, if one is available
  2141. //
  2142. GetAttribute(_T("DETAILS_URL"), pNode, &csURL);
  2143. //
  2144. // PARAMETER1 is an additional attribute you can specify for an APPHELP entry that
  2145. // you can refer to in apphelpu.xml. eg.
  2146. //
  2147. // in dbu.xml:
  2148. //
  2149. // <EXE NAME="logger.exe" ID="{BF2E0D9F-57D9-4BE5-A7A3-9085EE38DD10}">
  2150. // <APPHELP MESSAGE="ISA 2000" BLOCK="YES" PARAMETER1="LALALA" HTMLHELPID="21377"/>
  2151. // </EXE>
  2152. //
  2153. // then in apphelpu.xml you can do:
  2154. // <MESSAGE NAME="ISA 2000" TEMPLATE="PatchAvailable" ID="{B12CFA24-AF7F-43B1-95AC-269692955770}">
  2155. // <SUMMARY>
  2156. // This is <FIELD NAME="PARAMETER1"/>.
  2157. // </SUMMARY>
  2158. // </MESSAGE>
  2159. //
  2160. // When the apphelp entry is processed, the summary will be:
  2161. // This is LALALA.
  2162. //
  2163. // We should really not hard code this but we are about to ship server and I'd rather make
  2164. // as little change as possible.
  2165. //
  2166. // - MaoniS 01/10/2003
  2167. //
  2168. GetAttribute(_T("PARAMETER1"), pNode, &csParameter1);
  2169. //
  2170. // Get BLOCK attribute
  2171. //
  2172. Type = SDB_APPHELP_NOBLOCK;
  2173. if (GetAttribute(_T("BLOCK"), pNode, &csType)) {
  2174. if (GetNodeName(cpParentNode) == _T("WINNT_UPGRADE") ||
  2175. GetNodeName(cpParentNode) == _T("SYS")) {
  2176. SDBERROR_FORMAT((_T("<APPHELP> within <WINNT_UPGRADE> or <SYS> ")
  2177. _T("cannot use BLOCK attribute. Use BLOCK_UPGRADE instead.\n\n%s\n"),
  2178. GetXML(cpParentNode)));
  2179. goto eh;
  2180. }
  2181. if (csType == _T("YES")) {
  2182. Type = SDB_APPHELP_HARDBLOCK;
  2183. }
  2184. }
  2185. if (GetAttribute(_T("BLOCK_UPGRADE"), pNode, &csType)) {
  2186. if (GetNodeName(cpParentNode) != _T("WINNT_UPGRADE") &&
  2187. GetNodeName(cpParentNode) != _T("SYS")) {
  2188. SDBERROR_FORMAT((_T("<APPHELP> not within <WINNT_UPGRADE> or <SYS> ")
  2189. _T("cannot use BLOCK_UPGRADE attribute.\n\n%s\n"),
  2190. GetXML(cpParentNode)));
  2191. goto eh;
  2192. }
  2193. if (csType == _T("YES")) {
  2194. bBlockUpgrade = TRUE;
  2195. }
  2196. }
  2197. if (m_cpNode == NULL &&
  2198. !GetAttribute(_T("HTMLHELPID"), pNode, &csHTMLHELPID)) {
  2199. //
  2200. // Need to generate a new HTMLHELPID. Wait until
  2201. // the rest of the <APPHELP> tags for this app have
  2202. // been parsed and then we'll pass over this again.
  2203. //
  2204. pDB->m_pCurrentApp->m_rgAppHelpRefs.Add(this);
  2205. m_cpNode = pNode;
  2206. bSuccess = TRUE;
  2207. goto eh;
  2208. }
  2209. if (!GetAttribute(_T("HTMLHELPID"), pNode, &csHTMLHELPID)) {
  2210. //
  2211. // HTMLHELPID not found. Generate it.
  2212. //
  2213. for (i = 0; i < pDB->m_pCurrentApp->m_rgAppHelpRefs.GetSize(); i++) {
  2214. pAppHelpRef = (SdbAppHelpRef *) pDB->m_pCurrentApp->m_rgAppHelpRefs.GetAt(i);
  2215. if (pAppHelpRef->m_pAppHelp) {
  2216. if (pAppHelpRef->m_pAppHelp->m_csMessage == csMessage &&
  2217. pAppHelpRef->m_pAppHelp->m_Type == Type &&
  2218. pAppHelpRef->m_pAppHelp->m_csURL == csURL &&
  2219. pAppHelpRef->m_pAppHelp->m_bBlockUpgrade == bBlockUpgrade &&
  2220. pAppHelpRef->m_pAppHelp->m_csParameter1 == csParameter1) {
  2221. csHTMLHELPID = pAppHelpRef->m_pAppHelp->m_csName;
  2222. }
  2223. }
  2224. }
  2225. if (csHTMLHELPID.IsEmpty()) {
  2226. csHTMLHELPID.Format(_T("%d"), pDB->GetNextSequentialID(_T("HTMLHELPID")));
  2227. }
  2228. if (!AddAttribute(pNode, _T("HTMLHELPID"), csHTMLHELPID)) {
  2229. SDBERROR_PROPOGATE();
  2230. goto eh;
  2231. }
  2232. pDB->m_pCurrentInputFile->m_bSourceUpdated = TRUE;
  2233. }
  2234. //
  2235. // Create an AppHelp entry if one isn't there
  2236. //
  2237. m_pAppHelp = (SdbAppHelp *) pDB->m_rgAppHelps.LookupName(csHTMLHELPID);
  2238. if (m_pAppHelp == NULL) {
  2239. m_pAppHelp = new SdbAppHelp;
  2240. m_pAppHelp->m_csName = csHTMLHELPID;
  2241. m_pAppHelp->m_csMessage = csMessage;
  2242. m_pAppHelp->m_csURL = csURL;
  2243. m_pAppHelp->m_csParameter1 = csParameter1;
  2244. m_pAppHelp->m_pApp = pDB->m_pCurrentApp;
  2245. m_pAppHelp->m_Type = Type;
  2246. m_pAppHelp->m_bBlockUpgrade = bBlockUpgrade;
  2247. pDB->m_rgAppHelps.Add(m_pAppHelp, pDB);
  2248. } else {
  2249. if (m_pAppHelp->m_pApp != pDB->m_pCurrentApp ||
  2250. m_pAppHelp->m_csMessage != csMessage ||
  2251. m_pAppHelp->m_Type != Type ||
  2252. m_pAppHelp->m_bBlockUpgrade != bBlockUpgrade ||
  2253. m_pAppHelp->m_csURL != csURL ||
  2254. m_pAppHelp->m_csParameter1 != csParameter1) {
  2255. SDBERROR_FORMAT((_T("Duplicate HTMLHELPID with differing APP, MESSAGE, BLOCK, DETAILS_URL or PARAMETER1: %s\n"),
  2256. csHTMLHELPID));
  2257. goto eh;
  2258. }
  2259. }
  2260. pDB->m_pCurrentApp->m_rgAppHelpRefs.Add(this);
  2261. m_pDB = pDB;
  2262. bSuccess = TRUE;
  2263. eh:
  2264. return bSuccess;
  2265. }
  2266. BOOL SdbMessage::ReadFromXML(
  2267. IXMLDOMNode* pNode,
  2268. SdbDatabase* pDB)
  2269. {
  2270. BOOL bSuccess = FALSE;
  2271. IXMLDOMNodePtr cpChild;
  2272. CString csTemplate, csID;
  2273. if (!ReadName(pNode, &m_csName)) {
  2274. SDBERROR_PROPOGATE();
  2275. goto eh;
  2276. }
  2277. m_csLangID = pDB->m_csCurrentLangID;
  2278. if (GetAttribute(_T("TEMPLATE"), pNode, &csTemplate)) {
  2279. m_pTemplate = (SdbMessageTemplate *)
  2280. pDB->m_rgMessageTemplates.LookupName(csTemplate, m_csLangID);
  2281. if (m_pTemplate == NULL) {
  2282. SDBERROR_FORMAT((_T("Template \"%s\" not previously declared."), csTemplate));
  2283. goto eh;
  2284. }
  2285. }
  2286. if (!ProcureGuidIDAttribute(pDB, pNode, &m_ID, &csID)) {
  2287. SDBERROR_PROPOGATE();
  2288. goto eh;
  2289. }
  2290. if (GetChild(_T("CONTACT_INFO"), pNode, &cpChild)) {
  2291. m_csContactInfoXML = GetInnerXML(cpChild);
  2292. cpChild.Release();
  2293. }
  2294. if (GetChild(_T("SUMMARY"), pNode, &cpChild)) {
  2295. m_csSummaryXML = GetInnerXML(cpChild);
  2296. cpChild.Release();
  2297. }
  2298. if (GetChild(_T("DETAILS"), pNode, &cpChild)) {
  2299. m_csDetailsXML = GetInnerXML(cpChild);
  2300. cpChild.Release();
  2301. } else {
  2302. m_csDetailsXML = m_csSummaryXML;
  2303. }
  2304. if (!m_rgFields.ReadFromXML(_T("FIELD"), pDB, pNode)) {
  2305. SDBERROR_PROPOGATE();
  2306. goto eh;
  2307. }
  2308. m_pDB = pDB;
  2309. bSuccess = TRUE;
  2310. eh:
  2311. return bSuccess;
  2312. }
  2313. BOOL SdbMessageTemplate::ReadFromXML(
  2314. IXMLDOMNode* pNode,
  2315. SdbDatabase* pDB)
  2316. {
  2317. BOOL bSuccess = FALSE;
  2318. IXMLDOMNodePtr cpChild;
  2319. if (!ReadName(pNode, &m_csName)) {
  2320. SDBERROR_PROPOGATE();
  2321. goto eh;
  2322. }
  2323. m_csLangID = pDB->m_csCurrentLangID;
  2324. if (GetChild(_T("SUMMARY"), pNode, &cpChild)) {
  2325. m_csSummaryXML = GetInnerXML(cpChild);
  2326. cpChild.Release();
  2327. }
  2328. if (GetChild(_T("DETAILS"), pNode, &cpChild)) {
  2329. m_csDetailsXML = GetInnerXML(cpChild);
  2330. cpChild.Release();
  2331. } else {
  2332. m_csDetailsXML = m_csSummaryXML;
  2333. }
  2334. m_pDB = pDB;
  2335. bSuccess = TRUE;
  2336. eh:
  2337. return bSuccess;
  2338. }
  2339. BOOL SdbContactInfo::ReadFromXML(
  2340. IXMLDOMNode* pNode,
  2341. SdbDatabase* pDB)
  2342. {
  2343. BOOL bSuccess = FALSE;
  2344. CString csID;
  2345. if (!GetAttribute(_T("VENDOR"), pNode, &m_csName)) {
  2346. SDBERROR_FORMAT((_T("<CONTACT_INFO> requires VENDOR attribute:\n%s\n"), GetXML(pNode)));
  2347. goto eh;
  2348. }
  2349. m_csLangID = pDB->m_csCurrentLangID;
  2350. if (!ProcureGuidIDAttribute(pDB, pNode, &m_ID, &csID)) {
  2351. SDBERROR_PROPOGATE();
  2352. goto eh;
  2353. }
  2354. m_csXML = GetInnerXML(pNode);
  2355. m_pDB = pDB;
  2356. bSuccess = TRUE;
  2357. eh:
  2358. return bSuccess;
  2359. }
  2360. BOOL SdbData::ReadFromXML(
  2361. IXMLDOMNode* pNode,
  2362. SdbDatabase* pDB)
  2363. {
  2364. BOOL bSuccess = FALSE;
  2365. CString csValueType;
  2366. CString csValueAttr;
  2367. CString csValueText;
  2368. DWORD dwType;
  2369. if (!ReadName(pNode, &m_csName)) {
  2370. SDBERROR_PROPOGATE();
  2371. goto eh;
  2372. }
  2373. if (!GetAttribute(_T("VALUETYPE"), pNode, &csValueType)) {
  2374. SDBERROR(_T("<DATA> requires VALUETYPE attribute."));
  2375. goto eh;
  2376. }
  2377. if (!GetDataTypeIndicator(csValueType, &dwType)) {
  2378. SDBERROR_FORMAT((_T("<DATA> VALUETYPE \"%s\" not recognized."), csValueType));
  2379. goto eh;
  2380. }
  2381. GetNodeText(pNode, csValueText);
  2382. GetAttribute(_T("VALUE"), pNode, &csValueAttr);
  2383. if (csValueText.GetLength() && csValueAttr.GetLength()) {
  2384. SDBERROR_FORMAT((_T("<DATA NAME=\"%s\"> cannot contain both VALUE attribute and inner text."), m_csName));
  2385. goto eh;
  2386. } else if (csValueText.GetLength()) {
  2387. SetValue((SdbDataValueType) dwType, csValueText);
  2388. } else if (csValueAttr.GetLength()) {
  2389. SetValue((SdbDataValueType) dwType, csValueAttr);
  2390. }
  2391. m_DataType = (SdbDataValueType) dwType;
  2392. // finally, read all the child data elements
  2393. if (!m_rgData.ReadFromXML(_T("DATA"), pDB, pNode)) {
  2394. SDBERROR_PROPOGATE();
  2395. goto eh;
  2396. }
  2397. m_pDB = pDB;
  2398. bSuccess = TRUE;
  2399. eh:
  2400. return bSuccess;
  2401. }
  2402. BOOL SdbAction::ReadFromXML(
  2403. IXMLDOMNode* pNode,
  2404. SdbDatabase* pDB)
  2405. {
  2406. BOOL bSuccess = FALSE;
  2407. if (!ReadName(pNode, &m_csName)) {
  2408. SDBERROR_PROPOGATE();
  2409. goto eh;
  2410. }
  2411. GetAttribute(_T("TYPE"), pNode, &m_csType);
  2412. if (!m_rgData.ReadFromXML(_T("DATA"), pDB, pNode)) {
  2413. SDBERROR_PROPOGATE();
  2414. goto eh;
  2415. }
  2416. m_pDB = pDB;
  2417. bSuccess = TRUE;
  2418. eh:
  2419. return bSuccess;
  2420. }
  2421. BOOL SdbMessageField::ReadFromXML(
  2422. IXMLDOMNode* pNode,
  2423. SdbDatabase* pDB)
  2424. {
  2425. BOOL bSuccess = FALSE;
  2426. if (!ReadName(pNode, &m_csName)) {
  2427. SDBERROR_PROPOGATE();
  2428. goto eh;
  2429. }
  2430. m_csValue = GetInnerXML(pNode);
  2431. m_pDB = pDB;
  2432. bSuccess = TRUE;
  2433. eh:
  2434. return bSuccess;
  2435. }
  2436. BOOL SdbMatchOperation::ReadFromXML(
  2437. IXMLDOMNode* pNode,
  2438. SdbDatabase* pDB
  2439. )
  2440. {
  2441. BOOL bSuccess = FALSE;
  2442. if (GetNodeName(pNode) == _T("MATCH_ANY")) {
  2443. m_Type = SDB_MATCH_ANY;
  2444. } else {
  2445. m_Type = SDB_MATCH_ALL;
  2446. }
  2447. if (!m_rgMatchingFiles.ReadFromXML(_T("MATCHING_FILE"), pDB, pNode)) {
  2448. SDBERROR_PROPOGATE();
  2449. goto eh;
  2450. }
  2451. if (!m_rgSubMatchOps.ReadFromXML(_T("MATCH_ALL | MATCH_ANY"), pDB, pNode, NULL, FALSE, NULL)) {
  2452. SDBERROR_PROPOGATE();
  2453. goto eh;
  2454. }
  2455. bSuccess = TRUE;
  2456. eh:
  2457. return bSuccess;
  2458. }
  2459. BOOL SdbWin9xMigration::ReadFromXML(
  2460. IXMLDOMNode* pNode,
  2461. SdbDatabase* pDB)
  2462. {
  2463. BOOL bSuccess = FALSE;
  2464. CString csID, csTemp;
  2465. m_pApp = pDB->m_pCurrentApp; // grab app pointer from the db
  2466. if (!GetAttribute(_T("SECTION"), pNode, &m_csSection)) {
  2467. SDBERROR_FORMAT((_T("<WIN9X_MIGRATION> tag requires SECTION attribute:\n%s\n"),
  2468. GetXML(pNode)));
  2469. goto eh;
  2470. }
  2471. GetAttribute(_T("MESSAGE"), pNode, &m_csMessage);
  2472. if (!ProcureGuidIDAttribute(pDB, pNode, &m_ID, &csID)) {
  2473. SDBERROR_PROPOGATE();
  2474. goto eh;
  2475. }
  2476. if (g_bStrict) {
  2477. if (!CheckExeID(pDB, this, csID)) {
  2478. SDBERROR_PROPOGATE();
  2479. goto eh;
  2480. }
  2481. }
  2482. if (GetAttribute(_T("SHOW_IN_SIMPLIFIED_VIEW"), pNode, &csTemp)) {
  2483. m_bShowInSimplifiedView = (csTemp.CompareNoCase(_T("YES")) == 0);
  2484. }
  2485. if (!m_MatchOp.ReadFromXML(pNode, pDB)) {
  2486. SDBERROR_PROPOGATE();
  2487. goto eh;
  2488. }
  2489. m_pDB = pDB;
  2490. bSuccess = TRUE;
  2491. eh:
  2492. return bSuccess;
  2493. }
  2494. BOOL SdbWinNTUpgrade::ReadFromXML(
  2495. IXMLDOMNode* pNode,
  2496. SdbDatabase* pDB)
  2497. {
  2498. BOOL bSuccess = FALSE;
  2499. BOOL bMF = FALSE;
  2500. CString csType, csHTMLHELPID, csID;
  2501. XMLNodeList XQL;
  2502. IXMLDOMNodePtr cpNewNode, cpAppNode;
  2503. m_pApp = pDB->m_pCurrentApp; // grab app pointer from the db
  2504. XQL.Query(pNode, _T("APPHELP"));
  2505. if (XQL.GetSize() > 1) {
  2506. SDBERROR_FORMAT((_T("<WINNT_UPGRADE> blocks can only contain one <APPHELP> entry:\n%s\n"),
  2507. GetXML(pNode)));
  2508. goto eh;
  2509. } else if (XQL.GetSize() == 1) {
  2510. if (!XQL.GetItem(0, &cpNewNode)) {
  2511. SDBERROR_PROPOGATE();
  2512. goto eh;
  2513. }
  2514. if (!m_AppHelpRef.ReadFromXML(cpNewNode, pDB)) {
  2515. SDBERROR_PROPOGATE();
  2516. goto eh;
  2517. }
  2518. }
  2519. if (!ProcureGuidIDAttribute(pDB, pNode, &m_ID, &csID)) {
  2520. SDBERROR_PROPOGATE();
  2521. goto eh;
  2522. }
  2523. XQL.Query(pNode, _T("MATCHING_FILE"));
  2524. if (XQL.GetSize() > 1) {
  2525. SDBERROR_FORMAT((_T("<WINNT_UPGRADE> blocks can only contain one <MATCHING_xxx> entry:\n%s\n"),
  2526. GetXML(pNode)));
  2527. goto eh;
  2528. } else if (XQL.GetSize() == 1) {
  2529. if (!XQL.GetItem(0, &cpNewNode)) {
  2530. SDBERROR_PROPOGATE();
  2531. goto eh;
  2532. }
  2533. if (!m_MatchingFile.ReadFromXML(cpNewNode, pDB)) {
  2534. SDBERROR_PROPOGATE();
  2535. goto eh;
  2536. }
  2537. bMF = TRUE;
  2538. }
  2539. XQL.Query(pNode, _T("MATCHING_REGISTRY_ENTRY"));
  2540. if (XQL.GetSize() > 1 ||
  2541. (XQL.GetSize() == 1 && bMF)) {
  2542. SDBERROR_FORMAT((_T("<WINNT_UPGRADE> blocks can only contain one <MATCHING_xxx> entry:\n%s\n"),
  2543. GetXML(pNode)));
  2544. goto eh;
  2545. } else if(XQL.GetSize() == 1) {
  2546. if (!XQL.GetItem(0, &cpNewNode)) {
  2547. SDBERROR_PROPOGATE();
  2548. goto eh;
  2549. }
  2550. if (!m_MatchingRegistryEntry.ReadFromXML(cpNewNode, pDB)) {
  2551. SDBERROR_PROPOGATE();
  2552. goto eh;
  2553. }
  2554. bMF = TRUE;
  2555. }
  2556. m_AppHelpRef.m_pDB = pDB;
  2557. m_pDB = pDB;
  2558. pDB->m_rgWinNTUpgradeEntries.Add(this, pDB);
  2559. bSuccess = TRUE;
  2560. eh:
  2561. return bSuccess;
  2562. }