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.

473 lines
14 KiB

  1. #include <windows.h>
  2. #include <fusenetincludes.h>
  3. #include <msxml2.h>
  4. #include <stdio.h>
  5. #include <md5.h>
  6. #include "list.h"
  7. #include "xmlutil.h"
  8. class __declspec(uuid("f6d90f11-9c73-11d3-b32e-00c04f990bb4")) private_MSXML_DOMDocument30;
  9. #define HASHLENGTH 32
  10. #define HASHSTRINGLENGTH HASHLENGTH+1
  11. #define SAFERELEASE(p) if ((p) != NULL) { (p)->Release(); (p) = NULL; };
  12. /////////////////////////////////////////////////////////////////////////
  13. // FormatXML
  14. // Called recursively.
  15. // BUGBUG - t-peterf to document why selectNodes should not be used when
  16. // adding nodes to an existing document.
  17. /////////////////////////////////////////////////////////////////////////
  18. HRESULT FormatXML(IXMLDOMDocument2 *pXMLDoc, IXMLDOMNode *pRootNode, LONG dwLevel)
  19. {
  20. HRESULT hr = S_OK;
  21. IXMLDOMNode *pNode=NULL, *pNewNode=NULL;
  22. IXMLDOMNode *pTextNode1=NULL, *pTextNode2=NULL;
  23. CString sWhiteSpace1, sWhiteSpace2;
  24. BOOL bHasChildren = FALSE;
  25. int i = 0;
  26. sWhiteSpace1.Assign(L"\n");
  27. for (i = 0; i < (dwLevel-1); i++)
  28. sWhiteSpace1.Append(L"\t");
  29. sWhiteSpace2.Assign(L"\n");
  30. for (i = 0; i < dwLevel; i++)
  31. sWhiteSpace2.Append(L"\t");
  32. hr = pRootNode->get_firstChild(&pNode);
  33. while(pNode != NULL)
  34. {
  35. bHasChildren = TRUE;
  36. // create whitespace with one extra tab.
  37. if(FAILED(CreateXMLTextNode(pXMLDoc, sWhiteSpace2._pwz, &pTextNode2)))
  38. goto exit;
  39. VARIANT varRefNode;
  40. VariantInit(&varRefNode);
  41. varRefNode.vt = VT_UNKNOWN;
  42. V_UNKNOWN(&varRefNode) = pNode;
  43. if (FAILED(hr = pRootNode->insertBefore(pTextNode2, varRefNode, &pNewNode)))
  44. goto exit;
  45. SAFERELEASE(pNewNode);
  46. SAFERELEASE(pTextNode2);
  47. // Recursively call format on the node.
  48. if (FAILED(FormatXML(pXMLDoc, pNode, dwLevel+1)))
  49. goto exit;
  50. pNode->get_nextSibling(&pNewNode);
  51. SAFERELEASE(pNode);
  52. pNode = pNewNode;
  53. }
  54. if (bHasChildren)
  55. {
  56. if(FAILED(CreateXMLTextNode(pXMLDoc, sWhiteSpace1._pwz, &pTextNode1)))
  57. goto exit;
  58. if (FAILED(hr = pRootNode->appendChild(pTextNode1, &pNewNode)))
  59. goto exit;
  60. }
  61. exit:
  62. return hr;
  63. }
  64. /////////////////////////////////////////////////////////////////////////
  65. // GetAssemblyNode
  66. /////////////////////////////////////////////////////////////////////////
  67. HRESULT GetAssemblyNode(IXMLDOMDocument2 *pXMLDoc, IXMLDOMNode **ppAssemblyNode)
  68. {
  69. HRESULT hr = S_OK;
  70. BSTR bstrtQueryString;
  71. IXMLDOMNode *pAssemblyNode=NULL;
  72. IXMLDOMNodeList *pNodeList = NULL;
  73. LONG nNodes;
  74. bstrtQueryString = ::SysAllocString(L"assembly");
  75. if (!bstrtQueryString)
  76. {
  77. hr = E_OUTOFMEMORY;
  78. goto exit;
  79. }
  80. if ((hr = pXMLDoc->selectNodes(bstrtQueryString, &pNodeList)) != S_OK)
  81. goto exit;
  82. hr = pNodeList->get_length(&nNodes);
  83. if (nNodes > 1)
  84. {
  85. hr = HRESULT_FROM_WIN32(ERROR_BAD_FORMAT);
  86. goto exit;
  87. }
  88. if ((hr = pNodeList->get_item(0, &pAssemblyNode)) != S_OK)
  89. {
  90. hr = E_FAIL;
  91. goto exit;
  92. }
  93. *ppAssemblyNode=pAssemblyNode;
  94. (*ppAssemblyNode)->AddRef();
  95. exit:
  96. if(bstrtQueryString)
  97. ::SysFreeString(bstrtQueryString);
  98. return hr;
  99. }
  100. /////////////////////////////////////////////////////////////////////////
  101. // SetXMLElementAttribute
  102. /////////////////////////////////////////////////////////////////////////
  103. HRESULT CreatePatchManifest(List <LPWSTR> *pPatchedFiles, LPWSTR pwzPatchDir,
  104. LPWSTR pwzSourceManifestPath, LPWSTR pwzDestManifestPath)
  105. {
  106. HRESULT hr=S_OK;
  107. IXMLDOMDocument2 *pXMLDoc = NULL;
  108. IXMLDOMElement *pElement=NULL;
  109. IXMLDOMNode *pNewNode=NULL, *pRoot=NULL, *pPatchNode = NULL, *pSourceAssemblyNode= NULL;
  110. IAssemblyManifestImport *pSourceManImport = NULL;
  111. IAssemblyIdentity *pSourceAssemblyId = NULL;
  112. LISTNODE pos = NULL;
  113. CString sPatchFileName, sDestAppBase;
  114. LPWSTR pwzBuf=NULL;
  115. BSTR bstrText;
  116. sDestAppBase.Assign(pwzDestManifestPath);
  117. sDestAppBase.RemoveLastElement();
  118. sDestAppBase.Append(L"\\");
  119. //Load the manifest
  120. if(FAILED(hr = LoadXMLDocument(pwzDestManifestPath, &pXMLDoc)))
  121. goto exit;
  122. //Get the assemblyIdentity of the source assembly
  123. if((hr = CreateAssemblyManifestImport(&pSourceManImport, pwzSourceManifestPath, NULL, 0)) != S_OK)
  124. goto exit;
  125. if((hr = pSourceManImport->GetAssemblyIdentity(&pSourceAssemblyId)) != S_OK)
  126. goto exit;
  127. SAFERELEASE(pSourceManImport);
  128. //grab the first child(the only child) as the root node
  129. if(FAILED(GetAssemblyNode(pXMLDoc, &pRoot)))
  130. goto exit;
  131. //create the Patch node
  132. if(FAILED(hr = CreateXMLElement(pXMLDoc, L"Patch", &pElement)))
  133. goto exit;
  134. //append to the assembly (root) node
  135. if (FAILED(hr = pRoot->appendChild((IXMLDOMNode *)pElement, &pPatchNode)))
  136. goto exit;
  137. SAFERELEASE(pElement);
  138. //create the tempate assemblyIdentity node with blank attributes
  139. if(FAILED(hr = CreateXMLElement(pXMLDoc, L"SourceAssembly", &pElement)))
  140. goto exit;
  141. //append to the patch node
  142. if (FAILED(hr = pPatchNode->appendChild((IXMLDOMNode *)pElement, &pSourceAssemblyNode)))
  143. goto exit;
  144. SAFERELEASE(pElement);
  145. //Create the source assemblyId and append the source assembly node
  146. if(FAILED(hr = CreateXMLAssemblyIdElement(pXMLDoc, pSourceAssemblyId, &pElement)))
  147. goto exit;
  148. if (FAILED(hr = pSourceAssemblyNode->appendChild((IXMLDOMNode *)pElement, &pNewNode)))
  149. goto exit;
  150. SAFERELEASE(pElement);
  151. SAFERELEASE(pNewNode);
  152. //Add all the patchInfo node to the source assembly node
  153. pos = pPatchedFiles->GetHeadPosition();
  154. while (pos)
  155. {
  156. pwzBuf= pPatchedFiles->GetNext(pos);
  157. pwzBuf += sDestAppBase._cc -1;
  158. sPatchFileName.Assign(pwzPatchDir + sDestAppBase._cc -1);
  159. sPatchFileName.Append(pwzBuf);
  160. sPatchFileName.Append(L"._p");
  161. if(FAILED(hr = CreateXMLElement(pXMLDoc, L"PatchInfo", &pElement)))
  162. goto exit;
  163. hr = SetXMLElementAttribute(pElement, L"file", pwzBuf);
  164. hr = SetXMLElementAttribute(pElement, L"patchfile", sPatchFileName._pwz);
  165. if (FAILED(hr = pSourceAssemblyNode->appendChild((IXMLDOMNode *)pElement, &pNewNode)))
  166. goto exit;
  167. SAFERELEASE(pElement);
  168. SAFERELEASE(pNewNode);
  169. }
  170. hr = FormatXML(pXMLDoc, pRoot, 1);
  171. hr = SaveXMLDocument(pXMLDoc, pwzDestManifestPath);
  172. exit:
  173. SAFERELEASE(pXMLDoc)
  174. SAFERELEASE(pElement)
  175. SAFERELEASE(pNewNode)
  176. SAFERELEASE(pRoot)
  177. SAFERELEASE(pPatchNode)
  178. SAFERELEASE(pSourceAssemblyNode)
  179. SAFERELEASE(pSourceManImport)
  180. SAFERELEASE(pSourceAssemblyId);
  181. return hr;
  182. }
  183. /////////////////////////////////////////////////////////////////////////
  184. // SaveXMLDocument
  185. /////////////////////////////////////////////////////////////////////////
  186. HRESULT SaveXMLDocument(IXMLDOMDocument2 *pXMLDoc, LPWSTR pwzDocumentName)
  187. {
  188. HRESULT hr = S_OK;
  189. CString sDocumentName;
  190. BSTR bstrFileName = NULL;
  191. VARIANT varFileName;
  192. // Save the manifest to a file
  193. sDocumentName.Assign(pwzDocumentName);
  194. bstrFileName = ::SysAllocString(sDocumentName._pwz);
  195. if (!bstrFileName)
  196. {
  197. hr = E_OUTOFMEMORY;
  198. goto exit;
  199. }
  200. VariantInit(&varFileName);
  201. varFileName.vt = VT_BSTR;
  202. V_BSTR(&varFileName) = bstrFileName;
  203. hr = pXMLDoc->save(varFileName);
  204. exit:
  205. if(bstrFileName)
  206. ::SysFreeString(bstrFileName);
  207. return hr;
  208. }
  209. /////////////////////////////////////////////////////////////////////////
  210. //LoadXMLTemplate
  211. /////////////////////////////////////////////////////////////////////////
  212. HRESULT LoadXMLDocument(LPWSTR pwzTemplatePath, IXMLDOMDocument2 **ppXMLDoc)
  213. {
  214. HRESULT hr = S_OK;
  215. IXMLDOMDocument2 *pXMLDoc=NULL;
  216. VARIANT varFileName;
  217. VARIANT_BOOL varBool;
  218. BSTR bstrFileName;
  219. bstrFileName = ::SysAllocString(pwzTemplatePath);
  220. if (!bstrFileName)
  221. {
  222. hr = E_OUTOFMEMORY;
  223. goto exit;
  224. }
  225. VariantInit(&varFileName);
  226. varFileName.vt = VT_BSTR;
  227. V_BSTR(&varFileName) = bstrFileName;
  228. if(FAILED(hr = CoCreateInstance(__uuidof(private_MSXML_DOMDocument30),
  229. NULL, CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument2, (void**)&pXMLDoc)))
  230. goto exit;
  231. // Load synchronously
  232. if (FAILED(hr = pXMLDoc->put_async(VARIANT_FALSE)))
  233. goto exit;
  234. if ((hr = pXMLDoc->load(varFileName, &varBool)) != S_OK)
  235. goto exit;
  236. *ppXMLDoc=pXMLDoc;
  237. (*ppXMLDoc)->AddRef();
  238. exit:
  239. if(bstrFileName)
  240. ::SysFreeString(bstrFileName);
  241. SAFERELEASE(pXMLDoc);
  242. return hr;
  243. }
  244. /////////////////////////////////////////////////////////////////////////
  245. // CreateXMLElement
  246. /////////////////////////////////////////////////////////////////////////
  247. HRESULT CreateXMLTextNode(IXMLDOMDocument2 *pXMLDoc, LPWSTR pwzText, IXMLDOMNode **ppNode)
  248. {
  249. HRESULT hr = S_OK;
  250. IXMLDOMNode *pNode = NULL;
  251. BSTR bstrText = NULL;
  252. bstrText = ::SysAllocString(pwzText);
  253. if (!bstrText)
  254. {
  255. hr = E_OUTOFMEMORY;
  256. goto exit;
  257. }
  258. if(FAILED(pXMLDoc->createTextNode(bstrText, (IXMLDOMText**)&pNode)))
  259. goto exit;
  260. *ppNode = pNode;
  261. (*ppNode)->AddRef();
  262. exit:
  263. if (bstrText)
  264. ::SysFreeString(bstrText);
  265. SAFERELEASE (pNode);
  266. return hr;
  267. }
  268. /////////////////////////////////////////////////////////////////////////
  269. // CreateXMLElement
  270. /////////////////////////////////////////////////////////////////////////
  271. HRESULT CreateXMLElement(IXMLDOMDocument2 *pXMLDoc, LPWSTR pwzElementName,
  272. IXMLDOMElement **ppElement)
  273. {
  274. HRESULT hr=S_OK;
  275. BSTR bstrElementName = NULL;
  276. IXMLDOMElement *pElement = NULL;
  277. IXMLDOMNode *pNode =NULL, *pNewNode = NULL;
  278. bstrElementName = ::SysAllocString(pwzElementName);
  279. if (!bstrElementName)
  280. {
  281. hr = E_OUTOFMEMORY;
  282. goto exit;
  283. }
  284. // NOTENOTE - createElement doesn't append the node to the doc
  285. // so we're just using pXMLDoc for convenience of calling create.
  286. if(FAILED(hr = pXMLDoc->createElement(bstrElementName, &pElement)))
  287. goto exit;
  288. *ppElement = pElement;
  289. (*ppElement)->AddRef();
  290. exit:
  291. if (bstrElementName)
  292. ::SysFreeString(bstrElementName);
  293. SAFERELEASE(pNode);
  294. SAFERELEASE(pNewNode);
  295. SAFERELEASE(pElement);
  296. return hr;
  297. }
  298. /////////////////////////////////////////////////////////////////////////
  299. // SetXMLElementAttribute
  300. /////////////////////////////////////////////////////////////////////////
  301. HRESULT SetXMLElementAttribute(IXMLDOMElement *pElement, LPWSTR pwzAttributeName,
  302. LPWSTR pwzAttributeValue)
  303. {
  304. HRESULT hr=S_OK;
  305. BSTR bstrAttributeName = NULL, bstrAttributeValue = NULL;
  306. VARIANT varAttributeValue;
  307. bstrAttributeName = ::SysAllocString(pwzAttributeName);
  308. bstrAttributeValue = ::SysAllocString(pwzAttributeValue);
  309. if (!bstrAttributeName || (!bstrAttributeValue && pwzAttributeValue))
  310. {
  311. hr = E_OUTOFMEMORY;
  312. goto exit;
  313. }
  314. VariantInit(&varAttributeValue);
  315. varAttributeValue.vt = VT_BSTR;
  316. V_BSTR(&varAttributeValue) = bstrAttributeValue;
  317. hr = pElement->setAttribute(bstrAttributeName, varAttributeValue);
  318. exit:
  319. if (bstrAttributeName)
  320. ::SysFreeString(bstrAttributeName);
  321. if (bstrAttributeValue)
  322. ::SysFreeString(bstrAttributeValue);
  323. return hr;
  324. }
  325. /////////////////////////////////////////////////////////////////////////
  326. // CreateXMLAssemblyIdElement
  327. /////////////////////////////////////////////////////////////////////////
  328. HRESULT CreateXMLAssemblyIdElement(IXMLDOMDocument2 *pXMLDoc, IAssemblyIdentity *pAssemblyId,
  329. IXMLDOMElement **ppElement)
  330. {
  331. HRESULT hr = S_OK;
  332. IXMLDOMElement *pASMIdElement = NULL;
  333. LPWSTR pwzBuf = NULL;
  334. DWORD ccBuf = 0;
  335. CString sBuffer;
  336. LPWSTR rpwzAttrNames[6] =
  337. {
  338. SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_TYPE,
  339. SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_NAME,
  340. SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_VERSION,
  341. SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_PUBLIC_KEY_TOKEN,
  342. SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_PROCESSOR_ARCHITECTURE,
  343. SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_LANGUAGE,
  344. };
  345. //Create assemblyIdentity Element
  346. if(FAILED(hr=CreateXMLElement(pXMLDoc, L"assemblyIdentity", &pASMIdElement)))
  347. goto exit;
  348. for (int i = 0; i < 6; i++)
  349. {
  350. // BUGBUG - eventually, when we add support for type the only guy which
  351. // is optional is the public key token.
  352. if (FAILED(hr = pAssemblyId->GetAttribute(rpwzAttrNames[i], &pwzBuf, &ccBuf))
  353. && hr != HRESULT_FROM_WIN32(ERROR_NOT_FOUND))
  354. goto exit;
  355. else if (hr == S_OK)
  356. {
  357. sBuffer.TakeOwnership(pwzBuf, ccBuf);
  358. hr = SetXMLElementAttribute(pASMIdElement, rpwzAttrNames[i], sBuffer._pwz);
  359. }
  360. else
  361. hr = S_OK;
  362. }
  363. *ppElement = pASMIdElement;
  364. (*ppElement)->AddRef();
  365. exit:
  366. SAFERELEASE(pASMIdElement);
  367. return hr;
  368. }