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.

1176 lines
36 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 "manifestnode.h"
  8. #include "xmlutil.h"
  9. #include "version.h"
  10. #define ASSEMBLY L"assembly"
  11. #define NAMESPACE_TITLE L"xmlns:asm_namespace_v1"
  12. #define NAMESPACE_VALUE L"urn:schemas-microsoft-com:asm.v1"
  13. #define MANIFEST_VERSION_TITLE L"manifestVersion"
  14. #define MANIFEST_VERSION_VALUE L"1.0"
  15. #define DESCRIPTION L"description"
  16. #define ASSEMBLY_IDENTITY L"assemblyIdentity"
  17. #define DEPENDENCY L"dependency"
  18. #define DEPENDENCY_QUERY L"/assembly/dependency"
  19. #define DEPENDANT_ASSEMBLY L"dependentAssembly"
  20. #define INSTALL L"install"
  21. #define CODEBASE L"codebase"
  22. #define APPLICATION L"application"
  23. #define SHELL_STATE L"shellState"
  24. #define ACTIVATION L"activation"
  25. #define FILE L"file"
  26. #define FILE_NAME L"name"
  27. #define FILE_HASH L"hash"
  28. class __declspec(uuid("f6d90f11-9c73-11d3-b32e-00c04f990bb4")) private_MSXML_DOMDocument30;
  29. #define HASHLENGTH 32
  30. #define HASHSTRINGLENGTH HASHLENGTH+1
  31. /////////////////////////////////////////////////////////////////////////
  32. // FowardSlash
  33. /////////////////////////////////////////////////////////////////////////
  34. VOID FowardSlash(LPWSTR pwz)
  35. {
  36. LPWSTR ptr = pwz;
  37. while (*ptr)
  38. {
  39. if (*ptr == L'\\')
  40. *ptr = L'/';
  41. ptr++;
  42. }
  43. }
  44. /////////////////////////////////////////////////////////////////////////
  45. // GetHash
  46. /////////////////////////////////////////////////////////////////////////
  47. HRESULT GetHash(LPCWSTR pwzFilename, LPWSTR *ppwzHash)
  48. {
  49. HRESULT hr = S_OK;
  50. HANDLE hFile = INVALID_HANDLE_VALUE;
  51. DWORD dwLength = 0; // cblength
  52. LPWSTR pwzHash = new WCHAR[HASHSTRINGLENGTH];
  53. // BUGBUG - heap allocate large buffers like this.
  54. unsigned char buffer[16384];
  55. MD5_CTX md5c;
  56. int i;
  57. WCHAR* p;
  58. if(!pwzHash)
  59. {
  60. hr = E_OUTOFMEMORY;
  61. goto exit;
  62. }
  63. MD5Init(&md5c);
  64. hFile = CreateFile(pwzFilename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  65. if(hFile == INVALID_HANDLE_VALUE)
  66. {
  67. hr = HRESULT_FROM_WIN32(GetLastError());
  68. printf("Open file error during hashing\n");
  69. goto exit;
  70. }
  71. ZeroMemory(buffer, sizeof(buffer));
  72. // BUGBUG - error checking here.
  73. while(ReadFile(hFile, buffer, sizeof(buffer), &dwLength, NULL) && dwLength)
  74. MD5Update(&md5c, buffer, (unsigned) dwLength);
  75. CloseHandle(hFile);
  76. MD5Final(&md5c);
  77. // convert hash from byte array to hex
  78. p = pwzHash;
  79. for (int i = 0; i < sizeof(md5c.digest); i++)
  80. {
  81. wsprintf(p, L"%02X", md5c.digest[i]);
  82. p += 2;
  83. }
  84. *ppwzHash = pwzHash;
  85. pwzHash = NULL;
  86. exit:
  87. SAFEDELETEARRAY(pwzHash);
  88. return hr;
  89. }
  90. /////////////////////////////////////////////////////////////////////////
  91. // CreateXMLElement
  92. /////////////////////////////////////////////////////////////////////////
  93. HRESULT CreateXMLTextNode(IXMLDOMDocument2 *pXMLDoc, LPWSTR pwzText, IXMLDOMNode **ppNode)
  94. {
  95. HRESULT hr = S_OK;
  96. IXMLDOMNode *pNode = NULL;
  97. BSTR bstrText = NULL;
  98. bstrText = ::SysAllocString(pwzText);
  99. if (!bstrText)
  100. {
  101. hr = E_OUTOFMEMORY;
  102. goto exit;
  103. }
  104. if(FAILED(pXMLDoc->createTextNode(bstrText, (IXMLDOMText**)&pNode)))
  105. goto exit;
  106. *ppNode = pNode;
  107. (*ppNode)->AddRef();
  108. exit:
  109. if (bstrText)
  110. ::SysFreeString(bstrText);
  111. SAFERELEASE (pNode);
  112. return hr;
  113. }
  114. /////////////////////////////////////////////////////////////////////////
  115. // CreateXMLComment
  116. /////////////////////////////////////////////////////////////////////////
  117. HRESULT CreateXMLComment(IXMLDOMDocument2 *pXMLDoc, LPWSTR pwzComment,
  118. IXMLDOMComment **ppComment)
  119. {
  120. HRESULT hr=S_OK;
  121. BSTR bstrComment = NULL;
  122. IXMLDOMComment *pComment = NULL;
  123. bstrComment = ::SysAllocString(pwzComment);
  124. if (!bstrComment)
  125. {
  126. hr = E_OUTOFMEMORY;
  127. goto exit;
  128. }
  129. if(FAILED(hr = pXMLDoc->createComment(bstrComment, &pComment)))
  130. goto exit;
  131. *ppComment = pComment;
  132. (*ppComment)->AddRef();
  133. exit:
  134. if (bstrComment)
  135. ::SysFreeString(bstrComment);
  136. SAFERELEASE(pComment);
  137. return hr;
  138. }
  139. /////////////////////////////////////////////////////////////////////////
  140. // AddMgVersionAsComment
  141. /////////////////////////////////////////////////////////////////////////
  142. HRESULT AddMgVersionAsComment(IXMLDOMDocument2 *pXMLDoc, IXMLDOMNode **ppRoot)
  143. {
  144. HRESULT hr = S_OK;
  145. CString sComment;
  146. IXMLDOMComment *pComment = NULL;
  147. IXMLDOMNode *pNewNode = NULL;
  148. // ASSERT(pXMLDoc && ppRoot);
  149. sComment.Assign(L"Created using mg version ");
  150. sComment.Append(VER_PRODUCTVERSION_STR_L);
  151. if(FAILED(hr = CreateXMLComment(pXMLDoc, sComment._pwz, &pComment)))
  152. goto exit;
  153. if(*ppRoot)
  154. {
  155. if (FAILED(hr = (*ppRoot)->appendChild((IXMLDOMNode *)pComment, &pNewNode)))
  156. goto exit;
  157. }
  158. else
  159. {
  160. if (FAILED(hr = pXMLDoc->appendChild((IXMLDOMNode *)pComment, ppRoot)))
  161. goto exit;
  162. }
  163. exit:
  164. SAFERELEASE(pNewNode);
  165. SAFERELEASE(pComment);
  166. return hr;
  167. }
  168. /////////////////////////////////////////////////////////////////////////
  169. // CreateXMLElement
  170. /////////////////////////////////////////////////////////////////////////
  171. HRESULT CreateXMLElement(IXMLDOMDocument2 *pXMLDoc, LPWSTR pwzElementName,
  172. IXMLDOMElement **ppElement)
  173. {
  174. HRESULT hr=S_OK;
  175. BSTR bstrElementName = NULL;
  176. IXMLDOMElement *pElement = NULL;
  177. IXMLDOMNode *pNode =NULL, *pNewNode = NULL;
  178. bstrElementName = ::SysAllocString(pwzElementName);
  179. if (!bstrElementName)
  180. {
  181. hr = E_OUTOFMEMORY;
  182. goto exit;
  183. }
  184. // NOTENOTE - createElement doesn't append the node to the doc
  185. // so we're just using pXMLDoc for convenience of calling create.
  186. if(FAILED(hr = pXMLDoc->createElement(bstrElementName, &pElement)))
  187. goto exit;
  188. *ppElement = pElement;
  189. (*ppElement)->AddRef();
  190. exit:
  191. if (bstrElementName)
  192. ::SysFreeString(bstrElementName);
  193. SAFERELEASE(pNode);
  194. SAFERELEASE(pNewNode);
  195. SAFERELEASE(pElement);
  196. return hr;
  197. }
  198. /////////////////////////////////////////////////////////////////////////
  199. // SetXMLElementAttribute
  200. /////////////////////////////////////////////////////////////////////////
  201. HRESULT SetXMLElementAttribute(IXMLDOMElement *pElement, LPWSTR pwzAttributeName,
  202. LPWSTR pwzAttributeValue)
  203. {
  204. HRESULT hr=S_OK;
  205. BSTR bstrAttributeName = NULL, bstrAttributeValue = NULL;
  206. VARIANT varAttributeValue;
  207. bstrAttributeName = ::SysAllocString(pwzAttributeName);
  208. bstrAttributeValue = ::SysAllocString(pwzAttributeValue);
  209. if (!bstrAttributeName || (!bstrAttributeValue && pwzAttributeValue))
  210. {
  211. hr = E_OUTOFMEMORY;
  212. goto exit;
  213. }
  214. VariantInit(&varAttributeValue);
  215. varAttributeValue.vt = VT_BSTR;
  216. V_BSTR(&varAttributeValue) = bstrAttributeValue;
  217. hr = pElement->setAttribute(bstrAttributeName, varAttributeValue);
  218. exit:
  219. if (bstrAttributeName)
  220. ::SysFreeString(bstrAttributeName);
  221. if (bstrAttributeValue)
  222. ::SysFreeString(bstrAttributeValue);
  223. return hr;
  224. }
  225. /////////////////////////////////////////////////////////////////////////
  226. // CreateXMLAssemblyIdElement
  227. /////////////////////////////////////////////////////////////////////////
  228. HRESULT CreateXMLAssemblyIdElement(IXMLDOMDocument2 *pXMLDoc, IAssemblyIdentity *pAssemblyId,
  229. IXMLDOMElement **ppElement)
  230. {
  231. HRESULT hr = S_OK;
  232. IXMLDOMElement *pASMIdElement = NULL;
  233. LPWSTR pwzBuf = NULL;
  234. DWORD ccBuf = 0;
  235. CString sBuffer;
  236. LPWSTR rpwzAttrNames[6] =
  237. {
  238. SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_TYPE,
  239. SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_NAME,
  240. SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_VERSION,
  241. SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_PUBLIC_KEY_TOKEN,
  242. SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_PROCESSOR_ARCHITECTURE,
  243. SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_LANGUAGE,
  244. };
  245. //Create assemblyIdentity Element
  246. if(FAILED(hr=CreateXMLElement(pXMLDoc, ASSEMBLY_IDENTITY, &pASMIdElement)))
  247. goto exit;
  248. for (int i = 0; i < 6; i++)
  249. {
  250. // BUGBUG - eventually, when we add support for type the only guy which
  251. // is optional is the public key token.
  252. if (FAILED(hr = pAssemblyId->GetAttribute(rpwzAttrNames[i], &pwzBuf, &ccBuf))
  253. && hr != HRESULT_FROM_WIN32(ERROR_NOT_FOUND))
  254. goto exit;
  255. else if (hr == S_OK)
  256. {
  257. sBuffer.TakeOwnership(pwzBuf, ccBuf);
  258. hr = SetXMLElementAttribute(pASMIdElement, rpwzAttrNames[i], sBuffer._pwz);
  259. }
  260. else
  261. hr = S_OK;
  262. }
  263. *ppElement = pASMIdElement;
  264. (*ppElement)->AddRef();
  265. exit:
  266. SAFERELEASE(pASMIdElement);
  267. return hr;
  268. }
  269. /////////////////////////////////////////////////////////////////////////
  270. // CreateDependantAssemblyNode
  271. /////////////////////////////////////////////////////////////////////////
  272. HRESULT CreateDependantAssemblyNode(IXMLDOMDocument2 *pXMLDoc, ManifestNode*pManifestNode, IXMLDOMNode **ppDependantAssemblyNode)
  273. {
  274. HRESULT hr = S_OK;
  275. LPWSTR pwzBuf = NULL;
  276. DWORD dwType;
  277. IAssemblyIdentity *pAssemblyId = NULL;
  278. IXMLDOMElement *pDependantAssemblyNode = NULL, *pElement = NULL;
  279. IXMLDOMNode *pNewNode = NULL;
  280. CString sCodeBase;
  281. //Get ASMId for Unique Dependency
  282. if(FAILED(hr = pManifestNode->GetAssemblyIdentity(&pAssemblyId)))
  283. goto exit;
  284. //Get the type of manifest
  285. // - Private or GAC, for GACs you don't put the codebase.
  286. if(FAILED(hr = pManifestNode->GetManifestType(&dwType)))
  287. goto exit;
  288. //Get Codebase of the Unique Dependancy
  289. if(FAILED(hr = pManifestNode->GetManifestFilePath(&pwzBuf)))
  290. goto exit;
  291. sCodeBase.TakeOwnership(pwzBuf);
  292. //Create a dependentAssembly node
  293. if(FAILED(hr = CreateXMLElement(pXMLDoc, DEPENDANT_ASSEMBLY, &pDependantAssemblyNode)))
  294. goto exit;
  295. //Create the AssemblyId for the Dependant Assembly
  296. if (FAILED(CreateXMLAssemblyIdElement(pXMLDoc, pAssemblyId, &pElement)))
  297. goto exit;
  298. if (FAILED(hr=pDependantAssemblyNode->appendChild((IXMLDOMNode *)pElement, &pNewNode)))
  299. goto exit;
  300. // Node is added and element, node can be released.
  301. SAFERELEASE(pElement);
  302. SAFERELEASE(pNewNode);
  303. //read the codebase for this DependantAssembly
  304. // GACs don't have a codebase.
  305. if (1) // we need codebase for all assemblies (dwType == PRIVATE_ASSEMBLY)
  306. {
  307. if(FAILED(hr = CreateXMLElement(pXMLDoc, INSTALL, &pElement)))
  308. goto exit;
  309. FowardSlash(sCodeBase._pwz);
  310. if(FAILED(hr = SetXMLElementAttribute(pElement, CODEBASE, sCodeBase._pwz)))
  311. goto exit;
  312. if (FAILED(hr=pDependantAssemblyNode->appendChild((IXMLDOMNode *)pElement, &pNewNode)))
  313. goto exit;
  314. SAFERELEASE(pElement);
  315. SAFERELEASE(pNewNode);
  316. }
  317. *ppDependantAssemblyNode = pDependantAssemblyNode;
  318. (*ppDependantAssemblyNode)->AddRef();
  319. exit:
  320. SAFERELEASE(pAssemblyId);
  321. SAFERELEASE(pDependantAssemblyNode);
  322. return hr;
  323. }
  324. /////////////////////////////////////////////////////////////////////////
  325. // GetNode
  326. /////////////////////////////////////////////////////////////////////////
  327. HRESULT GetNode(IXMLDOMDocument2 *pXMLDoc, LPCWSTR pwzNode, IXMLDOMNode **ppNode)
  328. {
  329. HRESULT hr = S_OK;
  330. BSTR bstrtQueryString;
  331. IXMLDOMNode *pNode=NULL;
  332. IXMLDOMNodeList *pNodeList = NULL;
  333. LONG nNodes = 0;
  334. bstrtQueryString = ::SysAllocString(pwzNode);
  335. if (!bstrtQueryString)
  336. {
  337. hr = E_OUTOFMEMORY;
  338. goto exit;
  339. }
  340. if ((hr = pXMLDoc->selectNodes(bstrtQueryString, &pNodeList)) != S_OK)
  341. goto exit;
  342. // NOTENOTE - nNodes > 1 should never happen because only one root node in doc.
  343. hr = pNodeList->get_length(&nNodes);
  344. if (nNodes > 1)
  345. {
  346. // multiple file callouts having the exact same file name/path within a single source assembly
  347. hr = HRESULT_FROM_WIN32(ERROR_BAD_FORMAT);
  348. goto exit;
  349. }
  350. else if (nNodes < 1)
  351. {
  352. hr = S_FALSE;
  353. goto exit;
  354. }
  355. if ((hr = pNodeList->get_item(0, &pNode)) != S_OK)
  356. {
  357. hr = S_FALSE ? E_FAIL : hr;
  358. goto exit;
  359. }
  360. *ppNode=pNode;
  361. (*ppNode)->AddRef();
  362. exit:
  363. if(bstrtQueryString)
  364. ::SysFreeString(bstrtQueryString);
  365. SAFERELEASE(pNodeList);
  366. SAFERELEASE(pNode);
  367. return hr;
  368. }
  369. /////////////////////////////////////////////////////////////////////////
  370. // FormatXML
  371. // Called recursively.
  372. // BUGBUG - t-peterf to document why selectNodes should not be used when
  373. // adding nodes to an existing document.
  374. /////////////////////////////////////////////////////////////////////////
  375. HRESULT FormatXML(IXMLDOMDocument2 *pXMLDoc, IXMLDOMNode *pRootNode, LONG dwLevel)
  376. {
  377. HRESULT hr = S_OK;
  378. IXMLDOMNode *pNode=NULL, *pNewNode=NULL;
  379. IXMLDOMNode *pTextNode1=NULL, *pTextNode2=NULL;
  380. CString sWhiteSpace1, sWhiteSpace2;
  381. BOOL bHasChildren = FALSE;
  382. int i = 0;
  383. sWhiteSpace1.Assign(L"\n");
  384. for (i = 0; i < (dwLevel-1); i++)
  385. sWhiteSpace1.Append(L"\t");
  386. sWhiteSpace2.Assign(L"\n");
  387. for (i = 0; i < dwLevel; i++)
  388. sWhiteSpace2.Append(L"\t");
  389. hr = pRootNode->get_firstChild(&pNode);
  390. while(pNode != NULL)
  391. {
  392. bHasChildren = TRUE;
  393. // create whitespace with one extra tab.
  394. if(FAILED(CreateXMLTextNode(pXMLDoc, sWhiteSpace2._pwz, &pTextNode2)))
  395. goto exit;
  396. VARIANT varRefNode;
  397. VariantInit(&varRefNode);
  398. varRefNode.vt = VT_UNKNOWN;
  399. V_UNKNOWN(&varRefNode) = pNode;
  400. if (FAILED(hr = pRootNode->insertBefore(pTextNode2, varRefNode, &pNewNode)))
  401. goto exit;
  402. SAFERELEASE(pNewNode);
  403. SAFERELEASE(pTextNode2);
  404. // Recursively call format on the node.
  405. if (FAILED(FormatXML(pXMLDoc, pNode, dwLevel+1)))
  406. goto exit;
  407. pNode->get_nextSibling(&pNewNode);
  408. SAFERELEASE(pNode);
  409. pNode = pNewNode;
  410. }
  411. if (bHasChildren)
  412. {
  413. if(FAILED(CreateXMLTextNode(pXMLDoc, sWhiteSpace1._pwz, &pTextNode1)))
  414. goto exit;
  415. if (FAILED(hr = pRootNode->appendChild(pTextNode1, &pNewNode)))
  416. goto exit;
  417. }
  418. exit:
  419. return hr;
  420. }
  421. /////////////////////////////////////////////////////////////////////////
  422. // CreateManifestFromAssembly
  423. /////////////////////////////////////////////////////////////////////////
  424. HRESULT CreateAppManifestTemplate(LPWSTR pwzTempFile)
  425. {
  426. HRESULT hr=S_OK;
  427. IXMLDOMDocument2 *pXMLDoc = NULL;
  428. IXMLDOMElement *pElement=NULL, *pChildElement=NULL, *pChildElement2=NULL, *pChildElement3=NULL;
  429. IXMLDOMNode *pNewNode=NULL, *pRoot=NULL, *pTextNode = NULL;
  430. if(FAILED(hr = CoCreateInstance(__uuidof(private_MSXML_DOMDocument30),
  431. NULL, CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument2, (void**)&pXMLDoc)))
  432. goto exit;
  433. /*
  434. if(FAILED(hr = AddMgVersionAsComment(pXMLDoc, &pRoot)))
  435. goto exit;
  436. */
  437. //create the root assembly node and add the default properties
  438. if(FAILED(hr = CreateXMLElement(pXMLDoc, ASSEMBLY, &pElement)))
  439. goto exit;
  440. if(FAILED(hr = SetXMLElementAttribute(pElement, NAMESPACE_TITLE, NAMESPACE_VALUE)))
  441. goto exit;
  442. if(FAILED(hr = SetXMLElementAttribute(pElement, MANIFEST_VERSION_TITLE, MANIFEST_VERSION_VALUE)))
  443. goto exit;
  444. //append the root to the DOMDocument
  445. if (FAILED(hr = pXMLDoc->appendChild((IXMLDOMNode *)pElement, &pRoot)))
  446. goto exit;
  447. SAFERELEASE(pElement);
  448. //create the tempate assemblyIdentity node with blank attributes
  449. if(FAILED(hr = CreateXMLElement(pXMLDoc, ASSEMBLY_IDENTITY, &pElement)))
  450. goto exit;
  451. hr = SetXMLElementAttribute(pElement, L"type", L"application");
  452. hr = SetXMLElementAttribute(pElement, L"name", L"");
  453. hr = SetXMLElementAttribute(pElement, L"version", L"");
  454. hr = SetXMLElementAttribute(pElement, L"processorArchitecture", L"");
  455. hr = SetXMLElementAttribute(pElement, L"publicKeyToken", L"");
  456. hr = SetXMLElementAttribute(pElement, L"language", L"");
  457. //append this to the root node
  458. if (FAILED(hr=pRoot->appendChild((IXMLDOMNode *)pElement, &pNewNode)))
  459. goto exit;
  460. SAFERELEASE(pElement);
  461. SAFERELEASE(pNewNode);
  462. //create a sample description
  463. if(FAILED(hr = CreateXMLElement(pXMLDoc, DESCRIPTION, &pElement)))
  464. goto exit;
  465. if(FAILED(hr = CreateXMLTextNode(pXMLDoc, L"Put a description of your application here", &pTextNode)))
  466. goto exit;
  467. if (FAILED(hr=pElement->appendChild(pTextNode, &pNewNode)))
  468. goto exit;
  469. SAFERELEASE(pNewNode);
  470. SAFERELEASE(pTextNode);
  471. if (FAILED(hr=pRoot->appendChild((IXMLDOMNode *)pElement, &pNewNode)))
  472. goto exit;
  473. SAFERELEASE(pNewNode);
  474. SAFERELEASE(pElement);
  475. //Create the shellState tag and enter in default information
  476. if(FAILED(hr = CreateXMLElement(pXMLDoc, APPLICATION, &pElement)))
  477. goto exit;
  478. if(FAILED(hr = CreateXMLElement(pXMLDoc, SHELL_STATE, &pChildElement)))
  479. goto exit;
  480. if(FAILED(hr = SetXMLElementAttribute(pChildElement, L"friendlyName", L"")))
  481. goto exit;
  482. if(FAILED(hr = SetXMLElementAttribute(pChildElement, L"entryPoint", L"")))
  483. goto exit;
  484. if(FAILED(hr = SetXMLElementAttribute(pChildElement, L"entryImageType", L"")))
  485. goto exit;
  486. if(FAILED(hr = SetXMLElementAttribute(pChildElement, L"showCommand", L"")))
  487. goto exit;
  488. if(FAILED(hr = SetXMLElementAttribute(pChildElement, L"hotKey", L"")))
  489. goto exit;
  490. if (FAILED(hr=pElement->appendChild((IXMLDOMNode *)pChildElement, &pNewNode)))
  491. goto exit;
  492. SAFERELEASE (pNewNode);
  493. SAFERELEASE(pChildElement);
  494. if(FAILED(hr = CreateXMLElement(pXMLDoc, ACTIVATION, &pChildElement)))
  495. goto exit;
  496. if(FAILED(hr = SetXMLElementAttribute(pChildElement, L"assemblyName", L"")))
  497. goto exit;
  498. if(FAILED(hr = SetXMLElementAttribute(pChildElement, L"assemblyClass", L"")))
  499. goto exit;
  500. if(FAILED(hr = SetXMLElementAttribute(pChildElement, L"assemblyMethod", L"")))
  501. goto exit;
  502. if(FAILED(hr = SetXMLElementAttribute(pChildElement, L"assemblyMethodArgs", L"")))
  503. goto exit;
  504. if (FAILED(hr=pElement->appendChild((IXMLDOMNode *)pChildElement, &pNewNode)))
  505. goto exit;
  506. SAFERELEASE (pNewNode);
  507. SAFERELEASE(pChildElement);
  508. if (FAILED(hr=pRoot->appendChild((IXMLDOMNode *)pElement, &pNewNode)))
  509. goto exit;
  510. SAFERELEASE(pElement);
  511. SAFERELEASE (pNewNode);
  512. //Create the dependency platform tag and enter in default information
  513. if(FAILED(hr = CreateXMLElement(pXMLDoc, L"dependency", &pElement)))
  514. goto exit;
  515. if(FAILED(hr = CreateXMLElement(pXMLDoc, L"platform", &pChildElement)))
  516. goto exit;
  517. if(FAILED(hr = CreateXMLElement(pXMLDoc, L"osVersionInfo", &pChildElement2)))
  518. goto exit;
  519. if(FAILED(hr = CreateXMLElement(pXMLDoc, L"os", &pChildElement3)))
  520. goto exit;
  521. if(FAILED(hr = SetXMLElementAttribute(pChildElement3, L"majorVersion", L"5")))
  522. goto exit;
  523. if(FAILED(hr = SetXMLElementAttribute(pChildElement3, L"minorVersion", L"1")))
  524. goto exit;
  525. if(FAILED(hr = SetXMLElementAttribute(pChildElement3, L"buildNumber", L"2600")))
  526. goto exit;
  527. if(FAILED(hr = SetXMLElementAttribute(pChildElement3, L"servicePackMajor", L"0")))
  528. goto exit;
  529. if(FAILED(hr = SetXMLElementAttribute(pChildElement3, L"servicePackMinor", L"0")))
  530. goto exit;
  531. if (FAILED(hr=pChildElement2->appendChild((IXMLDOMNode *)pChildElement3, NULL)))
  532. goto exit;
  533. SAFERELEASE (pChildElement3);
  534. if (FAILED(hr=pChildElement->appendChild((IXMLDOMNode *)pChildElement2, NULL)))
  535. goto exit;
  536. SAFERELEASE (pChildElement2);
  537. if(FAILED(hr = CreateXMLElement(pXMLDoc, L"platformInfo", &pChildElement2)))
  538. goto exit;
  539. if(FAILED(hr = SetXMLElementAttribute(pChildElement2, L"friendlyName", L"Microsoft Windows XP")))
  540. goto exit;
  541. if(FAILED(hr = SetXMLElementAttribute(pChildElement2, L"href", L"http://www.microsoft.com/windows")))
  542. goto exit;
  543. if (FAILED(hr=pChildElement->appendChild((IXMLDOMNode *)pChildElement2, NULL)))
  544. goto exit;
  545. SAFERELEASE (pChildElement2);
  546. if (FAILED(hr=pElement->appendChild((IXMLDOMNode *)pChildElement, NULL)))
  547. goto exit;
  548. SAFERELEASE(pChildElement);
  549. if(FAILED(hr = CreateXMLElement(pXMLDoc, L"platform", &pChildElement)))
  550. goto exit;
  551. if(FAILED(hr = CreateXMLElement(pXMLDoc, L"dotNetVersionInfo", &pChildElement2)))
  552. goto exit;
  553. if(FAILED(hr = CreateXMLElement(pXMLDoc, L"supportedRuntime", &pChildElement3)))
  554. goto exit;
  555. if(FAILED(hr = SetXMLElementAttribute(pChildElement3, L"version", L"v1.0.3705")))
  556. goto exit;
  557. if (FAILED(hr=pChildElement2->appendChild((IXMLDOMNode *)pChildElement3, NULL)))
  558. goto exit;
  559. SAFERELEASE (pChildElement3);
  560. if (FAILED(hr=pChildElement->appendChild((IXMLDOMNode *)pChildElement2, NULL)))
  561. goto exit;
  562. SAFERELEASE (pChildElement2);
  563. if(FAILED(hr = CreateXMLElement(pXMLDoc, L"platformInfo", &pChildElement2)))
  564. goto exit;
  565. if(FAILED(hr = SetXMLElementAttribute(pChildElement2, L"friendlyName", L"Microsoft .Net Frameworks")))
  566. goto exit;
  567. if(FAILED(hr = SetXMLElementAttribute(pChildElement2, L"href", L"http://www.microsoft.com/net")))
  568. goto exit;
  569. if (FAILED(hr=pChildElement->appendChild((IXMLDOMNode *)pChildElement2, NULL)))
  570. goto exit;
  571. SAFERELEASE (pChildElement2);
  572. if (FAILED(hr=pElement->appendChild((IXMLDOMNode *)pChildElement, NULL)))
  573. goto exit;
  574. SAFERELEASE(pChildElement);
  575. if (FAILED(hr=pRoot->appendChild((IXMLDOMNode *)pElement, NULL)))
  576. goto exit;
  577. SAFERELEASE(pElement);
  578. //Format and save the document
  579. if(FAILED(hr = FormatXML(pXMLDoc, pRoot, 1)))
  580. goto exit;
  581. if(FAILED(hr = SaveXMLDocument(pXMLDoc, pwzTempFile)))
  582. goto exit;
  583. printf("\nTemplate file created succesfully\n%ws\n", pwzTempFile);
  584. exit:
  585. SAFERELEASE(pXMLDoc);
  586. SAFERELEASE(pElement);
  587. SAFERELEASE(pChildElement3);
  588. SAFERELEASE(pChildElement2);
  589. SAFERELEASE(pChildElement);
  590. SAFERELEASE(pNewNode);
  591. SAFERELEASE(pTextNode);
  592. SAFERELEASE(pRoot);
  593. return hr;
  594. }
  595. /////////////////////////////////////////////////////////////////////////
  596. // CreateSubscriptionManifest
  597. /////////////////////////////////////////////////////////////////////////
  598. HRESULT CreateXMLSubscriptionManifest(LPWSTR pwzSubscriptionPath,
  599. IAssemblyIdentity *pApplictionAssemblyId, LPWSTR pwzUrl, LPWSTR pwzPollingInterval)
  600. {
  601. HRESULT hr=S_OK;
  602. IXMLDOMDocument2 *pXMLDoc = NULL;
  603. IXMLDOMElement *pElement=NULL, *pChildElement=NULL, *pDependantAssemblyNode=NULL;
  604. IXMLDOMNode *pNewNode=NULL, *pRoot=NULL, *pTextNode = NULL, *pDependancyNode = NULL;
  605. CString sSubscriptionPath, sSubscriptionName;
  606. sSubscriptionPath.Assign(pwzSubscriptionPath);
  607. sSubscriptionPath.LastElement(sSubscriptionName);
  608. sSubscriptionPath.Append(L".manifest");
  609. if(FAILED(hr = CoCreateInstance(__uuidof(private_MSXML_DOMDocument30),
  610. NULL, CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument2, (void**)&pXMLDoc)))
  611. goto exit;
  612. if(FAILED(hr = AddMgVersionAsComment(pXMLDoc, &pRoot)))
  613. goto exit;
  614. //create the root assembly node and add the default properties
  615. if(FAILED(hr = CreateXMLElement(pXMLDoc, ASSEMBLY, &pElement)))
  616. goto exit;
  617. if(FAILED(hr = SetXMLElementAttribute(pElement, NAMESPACE_TITLE, NAMESPACE_VALUE)))
  618. goto exit;
  619. if(FAILED(hr = SetXMLElementAttribute(pElement, MANIFEST_VERSION_TITLE, MANIFEST_VERSION_VALUE)))
  620. goto exit;
  621. //append the root to the DOMDocument
  622. if (FAILED(hr = pXMLDoc->appendChild((IXMLDOMNode *)pElement, &pRoot)))
  623. goto exit;
  624. SAFERELEASE(pElement);
  625. //Create the AssemblyId for the Subscription
  626. //Use the AssemblyId of the application, but change the name and type
  627. if (FAILED(CreateXMLAssemblyIdElement(pXMLDoc, pApplictionAssemblyId, &pElement)))
  628. goto exit;
  629. // bugbug - check return code for consistency.
  630. hr = SetXMLElementAttribute(pElement, L"type", L"subscription");
  631. hr = SetXMLElementAttribute(pElement, L"name", sSubscriptionName._pwz);
  632. if (FAILED(hr=pRoot->appendChild((IXMLDOMNode *)pElement, &pNewNode)))
  633. goto exit;
  634. SAFERELEASE(pElement);
  635. SAFERELEASE(pNewNode);
  636. //create a sample description
  637. //bugbug, should grab description for original manifest and paste it here
  638. if(FAILED(hr = CreateXMLElement(pXMLDoc, L"description", &pElement)))
  639. goto exit;
  640. if(FAILED(hr = CreateXMLTextNode(pXMLDoc, L"Put a description of your application here", &pTextNode)))
  641. goto exit;
  642. if (FAILED(hr=pElement->appendChild(pTextNode, &pNewNode)))
  643. goto exit;
  644. SAFERELEASE(pNewNode);
  645. SAFERELEASE(pTextNode);
  646. if (FAILED(hr=pRoot->appendChild((IXMLDOMNode *)pElement, &pNewNode)))
  647. goto exit;
  648. SAFERELEASE(pNewNode);
  649. SAFERELEASE(pElement);
  650. //Create the Dependancy Node
  651. if(FAILED(hr = CreateXMLElement(pXMLDoc, DEPENDENCY, &pElement)))
  652. goto exit;
  653. if (FAILED(hr=pRoot->appendChild((IXMLDOMNode *)pElement, &pDependancyNode)))
  654. goto exit;
  655. SAFERELEASE(pElement);
  656. //Create a dependentAssembly node
  657. if(FAILED(hr = CreateXMLElement(pXMLDoc, DEPENDANT_ASSEMBLY, &pDependantAssemblyNode)))
  658. goto exit;
  659. //Create the AssemblyId for the Dependant Assembly
  660. if (FAILED(CreateXMLAssemblyIdElement(pXMLDoc, pApplictionAssemblyId, &pElement)))
  661. goto exit;
  662. //Append the AssemblyId to the dependantAssemblyNode
  663. if (FAILED(hr=pDependantAssemblyNode->appendChild((IXMLDOMNode *)pElement, &pNewNode)))
  664. goto exit;
  665. SAFERELEASE(pElement);
  666. SAFERELEASE(pNewNode);
  667. //Add the install codebase to the dependantAssemblyNode
  668. if(FAILED(hr = CreateXMLElement(pXMLDoc, INSTALL, &pElement)))
  669. goto exit;
  670. if(FAILED(hr = SetXMLElementAttribute(pElement, CODEBASE, pwzUrl)))
  671. goto exit;
  672. if(FAILED(hr = SetXMLElementAttribute(pElement, L"type", L"required")))
  673. goto exit;
  674. if (FAILED(hr=pDependantAssemblyNode->appendChild((IXMLDOMNode *)pElement, &pNewNode)))
  675. goto exit;
  676. SAFERELEASE(pElement);
  677. SAFERELEASE(pNewNode);
  678. //Add the install codebase to the dependantAssemblyNode
  679. if(FAILED(hr = CreateXMLElement(pXMLDoc, L"subscription", &pElement)))
  680. goto exit;
  681. if(FAILED(hr = SetXMLElementAttribute(pElement, L"synchronizeInterval", pwzPollingInterval)))
  682. goto exit;
  683. if(FAILED(hr = SetXMLElementAttribute(pElement, L"intervalUnit", L"hours")))
  684. goto exit;
  685. if(FAILED(hr = SetXMLElementAttribute(pElement, L"synchronizeEvent", L"onApplicationStartup")))
  686. goto exit;
  687. if(FAILED(hr = SetXMLElementAttribute(pElement, L"eventDemandConnection", L"no")))
  688. goto exit;
  689. if (FAILED(hr=pDependantAssemblyNode->appendChild((IXMLDOMNode *)pElement, &pNewNode)))
  690. goto exit;
  691. SAFERELEASE(pElement);
  692. SAFERELEASE(pNewNode);
  693. //Append the dependantAssemblyNode to the dependancy node
  694. if (FAILED(hr=pDependancyNode->appendChild(pDependantAssemblyNode, &pNewNode)))
  695. goto exit;
  696. SAFERELEASE(pDependantAssemblyNode);
  697. SAFERELEASE(pNewNode);
  698. //Format and save the document
  699. hr = FormatXML(pXMLDoc, pRoot, 1);
  700. if(FAILED(hr = SaveXMLDocument(pXMLDoc, sSubscriptionPath._pwz)))
  701. goto exit;
  702. printf("Subscription manifest succesfully created\n%ws\n", sSubscriptionPath._pwz);
  703. exit:
  704. SAFERELEASE(pXMLDoc);
  705. SAFERELEASE(pElement);
  706. SAFERELEASE(pChildElement);
  707. SAFERELEASE(pNewNode);
  708. SAFERELEASE(pTextNode);
  709. SAFERELEASE(pRoot);
  710. SAFERELEASE(pDependancyNode);
  711. SAFERELEASE(pDependantAssemblyNode);
  712. return hr;
  713. }
  714. /////////////////////////////////////////////////////////////////////////
  715. // CreateXMLAppManifest
  716. // Creates the app manifest - may want to rename.
  717. /////////////////////////////////////////////////////////////////////////
  718. // NOTENOTE: rename pList -> pAsmList ?
  719. HRESULT CreateXMLAppManifest(LPWSTR pwzAppBase, LPWSTR pwzTemplateFilePath, List<ManifestNode *> *pList, List<LPWSTR> *pFileList)
  720. {
  721. HRESULT hr = S_OK;
  722. DWORD cc = 0, cb = 0, ccName = 0;
  723. LPWSTR pwz=NULL, pwzCodeBase = NULL, pwzName = NULL;
  724. IAssemblyIdentity *pASMId= NULL;
  725. IXMLDOMDocument2 *pXMLDoc=NULL;
  726. IXMLDOMElement *pElement=NULL, *pAssemblyIdElement = NULL;
  727. IXMLDOMNode *pRoot=NULL, *pDependancyNode = NULL, *pNewNode = NULL;
  728. IXMLDOMNode *pAssemblyIdNode = NULL, *pDependantAssemblyNode=NULL;
  729. BSTR bstrAttribute = NULL;
  730. VARIANT varAttribute;
  731. ManifestNode *pManNode = NULL;
  732. CString sAppName, sFileName, sFileHash, sAbsoluteFilePath, sManifestFilePath;
  733. LISTNODE pos = NULL;
  734. VariantInit(&varAttribute);
  735. //Load the template
  736. if(FAILED(hr = LoadXMLDocument(pwzTemplateFilePath, &pXMLDoc)))
  737. goto exit;
  738. //grab the first child(the only child) as the root node
  739. if(FAILED(hr = GetNode(pXMLDoc, ASSEMBLY, &pRoot)))
  740. goto exit;
  741. if (hr == S_FALSE)
  742. {
  743. hr = E_INVALIDARG;
  744. goto exit;
  745. }
  746. //Get the name from the assemblyId, this will be the manifests file name
  747. if(FAILED(hr = pRoot->get_firstChild(&pAssemblyIdNode)))
  748. goto exit;
  749. //Query for the Element interface
  750. if (FAILED(hr = pAssemblyIdNode->QueryInterface(IID_IXMLDOMElement, (void**) &pAssemblyIdElement)))
  751. goto exit;
  752. bstrAttribute = ::SysAllocString(L"name");
  753. if (!bstrAttribute)
  754. {
  755. hr = E_OUTOFMEMORY;
  756. goto exit;
  757. }
  758. if ((hr = pAssemblyIdElement->getAttribute(bstrAttribute, &varAttribute)) != S_OK)
  759. goto exit;
  760. ccName = ::SysStringLen(varAttribute.bstrVal) + 1;
  761. pwzName = new WCHAR[ccName];
  762. if (!pwzName)
  763. {
  764. hr = E_OUTOFMEMORY;
  765. goto exit;
  766. }
  767. memcpy(pwzName, varAttribute.bstrVal, ccName * sizeof(WCHAR));
  768. if((*pwzName)== NULL)
  769. {
  770. hr = E_FAIL;
  771. printf("Invalid Template Format. Template must have a name attribute in the assemblyIdentity tag\n");
  772. goto exit;
  773. }
  774. ::SysFreeString(varAttribute.bstrVal);
  775. ::SysFreeString(bstrAttribute);
  776. SAFERELEASE(pAssemblyIdElement);
  777. SAFERELEASE(pAssemblyIdNode);
  778. if(FAILED(hr = AddMgVersionAsComment(pXMLDoc, &pRoot)))
  779. goto exit;
  780. // Add all the raw files to the manifest
  781. pos = pFileList->GetHeadPosition();
  782. while (pos)
  783. {
  784. pwz = pFileList->GetNext(pos);
  785. sFileName.Assign(pwz);
  786. if(FAILED(hr = CreateXMLElement(pXMLDoc, FILE, &pElement)))
  787. goto exit;
  788. if(FAILED(hr = SetXMLElementAttribute(pElement, FILE_NAME, sFileName._pwz)))
  789. goto exit;
  790. if (FAILED(hr=pRoot->appendChild((IXMLDOMNode *)pElement, &pNewNode)))
  791. goto exit;
  792. //Get Absolute File Path of file
  793. sAbsoluteFilePath.Assign(pwzAppBase);
  794. sAbsoluteFilePath.Append(sFileName);
  795. //get the hash of the file
  796. if(FAILED(hr = GetHash(sAbsoluteFilePath._pwz, &pwz)))
  797. goto exit;
  798. sFileHash.TakeOwnership(pwz);
  799. if(FAILED(hr = SetXMLElementAttribute(pElement, FILE_HASH, sFileHash._pwz)))
  800. goto exit;
  801. SAFERELEASE(pNewNode);
  802. }
  803. // Get Dependency Node if exists
  804. if (FAILED(hr = GetNode(pXMLDoc, DEPENDENCY_QUERY, &pDependancyNode)))
  805. goto exit;
  806. if (hr == S_FALSE)
  807. {
  808. //Create the Dependancy Node
  809. if(FAILED(hr = CreateXMLElement(pXMLDoc, DEPENDENCY, &pElement)))
  810. goto exit;
  811. if (FAILED(hr=pRoot->appendChild((IXMLDOMNode *)pElement, &pDependancyNode)))
  812. goto exit;
  813. SAFERELEASE(pElement);
  814. }
  815. //Walk thorugh the list of dependant assemblies and add them to the App Manifest
  816. pos = pList->GetHeadPosition();
  817. while (pos)
  818. {
  819. //Get next Dependant Assembly from list
  820. pManNode = pList->GetNext(pos);
  821. if (FAILED(hr = CreateDependantAssemblyNode(pXMLDoc, pManNode, &pDependantAssemblyNode)))
  822. goto exit;
  823. if (FAILED(hr=pDependancyNode->appendChild(pDependantAssemblyNode, &pNewNode)))
  824. goto exit;
  825. SAFERELEASE(pDependantAssemblyNode);
  826. SAFERELEASE(pNewNode);
  827. }
  828. //Indent the manifest
  829. hr = FormatXML(pXMLDoc, pRoot, 1);
  830. // Save the manifest to a file
  831. sManifestFilePath.Assign(pwzAppBase);
  832. sManifestFilePath.Append(pwzName);
  833. sManifestFilePath.Append(L".manifest");
  834. if(FAILED(hr = SaveXMLDocument(pXMLDoc, sManifestFilePath._pwz)))
  835. goto exit;
  836. printf("\nManifest created succesfully\n%ws\n", sManifestFilePath._pwz);
  837. exit:
  838. if (varAttribute.bstrVal)
  839. ::SysFreeString(varAttribute.bstrVal);
  840. SAFEDELETEARRAY(pwzName);
  841. SAFERELEASE(pXMLDoc);
  842. SAFERELEASE(pElement);
  843. SAFERELEASE(pAssemblyIdElement);
  844. SAFERELEASE(pNewNode);
  845. SAFERELEASE(pAssemblyIdNode);
  846. SAFERELEASE(pRoot);
  847. SAFERELEASE(pDependancyNode);
  848. SAFERELEASE(pDependantAssemblyNode);
  849. return hr;
  850. }
  851. /////////////////////////////////////////////////////////////////////////
  852. // SaveXMLDocument
  853. /////////////////////////////////////////////////////////////////////////
  854. HRESULT SaveXMLDocument(IXMLDOMDocument2 *pXMLDoc, LPWSTR pwzDocumentName)
  855. {
  856. HRESULT hr = S_OK;
  857. CString sDocumentName;
  858. BSTR bstrFileName = NULL;
  859. VARIANT varFileName;
  860. // Save the manifest to a file
  861. sDocumentName.Assign(pwzDocumentName);
  862. bstrFileName = ::SysAllocString(sDocumentName._pwz);
  863. if (!bstrFileName)
  864. {
  865. hr = E_OUTOFMEMORY;
  866. goto exit;
  867. }
  868. VariantInit(&varFileName);
  869. varFileName.vt = VT_BSTR;
  870. V_BSTR(&varFileName) = bstrFileName;
  871. hr = pXMLDoc->save(varFileName);
  872. exit:
  873. if(bstrFileName)
  874. ::SysFreeString(bstrFileName);
  875. return hr;
  876. }
  877. /////////////////////////////////////////////////////////////////////////
  878. //LoadXMLDocument
  879. /////////////////////////////////////////////////////////////////////////
  880. HRESULT LoadXMLDocument(LPWSTR pwzDocumentPath, IXMLDOMDocument2 **ppXMLDoc)
  881. {
  882. HRESULT hr = S_OK;
  883. IXMLDOMDocument2 *pXMLDoc;
  884. VARIANT varFileName;
  885. VARIANT_BOOL varBool;
  886. BSTR bstrFileName = NULL;
  887. bstrFileName = ::SysAllocString(pwzDocumentPath);
  888. if (!bstrFileName)
  889. {
  890. hr = E_OUTOFMEMORY;
  891. goto exit;
  892. }
  893. VariantInit(&varFileName);
  894. varFileName.vt = VT_BSTR;
  895. V_BSTR(&varFileName) = bstrFileName;
  896. if(FAILED(hr = CoCreateInstance(__uuidof(private_MSXML_DOMDocument30),
  897. NULL, CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument2, (void**)&pXMLDoc)))
  898. goto exit;
  899. // Load synchronously
  900. if (FAILED(hr = pXMLDoc->put_async(VARIANT_FALSE)))
  901. goto exit;
  902. if ((hr = pXMLDoc->load(varFileName, &varBool)) != S_OK)
  903. {
  904. if(!varBool)
  905. hr = E_INVALIDARG;
  906. goto exit;
  907. }
  908. *ppXMLDoc=pXMLDoc;
  909. (*ppXMLDoc)->AddRef();
  910. exit:
  911. if(bstrFileName)
  912. ::SysFreeString(bstrFileName);
  913. SAFERELEASE(pXMLDoc);
  914. return hr;
  915. }