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.

414 lines
15 KiB

  1. #include <fusenetincludes.h>
  2. #include <msxml2.h>
  3. #include <patchingutil.h>
  4. #include <manifestinfo.h>
  5. #include <manifestimport.h>
  6. #define PATCH_DIRECTORY L"__patch__\\"
  7. // ---------------------------------------------------------------------------
  8. // CreatePatchingUtil
  9. // ---------------------------------------------------------------------------
  10. STDAPI CreatePatchingUtil(IXMLDOMNode *pPatchNode, LPPATCHING_INTERFACE* ppPatchingInfo)
  11. {
  12. HRESULT hr = S_OK;
  13. MAKE_ERROR_MACROS_STATIC(hr);
  14. CPatchingUtil *pPatchingInfo = NULL;
  15. IF_ALLOC_FAILED_EXIT(pPatchingInfo = new(CPatchingUtil));
  16. IF_FAILED_EXIT(pPatchingInfo->Init(pPatchNode));
  17. *ppPatchingInfo = static_cast<IPatchingUtil*> (pPatchingInfo);
  18. pPatchingInfo = NULL;
  19. exit:
  20. SAFERELEASE(pPatchingInfo);
  21. return hr;
  22. }
  23. // ---------------------------------------------------------------------------
  24. // ctor
  25. // ---------------------------------------------------------------------------
  26. CPatchingUtil::CPatchingUtil()
  27. : _dwSig('UATP'), _cRef(1), _hr(S_OK), _pXMLPatchNode(NULL)
  28. {
  29. }
  30. // ---------------------------------------------------------------------------
  31. // dtor
  32. // ---------------------------------------------------------------------------
  33. CPatchingUtil::~CPatchingUtil()
  34. {
  35. SAFERELEASE(_pXMLPatchNode);
  36. }
  37. // ---------------------------------------------------------------------------
  38. // Init
  39. // ---------------------------------------------------------------------------
  40. HRESULT CPatchingUtil::Init(IXMLDOMNode *pPatchNode)
  41. {
  42. _hr = S_OK;
  43. _pXMLPatchNode = pPatchNode;
  44. _pXMLPatchNode->AddRef();
  45. return _hr;
  46. }
  47. // ---------------------------------------------------------------------------
  48. // MatchTarget
  49. // ---------------------------------------------------------------------------
  50. HRESULT CPatchingUtil::MatchTarget(LPWSTR pwzTarget, IManifestInfo **ppPatchInfo)
  51. {
  52. LPWSTR pwzBuf;
  53. DWORD ccBuf;
  54. CString sQueryString;
  55. BSTR bstrtQueryString;
  56. IXMLDOMNode *pNode=NULL;
  57. IXMLDOMNodeList *pNodeList = NULL;
  58. LONG nNodes;
  59. IManifestInfo *pPatchInfo = NULL;
  60. CString sSourceName, sPatchName, sTargetName;
  61. IF_FAILED_EXIT(sTargetName.Assign(pwzTarget));
  62. // set up serach string
  63. IF_FAILED_EXIT(sQueryString.Assign(L"PatchInfo[@file=\""));
  64. IF_FAILED_EXIT(sQueryString.Append(pwzTarget));
  65. IF_FAILED_EXIT(sQueryString.Append(L"\"] | PatchInfo[@target=\""));
  66. IF_FAILED_EXIT(sQueryString.Append(pwzTarget));
  67. IF_FAILED_EXIT(sQueryString.Append(L"\"]"));
  68. IF_ALLOC_FAILED_EXIT(bstrtQueryString = ::SysAllocString(sQueryString._pwz));
  69. IF_FAILED_EXIT(_pXMLPatchNode->selectNodes(bstrtQueryString, &pNodeList));
  70. IF_FAILED_EXIT(_hr = pNodeList->get_length(&nNodes));
  71. IF_FALSE_EXIT(nNodes <= 1, HRESULT_FROM_WIN32(ERROR_BAD_FORMAT));
  72. IF_TRUE_EXIT(nNodes == 0, S_FALSE);
  73. IF_FALSE_EXIT(pNodeList->get_item(0, &pNode) == S_OK, E_FAIL);
  74. IF_FAILED_EXIT(CreateManifestInfo(MAN_INFO_PATCH_INFO, &pPatchInfo));
  75. IF_FAILED_EXIT(pPatchInfo->Set(MAN_INFO_PATCH_INFO_TARGET, sTargetName._pwz, sTargetName.ByteCount(), MAN_INFO_FLAG_LPWSTR));
  76. IF_FAILED_EXIT(CAssemblyManifestImport::ParseAttribute(pNode, CAssemblyManifestImport::g_StringTable[CAssemblyManifestImport::File].bstr, &pwzBuf, &ccBuf));
  77. if(_hr == S_OK)
  78. {
  79. IF_FAILED_EXIT(sSourceName.TakeOwnership(pwzBuf, ccBuf));
  80. }
  81. else if (_hr == S_FALSE)
  82. {
  83. IF_FAILED_EXIT(CAssemblyManifestImport::ParseAttribute(pNode, CAssemblyManifestImport::g_StringTable[CAssemblyManifestImport::Source].bstr, &pwzBuf, &ccBuf));
  84. IF_FALSE_EXIT(_hr == S_OK, HRESULT_FROM_WIN32(ERROR_BAD_FORMAT));
  85. IF_FAILED_EXIT(sSourceName.TakeOwnership(pwzBuf, ccBuf));
  86. }
  87. IF_FAILED_EXIT(pPatchInfo->Set(MAN_INFO_PATCH_INFO_SOURCE, sSourceName._pwz, sSourceName.ByteCount(), MAN_INFO_FLAG_LPWSTR));
  88. IF_FAILED_EXIT(CAssemblyManifestImport::ParseAttribute(pNode, CAssemblyManifestImport::g_StringTable[CAssemblyManifestImport::PatchFile].bstr, &pwzBuf, &ccBuf));
  89. IF_TRUE_EXIT(_hr == S_FALSE, S_OK);
  90. IF_FAILED_EXIT(sPatchName.TakeOwnership(pwzBuf, ccBuf));
  91. IF_FAILED_EXIT(pPatchInfo->Set(MAN_INFO_PATCH_INFO_PATCH, sPatchName._pwz, sPatchName.ByteCount(), MAN_INFO_FLAG_LPWSTR));
  92. *ppPatchInfo = pPatchInfo;
  93. pPatchInfo = NULL;
  94. exit:
  95. if (bstrtQueryString)
  96. ::SysFreeString(bstrtQueryString);
  97. SAFERELEASE(pNode);
  98. SAFERELEASE(pNodeList);
  99. SAFERELEASE(pPatchInfo);
  100. return _hr;
  101. }
  102. // ---------------------------------------------------------------------------
  103. // MatchPatch
  104. // ---------------------------------------------------------------------------
  105. HRESULT CPatchingUtil::MatchPatch(LPWSTR pwzPatch, IManifestInfo **ppPatchInfo)
  106. {
  107. LPWSTR pwzBuf;
  108. DWORD ccBuf;
  109. CString sQueryString;
  110. BSTR bstrtQueryString;
  111. IXMLDOMNode *pNode=NULL;
  112. IXMLDOMNodeList *pNodeList = NULL;
  113. LONG nNodes;
  114. IManifestInfo *pPatchInfo = NULL;
  115. CString sSourceName, sTargetName, sFileName, sPatchName;
  116. IF_FAILED_EXIT(sPatchName.Assign (pwzPatch));
  117. // set up serach string
  118. IF_FAILED_EXIT(sQueryString.Assign(L"PatchInfo[@patchfile=\""));
  119. IF_FAILED_EXIT(sQueryString.Append(pwzPatch));
  120. IF_FAILED_EXIT(sQueryString.Append(L"\"]"));
  121. IF_ALLOC_FAILED_EXIT(bstrtQueryString = ::SysAllocString(sQueryString._pwz));
  122. if ((_hr = _pXMLPatchNode->selectNodes(bstrtQueryString, &pNodeList)) != S_OK)
  123. goto exit;
  124. _hr = pNodeList->get_length(&nNodes);
  125. IF_FALSE_EXIT(nNodes <= 1, HRESULT_FROM_WIN32(ERROR_BAD_FORMAT));
  126. IF_FALSE_EXIT(pNodeList->get_item(0, &pNode) == S_OK, E_FAIL);
  127. IF_FAILED_EXIT(CreateManifestInfo(MAN_INFO_PATCH_INFO, &pPatchInfo));
  128. IF_FAILED_EXIT(pPatchInfo->Set(MAN_INFO_PATCH_INFO_PATCH, sPatchName._pwz, sPatchName.ByteCount(), MAN_INFO_FLAG_LPWSTR));
  129. IF_FAILED_EXIT(CAssemblyManifestImport::ParseAttribute(pNode, CAssemblyManifestImport::g_StringTable[CAssemblyManifestImport::File].bstr, &pwzBuf, &ccBuf));
  130. if(_hr == S_OK)
  131. {
  132. IF_FAILED_EXIT(sSourceName.TakeOwnership(pwzBuf, ccBuf));
  133. IF_FAILED_EXIT(sTargetName.Assign(pwzBuf));
  134. }
  135. else if (_hr == S_FALSE)
  136. {
  137. IF_FALSE_EXIT(CAssemblyManifestImport::ParseAttribute(pNode, CAssemblyManifestImport::g_StringTable[CAssemblyManifestImport::Source].bstr, &pwzBuf, &ccBuf) == S_OK, HRESULT_FROM_WIN32(ERROR_BAD_FORMAT));
  138. IF_FAILED_EXIT(sSourceName.TakeOwnership(pwzBuf, ccBuf));
  139. IF_FALSE_EXIT(CAssemblyManifestImport::ParseAttribute(pNode, CAssemblyManifestImport::g_StringTable[CAssemblyManifestImport::Target].bstr, &pwzBuf, &ccBuf) == S_OK, HRESULT_FROM_WIN32(ERROR_BAD_FORMAT));
  140. IF_FAILED_EXIT(sTargetName.TakeOwnership(pwzBuf, ccBuf));
  141. }
  142. IF_FAILED_EXIT(pPatchInfo->Set(MAN_INFO_PATCH_INFO_SOURCE, sSourceName._pwz, sSourceName.ByteCount(), MAN_INFO_FLAG_LPWSTR));
  143. IF_FAILED_EXIT(pPatchInfo->Set(MAN_INFO_PATCH_INFO_TARGET, sTargetName._pwz, sTargetName.ByteCount(), MAN_INFO_FLAG_LPWSTR));
  144. *ppPatchInfo = pPatchInfo;
  145. pPatchInfo = NULL;
  146. _hr = S_OK;
  147. exit:
  148. if (bstrtQueryString)
  149. ::SysFreeString(bstrtQueryString);
  150. SAFERELEASE(pNode);
  151. SAFERELEASE(pNodeList);
  152. SAFERELEASE(pPatchInfo);
  153. return _hr;
  154. }
  155. // IUnknown Boilerplate
  156. // ---------------------------------------------------------------------------
  157. // CPatchingUtil::QI
  158. // ---------------------------------------------------------------------------
  159. STDMETHODIMP
  160. CPatchingUtil::QueryInterface(REFIID riid, void** ppvObj)
  161. {
  162. if ( IsEqualIID(riid, IID_IUnknown)
  163. || IsEqualIID(riid, IID_IPatchingUtil)
  164. )
  165. {
  166. *ppvObj = static_cast<IPatchingUtil*> (this);
  167. AddRef();
  168. return S_OK;
  169. }
  170. else
  171. {
  172. *ppvObj = NULL;
  173. return E_NOINTERFACE;
  174. }
  175. }
  176. // ---------------------------------------------------------------------------
  177. // CPatchingUtil::AddRef
  178. // ---------------------------------------------------------------------------
  179. STDMETHODIMP_(ULONG)
  180. CPatchingUtil::AddRef()
  181. {
  182. return InterlockedIncrement ((LONG*) &_cRef);
  183. }
  184. // ---------------------------------------------------------------------------
  185. // CPatchingUtil::Release
  186. // ---------------------------------------------------------------------------
  187. STDMETHODIMP_(ULONG)
  188. CPatchingUtil::Release()
  189. {
  190. ULONG lRet = InterlockedDecrement ((LONG*) &_cRef);
  191. if (!lRet)
  192. delete this;
  193. return lRet;
  194. }
  195. // ---------------------------------------------------------------------------
  196. // CreatePatchingInfo
  197. // ---------------------------------------------------------------------------
  198. HRESULT CPatchingUtil::CreatePatchingInfo(IXMLDOMDocument2 *pXMLDOMDocument, IAssemblyCacheImport *pCacheImport, IManifestInfo **ppPatchingInfo)
  199. {
  200. HRESULT hr = S_OK;
  201. MAKE_ERROR_MACROS_STATIC(hr);
  202. LPWSTR pwzBuf;
  203. DWORD cbBuf, ccBuf;
  204. CString sManifestDirectory, sSourceManifestDirectory, sTempDirectoryPath;
  205. CString sSourceAssemblyDisplayName;
  206. CString sQueryString;
  207. BSTR bstrtQueryString = NULL;
  208. IXMLDOMNodeList *pXMLMatchingNodeList = NULL;
  209. IXMLDOMNode *pXMLNode = NULL;
  210. IXMLDOMNode *pXMLASMNode = NULL;
  211. IAssemblyCacheImport *pSourceASMImport = NULL;
  212. IAssemblyIdentity *pAssemblyId = NULL, *pSourceASMId =NULL;
  213. IAssemblyManifestImport *pManifestImport = NULL;
  214. IManifestInfo *pPatchingInfo = NULL;
  215. IPatchingUtil *pPatchingUtil = NULL;
  216. *ppPatchingInfo = NULL;
  217. //Get the manifest import from the pCacheImport so we can grab the AssemblyId
  218. IF_FAILED_EXIT(pCacheImport->GetManifestImport(&pManifestImport));
  219. //Get the assemblyID
  220. IF_FAILED_EXIT(pManifestImport->GetAssemblyIdentity(&pAssemblyId));
  221. SAFERELEASE(pManifestImport);
  222. IF_FAILED_EXIT(sQueryString.Assign(L"/assembly/Patch/SourceAssembly"));
  223. IF_ALLOC_FAILED_EXIT(bstrtQueryString = ::SysAllocString(sQueryString._pwz));
  224. if ((hr = pXMLDOMDocument->selectNodes(bstrtQueryString, &pXMLMatchingNodeList)) != S_OK)
  225. goto exit;
  226. pXMLMatchingNodeList->reset();
  227. //enumerate through the Source Assemblies
  228. while ((hr = pXMLMatchingNodeList->nextNode(&pXMLNode)) == S_OK)
  229. {
  230. //Get the first child under the SourceAssemly (this is the ASM Id)
  231. if ((hr = pXMLNode->get_firstChild (&pXMLASMNode)) != S_OK)
  232. goto exit;
  233. //Convert the XML node to an actuall ASM Id
  234. if ((hr = CAssemblyManifestImport::XMLtoAssemblyIdentity(pXMLASMNode, &pSourceASMId)) != S_OK)
  235. goto exit;
  236. //Check to see if the SourceAssembly exists in cache
  237. // or if is the same as the Assembly we are currently downloading
  238. IF_FAILED_EXIT(CreateAssemblyCacheImport(&pSourceASMImport, pSourceASMId, CACHEIMP_CREATE_RETRIEVE));
  239. if (hr == S_FALSE)
  240. {
  241. IF_FAILED_EXIT(pSourceASMId->IsEqual(pAssemblyId));
  242. if (hr == S_OK)
  243. {
  244. pSourceASMImport = pCacheImport;
  245. pSourceASMImport->AddRef();
  246. }
  247. }
  248. //Found a suitable SourceAssembly
  249. if (hr == S_OK)
  250. {
  251. //Create a manifestInfo property bag
  252. IF_FAILED_EXIT(CreateManifestInfo(MAN_INFO_SOURCE_ASM, &pPatchingInfo));
  253. //Set the source ASMId in the property bag
  254. IF_FAILED_EXIT(pPatchingInfo->Set(MAN_INFO_SOURCE_ASM_ID, &pSourceASMId,
  255. sizeof(LPVOID), MAN_INFO_FLAG_IUNKNOWN_PTR));
  256. // grab the manifest directory
  257. IF_FAILED_EXIT(pCacheImport->GetManifestFileDir(&pwzBuf, &ccBuf));
  258. IF_FAILED_EXIT(sManifestDirectory.TakeOwnership(pwzBuf, ccBuf));
  259. //Set manifest Directory in patchingInfo property bag
  260. IF_FAILED_EXIT(pPatchingInfo->Set(MAN_INFO_SOURCE_ASM_INSTALL_DIR, sManifestDirectory._pwz,
  261. sManifestDirectory.ByteCount(), MAN_INFO_FLAG_LPWSTR));
  262. //grab directory of SourceAssembly
  263. IF_FAILED_EXIT(pSourceASMImport->GetManifestFileDir(&pwzBuf, &ccBuf));
  264. IF_FAILED_EXIT(sSourceManifestDirectory.TakeOwnership(pwzBuf, ccBuf));
  265. //Set SourceAssembly Directory in patchingInfo property bag
  266. IF_FAILED_EXIT(pPatchingInfo->Set(MAN_INFO_SOURCE_ASM_DIR, sSourceManifestDirectory._pwz,
  267. sSourceManifestDirectory.ByteCount(), MAN_INFO_FLAG_LPWSTR));
  268. //get display name of patch assembly identity
  269. IF_FAILED_EXIT(pSourceASMId->GetDisplayName(ASMID_DISPLAYNAME_NOMANGLING, &pwzBuf, &ccBuf));
  270. IF_FAILED_EXIT(sSourceAssemblyDisplayName.TakeOwnership (pwzBuf, ccBuf));
  271. //setup the path of the temporary directory
  272. IF_FAILED_EXIT(sTempDirectoryPath.Assign(sManifestDirectory));
  273. IF_FAILED_EXIT(DoPathCombine(sTempDirectoryPath, PATCH_DIRECTORY));
  274. IF_FAILED_EXIT(DoPathCombine(sTempDirectoryPath, sSourceAssemblyDisplayName._pwz));
  275. IF_FAILED_EXIT(sTempDirectoryPath.Append(L"\\"));
  276. //Set Temporary Directory in patchingInfo property bag
  277. IF_FAILED_EXIT(pPatchingInfo->Set(MAN_INFO_SOURCE_ASM_TEMP_DIR, sTempDirectoryPath._pwz,
  278. sTempDirectoryPath.ByteCount(), MAN_INFO_FLAG_LPWSTR));
  279. // Create patching info interface and insert into manifestInfo propertybag
  280. IF_FAILED_EXIT(CreatePatchingUtil(pXMLNode, &pPatchingUtil));
  281. IF_FAILED_EXIT(pPatchingInfo->Set(MAN_INFO_SOURCE_ASM_PATCH_UTIL, &pPatchingUtil,
  282. sizeof(LPVOID), MAN_INFO_FLAG_IUNKNOWN_PTR));
  283. }
  284. SAFERELEASE(pXMLNode);
  285. SAFERELEASE(pXMLASMNode);
  286. SAFERELEASE(pSourceASMId);
  287. SAFERELEASE(pSourceASMImport);
  288. if (pPatchingInfo)
  289. {
  290. *ppPatchingInfo = pPatchingInfo;
  291. pPatchingInfo = NULL;
  292. hr = S_OK; // this is the successful case.
  293. goto exit;
  294. }
  295. }
  296. IF_FAILED_EXIT(hr);
  297. // BUGBUG: what the hell is this?
  298. hr = S_FALSE;
  299. exit:
  300. if (bstrtQueryString)
  301. ::SysFreeString(bstrtQueryString);
  302. SAFERELEASE(pManifestImport);
  303. SAFERELEASE(pXMLNode);
  304. SAFERELEASE(pXMLASMNode);
  305. SAFERELEASE(pSourceASMId);
  306. SAFERELEASE(pSourceASMImport);
  307. SAFERELEASE(pXMLMatchingNodeList);
  308. SAFERELEASE(pPatchingUtil);
  309. SAFERELEASE(pPatchingInfo);
  310. SAFERELEASE(pAssemblyId);
  311. return hr;
  312. }