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.

1578 lines
53 KiB

  1. #include <fusenetincludes.h>
  2. #include <manifestimport.h>
  3. #include <manifestimportclr.h>
  4. #ifdef CONTAINER
  5. #include <manifestimportcontainer.h>
  6. #endif
  7. #include <sxsapi.h>
  8. #include <manifestdata.h>
  9. #include "dbglog.h"
  10. #define WZ_NAMESPACES L"xmlns:asm_namespace_v1='urn:schemas-microsoft-com:asm.v1'"
  11. #define WZ_SELECTION_NAMESPACES L"SelectionNamespaces"
  12. #define WZ_SELECTION_LANGUAGE L"SelectionLanguage"
  13. #define WZ_XPATH L"XPath"
  14. #define WZ_FILE_NODE L"/assembly/file"
  15. #define WZ_FILE_QUERYSTRING_PREFIX L"/assembly/file[@name = \""
  16. #define WZ_QUERYSTRING_SUFFIX L"\"]"
  17. #define WZ_ASSEMBLY_ID L"/assembly/assemblyIdentity"
  18. #define WZ_DEPENDENT_ASSEMBLY_NODE L"/assembly/dependency/dependentAssembly/assemblyIdentity"
  19. #define WZ_DEPENDENT_ASSEMBLY_CODEBASE L"../install[@codebase]"
  20. #define WZ_CODEBASE L"codebase"
  21. #define WZ_SHELLSTATE L"/assembly/application/shellState"
  22. #define WZ_ACTIVATION L"/assembly/application/activation"
  23. #define WZ_FILE_NAME L"name"
  24. #define WZ_FILE_HASH L"hash"
  25. #define WZ_FRIENDLYNAME L"friendlyName"
  26. #define WZ_ENTRYPOINT L"entryPoint"
  27. #define WZ_ENTRYIMAGETYPE L"entryImageType"
  28. #define WZ_ICONFILE L"iconFile"
  29. #define WZ_ICONINDEX L"iconIndex"
  30. #define WZ_SHOWCOMMAND L"showCommand"
  31. #define WZ_HOTKEY L"hotKey"
  32. #define WZ_ASSEMBLYNAME L"assemblyName"
  33. #define WZ_ASSEMBLYCLASS L"assemblyClass"
  34. #define WZ_ASSEMBLYMETHOD L"assemblyMethod"
  35. #define WZ_ASSEMBLYARGS L"assemblyMethodArgs"
  36. #define WZ_PATCH L"/assembly/Patch/SourceAssembly"
  37. #define WZ_PATCHINFO L"/PatchInfo/"
  38. #define WZ_SOURCE L"source"
  39. #define WZ_TARGET L"target"
  40. #define WZ_PATCHFILE L"patchfile"
  41. #define WZ_ASSEMBLY_ID_TAG L"assemblyIdentity"
  42. #define WZ_COMPRESSED L"compressed"
  43. #define WZ_SUBSCRIPTION L"/assembly/dependency/dependentAssembly/subscription"
  44. #define WZ_SYNC_INTERVAL L"synchronizeInterval"
  45. #define WZ_INTERVAL_UNIT L"intervalUnit"
  46. #define WZ_SYNC_EVENT L"synchronizeEvent"
  47. #define WZ_DEMAND_CONNECTION L"eventDemandConnection"
  48. #define WZ_FILE L"file"
  49. #define WZ_CAB L"cab"
  50. #define WZ_ASSEMBLY_NODE L"/assembly" //BUGBUG: match assembly with xmlns and/or manifestVersion attributes for versioning
  51. #define WZ_APPLICATION_NODE L"/assembly/application"
  52. #define WZ_VERSIONWILDCARD L"*"
  53. #define WZ_DESKTOP L"desktop"
  54. #define WZ_DEPENDENCY L"dependency"
  55. #define WZ_DEPENDENTASSEMBLY L"dependentAssembly"
  56. #define WZ_INSTALL L"install"
  57. #define WZ_INSTALL_TYPE L"type"
  58. #define WZ_PLATFORM L"/assembly/dependency/platform"
  59. #define WZ_PLATFORMINFO L"platformInfo"
  60. #define WZ_OSVERSIONINFO L"osVersionInfo"
  61. #define WZ_DOTNETVERSIONINFO L"dotNetVersionInfo"
  62. #define WZ_HREF L"href"
  63. #define WZ_OS L"os"
  64. #define WZ_MAJORVERSION L"majorVersion"
  65. #define WZ_MINORVERSION L"minorVersion"
  66. #define WZ_BUILDNUMBER L"buildNumber"
  67. #define WZ_SERVICEPACKMAJOR L"servicePackMajor"
  68. #define WZ_SERVICEPACKMINOR L"servicePackMinor"
  69. #define WZ_SUITE L"suite"
  70. #define WZ_PRODUCTTYPE L"productType"
  71. #define WZ_SUPPORTEDRUNTIME L"supportedRuntime"
  72. #define WZ_REQUIRED L"required"
  73. #define WZ_MINUTES L"minutes"
  74. //#define WZ_HOURS L"hours"
  75. #define WZ_DAYS L"days"
  76. #define WZ_ONAPPLICATIONSTARTUP L"onApplicationStartup"
  77. #define WZ_YES L"yes"
  78. //#define WZ_NO L"no"
  79. #ifdef DEVMODE
  80. #define WZ_DEVSYNC L"devSync"
  81. #endif
  82. //BUGBUG: default sync interval==6hrs; should be documented
  83. #define DW_DEFAULT_SYNC_INTERVAL 6
  84. #undef NUMBER_OF
  85. #define NUMBER_OF(x) ( (sizeof(x) / sizeof(*x) ) )
  86. #undef ENTRY
  87. #define ENTRY(x) { x, NULL, NUMBER_OF(x) - 1 },
  88. CAssemblyManifestImport::StringTableEntry CAssemblyManifestImport::g_StringTable[] =
  89. {
  90. ENTRY(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_NAME)
  91. ENTRY(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_VERSION)
  92. ENTRY(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_LANGUAGE)
  93. ENTRY(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_PUBLIC_KEY)
  94. ENTRY(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_PUBLIC_KEY_TOKEN)
  95. ENTRY(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_PROCESSOR_ARCHITECTURE)
  96. ENTRY(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_TYPE)
  97. ENTRY(WZ_SELECTION_NAMESPACES)
  98. ENTRY(WZ_NAMESPACES)
  99. ENTRY(WZ_SELECTION_LANGUAGE)
  100. ENTRY(WZ_XPATH)
  101. ENTRY(WZ_FILE_NODE)
  102. ENTRY(WZ_FILE_NAME)
  103. ENTRY(WZ_FILE_HASH)
  104. ENTRY(WZ_ASSEMBLY_ID)
  105. ENTRY(WZ_DEPENDENT_ASSEMBLY_NODE)
  106. ENTRY(WZ_DEPENDENT_ASSEMBLY_CODEBASE)
  107. ENTRY(WZ_CODEBASE)
  108. ENTRY(WZ_SHELLSTATE)
  109. ENTRY(WZ_FRIENDLYNAME)
  110. ENTRY(WZ_ENTRYPOINT)
  111. ENTRY(WZ_ENTRYIMAGETYPE)
  112. ENTRY(WZ_ICONFILE)
  113. ENTRY(WZ_ICONINDEX)
  114. ENTRY(WZ_SHOWCOMMAND)
  115. ENTRY(WZ_HOTKEY)
  116. ENTRY(WZ_ACTIVATION)
  117. ENTRY(WZ_ASSEMBLYNAME)
  118. ENTRY(WZ_ASSEMBLYCLASS)
  119. ENTRY(WZ_ASSEMBLYMETHOD)
  120. ENTRY(WZ_ASSEMBLYARGS)
  121. ENTRY(WZ_PATCH)
  122. ENTRY(WZ_PATCHINFO)
  123. ENTRY(WZ_SOURCE)
  124. ENTRY(WZ_TARGET)
  125. ENTRY(WZ_PATCHFILE)
  126. ENTRY(WZ_ASSEMBLY_ID_TAG)
  127. ENTRY(WZ_COMPRESSED)
  128. ENTRY(WZ_SUBSCRIPTION)
  129. ENTRY(WZ_SYNC_INTERVAL)
  130. ENTRY(WZ_INTERVAL_UNIT)
  131. ENTRY(WZ_SYNC_EVENT)
  132. ENTRY(WZ_DEMAND_CONNECTION)
  133. ENTRY(WZ_FILE)
  134. ENTRY(WZ_CAB)
  135. ENTRY(WZ_ASSEMBLY_NODE)
  136. ENTRY(WZ_APPLICATION_NODE)
  137. ENTRY(WZ_VERSIONWILDCARD)
  138. ENTRY(WZ_DESKTOP)
  139. ENTRY(WZ_DEPENDENCY)
  140. ENTRY(WZ_DEPENDENTASSEMBLY)
  141. ENTRY(WZ_INSTALL)
  142. ENTRY(WZ_INSTALL_TYPE)
  143. ENTRY(WZ_PLATFORM)
  144. ENTRY(WZ_PLATFORMINFO)
  145. ENTRY(WZ_OSVERSIONINFO)
  146. ENTRY(WZ_DOTNETVERSIONINFO)
  147. ENTRY(WZ_HREF)
  148. ENTRY(WZ_OS)
  149. ENTRY(WZ_MAJORVERSION)
  150. ENTRY(WZ_MINORVERSION)
  151. ENTRY(WZ_BUILDNUMBER)
  152. ENTRY(WZ_SERVICEPACKMAJOR)
  153. ENTRY(WZ_SERVICEPACKMINOR)
  154. ENTRY(WZ_SUITE)
  155. ENTRY(WZ_PRODUCTTYPE)
  156. ENTRY(WZ_SUPPORTEDRUNTIME)
  157. };
  158. CRITICAL_SECTION CAssemblyManifestImport::g_cs;
  159. // CLSID_XML DOM Document 3.0
  160. class __declspec(uuid("f6d90f11-9c73-11d3-b32e-00c04f990bb4")) private_MSXML_DOMDocument30;
  161. // Publics
  162. // ---------------------------------------------------------------------------
  163. // InitGlobalStringTable
  164. // ---------------------------------------------------------------------------
  165. HRESULT CAssemblyManifestImport::InitGlobalStringTable()
  166. {
  167. for (eStringTableId i = Name; i < MAX_STRINGS; i++)
  168. if (!(g_StringTable[i].bstr = ::SysAllocString(g_StringTable[i].pwz)))
  169. return E_OUTOFMEMORY;
  170. return S_OK;
  171. }
  172. // ---------------------------------------------------------------------------
  173. // FreeGlobalStringTable
  174. // ---------------------------------------------------------------------------
  175. HRESULT CAssemblyManifestImport::FreeGlobalStringTable()
  176. {
  177. for (eStringTableId i = Name; i <= MAX_STRINGS; i++)
  178. ::SysFreeString(g_StringTable[i].bstr);
  179. return S_OK;
  180. }
  181. // ---------------------------------------------------------------------------
  182. // CreateAssemblyManifestImport
  183. // ---------------------------------------------------------------------------
  184. STDAPI CreateAssemblyManifestImport(IAssemblyManifestImport** ppImport,
  185. LPCOLESTR pwzManifestFilePath, CDebugLog *pDbgLog, DWORD dwFlags)
  186. {
  187. HRESULT hr = S_OK;
  188. MAKE_ERROR_MACROS_STATIC(hr);
  189. CAssemblyManifestImportCLR * pImportCLR = NULL;
  190. CAssemblyManifestImport * pImportXML = NULL;
  191. IAssemblyManifestImport* pImport = NULL;
  192. IAssemblyIdentity * pAsmId=NULL;
  193. *ppImport = NULL;
  194. // BUGBUG - currently we sniff for "MZ" and assume it's a complib manifest.
  195. // This won't work when we start looking at Win32 PEs with embedded manifests.
  196. hr = CAssemblyManifestImport::IsCLRManifest(pwzManifestFilePath);
  197. IF_TRUE_EXIT(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), hr);
  198. IF_FAILED_EXIT(hr);
  199. if(hr == S_OK)
  200. {
  201. IF_ALLOC_FAILED_EXIT(pImportCLR = new(CAssemblyManifestImportCLR));
  202. hr = pImportCLR->Init(pwzManifestFilePath);
  203. IF_TRUE_EXIT(hr == HRESULT_FROM_WIN32(ERROR_BAD_FORMAT), hr); // do not assert
  204. IF_FAILED_EXIT(hr);
  205. pImport = (IAssemblyManifestImport*)pImportCLR;
  206. pImportCLR = NULL;
  207. }
  208. else //if (hr == S_FALSE)
  209. {
  210. #ifdef CONTAINER
  211. IF_FAILED_EXIT(CAssemblyManifestImport::IsContainer(pwzManifestFilePath));
  212. if (hr == S_OK)
  213. {
  214. IF_ALLOC_FAILED_EXIT(pImportXML = new (CAssemblyManifestImportContainer) (pDbgLog) );
  215. }
  216. else //if (hr == S_FALSE)
  217. {
  218. #endif
  219. IF_ALLOC_FAILED_EXIT(pImportXML = new (CAssemblyManifestImport) (pDbgLog) );
  220. #ifdef CONTAINER
  221. }
  222. #endif
  223. hr = pImportXML->Init(pwzManifestFilePath);
  224. IF_TRUE_EXIT(hr == HRESULT_FROM_WIN32(ERROR_BAD_FORMAT), hr); // do not assert
  225. IF_FAILED_EXIT(hr);
  226. pImport = (IAssemblyManifestImport*)pImportXML;
  227. pImportXML = NULL;
  228. }
  229. IF_FAILED_EXIT(pImport->GetAssemblyIdentity(&pAsmId));
  230. IF_TRUE_EXIT(hr != S_OK, HRESULT_FROM_WIN32(ERROR_BAD_FORMAT));
  231. *ppImport = pImport;
  232. pImport = NULL;
  233. exit:
  234. SAFERELEASE(pImport);
  235. SAFERELEASE(pAsmId);
  236. SAFERELEASE(pImportXML);
  237. SAFERELEASE(pImportCLR);
  238. return hr;
  239. }
  240. // ---------------------------------------------------------------------------
  241. // CreateAssemblyManifestImportFromXMLStream
  242. // ---------------------------------------------------------------------------
  243. STDAPI CreateAssemblyManifestImportFromXMLStream(IAssemblyManifestImport * * ppImport,
  244. IStream* piStream, CDebugLog * pDbgLog, DWORD dwFlags)
  245. {
  246. HRESULT hr = S_OK;
  247. MAKE_ERROR_MACROS_STATIC(hr);
  248. CAssemblyManifestImport* pImport = NULL;
  249. IAssemblyIdentity * pAsmId=NULL;
  250. IF_NULL_EXIT(ppImport, E_INVALIDARG);
  251. IF_NULL_EXIT(piStream, E_INVALIDARG);
  252. *ppImport = NULL;
  253. IF_ALLOC_FAILED_EXIT(pImport = new (CAssemblyManifestImport) (pDbgLog) );
  254. // load XML from IStream
  255. // call loaddocument directly, for now
  256. hr = pImport->LoadDocumentSync(piStream);
  257. IF_TRUE_EXIT(hr == HRESULT_FROM_WIN32(ERROR_BAD_FORMAT), hr); // do not assert
  258. IF_FAILED_EXIT(hr);
  259. IF_FAILED_EXIT(pImport->GetAssemblyIdentity(&pAsmId));
  260. IF_TRUE_EXIT(hr != S_OK, HRESULT_FROM_WIN32(ERROR_BAD_FORMAT));
  261. *ppImport = pImport;
  262. pImport = NULL;
  263. exit:
  264. SAFERELEASE(pImport);
  265. SAFERELEASE(pAsmId);
  266. return hr;
  267. }
  268. // ---------------------------------------------------------------------------
  269. // ctor
  270. // ---------------------------------------------------------------------------
  271. CAssemblyManifestImport::CAssemblyManifestImport(CDebugLog * pDbgLog)
  272. : _dwSig('TRPM'), _cRef(1), _hr(S_OK), _pAssemblyId(NULL), _pXMLDoc(NULL),
  273. _pXMLFileNodeList(NULL), _pXMLAssemblyNodeList(NULL), _pXMLPlatformNodeList(NULL),
  274. _nFileNodes(0), _nAssemblyNodes(0), _nPlatformNodes(0), _bstrManifestFilePath(NULL)
  275. {
  276. _pDbgLog = pDbgLog;
  277. if(pDbgLog)
  278. {
  279. pDbgLog->AddRef();
  280. }
  281. }
  282. // ---------------------------------------------------------------------------
  283. // dtor
  284. // ---------------------------------------------------------------------------
  285. CAssemblyManifestImport::~CAssemblyManifestImport()
  286. {
  287. SAFERELEASE(_pDbgLog);
  288. SAFERELEASE(_pAssemblyId);
  289. SAFERELEASE(_pXMLFileNodeList);
  290. SAFERELEASE(_pXMLAssemblyNodeList);
  291. SAFERELEASE(_pXMLPlatformNodeList);
  292. SAFERELEASE(_pXMLDoc);
  293. if (_bstrManifestFilePath)
  294. ::SysFreeString(_bstrManifestFilePath);
  295. }
  296. // ---------------------------------------------------------------------------
  297. // GetNextPlatform
  298. // ---------------------------------------------------------------------------
  299. HRESULT CAssemblyManifestImport::GetNextPlatform(DWORD nIndex, IManifestData **ppPlatformInfo)
  300. {
  301. IXMLDOMNode *pIDOMNode = NULL;
  302. IXMLDOMNode *pIDOMIdNode = NULL;
  303. IXMLDOMNode *pIDOMInfoNode = NULL;
  304. IXMLDOMNodeList *pXMLIdNodeList = NULL;
  305. IXMLDOMNodeList *pXMLInfoNodeList = NULL;
  306. LPASSEMBLY_IDENTITY pAssemblyId = NULL;
  307. LPMANIFEST_DATA pPlatformInfo = NULL;
  308. LPWSTR pwzBuf = NULL;
  309. DWORD ccBuf;
  310. LONG nMatchingNodes = 0;
  311. BOOL bFoundManagedPlatform = FALSE;
  312. IF_NULL_EXIT(ppPlatformInfo, E_INVALIDARG);
  313. *ppPlatformInfo = NULL;
  314. // Initialize the platform node list if necessary.
  315. if (!_pXMLPlatformNodeList)
  316. {
  317. if ((_hr = _pXMLDoc->selectNodes(g_StringTable[Platform].bstr,
  318. &_pXMLPlatformNodeList)) != S_OK)
  319. goto exit;
  320. IF_FAILED_EXIT(_pXMLPlatformNodeList->get_length(&_nPlatformNodes));
  321. IF_FAILED_EXIT(_pXMLPlatformNodeList->reset());
  322. }
  323. if (nIndex >= (DWORD) _nPlatformNodes)
  324. {
  325. if(_nPlatformNodes <= 0)
  326. DEBUGOUT(_pDbgLog, 1, L" LOG: No platform dependency found");
  327. // no more
  328. _hr = S_FALSE;
  329. goto exit;
  330. }
  331. IF_FAILED_EXIT(_pXMLPlatformNodeList->get_item(nIndex, &pIDOMNode));
  332. // first try assemblyIdentity
  333. IF_FAILED_EXIT(pIDOMNode->selectNodes(g_StringTable[AssemblyIdTag].bstr, &pXMLIdNodeList));
  334. IF_FAILED_EXIT(pXMLIdNodeList->get_length(&nMatchingNodes));
  335. IF_FALSE_EXIT_LOG1(nMatchingNodes <= 1, HRESULT_FROM_WIN32(ERROR_BAD_FORMAT),
  336. _pDbgLog, 0, L" ERR: %d assemblyIdentity nodes in a dependent platform node found. only 1 expected", nMatchingNodes);
  337. if (nMatchingNodes > 0)
  338. {
  339. bFoundManagedPlatform = TRUE;
  340. IF_FAILED_EXIT(pXMLIdNodeList->reset());
  341. IF_FAILED_EXIT(pXMLIdNodeList->get_item(0, &pIDOMIdNode));
  342. IF_FAILED_EXIT(XMLtoAssemblyIdentity(pIDOMIdNode, &pAssemblyId));
  343. IF_FAILED_EXIT(CreateManifestData(WZ_DATA_PLATFORM_MANAGED, &pPlatformInfo));
  344. IF_FAILED_EXIT(pPlatformInfo->Set(g_StringTable[AssemblyIdTag].pwz,
  345. pAssemblyId,
  346. sizeof(LPVOID),
  347. MAN_DATA_TYPE_IUNKNOWN_PTR));
  348. }
  349. SAFERELEASE(pXMLIdNodeList);
  350. // then try osVersionInfo
  351. IF_FAILED_EXIT(pIDOMNode->selectNodes(g_StringTable[OSVersionInfo].bstr, &pXMLIdNodeList));
  352. IF_FAILED_EXIT(pXMLIdNodeList->get_length(&nMatchingNodes));
  353. IF_FALSE_EXIT_LOG1(nMatchingNodes <= 1, HRESULT_FROM_WIN32(ERROR_BAD_FORMAT),
  354. _pDbgLog, 0, L" ERR: %d osVersionInfo nodes in a dependent platform node found. only 1 expected", nMatchingNodes);
  355. if (nMatchingNodes > 0)
  356. {
  357. IF_FALSE_EXIT_LOG(pPlatformInfo == NULL, HRESULT_FROM_WIN32(ERROR_BAD_FORMAT),
  358. _pDbgLog, 0, L" ERR: More than 1 of assemblyIdentity and osVersionInfo specified. only 1 expected");
  359. IF_FAILED_EXIT(pXMLIdNodeList->reset());
  360. IF_FAILED_EXIT(pXMLIdNodeList->get_item(0, &pIDOMIdNode));
  361. IF_FAILED_EXIT(CreateManifestData(WZ_DATA_PLATFORM_OS, &pPlatformInfo));
  362. IF_FAILED_EXIT(XMLtoOSVersionInfo(pIDOMIdNode, pPlatformInfo));
  363. }
  364. SAFERELEASE(pXMLIdNodeList);
  365. // then try .NetVersionInfo
  366. IF_FAILED_EXIT(pIDOMNode->selectNodes(g_StringTable[DotNetVersionInfo].bstr, &pXMLIdNodeList));
  367. IF_FAILED_EXIT(pXMLIdNodeList->get_length(&nMatchingNodes));
  368. IF_FALSE_EXIT_LOG1(nMatchingNodes <= 1, HRESULT_FROM_WIN32(ERROR_BAD_FORMAT),
  369. _pDbgLog, 0, L" ERR: %d .NetVersionInfo nodes in a dependent platform node found. only 1 expected", nMatchingNodes);
  370. if (nMatchingNodes > 0)
  371. {
  372. IF_FALSE_EXIT_LOG(pPlatformInfo == NULL, HRESULT_FROM_WIN32(ERROR_BAD_FORMAT),
  373. _pDbgLog, 0, L" ERR: More than 1 of assemblyIdentity, osVersionInfo, and .NetVersionInfo specified. only 1 expected");
  374. IF_FAILED_EXIT(pXMLIdNodeList->reset());
  375. IF_FAILED_EXIT(pXMLIdNodeList->get_item(0, &pIDOMIdNode));
  376. IF_FAILED_EXIT(CreateManifestData(WZ_DATA_PLATFORM_DOTNET, &pPlatformInfo));
  377. IF_FAILED_EXIT(XMLtoDotNetVersionInfo(pIDOMIdNode, pPlatformInfo));
  378. }
  379. IF_FALSE_EXIT_LOG(pPlatformInfo != NULL, HRESULT_FROM_WIN32(ERROR_BAD_FORMAT),
  380. _pDbgLog, 0, L" ERR: No assemblyIdentity, osVersionInfo, or .NetVersionInfo specified. 1 expected");
  381. IF_FAILED_EXIT(pIDOMNode->selectNodes(g_StringTable[PlatformInfo].bstr, &pXMLInfoNodeList));
  382. IF_FAILED_EXIT(pXMLInfoNodeList->get_length(&nMatchingNodes));
  383. IF_FALSE_EXIT_LOG1(nMatchingNodes <= 1, HRESULT_FROM_WIN32(ERROR_BAD_FORMAT),
  384. _pDbgLog, 0, L" ERR: %d platformInfo nodes in a dependent platform node found. only 1 expected", nMatchingNodes);
  385. IF_FALSE_EXIT_LOG(nMatchingNodes > 0, HRESULT_FROM_WIN32(ERROR_BAD_FORMAT),
  386. _pDbgLog, 0, L" ERR: No platformInfo nodes in a dependent platform node found");
  387. IF_FAILED_EXIT(pXMLInfoNodeList->reset());
  388. IF_FAILED_EXIT(pXMLInfoNodeList->get_item(0, &pIDOMInfoNode));
  389. // ISSUE? is friendlyName optional? ....
  390. IF_FAILED_EXIT(ParseAttribute(pIDOMInfoNode, g_StringTable[FriendlyName].bstr,
  391. &pwzBuf, &ccBuf));
  392. IF_FALSE_EXIT_LOG1(_hr == S_OK, HRESULT_FROM_WIN32(ERROR_BAD_FORMAT),
  393. _pDbgLog, 0, L" ERR: %s attribute missing in a dependent platform node", g_StringTable[FriendlyName].pwz);
  394. IF_FAILED_EXIT(pPlatformInfo->Set(g_StringTable[FriendlyName].pwz,
  395. (LPVOID) pwzBuf,
  396. ccBuf*sizeof(WCHAR),
  397. MAN_DATA_TYPE_LPWSTR));
  398. SAFEDELETEARRAY(pwzBuf);
  399. // ISSUE? href could be optional...
  400. IF_FAILED_EXIT(ParseAttribute(pIDOMInfoNode, g_StringTable[Href].bstr, &pwzBuf, &ccBuf));
  401. IF_FALSE_EXIT_LOG1(_hr == S_OK, HRESULT_FROM_WIN32(ERROR_BAD_FORMAT),
  402. _pDbgLog, 0, L" ERR: %s attribute missing in a dependent platform node", g_StringTable[Href].pwz);
  403. IF_FAILED_EXIT(pPlatformInfo->Set(g_StringTable[Href].pwz,
  404. (LPVOID) pwzBuf,
  405. ccBuf*sizeof(WCHAR),
  406. MAN_DATA_TYPE_LPWSTR));
  407. SAFEDELETEARRAY(pwzBuf);
  408. SAFERELEASE(pXMLInfoNodeList);
  409. SAFERELEASE(pIDOMInfoNode);
  410. IF_FAILED_EXIT(pIDOMNode->selectNodes(g_StringTable[Install].bstr, &pXMLInfoNodeList));
  411. IF_FAILED_EXIT(pXMLInfoNodeList->get_length(&nMatchingNodes));
  412. IF_FALSE_EXIT_LOG1(nMatchingNodes <= 1, HRESULT_FROM_WIN32(ERROR_BAD_FORMAT),
  413. _pDbgLog, 0, L" ERR: %d install nodes in a dependent platform node found. only 1 expected", nMatchingNodes);
  414. IF_FALSE_EXIT_LOG((bFoundManagedPlatform || nMatchingNodes <= 0), HRESULT_FROM_WIN32(ERROR_BAD_FORMAT),
  415. _pDbgLog, 0, L" ERR: The install node can only be specified for a managed dependent platform node");
  416. // install codebase is optional
  417. if (nMatchingNodes > 0)
  418. {
  419. IF_FAILED_EXIT(pXMLInfoNodeList->reset());
  420. IF_FAILED_EXIT(pXMLInfoNodeList->get_item(0, &pIDOMInfoNode));
  421. IF_FAILED_EXIT(ParseAttribute(pIDOMInfoNode, g_StringTable[Codebase].bstr, &pwzBuf, &ccBuf));
  422. IF_FALSE_EXIT_LOG1(_hr == S_OK, HRESULT_FROM_WIN32(ERROR_BAD_FORMAT),
  423. _pDbgLog, 0, L" ERR: %s attribute missing in a dependent platform node", g_StringTable[Codebase].pwz);
  424. IF_FAILED_EXIT(pPlatformInfo->Set(g_StringTable[Codebase].pwz,
  425. (LPVOID) pwzBuf,
  426. ccBuf*sizeof(WCHAR),
  427. MAN_DATA_TYPE_LPWSTR));
  428. SAFEDELETEARRAY(pwzBuf);
  429. }
  430. // Handout refcounted manifest data.
  431. *ppPlatformInfo = pPlatformInfo;
  432. pPlatformInfo = NULL;
  433. _hr = S_OK;
  434. exit:
  435. SAFEDELETEARRAY(pwzBuf);
  436. SAFERELEASE(pAssemblyId);
  437. SAFERELEASE(pIDOMInfoNode);
  438. SAFERELEASE(pIDOMIdNode);
  439. SAFERELEASE(pIDOMNode);
  440. SAFERELEASE(pXMLInfoNodeList);
  441. SAFERELEASE(pXMLIdNodeList);
  442. SAFERELEASE(pPlatformInfo);
  443. return _hr;
  444. }
  445. // ---------------------------------------------------------------------------
  446. // XMLtoOSVersionInfo
  447. // ---------------------------------------------------------------------------
  448. HRESULT CAssemblyManifestImport::XMLtoOSVersionInfo(IXMLDOMNode *pIDOMNode, LPMANIFEST_DATA pPlatformInfo)
  449. {
  450. IXMLDOMNode *pIDOMVersionNode = NULL;
  451. IXMLDOMNodeList *pXMLVersionNodeList = NULL;
  452. LPMANIFEST_DATA pOSInfo = NULL;
  453. LONG nNodes = 0;
  454. LPWSTR pwzBuf = NULL;
  455. DWORD ccBuf = 0;
  456. BOOL bFoundAtLeastOneAttribute = FALSE;
  457. IF_FAILED_EXIT(pIDOMNode->selectNodes(g_StringTable[OS].bstr, &pXMLVersionNodeList));
  458. IF_FAILED_EXIT(pXMLVersionNodeList->get_length(&nNodes));
  459. IF_FALSE_EXIT_LOG(nNodes > 0, HRESULT_FROM_WIN32(ERROR_BAD_FORMAT),
  460. _pDbgLog, 0, L" ERR: No os nodes in a dependent platform OSVersionInfo node found. At least 1 expected");
  461. IF_FAILED_EXIT(pXMLVersionNodeList->reset());
  462. for (LONG lIndex = 0; lIndex < nNodes; lIndex++)
  463. {
  464. IF_FAILED_EXIT(pXMLVersionNodeList->get_item(lIndex, &pIDOMVersionNode));
  465. IF_FAILED_EXIT(CreateManifestData(WZ_DATA_OSVERSIONINFO, &pOSInfo));
  466. bFoundAtLeastOneAttribute = FALSE;
  467. for (eStringTableId i = MajorVersion; i <= ProductType; i++)
  468. {
  469. IF_FAILED_EXIT(ParseAttribute(pIDOMVersionNode, g_StringTable[i].bstr,
  470. &pwzBuf, &ccBuf));
  471. if (_hr != S_FALSE)
  472. {
  473. bFoundAtLeastOneAttribute = TRUE;
  474. if (i >= MajorVersion && i <= ServicePackMinor)
  475. {
  476. LPWSTR pwzStopString = NULL;
  477. int num = wcstol(pwzBuf, &pwzStopString, 10);
  478. IF_FALSE_EXIT_LOG1(num >= 0, HRESULT_FROM_WIN32(ERROR_BAD_FORMAT),
  479. _pDbgLog, 0, L" ERR: Invalid %s attribute value less than zero", g_StringTable[i].pwz);
  480. DWORD dwValue = num;
  481. if (i >= ServicePackMajor && i <= ServicePackMinor)
  482. {
  483. // WORD
  484. #define WORD_MAX 0xffff
  485. IF_FALSE_EXIT_LOG1(dwValue <= WORD_MAX, HRESULT_FROM_WIN32(ERROR_BAD_FORMAT),
  486. _pDbgLog, 0, L" ERR: Invalid %s attribute value greater than WORD size", g_StringTable[i].pwz);
  487. }
  488. //else
  489. // DWORD
  490. IF_FAILED_EXIT(pOSInfo->Set(g_StringTable[i].pwz,
  491. (LPVOID) &dwValue,
  492. sizeof(dwValue),
  493. MAN_DATA_TYPE_DWORD));
  494. }
  495. else
  496. {
  497. IF_FAILED_EXIT(pOSInfo->Set(g_StringTable[i].pwz,
  498. (LPVOID) pwzBuf,
  499. ccBuf*sizeof(WCHAR),
  500. MAN_DATA_TYPE_LPWSTR));
  501. }
  502. SAFEDELETEARRAY(pwzBuf);
  503. }
  504. }
  505. IF_FALSE_EXIT_LOG(bFoundAtLeastOneAttribute, HRESULT_FROM_WIN32(ERROR_BAD_FORMAT),
  506. _pDbgLog, 0, L" ERR: No known os attribute in a dependent platform OSVersionInfo node found. At least 1 expected");
  507. IF_FAILED_EXIT((static_cast<CManifestData*>(pPlatformInfo))->Set(lIndex,
  508. pOSInfo,
  509. sizeof(LPVOID),
  510. MAN_DATA_TYPE_IUNKNOWN_PTR));
  511. SAFERELEASE(pOSInfo);
  512. SAFERELEASE(pIDOMVersionNode);
  513. }
  514. exit:
  515. SAFEDELETEARRAY(pwzBuf);
  516. SAFERELEASE(pOSInfo);
  517. SAFERELEASE(pIDOMVersionNode);
  518. SAFERELEASE(pXMLVersionNodeList);
  519. return _hr;
  520. }
  521. // ---------------------------------------------------------------------------
  522. // XMLtoDotNetVersionInfo
  523. // ---------------------------------------------------------------------------
  524. HRESULT CAssemblyManifestImport::XMLtoDotNetVersionInfo(IXMLDOMNode *pIDOMNode, LPMANIFEST_DATA pPlatformInfo)
  525. {
  526. IXMLDOMNode *pIDOMVersionNode = NULL;
  527. IXMLDOMNodeList *pXMLVersionNodeList = NULL;
  528. LONG nNodes = 0;
  529. LPWSTR pwzBuf = NULL;
  530. DWORD ccBuf = 0;
  531. IF_FAILED_EXIT(pIDOMNode->selectNodes(g_StringTable[SupportedRuntime].bstr, &pXMLVersionNodeList));
  532. IF_FAILED_EXIT(pXMLVersionNodeList->get_length(&nNodes));
  533. IF_FALSE_EXIT_LOG(nNodes > 0, HRESULT_FROM_WIN32(ERROR_BAD_FORMAT),
  534. _pDbgLog, 0, L" ERR: No supportedRuntime nodes in a dependent platform .NetVersionInfo node found. At least 1 expected");
  535. IF_FAILED_EXIT(pXMLVersionNodeList->reset());
  536. for (LONG lIndex = 0; lIndex < nNodes; lIndex++)
  537. {
  538. IF_FAILED_EXIT(pXMLVersionNodeList->get_item(lIndex, &pIDOMVersionNode));
  539. IF_FAILED_EXIT(ParseAttribute(pIDOMVersionNode, g_StringTable[Version].bstr,
  540. &pwzBuf, &ccBuf));
  541. IF_FALSE_EXIT_LOG1(_hr != S_FALSE, HRESULT_FROM_WIN32(ERROR_BAD_FORMAT),
  542. _pDbgLog, 0, L" ERR: No %s attribute in a dependent platform .NetVersionInfo node found", g_StringTable[Version].pwz);
  543. IF_FAILED_EXIT((static_cast<CManifestData*>(pPlatformInfo))->Set(lIndex,
  544. (LPVOID) pwzBuf,
  545. ccBuf*sizeof(WCHAR),
  546. MAN_DATA_TYPE_LPWSTR));
  547. SAFEDELETEARRAY(pwzBuf);
  548. SAFERELEASE(pIDOMVersionNode);
  549. }
  550. exit:
  551. SAFEDELETEARRAY(pwzBuf);
  552. SAFERELEASE(pIDOMVersionNode);
  553. SAFERELEASE(pXMLVersionNodeList);
  554. return _hr;
  555. }
  556. // ---------------------------------------------------------------------------
  557. // GetSubscriptionInfo
  558. // returns defaults if not specified in the manifest
  559. // ---------------------------------------------------------------------------
  560. HRESULT CAssemblyManifestImport::GetSubscriptionInfo(IManifestInfo **ppSubsInfo)
  561. {
  562. DWORD dwInterval = DW_DEFAULT_SYNC_INTERVAL;
  563. DWORD dwUnit = SUBSCRIPTION_INTERVAL_UNIT_HOURS;
  564. DWORD dwSyncEvent = SUBSCRIPTION_SYNC_EVENT_NONE;
  565. BOOL bEventDemandNet = FALSE; //��no�� (default)
  566. IXMLDOMNode *pIDOMNode = NULL;
  567. IXMLDOMNodeList *pXMLMatchingNodeList = NULL;
  568. IManifestInfo *pSubsInfo = NULL;
  569. LPWSTR pwzBuf = NULL;
  570. DWORD ccBuf;
  571. LONG nMatchingNodes = 0;
  572. IF_NULL_EXIT(ppSubsInfo, E_INVALIDARG);
  573. *ppSubsInfo = NULL;
  574. IF_FAILED_EXIT(_pXMLDoc->selectNodes(g_StringTable[Subscription].bstr,
  575. &pXMLMatchingNodeList));
  576. IF_FAILED_EXIT(pXMLMatchingNodeList->get_length(&nMatchingNodes));
  577. IF_FALSE_EXIT_LOG1(nMatchingNodes <= 1, HRESULT_FROM_WIN32(ERROR_BAD_FORMAT),
  578. _pDbgLog, 0, L" ERR: %d subscription nodes found. only 1 expected", nMatchingNodes);
  579. if (nMatchingNodes)
  580. {
  581. IF_FAILED_EXIT(pXMLMatchingNodeList->reset());
  582. IF_FAILED_EXIT(pXMLMatchingNodeList->get_item(0, &pIDOMNode));
  583. IF_FAILED_EXIT(ParseAttribute(pIDOMNode, g_StringTable[SynchronizeInterval].bstr,
  584. &pwzBuf, &ccBuf));
  585. if (_hr == S_OK)
  586. {
  587. LPWSTR pwzStopString = NULL;
  588. int num = wcstol(pwzBuf, &pwzStopString, 10);
  589. SAFEDELETEARRAY(pwzBuf);
  590. if (num > 0)
  591. {
  592. dwInterval = (DWORD) num; // ignore <= 0 intervals
  593. // only check interval unit if valid interval is specified
  594. IF_FAILED_EXIT(ParseAttribute(pIDOMNode, g_StringTable[IntervalUnit].bstr,
  595. &pwzBuf, &ccBuf));
  596. if (_hr == S_OK)
  597. {
  598. // note: case sensitive comparison
  599. IF_FAILED_EXIT(FusionCompareString(pwzBuf, WZ_MINUTES, 0));
  600. if(_hr == S_OK)
  601. {
  602. dwUnit = SUBSCRIPTION_INTERVAL_UNIT_MINUTES;
  603. }
  604. else
  605. {
  606. IF_FAILED_EXIT(FusionCompareString(pwzBuf, WZ_DAYS, 0));
  607. if(_hr == S_OK)
  608. dwUnit = SUBSCRIPTION_INTERVAL_UNIT_DAYS;
  609. }
  610. //else default
  611. }
  612. }
  613. }
  614. else
  615. DEBUGOUT(_pDbgLog, 1, L" LOG: No synchronizeInterval specified in the subscription node found. Default interval is assumed");
  616. SAFEDELETEARRAY(pwzBuf);
  617. IF_FAILED_EXIT(ParseAttribute(pIDOMNode, g_StringTable[SynchronizeEvent].bstr,
  618. &pwzBuf, &ccBuf));
  619. if (_hr == S_OK)
  620. {
  621. // note: case sensitive comparison
  622. IF_FAILED_EXIT(FusionCompareString(pwzBuf, WZ_ONAPPLICATIONSTARTUP, 0));
  623. if(_hr == S_OK)
  624. dwSyncEvent = SUBSCRIPTION_SYNC_EVENT_ON_APP_STARTUP;
  625. //else default
  626. }
  627. SAFEDELETEARRAY(pwzBuf);
  628. if (dwSyncEvent != SUBSCRIPTION_SYNC_EVENT_NONE)
  629. {
  630. // only check demand connection if an event is specified
  631. IF_FAILED_EXIT(ParseAttribute(pIDOMNode, g_StringTable[EventDemandConnection].bstr,
  632. &pwzBuf, &ccBuf));
  633. if (_hr == S_OK)
  634. {
  635. // note: case sensitive comparison
  636. IF_FAILED_EXIT(FusionCompareString(pwzBuf, WZ_YES, 0));
  637. if(_hr == S_OK)
  638. bEventDemandNet = TRUE;
  639. //else default
  640. }
  641. SAFEDELETEARRAY(pwzBuf);
  642. }
  643. }
  644. IF_FAILED_EXIT(CreateManifestInfo(MAN_INFO_SUBSCRIPTION, &pSubsInfo));
  645. IF_FAILED_EXIT(pSubsInfo->Set(MAN_INFO_SUBSCRIPTION_SYNCHRONIZE_INTERVAL,
  646. (LPVOID) &dwInterval,
  647. sizeof(dwInterval),
  648. MAN_INFO_FLAG_DWORD));
  649. IF_FAILED_EXIT(pSubsInfo->Set(MAN_INFO_SUBSCRIPTION_INTERVAL_UNIT,
  650. (LPVOID) &dwUnit,
  651. sizeof(dwUnit),
  652. MAN_INFO_FLAG_ENUM));
  653. IF_FAILED_EXIT(pSubsInfo->Set(MAN_INFO_SUBSCRIPTION_SYNCHRONIZE_EVENT,
  654. (LPVOID) &dwSyncEvent,
  655. sizeof(dwSyncEvent),
  656. MAN_INFO_FLAG_ENUM));
  657. IF_FAILED_EXIT(pSubsInfo->Set(MAN_INFO_SUBSCRIPTION_EVENT_DEMAND_CONNECTION,
  658. (LPVOID) &bEventDemandNet,
  659. sizeof(bEventDemandNet),
  660. MAN_INFO_FLAG_BOOL));
  661. // Handout refcounted manifest info.
  662. *ppSubsInfo = pSubsInfo;
  663. pSubsInfo = NULL;
  664. _hr = S_OK;
  665. exit:
  666. SAFEDELETEARRAY(pwzBuf);
  667. SAFERELEASE(pIDOMNode);
  668. SAFERELEASE(pXMLMatchingNodeList);
  669. SAFERELEASE(pSubsInfo);
  670. return _hr;
  671. }
  672. // ---------------------------------------------------------------------------
  673. // GetNextFile
  674. // ---------------------------------------------------------------------------
  675. HRESULT CAssemblyManifestImport::GetNextFile(DWORD nIndex, IManifestInfo **ppAssemblyFile)
  676. {
  677. LPWSTR pwzBuf = NULL;
  678. DWORD ccBuf = 0;
  679. CString sFileName;
  680. CString sFileHash;
  681. IXMLDOMNode *pIDOMNode = NULL;
  682. IManifestInfo *pAssemblyFile = NULL;
  683. // Initialize the file node list if necessary.
  684. if (!_pXMLFileNodeList)
  685. {
  686. if ((_hr = _pXMLDoc->selectNodes(g_StringTable[FileNode].bstr,
  687. &_pXMLFileNodeList)) != S_OK)
  688. goto exit;
  689. IF_FAILED_EXIT(_pXMLFileNodeList->get_length(&_nFileNodes));
  690. IF_FAILED_EXIT(_pXMLFileNodeList->reset());
  691. }
  692. if (nIndex >= (DWORD) _nFileNodes)
  693. {
  694. _hr = S_FALSE;
  695. goto exit;
  696. }
  697. if ((_hr = _pXMLFileNodeList->get_item(nIndex, &pIDOMNode)) != S_OK)
  698. goto exit;
  699. IF_FAILED_EXIT(CreateAssemblyFileEx (&pAssemblyFile, pIDOMNode));
  700. *ppAssemblyFile = pAssemblyFile;
  701. pAssemblyFile = NULL;
  702. _hr = S_OK;
  703. exit:
  704. SAFERELEASE(pAssemblyFile);
  705. SAFERELEASE(pIDOMNode);
  706. return _hr;
  707. }
  708. // ---------------------------------------------------------------------------
  709. // QueryFile
  710. // return:
  711. // S_OK
  712. // S_FALSE -not exist or not match or missing attribute
  713. // E_*
  714. // ---------------------------------------------------------------------------
  715. HRESULT CAssemblyManifestImport::QueryFile(LPCOLESTR pcwzFileName, IManifestInfo **ppAssemblyFile)
  716. {
  717. CString sQueryString;
  718. BSTR bstrtQueryString = NULL;
  719. IXMLDOMNode *pIDOMNode = NULL;
  720. IXMLDOMNodeList *pXMLMatchingFileNodeList = NULL;
  721. IManifestInfo *pAssemblyFile = NULL;
  722. LONG nMatchingFileNodes = 0;
  723. IF_NULL_EXIT(pcwzFileName, E_INVALIDARG);
  724. IF_NULL_EXIT(ppAssemblyFile, E_INVALIDARG);
  725. *ppAssemblyFile = NULL;
  726. // XPath query string: "file[@name = "path\filename"]"
  727. IF_FAILED_EXIT(sQueryString.Assign(WZ_FILE_QUERYSTRING_PREFIX));
  728. IF_FAILED_EXIT(sQueryString.Append((LPWSTR)pcwzFileName));
  729. IF_FAILED_EXIT(sQueryString.Append(WZ_QUERYSTRING_SUFFIX));
  730. IF_ALLOC_FAILED_EXIT(bstrtQueryString = ::SysAllocString(sQueryString._pwz));
  731. if ((_hr = _pXMLDoc->selectNodes(bstrtQueryString, &pXMLMatchingFileNodeList)) != S_OK)
  732. goto exit;
  733. IF_FAILED_EXIT( pXMLMatchingFileNodeList->get_length(&nMatchingFileNodes));
  734. IF_FALSE_EXIT(nMatchingFileNodes <= 1, HRESULT_FROM_WIN32(ERROR_BAD_FORMAT)); // multiple file callouts having the exact same file name/path within a single manifest...
  735. IF_TRUE_EXIT(nMatchingFileNodes <= 0, S_FALSE);
  736. IF_FAILED_EXIT(pXMLMatchingFileNodeList->reset());
  737. IF_FALSE_EXIT( pXMLMatchingFileNodeList->get_item(0, &pIDOMNode) == S_OK, E_FAIL);
  738. IF_FAILED_EXIT(CreateAssemblyFileEx (&pAssemblyFile, pIDOMNode));
  739. *ppAssemblyFile = pAssemblyFile;
  740. pAssemblyFile = NULL;
  741. _hr = S_OK;
  742. exit:
  743. if (bstrtQueryString)
  744. ::SysFreeString(bstrtQueryString);
  745. SAFERELEASE(pIDOMNode);
  746. SAFERELEASE(pXMLMatchingFileNodeList);
  747. SAFERELEASE(pAssemblyFile);
  748. return _hr;
  749. }
  750. // ---------------------------------------------------------------------------
  751. // CreateAssemblyFileEx
  752. // ---------------------------------------------------------------------------
  753. HRESULT CAssemblyManifestImport::CreateAssemblyFileEx(IManifestInfo **ppAssemblyFile, IXMLDOMNode *pIDOMNode)
  754. {
  755. LPWSTR pwzBuf;
  756. DWORD ccBuf;
  757. BOOL compressed;
  758. CString sFileName, sFileHash;
  759. IManifestInfo *pAssemblyFile=NULL;
  760. //Create new ManifestInfo
  761. IF_FAILED_EXIT(CreateManifestInfo(MAN_INFO_FILE, &pAssemblyFile));
  762. // Parse out relevent information from IDOMNode
  763. IF_FAILED_EXIT(ParseAttribute(pIDOMNode, g_StringTable[FileName].bstr, &pwzBuf, &ccBuf));
  764. // BUGBUG:: IF_FALSE_EXIT(_hr == S_OK, E_FAIL);
  765. sFileName.TakeOwnership(pwzBuf, ccBuf);
  766. IF_FAILED_EXIT(ParseAttribute(pIDOMNode, g_StringTable[FileHash].bstr,
  767. &pwzBuf, &ccBuf));
  768. // BUGBUG:: IF_FALSE_EXIT(_hr == S_OK, E_FAIL);
  769. sFileHash.TakeOwnership(pwzBuf, ccBuf);
  770. // Set all aboved pased info into the AssemblyFIle
  771. IF_FAILED_EXIT(pAssemblyFile->Set(MAN_INFO_ASM_FILE_NAME, sFileName._pwz,
  772. sFileName.ByteCount(), MAN_INFO_FLAG_LPWSTR));
  773. IF_FAILED_EXIT(pAssemblyFile->Set(MAN_INFO_ASM_FILE_HASH, sFileHash._pwz,
  774. sFileHash.ByteCount(), MAN_INFO_FLAG_LPWSTR));
  775. *ppAssemblyFile = pAssemblyFile;
  776. pAssemblyFile = NULL;
  777. exit:
  778. SAFERELEASE (pAssemblyFile);
  779. return _hr;
  780. }
  781. // ---------------------------------------------------------------------------
  782. // XMLtoAssemblyIdentiy IXMLDOMDocument2 *pXMLDoc
  783. // ---------------------------------------------------------------------------
  784. HRESULT CAssemblyManifestImport::XMLtoAssemblyIdentity(IXMLDOMNode *pIDOMNode, LPASSEMBLY_IDENTITY *ppAssemblyId)
  785. {
  786. HRESULT hr;
  787. MAKE_ERROR_MACROS_STATIC(hr);
  788. LPASSEMBLY_IDENTITY pAssemblyId = NULL;
  789. LPWSTR pwzBuf = NULL;
  790. DWORD ccBuf = 0;
  791. IF_FAILED_EXIT(CreateAssemblyIdentity(&pAssemblyId, 0));
  792. for (eStringTableId i = Name; i <= Type; i++)
  793. {
  794. CString sBuf;
  795. IF_FAILED_EXIT(ParseAttribute(pIDOMNode, g_StringTable[i].bstr,
  796. &pwzBuf, &ccBuf));
  797. if (hr != S_FALSE)
  798. {
  799. sBuf.TakeOwnership(pwzBuf, ccBuf);
  800. IF_FAILED_EXIT(pAssemblyId->SetAttribute(g_StringTable[i].pwz,
  801. sBuf._pwz, sBuf._cc));
  802. }
  803. }
  804. *ppAssemblyId = pAssemblyId;
  805. pAssemblyId = NULL;
  806. hr = S_OK;
  807. exit:
  808. SAFERELEASE (pAssemblyId);
  809. return hr;
  810. }
  811. // ---------------------------------------------------------------------------
  812. // GetNextAssembly
  813. // ---------------------------------------------------------------------------
  814. HRESULT CAssemblyManifestImport::GetNextAssembly(DWORD nIndex, IManifestInfo **ppDependAsm)
  815. {
  816. CString sCodebase;
  817. DWORD dwType = DEPENDENT_ASM_INSTALL_TYPE_NORMAL;
  818. IXMLDOMNode *pIDOMNode = NULL;
  819. IXMLDOMNode *pIDOMCodebaseNode = NULL;
  820. IXMLDOMNodeList *pXMLCodebaseNodeList = NULL;
  821. LPASSEMBLY_IDENTITY pAssemblyId = NULL;
  822. IManifestInfo *pDependAsm = NULL;
  823. LPWSTR pwzBuf = NULL;
  824. DWORD ccBuf = NULL;
  825. LONG nCodebaseNodes = 0;
  826. IF_NULL_EXIT(ppDependAsm, E_INVALIDARG);
  827. *ppDependAsm = NULL;
  828. // Initialize the assembly node list if necessary.
  829. if (!_pXMLAssemblyNodeList)
  830. {
  831. if ((_hr = _pXMLDoc->selectNodes(g_StringTable[DependentAssemblyNode].bstr,
  832. &_pXMLAssemblyNodeList)) != S_OK)
  833. goto exit;
  834. IF_FAILED_EXIT(_pXMLAssemblyNodeList->get_length(&_nAssemblyNodes));
  835. IF_FAILED_EXIT(_pXMLAssemblyNodeList->reset());
  836. }
  837. if (nIndex >= (DWORD) _nAssemblyNodes)
  838. {
  839. _hr = S_FALSE;
  840. goto exit;
  841. }
  842. IF_FAILED_EXIT(_pXMLAssemblyNodeList->get_item(nIndex, &pIDOMNode));
  843. IF_FAILED_EXIT(XMLtoAssemblyIdentity(pIDOMNode, &pAssemblyId));
  844. // note: check for multiple qualified nodes. As the use of "../install" XPath expression
  845. // can result in either preceding _or_ following siblings with node name "install",
  846. // this is to ensure codebase is not defined > 1 for this particular dependent
  847. // BUGBUG: should just take the 1st codebase and ignore all others?
  848. if ((_hr = pIDOMNode->selectNodes(g_StringTable[DependentAssemblyCodebase].bstr, &pXMLCodebaseNodeList)) != S_OK)
  849. goto exit;
  850. IF_FAILED_EXIT(pXMLCodebaseNodeList->get_length(&nCodebaseNodes));
  851. IF_FALSE_EXIT(nCodebaseNodes <= 1, HRESULT_FROM_WIN32(ERROR_BAD_FORMAT)); // multiple codebases for a single dependent assembly identity...
  852. IF_FAILED_EXIT(CreateManifestInfo(MAN_INFO_DEPENDTANT_ASM,&pDependAsm));
  853. if (nCodebaseNodes)
  854. {
  855. IF_FAILED_EXIT(pXMLCodebaseNodeList->reset());
  856. IF_FALSE_EXIT(pXMLCodebaseNodeList->get_item(0, &pIDOMCodebaseNode) == S_OK, E_FAIL);
  857. IF_FAILED_EXIT(ParseAttribute(pIDOMCodebaseNode, g_StringTable[Codebase].bstr,
  858. &pwzBuf, &ccBuf));
  859. if(_hr == S_OK) // BUGBUG: do we want to exit if S_FALSE ??
  860. {
  861. sCodebase.TakeOwnership(pwzBuf, ccBuf);
  862. IF_FAILED_EXIT(pDependAsm->Set(MAN_INFO_DEPENDENT_ASM_CODEBASE, sCodebase._pwz,
  863. sCodebase.ByteCount(), MAN_INFO_FLAG_LPWSTR));
  864. }
  865. IF_FAILED_EXIT(ParseAttribute(pIDOMCodebaseNode, g_StringTable[InstallType].bstr,
  866. &pwzBuf, &ccBuf));
  867. if (_hr == S_OK)
  868. {
  869. // note: case sensitive comparison
  870. IF_FAILED_EXIT(FusionCompareString(pwzBuf, WZ_REQUIRED, 0));
  871. if(_hr == S_OK)
  872. dwType = DEPENDENT_ASM_INSTALL_TYPE_REQUIRED;
  873. #ifdef DEVMODE
  874. else
  875. {
  876. IF_FAILED_EXIT(FusionCompareString(pwzBuf, WZ_DEVSYNC, 0));
  877. if(_hr == S_OK)
  878. dwType = DEPENDENT_ASM_INSTALL_TYPE_DEVSYNC;
  879. }
  880. #endif
  881. }
  882. SAFEDELETEARRAY(pwzBuf);
  883. IF_FAILED_EXIT(pDependAsm->Set(MAN_INFO_DEPENDENT_ASM_TYPE, (LPVOID)&dwType, sizeof(dwType), MAN_INFO_FLAG_ENUM));
  884. }
  885. // Handout refcounted assemblyid.
  886. IF_FAILED_EXIT(pDependAsm->Set(MAN_INFO_DEPENDENT_ASM_ID, &pAssemblyId, sizeof(LPVOID), MAN_INFO_FLAG_IUNKNOWN_PTR));
  887. *ppDependAsm = pDependAsm;
  888. pDependAsm = NULL;
  889. _hr = S_OK;
  890. exit:
  891. SAFERELEASE(pIDOMCodebaseNode);
  892. SAFERELEASE(pXMLCodebaseNodeList);
  893. SAFERELEASE(pIDOMNode);
  894. SAFERELEASE(pAssemblyId);
  895. SAFERELEASE(pDependAsm);
  896. return _hr;
  897. }
  898. // ---------------------------------------------------------------------------
  899. // GetAssemblyIdentity
  900. // ---------------------------------------------------------------------------
  901. HRESULT CAssemblyManifestImport::GetAssemblyIdentity(LPASSEMBLY_IDENTITY *ppAssemblyId)
  902. {
  903. IXMLDOMNode *pIDOMNode = NULL;
  904. LPASSEMBLY_IDENTITY pAssemblyId = NULL;
  905. LPWSTR pwzBuf = NULL;
  906. DWORD ccBuf = 0;
  907. if (_pAssemblyId)
  908. {
  909. *ppAssemblyId = _pAssemblyId;
  910. (*ppAssemblyId)->AddRef();
  911. _hr = S_OK;
  912. goto exit;
  913. }
  914. if ((_hr = _pXMLDoc->selectSingleNode(g_StringTable[AssemblyId].bstr,
  915. &pIDOMNode)) != S_OK)
  916. goto exit;
  917. IF_FAILED_EXIT(XMLtoAssemblyIdentity(pIDOMNode, &pAssemblyId));
  918. *ppAssemblyId = pAssemblyId;
  919. (*ppAssemblyId)->AddRef();
  920. // do not release AsmId, cache it
  921. _pAssemblyId = pAssemblyId;
  922. exit:
  923. SAFERELEASE(pIDOMNode);
  924. return _hr;
  925. }
  926. // ---------------------------------------------------------------------------
  927. // GetManifestApplicationInfo
  928. // ---------------------------------------------------------------------------
  929. HRESULT CAssemblyManifestImport::GetManifestApplicationInfo(IManifestInfo ** ppAppInfo)
  930. {
  931. IXMLDOMNode *pIDOMNode = NULL;
  932. IManifestInfo *pAppInfo = NULL;
  933. LPWSTR pwzBuf = NULL;
  934. DWORD ccBuf = 0;
  935. IF_NULL_EXIT(ppAppInfo, E_INVALIDARG);
  936. *ppAppInfo = NULL;
  937. IF_FAILED_EXIT(_pXMLDoc->selectSingleNode(g_StringTable[ShellState].bstr, &pIDOMNode));
  938. IF_TRUE_EXIT(_hr != S_OK, _hr);
  939. IF_FAILED_EXIT(CreateManifestInfo(MAN_INFO_APPLICATION, &pAppInfo));
  940. for (eStringTableId i = FriendlyName; i <= HotKey; i++)
  941. {
  942. CString sBuf;
  943. IF_FAILED_EXIT(ParseAttribute(pIDOMNode, g_StringTable[i].bstr, &pwzBuf, &ccBuf));
  944. if (_hr != S_FALSE)
  945. {
  946. IF_FAILED_EXIT(sBuf.TakeOwnership(pwzBuf, ccBuf));
  947. IF_FAILED_EXIT(pAppInfo->Set(MAN_INFO_APPLICATION_FRIENDLYNAME+i-FriendlyName,
  948. sBuf._pwz, sBuf.ByteCount(), MAN_INFO_FLAG_LPWSTR));
  949. }
  950. }
  951. IF_FAILED_EXIT(_pXMLDoc->selectSingleNode(g_StringTable[Activation].bstr, &pIDOMNode));
  952. if(_hr == S_OK)
  953. {
  954. for (eStringTableId i = AssemblyName; i <= AssemblyArgs; i++)
  955. {
  956. CString sBuf;
  957. IF_FAILED_EXIT(ParseAttribute(pIDOMNode, g_StringTable[i].bstr,
  958. &pwzBuf, &ccBuf));
  959. if (_hr != S_FALSE)
  960. {
  961. sBuf.TakeOwnership(pwzBuf, ccBuf);
  962. IF_FAILED_EXIT(pAppInfo->Set(MAN_INFO_APPLICATION_FRIENDLYNAME+i-FriendlyName-1, // MAN_INFO_APPLICATION_ASSEMBLYNAME+i-AssemblyName,
  963. sBuf._pwz, sBuf.ByteCount(), MAN_INFO_FLAG_LPWSTR));
  964. }
  965. }
  966. }
  967. // reset so that S_FALSE is returned only if Subscription node is not found but not its attributes
  968. _hr = S_OK;
  969. *ppAppInfo = pAppInfo;
  970. pAppInfo = NULL;
  971. exit:
  972. SAFERELEASE(pIDOMNode);
  973. SAFERELEASE(pAppInfo);
  974. return _hr;
  975. }
  976. // IUnknown Boilerplate
  977. // ---------------------------------------------------------------------------
  978. // CAssemblyManifestImport::QI
  979. // ---------------------------------------------------------------------------
  980. STDMETHODIMP
  981. CAssemblyManifestImport::QueryInterface(REFIID riid, void** ppvObj)
  982. {
  983. if ( IsEqualIID(riid, IID_IUnknown)
  984. || IsEqualIID(riid, IID_IAssemblyManifestImport)
  985. )
  986. {
  987. *ppvObj = static_cast<IAssemblyManifestImport*> (this);
  988. AddRef();
  989. return S_OK;
  990. }
  991. else
  992. {
  993. *ppvObj = NULL;
  994. return E_NOINTERFACE;
  995. }
  996. }
  997. // ---------------------------------------------------------------------------
  998. // CAssemblyManifestImport::AddRef
  999. // ---------------------------------------------------------------------------
  1000. STDMETHODIMP_(ULONG)
  1001. CAssemblyManifestImport::AddRef()
  1002. {
  1003. return InterlockedIncrement ((LONG*) &_cRef);
  1004. }
  1005. // ---------------------------------------------------------------------------
  1006. // CAssemblyManifestImport::Release
  1007. // ---------------------------------------------------------------------------
  1008. STDMETHODIMP_(ULONG)
  1009. CAssemblyManifestImport::Release()
  1010. {
  1011. ULONG lRet = InterlockedDecrement ((LONG*) &_cRef);
  1012. if (!lRet)
  1013. delete this;
  1014. return lRet;
  1015. }
  1016. // Privates
  1017. // ---------------------------------------------------------------------------
  1018. // Init
  1019. // ---------------------------------------------------------------------------
  1020. HRESULT CAssemblyManifestImport::Init(LPCOLESTR pwzManifestFilePath)
  1021. {
  1022. IF_NULL_EXIT(pwzManifestFilePath, E_INVALIDARG);
  1023. // Alloc manifest file path.
  1024. IF_ALLOC_FAILED_EXIT(_bstrManifestFilePath = ::SysAllocString((LPWSTR) pwzManifestFilePath));
  1025. // Load the DOM document.
  1026. _hr = LoadDocumentSync(NULL);
  1027. exit:
  1028. return _hr;
  1029. }
  1030. // ---------------------------------------------------------------------------
  1031. // LoadDocumentSync
  1032. // ---------------------------------------------------------------------------
  1033. HRESULT CAssemblyManifestImport::LoadDocumentSync(IUnknown* punk)
  1034. {
  1035. VARIANT varDoc;
  1036. VARIANT varNameSpaces;
  1037. VARIANT varXPath;
  1038. VARIANT_BOOL varb;
  1039. IXMLDOMDocument2 *pXMLDoc = NULL;
  1040. IF_FALSE_EXIT(((_bstrManifestFilePath != NULL || punk != NULL)
  1041. && (_bstrManifestFilePath == NULL || punk == NULL)), E_INVALIDARG);
  1042. // Create the DOM Doc interface
  1043. IF_FAILED_EXIT(CoCreateInstance(__uuidof(private_MSXML_DOMDocument30),
  1044. NULL, CLSCTX_INPROC_SERVER, IID_IXMLDOMDocument2, (void**)&_pXMLDoc));
  1045. // Load synchronously
  1046. IF_FAILED_EXIT(_pXMLDoc->put_async(VARIANT_FALSE));
  1047. VariantInit(&varDoc);
  1048. if (_bstrManifestFilePath != NULL)
  1049. {
  1050. // Load xml document from the given URL or file path
  1051. varDoc.vt = VT_BSTR;
  1052. V_BSTR(&varDoc) = _bstrManifestFilePath;
  1053. }
  1054. else
  1055. {
  1056. // punk != NULL
  1057. varDoc.vt = VT_UNKNOWN;
  1058. V_UNKNOWN(&varDoc) = punk;
  1059. }
  1060. IF_FAILED_EXIT(_pXMLDoc->load(varDoc, &varb));
  1061. // ISSUE-2002/04/16-felixybc Hack for mg. Not clear returning ERROR_BAD_FORMAT is correct in all cases
  1062. // however, load() returns S_FALSE when loading fails, and the error is unknown.
  1063. IF_TRUE_EXIT(_hr != S_OK, HRESULT_FROM_WIN32(ERROR_BAD_FORMAT)); // S_FALSE returned if the load fails
  1064. // Setup namespace filter
  1065. VariantInit(&varNameSpaces);
  1066. varNameSpaces.vt = VT_BSTR;
  1067. V_BSTR(&varNameSpaces) = g_StringTable[NameSpace].bstr;
  1068. IF_FAILED_EXIT(_pXMLDoc->setProperty(g_StringTable[SelNameSpaces].bstr, varNameSpaces));
  1069. // Setup query type
  1070. VariantInit(&varXPath);
  1071. varXPath.vt = VT_BSTR;
  1072. V_BSTR(&varXPath) = g_StringTable[XPath].bstr;
  1073. IF_FAILED_EXIT(_pXMLDoc->setProperty(g_StringTable[SelLanguage].bstr, varXPath));
  1074. _hr = S_OK;
  1075. exit:
  1076. if (FAILED(_hr))
  1077. SAFERELEASE(_pXMLDoc);
  1078. return _hr;
  1079. }
  1080. // ---------------------------------------------------------------------------
  1081. // ParseAttribute
  1082. // ---------------------------------------------------------------------------
  1083. HRESULT CAssemblyManifestImport::ParseAttribute(IXMLDOMNode *pIXMLDOMNode,
  1084. BSTR bstrAttributeName, LPWSTR *ppwzAttributeValue, LPDWORD pccAttributeValue)
  1085. {
  1086. HRESULT hr;
  1087. MAKE_ERROR_MACROS_STATIC(hr);
  1088. DWORD ccAttributeValue = 0;
  1089. LPWSTR pwzAttributeValue = NULL;
  1090. VARIANT varValue;
  1091. IXMLDOMElement *pIXMLDOMElement = NULL;
  1092. *ppwzAttributeValue = NULL;
  1093. *pccAttributeValue = 0;
  1094. VariantInit(&varValue);
  1095. IF_FAILED_EXIT(pIXMLDOMNode->QueryInterface(IID_IXMLDOMElement, (void**) &pIXMLDOMElement));
  1096. if ((hr = pIXMLDOMElement->getAttribute(bstrAttributeName,
  1097. &varValue)) != S_OK)
  1098. goto exit;
  1099. // BUGBUG - what is meaning of NULL value here?
  1100. if(varValue.vt != VT_NULL)
  1101. {
  1102. ccAttributeValue = ::SysStringLen(varValue.bstrVal) + 1;
  1103. IF_ALLOC_FAILED_EXIT(pwzAttributeValue = new WCHAR[ccAttributeValue]);
  1104. memcpy(pwzAttributeValue, varValue.bstrVal, ccAttributeValue * sizeof(WCHAR));
  1105. *ppwzAttributeValue = pwzAttributeValue;
  1106. *pccAttributeValue = ccAttributeValue;
  1107. }
  1108. else
  1109. hr = S_FALSE;
  1110. exit:
  1111. SAFERELEASE(pIXMLDOMElement);
  1112. if (varValue.bstrVal)
  1113. ::SysFreeString(varValue.bstrVal);
  1114. return hr;
  1115. }
  1116. // ---------------------------------------------------------------------------
  1117. // InitGlobalCritSect
  1118. // ---------------------------------------------------------------------------
  1119. HRESULT CAssemblyManifestImport::InitGlobalCritSect()
  1120. {
  1121. HRESULT hr = S_OK;
  1122. __try {
  1123. InitializeCriticalSection(&g_cs);
  1124. }
  1125. __except (GetExceptionCode() == STATUS_NO_MEMORY ?
  1126. EXCEPTION_EXECUTE_HANDLER :
  1127. EXCEPTION_CONTINUE_SEARCH )
  1128. {
  1129. hr = E_OUTOFMEMORY;
  1130. }
  1131. return hr;
  1132. }
  1133. // ---------------------------------------------------------------------------
  1134. // DelGlobalCritSect
  1135. // ---------------------------------------------------------------------------
  1136. void CAssemblyManifestImport::DelGlobalCritSect()
  1137. {
  1138. DeleteCriticalSection(&g_cs);
  1139. }
  1140. // ---------------------------------------------------------------------------
  1141. // ReportManifestType
  1142. // ---------------------------------------------------------------------------
  1143. HRESULT CAssemblyManifestImport::ReportManifestType(DWORD *pdwType)
  1144. {
  1145. LPWSTR pwzType = NULL;
  1146. DWORD dwCC = 0;
  1147. IF_NULL_EXIT(pdwType, E_INVALIDARG);
  1148. *pdwType = MANIFEST_TYPE_UNKNOWN;
  1149. // ensure _pAssemblyId is initialized/cached
  1150. if (!_pAssemblyId)
  1151. {
  1152. LPASSEMBLY_IDENTITY pAssemblyId = NULL;
  1153. if ((_hr = GetAssemblyIdentity(&pAssemblyId)) != S_OK)
  1154. goto exit;
  1155. SAFERELEASE(pAssemblyId);
  1156. }
  1157. if ((_hr = _pAssemblyId->GetAttribute(SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_TYPE, &pwzType, &dwCC)) == S_OK)
  1158. {
  1159. // note: case sensitive comparison
  1160. IF_FAILED_EXIT(FusionCompareString(pwzType, L"desktop", 0));
  1161. if(_hr == S_OK)
  1162. *pdwType = MANIFEST_TYPE_DESKTOP;
  1163. else
  1164. {
  1165. IF_FAILED_EXIT(FusionCompareString(pwzType, L"subscription", 0));
  1166. if(_hr == S_OK)
  1167. {
  1168. *pdwType = MANIFEST_TYPE_SUBSCRIPTION;
  1169. }
  1170. else
  1171. {
  1172. IF_FAILED_EXIT(FusionCompareString(pwzType, L"application", 0));
  1173. if(_hr == S_OK)
  1174. *pdwType = MANIFEST_TYPE_APPLICATION;
  1175. }
  1176. // else MANIFEST_TYPE_UNKNOWN
  1177. }
  1178. SAFEDELETEARRAY(pwzType);
  1179. }
  1180. exit:
  1181. SAFEDELETEARRAY(pwzType);
  1182. return _hr;
  1183. }
  1184. // ---------------------------------------------------------------------------
  1185. // GetXMLDoc
  1186. // ---------------------------------------------------------------------------
  1187. HRESULT CAssemblyManifestImport::GetXMLDoc(IXMLDOMDocument2 **pXMLDoc)
  1188. {
  1189. _hr = S_OK;
  1190. *pXMLDoc = NULL;
  1191. if (!_pXMLDoc)
  1192. {
  1193. _hr = S_FALSE;
  1194. goto exit;
  1195. }
  1196. *pXMLDoc = _pXMLDoc;
  1197. (*pXMLDoc)->AddRef();
  1198. exit:
  1199. return _hr;
  1200. }
  1201. // ---------------------------------------------------------------------------
  1202. // IsCLRManifest
  1203. // ---------------------------------------------------------------------------
  1204. HRESULT CAssemblyManifestImport::IsCLRManifest(LPCOLESTR pwzManifestFilePath)
  1205. {
  1206. HRESULT hr = S_OK;
  1207. MAKE_ERROR_MACROS_STATIC(hr);
  1208. HANDLE hFile = INVALID_HANDLE_VALUE;
  1209. DWORD dwLength=0;
  1210. unsigned char buffer[2];
  1211. ZeroMemory(buffer, sizeof(buffer));
  1212. hFile = CreateFile(pwzManifestFilePath,
  1213. GENERIC_READ,
  1214. FILE_SHARE_READ,
  1215. NULL,
  1216. OPEN_EXISTING,
  1217. FILE_ATTRIBUTE_NORMAL,
  1218. NULL);
  1219. if(hFile == INVALID_HANDLE_VALUE)
  1220. {
  1221. hr = FusionpHresultFromLastError();
  1222. // ISSUE-2002/04/12-felixybc File could be deleted when called by shell in the shell ext context
  1223. // do not assert in that case
  1224. ASSERT(hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
  1225. goto exit;
  1226. }
  1227. IF_WIN32_FALSE_EXIT(ReadFile(hFile, buffer, sizeof(buffer), &dwLength, NULL));
  1228. if (dwLength && !strncmp((const char *)buffer, "MZ", 2))
  1229. hr = S_OK;
  1230. else
  1231. hr = S_FALSE;
  1232. exit:
  1233. if (hFile != INVALID_HANDLE_VALUE)
  1234. CloseHandle(hFile);
  1235. return hr;
  1236. }
  1237. #ifdef CONTAINER
  1238. // ---------------------------------------------------------------------------
  1239. // IsContainer
  1240. // ---------------------------------------------------------------------------
  1241. HRESULT CAssemblyManifestImport::IsContainer(LPCOLESTR pwzManifestFilePath)
  1242. {
  1243. HRESULT hr = S_OK;
  1244. MAKE_ERROR_MACROS_STATIC(hr);
  1245. CString sPath;
  1246. IF_FAILED_EXIT(sPath.Assign(pwzManifestFilePath));
  1247. // ISSUE-2002/07/03-felixybc only checks extension for now
  1248. IF_FAILED_EXIT(sPath.EndsWith(L".container"));
  1249. exit:
  1250. return hr;
  1251. }
  1252. #endif