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.

1304 lines
32 KiB

  1. /*++
  2. Copyright (c) 1999-2001 Microsoft Corporation
  3. Module Name:
  4. merge.cpp
  5. Abstract:
  6. This module implements routines for service
  7. specific SSR Knowledge Base merging via KBreg.xml.
  8. Author:
  9. Vishnu Patankar (VishnuP) - Jun 2002
  10. Environment:
  11. User mode only.
  12. Exported Functions:
  13. Revision History:
  14. Created - Jun 2002
  15. --*/
  16. #include "stdafx.h"
  17. #include "kbproc.h"
  18. #include "process.h"
  19. #include <Wbemcli.h>
  20. HRESULT
  21. process::SsrpProcessKBsMerge(
  22. IN PWSTR pszKBDir,
  23. IN PWSTR pszMachineName,
  24. OUT IXMLDOMElement **ppElementRoot,
  25. OUT IXMLDOMDocument **ppXMLDoc
  26. )
  27. /*++
  28. Routine Description:
  29. Routine called to merge KBs
  30. Arguments:
  31. pszKBDir - the root directory from which to get the KBs
  32. pszMachineName - name of the machine to preprocess
  33. ppElementRoot - the root element pointer to be filled in
  34. ppXMLDoc - document pointer to be filled in
  35. Return:
  36. HRESULT error code
  37. ++*/
  38. {
  39. //
  40. // load the KB registration document
  41. //
  42. WCHAR szKBregs[MAX_PATH + 50];
  43. WCHAR szWindir[MAX_PATH + 50];
  44. WCHAR szMergedKB[MAX_PATH + 50];
  45. DWORD rc = ERROR_SUCCESS;
  46. HRESULT hr = S_OK;
  47. CComPtr <IXMLDOMDocument> pXMLKBDoc;
  48. OSVERSIONINFOEX osVersionInfo;
  49. CComPtr <IXMLDOMNodeList> pKBList;
  50. CComPtr <IXMLDOMNode> pKB;
  51. CComPtr <IXMLDOMElement> pXMLDocElemRoot;
  52. BOOL bOsKbMatch = FALSE;
  53. if ( !GetSystemWindowsDirectory(szWindir, MAX_PATH + 1) ) {
  54. SsrpLogError(L"Error GetSystemWindowsDirectory() \n");
  55. SsrpLogWin32Error(GetLastError());
  56. return E_INVALIDARG;
  57. }
  58. wcscpy(szMergedKB, szWindir);
  59. wcscat(szMergedKB, L"\\security\\ssr\\kbs\\MergedRawKB.xml");
  60. CComVariant MergedKB(szMergedKB);
  61. wcscpy(szKBregs, pszKBDir);
  62. wcscat(szKBregs, L"KBreg.xml");
  63. CComVariant KBregsFile(szKBregs);
  64. hr = CoCreateInstance(CLSID_DOMDocument,
  65. NULL,
  66. CLSCTX_INPROC_SERVER,
  67. IID_IXMLDOMDocument,
  68. (void**)&pXMLKBDoc);
  69. if (FAILED(hr) || pXMLKBDoc == NULL ) {
  70. SsrpLogError(L"COM failed to create a DOM instance");
  71. goto ExitHandler;
  72. }
  73. VARIANT_BOOL vtSuccess;
  74. hr = pXMLKBDoc->load(KBregsFile, &vtSuccess);
  75. if (FAILED(hr) || vtSuccess == VARIANT_FALSE ) {
  76. SsrpLogParseError(hr);
  77. goto ExitHandler;
  78. }
  79. //
  80. // get the root element
  81. //
  82. hr = pXMLKBDoc->get_documentElement(&pXMLDocElemRoot);
  83. if (FAILED(hr) || pXMLDocElemRoot == NULL ) {
  84. SsrpLogParseError(hr);
  85. goto ExitHandler;
  86. }
  87. if (NULL == pszMachineName) {
  88. //
  89. // local machine
  90. //
  91. osVersionInfo.dwOSVersionInfoSize = sizeof(osVersionInfo);
  92. if (!GetVersionEx((LPOSVERSIONINFOW)&osVersionInfo)){
  93. SsrpLogError(L"Error GetVersionEx \n");
  94. SsrpLogWin32Error(GetLastError());
  95. goto ExitHandler;
  96. }
  97. }
  98. else {
  99. //
  100. // remote machine - use WMI
  101. //
  102. hr = SsrpGetRemoteOSVersionInfo(pszMachineName,
  103. &osVersionInfo);
  104. if (FAILED(hr)) {
  105. SsrpLogError(L"SsrpGetRemoteOSVersionInfo failed");
  106. goto ExitHandler;
  107. }
  108. }
  109. hr = pXMLDocElemRoot->selectNodes(L"KBs", &pKBList);
  110. if (FAILED(hr) || pKBList == NULL ) {
  111. SsrpLogParseError(hr);
  112. goto ExitHandler;
  113. }
  114. hr = pKBList->nextNode(&pKB);
  115. if (FAILED(hr) || pKB == NULL ) {
  116. SsrpLogParseError(hr);
  117. goto ExitHandler;
  118. }
  119. while (pKB) {
  120. CComBSTR bstrText;
  121. CComPtr <IXMLDOMNode> pName;
  122. CComPtr <IXMLDOMNode> pXDNodeServiceStartup;
  123. CComPtr <IXMLDOMNamedNodeMap> pXMLAttribNode;
  124. CComPtr <IXMLDOMNode> pXMLMajorInfo;
  125. CComPtr <IXMLDOMNode> pXMLMinorInfo;
  126. hr = pKB->get_attributes( &pXMLAttribNode );
  127. if (FAILED(hr) || pXMLAttribNode == NULL){
  128. SsrpLogParseError(hr);
  129. goto ExitHandler;
  130. }
  131. hr = pXMLAttribNode->getNamedItem(L"OSVersionMajorInfo", &pXMLMajorInfo );
  132. if (FAILED(hr) || pXMLMajorInfo == NULL){
  133. SsrpLogParseError(hr);
  134. goto ExitHandler;
  135. }
  136. hr = pXMLAttribNode->getNamedItem(L"OSVersionMinorInfo", &pXMLMinorInfo );
  137. if (FAILED(hr) || pXMLMinorInfo == NULL){
  138. SsrpLogParseError(hr);
  139. goto ExitHandler;
  140. }
  141. CComBSTR bstrValue;
  142. DWORD dwMajor;
  143. DWORD dwMinor;
  144. hr = pXMLMajorInfo->get_text(&bstrValue);
  145. if (FAILED(hr) || !bstrValue ) {
  146. SsrpLogParseError(hr);
  147. goto ExitHandler;
  148. }
  149. dwMajor = _wtoi(bstrValue);
  150. hr = pXMLMinorInfo->get_text(&bstrValue);
  151. if (FAILED(hr) || !bstrValue ) {
  152. SsrpLogParseError(hr);
  153. goto ExitHandler;
  154. }
  155. dwMinor = _wtoi(bstrValue);
  156. if (osVersionInfo.dwMajorVersion == dwMajor &&
  157. osVersionInfo.dwMinorVersion == dwMinor) {
  158. //
  159. // got the required KB node
  160. //
  161. bOsKbMatch = TRUE;
  162. break;
  163. }
  164. hr = pKBList->nextNode(&pKB);
  165. if (FAILED(hr) || pKB == NULL ) {
  166. SsrpLogParseError(hr);
  167. goto ExitHandler;
  168. }
  169. }
  170. if (bOsKbMatch == FALSE) {
  171. SsrpLogError(L"Failed to map OSversion to KB information in registration");
  172. hr = E_INVALIDARG;
  173. goto ExitHandler;
  174. }
  175. //
  176. // merge according to precedence
  177. //
  178. hr = SsrpMergeAccordingToPrecedence(L"Extensions",
  179. pszKBDir,
  180. ppElementRoot,
  181. ppXMLDoc,
  182. pKB);
  183. if (FAILED(hr)) {
  184. SsrpLogError(L"Failed to merge Extension KB");
  185. goto ExitHandler;
  186. }
  187. hr = SsrpMergeAccordingToPrecedence(L"Root",
  188. pszKBDir,
  189. ppElementRoot,
  190. ppXMLDoc,
  191. pKB);
  192. if (FAILED(hr)) {
  193. SsrpLogError(L"Failed to merge Root KB");
  194. goto ExitHandler;
  195. }
  196. hr = SsrpMergeAccordingToPrecedence(L"Custom",
  197. pszKBDir,
  198. ppElementRoot,
  199. ppXMLDoc,
  200. pKB);
  201. if (FAILED(hr)) {
  202. SsrpLogError(L"Failed to merge Custom KB");
  203. goto ExitHandler;
  204. }
  205. hr = SsrpOverwriteServiceLocalizationFromSystem(*ppElementRoot, *ppXMLDoc);
  206. if (FAILED(hr)) {
  207. SsrpLogError(L"Failed to merge Custom KB");
  208. goto ExitHandler;
  209. }
  210. hr = (*ppXMLDoc)->save(MergedKB);
  211. if (FAILED(hr)) {
  212. SsrpLogParseError(hr);
  213. }
  214. ExitHandler:
  215. return hr;
  216. }
  217. HRESULT
  218. process::SsrpGetRemoteOSVersionInfo(
  219. IN PWSTR pszMachineName,
  220. OUT OSVERSIONINFOEX *posVersionInfo
  221. )
  222. /*++
  223. Routine Description:
  224. Routine called to get version info from remote machine via WMI
  225. Arguments:
  226. pszMachineName - remote machine name
  227. posVersionInfo - os version info to fill via WMI queries
  228. Return:
  229. HRESULT error code
  230. ++*/
  231. {
  232. HRESULT hr = S_OK;
  233. CComPtr <IWbemLocator> pWbemLocator = NULL;
  234. CComPtr <IWbemServices> pWbemServices = NULL;
  235. CComPtr <IWbemClassObject> pWbemOsObjectInstance = NULL;
  236. CComPtr <IEnumWbemClassObject> pWbemEnumObject = NULL;
  237. CComBSTR bstrMachineAndNamespace;
  238. ULONG nReturned = 0;
  239. bstrMachineAndNamespace = pszMachineName;
  240. bstrMachineAndNamespace += L"\\root\\cimv2";
  241. hr = CoCreateInstance(
  242. CLSID_WbemLocator,
  243. 0,
  244. CLSCTX_INPROC_SERVER,
  245. IID_IWbemLocator,
  246. (LPVOID *) &pWbemLocator
  247. );
  248. if (FAILED(hr) || pWbemLocator == NULL ) {
  249. SsrpLogError(L"Error getting instance of CLSID_WbemLocator \n");
  250. SsrpLogParseError(hr);
  251. goto ExitHandler;
  252. }
  253. hr = pWbemLocator->ConnectServer(
  254. bstrMachineAndNamespace,
  255. NULL,
  256. NULL,
  257. NULL,
  258. 0L,
  259. NULL,
  260. NULL,
  261. &pWbemServices
  262. );
  263. if (FAILED(hr) || pWbemServices == NULL ) {
  264. SsrpLogError(L"Error ConnectServer \n");
  265. SsrpLogParseError(hr);
  266. goto ExitHandler;
  267. }
  268. hr = CoSetProxyBlanket(
  269. pWbemServices,
  270. RPC_C_AUTHN_WINNT,
  271. RPC_C_AUTHZ_NONE,
  272. NULL,
  273. RPC_C_AUTHN_LEVEL_PKT,
  274. RPC_C_IMP_LEVEL_IMPERSONATE,
  275. NULL,
  276. EOAC_NONE
  277. );
  278. if (FAILED(hr)) {
  279. SsrpLogError(L"Error CoSetProxyBlanket \n");
  280. SsrpLogParseError(hr);
  281. goto ExitHandler;
  282. }
  283. hr = pWbemServices->ExecQuery(CComBSTR(L"WQL"),
  284. CComBSTR(L"SELECT * FROM Win32_OperatingSystem"),
  285. WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY,
  286. NULL,
  287. &pWbemEnumObject);
  288. if (FAILED(hr) || pWbemEnumObject == NULL) {
  289. SsrpLogError(L"Error SELECT * FROM Win32_OperatingSystem\n");
  290. SsrpLogParseError(hr);
  291. goto ExitHandler;
  292. }
  293. hr = pWbemEnumObject->Next(WBEM_INFINITE, 1, &pWbemOsObjectInstance, &nReturned);
  294. if (FAILED(hr) || pWbemOsObjectInstance == NULL) {
  295. SsrpLogError(L"Error enumerating\n");
  296. SsrpLogParseError(hr);
  297. goto ExitHandler;
  298. }
  299. VARIANT vVersion;
  300. VariantInit(&vVersion);
  301. hr = pWbemOsObjectInstance->Get(CComBSTR(L"Version"),
  302. 0,
  303. &vVersion,
  304. NULL,
  305. NULL);
  306. if (FAILED(hr)) {
  307. SsrpLogError(L"Error getting Version property \n");
  308. SsrpLogParseError(hr);
  309. goto ExitHandler;
  310. }
  311. if (V_VT(&vVersion) == VT_NULL) {
  312. SsrpLogError(L"Error Version property is null\n");
  313. goto ExitHandler;
  314. }
  315. //
  316. // extract the version information into DWORDs since
  317. // the return type of this property is BSTR variant
  318. // of the form "5.1.2195"
  319. //
  320. BSTR bstrVersion = V_BSTR(&vVersion);
  321. WCHAR szVersion[5];
  322. szVersion[0] = L'\0';
  323. PWSTR pszDot = wcsstr(bstrVersion, L".");
  324. if (NULL == pszDot) {
  325. SsrpLogError(L"Version property has no '.' \n");
  326. hr = E_INVALIDARG;
  327. goto ExitHandler;
  328. }
  329. wcsncpy(szVersion, bstrVersion, 1);
  330. posVersionInfo->dwMajorVersion = (DWORD)_wtoi(szVersion);
  331. wcsncpy(szVersion, pszDot+1, 1);
  332. posVersionInfo->dwMinorVersion = (DWORD)_wtoi(szVersion);
  333. ExitHandler:
  334. if (V_VT(&vVersion) != VT_NULL) {
  335. VariantClear( &vVersion );
  336. }
  337. return hr;
  338. }
  339. HRESULT
  340. process::SsrpMergeAccordingToPrecedence(
  341. IN PWSTR pszKBType,
  342. IN PWSTR pszKBDir,
  343. OUT IXMLDOMElement **ppElementRoot,
  344. OUT IXMLDOMDocument **ppXMLDoc,
  345. IN IXMLDOMNode *pKB
  346. )
  347. /*++
  348. Routine Description:
  349. Routine called to load and merge XML KBs
  350. Arguments:
  351. pszKBType - type of KB - i.e. Custom/Extension/Root
  352. pszKBDir - path to KB directory
  353. ppElementRoot - the root element pointer to be filled in
  354. ppXMLDoc - document pointer to be filled in
  355. pKB - pointer to KB registration node
  356. Return:
  357. HRESULT error code
  358. ++*/
  359. {
  360. HRESULT hr = S_OK;
  361. WCHAR szKBandName[MAX_PATH];
  362. CComPtr <IXMLDOMNodeList> pKBList;
  363. WCHAR szKBFile[MAX_PATH + 20];
  364. WCHAR szWindir[MAX_PATH + 20];
  365. wcscpy(szKBandName, pszKBType);
  366. wcscat(szKBandName, L"/Name");
  367. hr = pKB->selectNodes(szKBandName, &pKBList);
  368. if (FAILED(hr) || pKBList == NULL ) {
  369. SsrpLogError(L"No KBs in this category \n");
  370. hr = S_OK;
  371. goto ExitHandler;
  372. }
  373. hr = pKBList->nextNode(&pKB);
  374. if (FAILED(hr)) {
  375. SsrpLogParseError(hr);
  376. goto ExitHandler;
  377. }
  378. while (pKB) {
  379. CComBSTR bstrValue;
  380. hr = pKB->get_text(&bstrValue);
  381. if (FAILED(hr) || !bstrValue ) {
  382. SsrpLogParseError(hr);
  383. goto ExitHandler;
  384. }
  385. SsrpConvertBstrToPwstr(bstrValue);
  386. wcscpy(szKBFile, pszKBDir);
  387. wcscat(szKBFile, bstrValue);
  388. if ( 0xFFFFFFFF == GetFileAttributes(szKBFile) ) {
  389. SsrpLogError(L"KB File not found");
  390. hr = E_INVALIDARG;
  391. goto ExitHandler;
  392. }
  393. hr = SsrpMergeDOMTrees(ppElementRoot, ppXMLDoc, szKBFile);
  394. if (FAILED(hr)) {
  395. SsrpLogParseError(hr);
  396. goto ExitHandler;
  397. }
  398. hr = pKBList->nextNode(&pKB);
  399. if (FAILED(hr)) {
  400. SsrpLogParseError(hr);
  401. goto ExitHandler;
  402. }
  403. }
  404. ExitHandler:
  405. return hr;
  406. }
  407. HRESULT
  408. process::SsrpMergeDOMTrees(
  409. OUT IXMLDOMElement **ppMergedKBElementRoot,
  410. OUT IXMLDOMDocument **ppMergedKBXMLDoc,
  411. IN WCHAR *szXMLFileName
  412. )
  413. /*++
  414. Routine Description:
  415. Routine called to load and merge XML KBs
  416. Arguments:
  417. *ppElementRoot - pointer to final merged KB root
  418. *ppXMLDoc - pointer to final merged KB doc to which merges are made
  419. Return:
  420. HRESULT error code
  421. ++*/
  422. {
  423. CComPtr <IXMLDOMDocument> pXMLKBDoc;
  424. CComPtr <IXMLDOMElement> pXMLKBElemRoot;
  425. CComVariant KBFile(szXMLFileName);
  426. CComPtr <IXMLDOMNode> pNewNode;
  427. HRESULT hr = S_OK;
  428. VARIANT_BOOL vtSuccess = VARIANT_FALSE;
  429. //
  430. // instantiate DOM document object to read and store each KB
  431. //
  432. hr = CoCreateInstance(CLSID_DOMDocument,
  433. NULL,
  434. CLSCTX_INPROC_SERVER,
  435. IID_IXMLDOMDocument,
  436. (void**)&pXMLKBDoc);
  437. if (FAILED(hr) || pXMLKBDoc == NULL ) {
  438. SsrpLogError(L"COM failed to create a DOM instance");
  439. goto ExitHandler;
  440. }
  441. hr = pXMLKBDoc->put_preserveWhiteSpace(VARIANT_TRUE);
  442. if (FAILED(hr)) {
  443. SsrpLogParseError(hr);
  444. goto ExitHandler;
  445. }
  446. //
  447. // load the KB XML into DOM
  448. //
  449. hr = pXMLKBDoc->load(KBFile, &vtSuccess);
  450. if (FAILED(hr) || vtSuccess == VARIANT_FALSE ) {
  451. SsrpLogParseError(hr);
  452. goto ExitHandler;
  453. }
  454. //
  455. // get the root element
  456. //
  457. hr = pXMLKBDoc->get_documentElement(&pXMLKBElemRoot);
  458. if (FAILED(hr) || pXMLKBElemRoot == NULL ) {
  459. SsrpLogParseError(hr);
  460. goto ExitHandler;
  461. }
  462. if (*ppMergedKBElementRoot == NULL) {
  463. //
  464. // special case: this is the first KB, so simply clone the empty merged KB tree with it
  465. //
  466. hr = pXMLKBElemRoot->cloneNode(VARIANT_TRUE, &pNewNode);
  467. if (FAILED(hr) || pNewNode == NULL ) {
  468. SsrpLogParseError(hr);
  469. goto ExitHandler;
  470. }
  471. hr = (*ppMergedKBXMLDoc)->appendChild(pNewNode, NULL);
  472. if (FAILED(hr) ) {
  473. SsrpLogParseError(hr);
  474. goto ExitHandler;
  475. }
  476. //
  477. // update the empty values so that next time around, we know that
  478. // the merged KB is initialized with the first KB
  479. //
  480. hr = (*ppMergedKBXMLDoc)->get_documentElement(ppMergedKBElementRoot);
  481. if (FAILED(hr) || *ppMergedKBElementRoot == NULL ) {
  482. SsrpLogParseError(hr);
  483. goto ExitHandler;
  484. }
  485. goto ExitHandler;
  486. }
  487. //
  488. // this is not the first KB - perform actual merges in the following way:
  489. //
  490. // number of mergeable entities in MergedKB = n
  491. // number of mergeable entities in CurrentKB = m
  492. //
  493. // O(m x n) algorithm for merging:
  494. //
  495. // foreach mergeable entity in CurrentKB
  496. // foreach mergeable entity in MergedKB
  497. // if no <Name> based collision
  498. // append entity from CurrentKB into MergedKB
  499. // else
  500. // replace existing entity in MergedKB by entity from CurrentKB
  501. //
  502. hr = SsrpAppendOrReplaceMergeableEntities(L"Description/Name",
  503. *ppMergedKBElementRoot,
  504. *ppMergedKBXMLDoc,
  505. pXMLKBDoc,
  506. pXMLKBElemRoot,
  507. szXMLFileName
  508. );
  509. if (FAILED(hr)) {
  510. SsrpLogParseError(hr);
  511. goto ExitHandler;
  512. }
  513. hr = SsrpAppendOrReplaceMergeableEntities(L"SecurityLevels/Level/Name",
  514. *ppMergedKBElementRoot,
  515. *ppMergedKBXMLDoc,
  516. pXMLKBDoc,
  517. pXMLKBElemRoot,
  518. szXMLFileName
  519. );
  520. if (FAILED(hr)) {
  521. SsrpLogParseError(hr);
  522. goto ExitHandler;
  523. }
  524. hr = SsrpAppendOrReplaceMergeableEntities(L"Roles/Role/Name",
  525. *ppMergedKBElementRoot,
  526. *ppMergedKBXMLDoc,
  527. pXMLKBDoc,
  528. pXMLKBElemRoot,
  529. szXMLFileName
  530. );
  531. if (FAILED(hr)) {
  532. SsrpLogParseError(hr);
  533. goto ExitHandler;
  534. }
  535. hr = SsrpAppendOrReplaceMergeableEntities(L"Tasks/Task/Name",
  536. *ppMergedKBElementRoot,
  537. *ppMergedKBXMLDoc,
  538. pXMLKBDoc,
  539. pXMLKBElemRoot,
  540. szXMLFileName
  541. );
  542. if (FAILED(hr)) {
  543. SsrpLogParseError(hr);
  544. goto ExitHandler;
  545. }
  546. hr = SsrpAppendOrReplaceMergeableEntities(L"Services/Service/Name",
  547. *ppMergedKBElementRoot,
  548. *ppMergedKBXMLDoc,
  549. pXMLKBDoc,
  550. pXMLKBElemRoot,
  551. szXMLFileName
  552. );
  553. if (FAILED(hr)) {
  554. SsrpLogParseError(hr);
  555. goto ExitHandler;
  556. }
  557. hr = SsrpAppendOrReplaceMergeableEntities(L"RoleLocalization/Role/Name",
  558. *ppMergedKBElementRoot,
  559. *ppMergedKBXMLDoc,
  560. pXMLKBDoc,
  561. pXMLKBElemRoot,
  562. szXMLFileName
  563. );
  564. if (FAILED(hr)) {
  565. SsrpLogParseError(hr);
  566. goto ExitHandler;
  567. }
  568. hr = SsrpAppendOrReplaceMergeableEntities(L"TaskLocalization/Task/Name",
  569. *ppMergedKBElementRoot,
  570. *ppMergedKBXMLDoc,
  571. pXMLKBDoc,
  572. pXMLKBElemRoot,
  573. szXMLFileName
  574. );
  575. if (FAILED(hr)) {
  576. SsrpLogParseError(hr);
  577. goto ExitHandler;
  578. }
  579. hr = SsrpAppendOrReplaceMergeableEntities(L"ServiceLocalization/Service/Name",
  580. *ppMergedKBElementRoot,
  581. *ppMergedKBXMLDoc,
  582. pXMLKBDoc,
  583. pXMLKBElemRoot,
  584. szXMLFileName
  585. );
  586. if (FAILED(hr)) {
  587. SsrpLogParseError(hr);
  588. goto ExitHandler;
  589. }
  590. ExitHandler:
  591. return hr;
  592. }
  593. HRESULT
  594. process::SsrpAppendOrReplaceMergeableEntities(
  595. IN PWSTR pszFullyQualifiedEntityName,
  596. IN IXMLDOMElement *pMergedKBElementRoot,
  597. IN IXMLDOMDocument *pMergedKBXMLDoc,
  598. IN IXMLDOMDocument *pCurrentKBDoc,
  599. IN IXMLDOMElement *pCurrentKBElemRoot,
  600. IN PWSTR pszKBName
  601. )
  602. /*++
  603. Routine Description:
  604. Routine called to load and merge XML KBs
  605. Arguments:
  606. pszFullyQualifiedEntityName - string containing the entity name representing the entity
  607. pMergedKBElementRoot - pointer to final merged KB root
  608. pMergedKBXMLDoc - pointer to final merged KB doc to which merges are made
  609. pElementRoot - root of current KB
  610. pXMLDoc - pointer to current KB doc from which merges are made
  611. pszKBName - name of the source KB
  612. Return:
  613. HRESULT error code
  614. ++*/
  615. {
  616. HRESULT hr = S_OK;
  617. CComPtr <IXMLDOMNode> pNameCurrent;
  618. CComPtr <IXMLDOMNodeList> pNameListCurrent;
  619. CComPtr <IXMLDOMNamedNodeMap> pAttribNodeMap;
  620. CComPtr <IXMLDOMAttribute> pAttrib;
  621. CComBSTR bstrSourceKB(L"SourceKB");
  622. CComBSTR bstrSourceKBName(wcsrchr(pszKBName, L'\\')+1);
  623. hr = pCurrentKBElemRoot->selectNodes(pszFullyQualifiedEntityName, &pNameListCurrent);
  624. if (FAILED(hr) || pNameListCurrent == NULL ) {
  625. hr = S_OK;
  626. goto ExitHandler;
  627. }
  628. hr = pNameListCurrent->nextNode(&pNameCurrent);
  629. if (FAILED(hr) || pNameCurrent == NULL) {
  630. #if 0
  631. //
  632. // no need to error out if these nodes are not present in the source KB
  633. //
  634. #endif
  635. SsrpLogParseError(hr);
  636. goto ExitHandler;
  637. }
  638. while (pNameCurrent) {
  639. CComBSTR bstrCurrentText;
  640. CComPtr <IXMLDOMNode> pNameMerged;
  641. CComPtr <IXMLDOMNodeList> pNameListMerged;
  642. CComPtr <IXMLDOMNode> pRootOfEntityName;
  643. LONG ulLength;
  644. hr = pNameCurrent->get_text(&bstrCurrentText);
  645. if (FAILED(hr) || !bstrCurrentText ) {
  646. SsrpLogParseError(hr);
  647. goto ExitHandler;
  648. }
  649. hr = pMergedKBElementRoot->selectNodes(pszFullyQualifiedEntityName, &pNameListMerged);
  650. if (FAILED(hr) || pNameListMerged == NULL ) {
  651. SsrpLogParseError(hr);
  652. goto ExitHandler;
  653. }
  654. hr = pNameListMerged->get_length(&ulLength);
  655. if (FAILED(hr)) {
  656. SsrpLogParseError(hr);
  657. goto ExitHandler;
  658. }
  659. if (ulLength == 0) {
  660. PWSTR pszRootOfFullyQualifiedEntityName;
  661. WCHAR szRootOfEntityName[MAX_PATH];
  662. memset(szRootOfEntityName, L'\0', MAX_PATH * sizeof(WCHAR));
  663. //
  664. // no need to error out if these nodes are not present - but append is necessary
  665. //
  666. wcscpy(szRootOfEntityName, pszFullyQualifiedEntityName);
  667. pszRootOfFullyQualifiedEntityName = wcschr(szRootOfEntityName, L'/');
  668. pszRootOfFullyQualifiedEntityName[0] = L'\0';
  669. hr = pCurrentKBElemRoot->selectSingleNode(szRootOfEntityName, &pRootOfEntityName);
  670. if (FAILED(hr) || pRootOfEntityName == NULL) {
  671. SsrpLogParseError(hr);
  672. goto ExitHandler;
  673. }
  674. hr = pMergedKBElementRoot->appendChild(pRootOfEntityName,
  675. NULL);
  676. if (FAILED(hr)) {
  677. SsrpLogParseError(hr);
  678. }
  679. goto ExitHandler;
  680. }
  681. hr = pNameListMerged->nextNode(&pNameMerged);
  682. if (FAILED(hr) || pNameMerged == NULL) {
  683. SsrpLogParseError(hr);
  684. goto ExitHandler;
  685. }
  686. while (pNameMerged) {
  687. CComBSTR bstrMergedText;
  688. CComPtr <IXMLDOMNode> pCurrentNameParent;
  689. CComPtr <IXMLDOMNode> pMergedNameParent;
  690. CComPtr <IXMLDOMNode> pMergedNameGrandParent;
  691. hr = pNameMerged->get_text(&bstrMergedText);
  692. if (FAILED(hr) || !bstrMergedText ) {
  693. SsrpLogParseError(hr);
  694. goto ExitHandler;
  695. }
  696. hr = pNameCurrent->get_parentNode(&pCurrentNameParent);
  697. if (FAILED(hr) || pCurrentNameParent == NULL ) {
  698. SsrpLogParseError(hr);
  699. goto ExitHandler;
  700. }
  701. hr = pNameMerged->get_parentNode(&pMergedNameParent);
  702. if (FAILED(hr) || pMergedNameParent == NULL ) {
  703. SsrpLogParseError(hr);
  704. goto ExitHandler;
  705. }
  706. hr = pMergedNameParent->get_parentNode(&pMergedNameGrandParent);
  707. if (FAILED(hr) || pMergedNameGrandParent == NULL ) {
  708. SsrpLogParseError(hr);
  709. goto ExitHandler;
  710. }
  711. hr = pCurrentNameParent->get_attributes(&pAttribNodeMap);
  712. if (FAILED(hr) || pAttribNodeMap == NULL ) {
  713. SsrpLogParseError(hr);
  714. goto ExitHandler;
  715. }
  716. hr = pCurrentKBDoc->createAttribute( bstrSourceKB, &pAttrib );
  717. if (FAILED(hr) || pAttrib == NULL ) {
  718. SsrpLogParseError(hr);
  719. goto ExitHandler;
  720. }
  721. hr = pAttrib->put_text(bstrSourceKBName);
  722. if (FAILED(hr)) {
  723. SsrpLogParseError(hr);
  724. goto ExitHandler;
  725. }
  726. hr = pAttribNodeMap->setNamedItem(pAttrib, NULL);
  727. if (FAILED(hr)) {
  728. SsrpLogParseError(hr);
  729. goto ExitHandler;
  730. }
  731. if (0 == SsrpICompareBstrPwstr(bstrCurrentText, bstrMergedText)) {
  732. //
  733. // collision - need to delete pNameMerged's parent and
  734. // replace pMergedNameParent with pCurrentNameParent
  735. //
  736. hr = pMergedNameGrandParent->replaceChild(pCurrentNameParent,
  737. pMergedNameParent,
  738. NULL);
  739. if (FAILED(hr)) {
  740. SsrpLogParseError(hr);
  741. goto ExitHandler;
  742. }
  743. }
  744. else {
  745. //
  746. // no collision - need to append pNameCurrent's parent to
  747. // pNameMerged's grandparent's section
  748. //
  749. hr = pMergedNameGrandParent->appendChild(pCurrentNameParent,
  750. NULL);
  751. if (FAILED(hr)) {
  752. SsrpLogParseError(hr);
  753. goto ExitHandler;
  754. }
  755. }
  756. hr = pNameListMerged->nextNode(&pNameMerged);
  757. if (FAILED(hr)) {
  758. SsrpLogParseError(hr);
  759. goto ExitHandler;
  760. }
  761. }
  762. hr = pNameListCurrent->nextNode(&pNameCurrent);
  763. if (FAILED(hr)) {
  764. SsrpLogParseError(hr);
  765. goto ExitHandler;
  766. }
  767. }
  768. ExitHandler:
  769. return hr;
  770. }
  771. HRESULT
  772. process::SsrpOverwriteServiceLocalizationFromSystem(
  773. IN IXMLDOMElement *pMergedKBElementRoot,
  774. IN IXMLDOMDocument *pMergedKBXMLDoc
  775. )
  776. /*++
  777. Routine Description:
  778. Routine called to overwrite service info in localization section
  779. Arguments:
  780. pMergedKBElementRoot - pointer to root of merged DOM
  781. pMergedKBXMLDoc - pointer to merged Document
  782. Return:
  783. HRESULT error code
  784. ++*/
  785. {
  786. CComPtr <IXMLDOMNode> pServiceName;
  787. CComPtr <IXMLDOMNodeList> pServiceNameList;
  788. HRESULT hr = S_OK;
  789. hr = pMergedKBElementRoot->selectNodes(L"ServiceLocalization/Service/Name", &pServiceNameList);
  790. if (FAILED(hr) || pServiceNameList == NULL ) {
  791. SsrpLogParseError(hr);
  792. goto ExitHandler;
  793. }
  794. hr = pServiceNameList->nextNode(&pServiceName);
  795. if (FAILED(hr) || pServiceName == NULL) {
  796. SsrpLogParseError(hr);
  797. goto ExitHandler;
  798. }
  799. while (pServiceName) {
  800. CComBSTR bstrServiceText;
  801. PWSTR pszDescription = NULL;
  802. PWSTR pszDisplay = NULL;
  803. LPSERVICE_DESCRIPTION pServiceDescription = NULL;
  804. hr = pServiceName->get_text(&bstrServiceText);
  805. if (FAILED(hr) || !bstrServiceText) {
  806. SsrpLogError(L"Failed to ");
  807. goto ExitHandler;
  808. }
  809. pszDisplay = SsrpQueryServiceDisplayName(bstrServiceText);
  810. SsrpConvertBstrToPwstr(bstrServiceText);
  811. if ( SsrpQueryServiceDescription(bstrServiceText, &pServiceDescription) &&
  812. pServiceDescription != NULL){
  813. pszDescription = pServiceDescription->lpDescription;
  814. }
  815. if ( pszDisplay != NULL && pszDescription != NULL) {
  816. CComPtr <IXMLDOMNode> pServiceNameParent;
  817. CComPtr <IXMLDOMNode> pDescription;
  818. CComPtr <IXMLDOMNode> pDisplayName;
  819. pServiceName->get_parentNode(&pServiceNameParent);
  820. if (FAILED(hr) || pServiceNameParent == NULL) {
  821. SsrpLogParseError(hr);
  822. goto ExitHandler;
  823. }
  824. hr = pServiceNameParent->selectSingleNode(L"Description", &pDescription);
  825. if (FAILED(hr) || pDescription == NULL) {
  826. SsrpLogParseError(hr);
  827. goto ExitHandler;
  828. }
  829. hr = pDescription->put_text(pszDescription);
  830. if (FAILED(hr)) {
  831. SsrpLogParseError(hr);
  832. goto ExitHandler;
  833. }
  834. hr = pServiceNameParent->selectSingleNode(L"DisplayName", &pDisplayName);
  835. if (FAILED(hr) || pDisplayName == NULL) {
  836. SsrpLogParseError(hr);
  837. goto ExitHandler;
  838. }
  839. hr = pDisplayName->put_text(pszDisplay);
  840. if (FAILED(hr)) {
  841. SsrpLogParseError(hr);
  842. goto ExitHandler;
  843. }
  844. }
  845. if (pServiceDescription) {
  846. LocalFree(pServiceDescription);
  847. pServiceDescription = NULL;
  848. }
  849. hr = pServiceNameList->nextNode(&pServiceName);
  850. if (FAILED(hr)) {
  851. SsrpLogError(L"Failed to ");
  852. goto ExitHandler;
  853. }
  854. }
  855. ExitHandler:
  856. return hr;
  857. }