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.

1828 lines
70 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation
  3. Module Name:
  4. actctxgen.cpp
  5. Abstract:
  6. APIs for generating activation contexts.
  7. Author:
  8. Michael J. Grier (MGrier) 23-Feb-2000
  9. Revision History:
  10. xiaoyuw 09/2000 replace attributes with assembly identity
  11. --*/
  12. #include "stdinc.h"
  13. #include <windows.h>
  14. #include <sxsp.h>
  15. #include <ole2.h>
  16. #include <xmlparser.h>
  17. #include "nodefactory.h"
  18. #include <wchar.h>
  19. #include "filestream.h"
  20. #include "fusionhandle.h"
  21. #include "cteestream.h"
  22. #include "cresourcestream.h"
  23. #include "fusionxml.h"
  24. #include "util.h"
  25. #include "sxsexceptionhandling.h"
  26. #include "csxspreservelasterror.h"
  27. #include "smartptr.h"
  28. #include "cstreamtap.h"
  29. #include "pendingassembly.h"
  30. #include "actctxgenctx.h"
  31. BOOL
  32. SxspFindAssemblyByName(
  33. PACTCTXGENCTX pActCtxGenCtx,
  34. PCWSTR AssemblyName,
  35. SIZE_T AssemblyNameCch,
  36. PASSEMBLY *AssemblyFound
  37. );
  38. BOOL
  39. SxspAddAssemblyToActivationContextGenerationContext(
  40. PACTCTXGENCTX pActCtxGenCtx,
  41. PASSEMBLY Asm
  42. );
  43. _ACTCTXGENCTX::_ACTCTXGENCTX()
  44. :
  45. m_Contributors(NULL),
  46. m_ContributorCount(0),
  47. m_ProcessorArchitecture(0),
  48. m_LangID(0),
  49. m_Flags(0),
  50. m_ManifestOperation(MANIFEST_OPERATION_INVALID),
  51. m_ManifestOperationFlags(0),
  52. m_NextAssemblyRosterIndex(1),
  53. m_fClsidMapInitialized(FALSE),
  54. m_InitializedContributorCount(0),
  55. m_NoInherit(false),
  56. m_pNodeFactory(NULL),
  57. m_ulFileCount(0),
  58. m_fAppApplyPublisherPolicy(SXS_PUBLISHER_POLICY_APPLY_DEFAULT),
  59. m_ApplicationDirectoryHasBeenProbedForLanguageSubdirs(false),
  60. m_ApplicationDirectoryHasSpecificLanguageSubdir(false),
  61. m_ApplicationDirectoryHasGenericLanguageSubdir(false),
  62. m_ApplicationDirectoryHasSpecificSystemLanguageSubdir(false),
  63. m_ApplicationDirectoryHasGenericSystemLanguageSubdir(false)
  64. {
  65. }
  66. _ACTCTXGENCTX::~_ACTCTXGENCTX()
  67. {
  68. while (m_InitializedContributorCount)
  69. {
  70. m_InitializedContributorCount -= 1;
  71. CActivationContextGenerationContextContributor *Ctb = &m_Contributors[m_InitializedContributorCount];
  72. Ctb->Fire_ParseEnded(this, NULL);
  73. Ctb->Fire_ActCtxGenEnded(this);
  74. }
  75. FUSION_DELETE_ARRAY(m_Contributors);
  76. m_Contributors = NULL;
  77. m_AssemblyTable.ClearNoCallback();
  78. m_ComponentPolicyTable.ClearNoCallback();
  79. m_PendingAssemblyList.Clear(&CPendingAssembly::DeleteYourself);
  80. m_AssemblyList.Clear(&ASSEMBLY::Release);
  81. if (m_fClsidMapInitialized)
  82. {
  83. m_fClsidMapInitialized = false;
  84. VERIFY_NTC(m_ClsidMap.Uninitialize());
  85. }
  86. FUSION_DELETE_SINGLETON(m_pNodeFactory);
  87. m_pNodeFactory = NULL;
  88. }
  89. BOOL
  90. SxspInitActCtxGenCtx(
  91. PACTCTXGENCTX pActCtxGenCtx,
  92. ULONG ulManifestOperation,
  93. DWORD dwFlags,
  94. DWORD dwManifestOperationFlags,
  95. const CImpersonationData &ImpersonationData,
  96. USHORT ProcessorArchitecture,
  97. LANGID LangId,
  98. ULONG ApplicationDirectoryPathType,
  99. SIZE_T ApplicationDirectoryCch,
  100. PCWSTR ApplicationDirectory
  101. )
  102. {
  103. BOOL fSuccess = FALSE;
  104. FN_TRACE_WIN32(fSuccess);
  105. PACTCTXCTB Ctb = NULL;
  106. CSxsLockCriticalSection lock(g_ActCtxCtbListCritSec);
  107. CStringBufferAccessor acc; // used for LangID String buffer
  108. LANGID SystemLangId = ::GetSystemDefaultUILanguage();
  109. bool fEqual = false;
  110. PARAMETER_CHECK(pActCtxGenCtx != NULL);
  111. PARAMETER_CHECK(
  112. (ulManifestOperation == SXSP_INIT_ACT_CTX_GEN_CTX_OPERATION_PARSE_ONLY) ||
  113. (ulManifestOperation == SXSP_INIT_ACT_CTX_GEN_CTX_OPERATION_GENERATE_ACTIVATION_CONTEXT) ||
  114. (ulManifestOperation == SXSP_INIT_ACT_CTX_GEN_CTX_OPERATION_INSTALL));
  115. PARAMETER_CHECK(
  116. (ApplicationDirectoryPathType == ACTIVATION_CONTEXT_PATH_TYPE_NONE) ||
  117. (ApplicationDirectoryPathType == ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE));
  118. PARAMETER_CHECK((dwFlags & ~(SXS_GENERATE_ACTCTX_SYSTEM_DEFAULT | SXS_GENERATE_ACTCTX_APP_RUNNING_IN_SAFEMODE)) == 0);
  119. PARAMETER_CHECK((dwFlags == 0) || (dwFlags == SXS_GENERATE_ACTCTX_SYSTEM_DEFAULT) || (dwFlags == SXS_GENERATE_ACTCTX_APP_RUNNING_IN_SAFEMODE));
  120. switch (ulManifestOperation)
  121. {
  122. case SXSP_INIT_ACT_CTX_GEN_CTX_OPERATION_PARSE_ONLY:
  123. PARAMETER_CHECK(dwManifestOperationFlags == 0);
  124. break;
  125. case SXSP_INIT_ACT_CTX_GEN_CTX_OPERATION_GENERATE_ACTIVATION_CONTEXT:
  126. PARAMETER_CHECK(dwManifestOperationFlags == 0);
  127. break;
  128. case SXSP_INIT_ACT_CTX_GEN_CTX_OPERATION_INSTALL:
  129. PARAMETER_CHECK(
  130. (dwManifestOperationFlags & ~(
  131. MANIFEST_OPERATION_INSTALL_FLAG_NOT_TRANSACTIONAL |
  132. MANIFEST_OPERATION_INSTALL_FLAG_NO_VERIFY |
  133. MANIFEST_OPERATION_INSTALL_FLAG_REPLACE_EXISTING |
  134. MANIFEST_OPERATION_INSTALL_FLAG_ABORT |
  135. MANIFEST_OPERATION_INSTALL_FLAG_FROM_DIRECTORY |
  136. MANIFEST_OPERATION_INSTALL_FLAG_FROM_DIRECTORY_RECURSIVE |
  137. MANIFEST_OPERATION_INSTALL_FLAG_MOVE |
  138. MANIFEST_OPERATION_INSTALL_FLAG_INCLUDE_CODEBASE |
  139. MANIFEST_OPERATION_INSTALL_FLAG_FROM_RESOURCE |
  140. MANIFEST_OPERATION_INSTALL_FLAG_INSTALLED_BY_DARWIN |
  141. MANIFEST_OPERATION_INSTALL_FLAG_INSTALLED_BY_OSSETUP |
  142. MANIFEST_OPERATION_INSTALL_FLAG_INSTALLED_BY_MIGRATION |
  143. MANIFEST_OPERATION_INSTALL_FLAG_CREATE_LOGFILE |
  144. MANIFEST_OPERATION_INSTALL_FLAG_REFERENCE_VALID |
  145. MANIFEST_OPERATION_INSTALL_FLAG_REFRESH |
  146. MANIFEST_OPERATION_INSTALL_FLAG_FROM_CABINET |
  147. MANIFEST_OPERATION_INSTALL_FLAG_APPLY_PATCHES |
  148. MANIFEST_OPERATION_INSTALL_FLAG_FORCE_LOOK_FOR_CATALOG |
  149. MANIFEST_OPERATION_INSTALL_FLAG_COMMIT)) == 0);
  150. break;
  151. }
  152. pActCtxGenCtx->m_ProcessorArchitecture = ProcessorArchitecture;
  153. pActCtxGenCtx->m_LangID = LangId;
  154. pActCtxGenCtx->m_SystemLangID = SystemLangId;
  155. pActCtxGenCtx->m_SpecificLanguage.Clear();
  156. IFW32FALSE_EXIT(pActCtxGenCtx->m_ApplicationDirectoryBuffer.Win32Assign(ApplicationDirectory, ApplicationDirectoryCch));
  157. pActCtxGenCtx->m_ApplicationDirectoryPathType = ApplicationDirectoryPathType;
  158. IFW32FALSE_EXIT(::SxspMapLANGIDToCultures(LangId, pActCtxGenCtx->m_GenericLanguage, pActCtxGenCtx->m_SpecificLanguage));
  159. IFW32FALSE_EXIT(::SxspMapLANGIDToCultures(SystemLangId, pActCtxGenCtx->m_GenericSystemLanguage, pActCtxGenCtx->m_SpecificSystemLanguage));
  160. // If these match the user's language, clear them to avoid the probing later on.
  161. IFW32FALSE_EXIT(pActCtxGenCtx->m_SpecificSystemLanguage.Win32Equals(pActCtxGenCtx->m_SpecificLanguage, fEqual, true));
  162. if (fEqual)
  163. pActCtxGenCtx->m_SpecificSystemLanguage.Clear();
  164. IFW32FALSE_EXIT(pActCtxGenCtx->m_GenericSystemLanguage.Win32Equals(pActCtxGenCtx->m_GenericLanguage, fEqual, true));
  165. if (fEqual)
  166. pActCtxGenCtx->m_GenericSystemLanguage.Clear();
  167. pActCtxGenCtx->m_ImpersonationData = ImpersonationData;
  168. pActCtxGenCtx->m_ManifestOperation = ulManifestOperation;
  169. pActCtxGenCtx->m_Flags = dwFlags;
  170. pActCtxGenCtx->m_ManifestOperationFlags = dwManifestOperationFlags;
  171. pActCtxGenCtx->m_fAppApplyPublisherPolicy = SXS_PUBLISHER_POLICY_APPLY_DEFAULT;
  172. IFW32FALSE_EXIT(pActCtxGenCtx->m_AssemblyTable.Initialize());
  173. IFW32FALSE_EXIT(pActCtxGenCtx->m_ComponentPolicyTable.Initialize());
  174. IFW32FALSE_EXIT(pActCtxGenCtx->m_ApplicationPolicyTable.Initialize());
  175. IFW32FALSE_EXIT(pActCtxGenCtx->m_ClsidMap.Initialize());
  176. pActCtxGenCtx->m_fClsidMapInitialized = TRUE;
  177. pActCtxGenCtx->m_ClsidMappingContext.Map = &(pActCtxGenCtx->m_ClsidMap);
  178. IFW32FALSE_EXIT(::SxspGetAssemblyRootDirectory(pActCtxGenCtx->m_AssemblyRootDirectoryBuffer));
  179. pActCtxGenCtx->m_AssemblyRootDirectoryPathType = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE;
  180. lock.Lock();
  181. IFALLOCFAILED_EXIT(pActCtxGenCtx->m_Contributors = FUSION_NEW_ARRAY(CActivationContextGenerationContextContributor, g_ActCtxCtbListCount));
  182. pActCtxGenCtx->m_ContributorCount = g_ActCtxCtbListCount;
  183. for (
  184. (pActCtxGenCtx->m_InitializedContributorCount = 0), (Ctb=g_ActCtxCtbListHead);
  185. (Ctb != NULL) && (pActCtxGenCtx->m_InitializedContributorCount < g_ActCtxCtbListCount);
  186. (pActCtxGenCtx->m_InitializedContributorCount++), (Ctb = Ctb->m_Next)
  187. )
  188. {
  189. ACTCTXCTB_CBACTCTXGENBEGINNING CBData;
  190. CBData.Header.Reason = ACTCTXCTB_CBREASON_ACTCTXGENBEGINNING;
  191. CBData.Header.ExtensionGuid = Ctb->GetExtensionGuidPtr();
  192. CBData.Header.SectionId = Ctb->m_SectionId;
  193. CBData.Header.ContributorContext = Ctb->m_ContributorContext;
  194. CBData.Header.ActCtxGenContext = NULL;
  195. CBData.Header.ManifestParseContext = NULL;
  196. CBData.Header.ManifestOperation = ulManifestOperation;
  197. CBData.Header.ManifestOperationFlags = dwManifestOperationFlags;
  198. CBData.Header.Flags = dwFlags;
  199. CBData.Header.pOriginalActCtxGenCtx = pActCtxGenCtx;
  200. CBData.Header.InstallationContext = &(pActCtxGenCtx->m_InstallationContext);
  201. CBData.Header.ClsidMappingContext = &(pActCtxGenCtx->m_ClsidMappingContext);
  202. CBData.ApplicationDirectory = pActCtxGenCtx->m_ApplicationDirectoryBuffer;
  203. CBData.ApplicationDirectoryCch = pActCtxGenCtx->m_ApplicationDirectoryBuffer.Cch();
  204. CBData.ApplicationDirectoryPathType = pActCtxGenCtx->m_ApplicationDirectoryPathType;
  205. CBData.Success = TRUE;
  206. (*(Ctb->m_CallbackFunction))((PACTCTXCTB_CALLBACK_DATA) &CBData.Header);
  207. if (!CBData.Success)
  208. {
  209. ASSERT(::FusionpGetLastWin32Error() != ERROR_SUCCESS);
  210. if (::FusionpGetLastWin32Error() == ERROR_SUCCESS)
  211. ::FusionpSetLastWin32Error(ERROR_INTERNAL_ERROR);
  212. goto Exit;
  213. }
  214. IFW32FALSE_EXIT(pActCtxGenCtx->m_Contributors[pActCtxGenCtx->m_InitializedContributorCount].Initialize(Ctb, CBData.Header.ActCtxGenContext));
  215. }
  216. // If the list count is correct, we should be both at the end of the list
  217. // and at the max index.
  218. ASSERT(pActCtxGenCtx->m_InitializedContributorCount == g_ActCtxCtbListCount);
  219. ASSERT(Ctb == NULL);
  220. qsort(pActCtxGenCtx->m_Contributors, pActCtxGenCtx->m_ContributorCount, sizeof(CActivationContextGenerationContextContributor), &CActivationContextGenerationContextContributor::Compare);
  221. fSuccess = TRUE;
  222. Exit:
  223. return fSuccess;
  224. }
  225. BOOL
  226. SxspFireActCtxGenEnding(
  227. PACTCTXGENCTX pActCtxGenCtx
  228. )
  229. {
  230. BOOL fSuccess = FALSE;
  231. FN_TRACE_WIN32(fSuccess);
  232. ULONG i;
  233. PARAMETER_CHECK(pActCtxGenCtx != NULL);
  234. for (i=0; i<pActCtxGenCtx->m_InitializedContributorCount; i++)
  235. IFW32FALSE_EXIT(pActCtxGenCtx->m_Contributors[i].Fire_ActCtxGenEnding(pActCtxGenCtx));
  236. fSuccess = TRUE;
  237. Exit:
  238. return fSuccess;
  239. }
  240. class CSxspResolvePartialReferenceLocals
  241. {
  242. public:
  243. CProbedAssemblyInformation TestReference;
  244. CSmallStringBuffer buffProcessorArchitecture;
  245. };
  246. BOOL
  247. SxspResolvePartialReference(
  248. DWORD Flags,
  249. PCASSEMBLY ParsingAssemblyContext,
  250. PACTCTXGENCTX pActCtxGenCtx,
  251. const CAssemblyReference &PartialReference,
  252. CProbedAssemblyInformation &ProbedAssemblyInformation,
  253. bool &rfFound,
  254. CSxspResolvePartialReferenceLocals *Locals
  255. )
  256. {
  257. BOOL fSuccess = FALSE;
  258. FN_TRACE_WIN32(fSuccess);
  259. CProbedAssemblyInformation &TestReference = Locals->TestReference;
  260. CSmallStringBuffer &buffProcessorArchitecture = Locals->buffProcessorArchitecture;
  261. bool fWildcardedLanguage = false;
  262. bool fWildcardedProcessorArchitecture = false;
  263. bool fAutoWow64Probing = false;
  264. bool fHasPKToken = false;
  265. bool fFound = false;
  266. USHORT wCurrentProcessorArchitecture = PROCESSOR_ARCHITECTURE_UNKNOWN;
  267. DWORD dwProbeAssemblyFlags = 0;
  268. PCWSTR pszOriginalProcessorArchitecture = NULL;
  269. SIZE_T cchOriginalProcessorArchitecture = 0;
  270. PCWSTR pszOriginalLanguage = NULL;
  271. SIZE_T cchOriginalLanguage = 0;
  272. fHasPKToken = false;
  273. rfFound = false;
  274. PARAMETER_CHECK(pActCtxGenCtx != NULL);
  275. IFINVALID_FLAGS_EXIT_WIN32(Flags, SXSP_RESOLVE_PARTIAL_REFERENCE_FLAG_OPTIONAL |
  276. SXSP_RESOLVE_PARTIAL_REFERENCE_FLAG_SKIP_WORLDWIDE);
  277. //
  278. // A partial reference needs to have processor architecture, assembly name and
  279. // assembly version filled in. We only probe based on langid.
  280. //
  281. // Copy the attributes over...
  282. IFW32FALSE_EXIT(TestReference.Initialize(PartialReference, pActCtxGenCtx));
  283. fWildcardedProcessorArchitecture = false;
  284. fAutoWow64Probing = false;
  285. // Find out if we're either processing a processorArchitecture="*" bind or
  286. // if we're supposed to do wow64 probing
  287. IFW32FALSE_EXIT(PartialReference.IsProcessorArchitectureWildcarded(fWildcardedProcessorArchitecture));
  288. if (pActCtxGenCtx->m_ProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA32_ON_WIN64)
  289. {
  290. IFW32FALSE_EXIT(PartialReference.IsProcessorArchitectureX86(fAutoWow64Probing));
  291. }
  292. if (fWildcardedProcessorArchitecture || fAutoWow64Probing)
  293. {
  294. wCurrentProcessorArchitecture = pActCtxGenCtx->m_ProcessorArchitecture;
  295. IFW32FALSE_EXIT(::FusionpFormatProcessorArchitecture(wCurrentProcessorArchitecture, buffProcessorArchitecture));
  296. IFW32FALSE_EXIT(TestReference.SetProcessorArchitecture(buffProcessorArchitecture, buffProcessorArchitecture.Cch()));
  297. // We do not probe for private wow64 assemblies.
  298. if (wCurrentProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA32_ON_WIN64)
  299. dwProbeAssemblyFlags |= CProbedAssemblyInformation::ProbeAssembly_SkipPrivateAssemblies;
  300. }
  301. IFW32FALSE_EXIT(PartialReference.GetProcessorArchitecture(pszOriginalProcessorArchitecture, cchOriginalProcessorArchitecture));
  302. IFW32FALSE_EXIT(PartialReference.GetLanguage(pszOriginalLanguage, cchOriginalLanguage));
  303. TryItAllAgain:
  304. // Let's try the few languages we can.
  305. IFW32FALSE_EXIT(PartialReference.IsLanguageWildcarded(fWildcardedLanguage));
  306. if (!fWildcardedLanguage)
  307. {
  308. // If there's no language="*" in the dependency, let's just look for the exact match and
  309. // call it a day.
  310. if (fWildcardedProcessorArchitecture || fAutoWow64Probing)
  311. IFW32FALSE_EXIT(TestReference.SetProcessorArchitecture(buffProcessorArchitecture, buffProcessorArchitecture.Cch()));
  312. IFW32FALSE_EXIT(TestReference.ProbeAssembly(dwProbeAssemblyFlags, pActCtxGenCtx, CProbedAssemblyInformation::eExplicitBind, fFound));
  313. if ((!fFound) && (fWildcardedProcessorArchitecture || fAutoWow64Probing))
  314. IFW32FALSE_EXIT(TestReference.SetProcessorArchitecture(pszOriginalProcessorArchitecture, cchOriginalProcessorArchitecture));
  315. }
  316. else
  317. {
  318. // Let's try the user's language...
  319. if (pActCtxGenCtx->m_SpecificLanguage[0] != L'\0')
  320. {
  321. // Since this is the first probe, we don't have to reset to original...
  322. if (fWildcardedProcessorArchitecture || fAutoWow64Probing)
  323. IFW32FALSE_EXIT(TestReference.SetProcessorArchitecture(buffProcessorArchitecture, buffProcessorArchitecture.Cch()));
  324. IFW32FALSE_EXIT(TestReference.SetLanguage(pActCtxGenCtx->m_SpecificLanguage));
  325. IFW32FALSE_EXIT(TestReference.ProbeAssembly(dwProbeAssemblyFlags, pActCtxGenCtx, CProbedAssemblyInformation::eSpecificLanguage, fFound));
  326. if (!fFound)
  327. {
  328. if (fWildcardedProcessorArchitecture || fAutoWow64Probing)
  329. IFW32FALSE_EXIT(
  330. TestReference.SetProcessorArchitecture(
  331. pszOriginalProcessorArchitecture,
  332. cchOriginalProcessorArchitecture));
  333. IFW32FALSE_EXIT(TestReference.SetLanguage(pszOriginalLanguage, cchOriginalLanguage));
  334. }
  335. }
  336. if (!fFound && (pActCtxGenCtx->m_GenericLanguage[0] != L'\0'))
  337. {
  338. // Try the user's slightly more generic version of the language...
  339. if (fWildcardedProcessorArchitecture || fAutoWow64Probing)
  340. IFW32FALSE_EXIT(TestReference.SetProcessorArchitecture(buffProcessorArchitecture, buffProcessorArchitecture.Cch()));
  341. IFW32FALSE_EXIT(TestReference.SetLanguage(pActCtxGenCtx->m_GenericLanguage));
  342. IFW32FALSE_EXIT(TestReference.ProbeAssembly(dwProbeAssemblyFlags, pActCtxGenCtx, CProbedAssemblyInformation::eGenericLanguage, fFound));
  343. if (!fFound)
  344. {
  345. if (fWildcardedProcessorArchitecture || fAutoWow64Probing)
  346. IFW32FALSE_EXIT(
  347. TestReference.SetProcessorArchitecture(
  348. pszOriginalProcessorArchitecture,
  349. cchOriginalProcessorArchitecture));
  350. IFW32FALSE_EXIT(TestReference.SetLanguage(pszOriginalLanguage, cchOriginalLanguage));
  351. }
  352. }
  353. // Let's try the system's installed language...
  354. if (!fFound && (pActCtxGenCtx->m_SpecificSystemLanguage[0] != L'\0'))
  355. {
  356. if (fWildcardedProcessorArchitecture || fAutoWow64Probing)
  357. IFW32FALSE_EXIT(TestReference.SetProcessorArchitecture(buffProcessorArchitecture, buffProcessorArchitecture.Cch()));
  358. IFW32FALSE_EXIT(TestReference.SetLanguage(pActCtxGenCtx->m_SpecificSystemLanguage));
  359. IFW32FALSE_EXIT(TestReference.ProbeAssembly(dwProbeAssemblyFlags, pActCtxGenCtx, CProbedAssemblyInformation::eSpecificSystemLanguage, fFound));
  360. if (!fFound)
  361. {
  362. if (fWildcardedProcessorArchitecture || fAutoWow64Probing)
  363. IFW32FALSE_EXIT(
  364. TestReference.SetProcessorArchitecture(
  365. pszOriginalProcessorArchitecture,
  366. cchOriginalProcessorArchitecture));
  367. IFW32FALSE_EXIT(TestReference.SetLanguage(pszOriginalLanguage, cchOriginalLanguage));
  368. }
  369. }
  370. if (!fFound && (pActCtxGenCtx->m_GenericSystemLanguage[0] != L'\0'))
  371. {
  372. // Try the user's slightly more generic version of the language...
  373. if (fWildcardedProcessorArchitecture || fAutoWow64Probing)
  374. IFW32FALSE_EXIT(TestReference.SetProcessorArchitecture(buffProcessorArchitecture, buffProcessorArchitecture.Cch()));
  375. IFW32FALSE_EXIT(TestReference.SetLanguage(pActCtxGenCtx->m_GenericSystemLanguage));
  376. IFW32FALSE_EXIT(TestReference.ProbeAssembly(dwProbeAssemblyFlags, pActCtxGenCtx, CProbedAssemblyInformation::eGenericSystemLanguage, fFound));
  377. if (!fFound)
  378. {
  379. if (fWildcardedProcessorArchitecture || fAutoWow64Probing)
  380. IFW32FALSE_EXIT(
  381. TestReference.SetProcessorArchitecture(
  382. pszOriginalProcessorArchitecture,
  383. cchOriginalProcessorArchitecture));
  384. IFW32FALSE_EXIT(TestReference.SetLanguage(pszOriginalLanguage, cchOriginalLanguage));
  385. }
  386. }
  387. // If we haven't found a language specific one and the caller did not
  388. // request us to skip the language-dependent ones, try for a language neutral
  389. if (!fFound &&
  390. ((Flags & SXSP_RESOLVE_PARTIAL_REFERENCE_FLAG_SKIP_WORLDWIDE) == 0))
  391. {
  392. // Try with no language!
  393. if (fWildcardedProcessorArchitecture || fAutoWow64Probing)
  394. IFW32FALSE_EXIT(TestReference.SetProcessorArchitecture(buffProcessorArchitecture, buffProcessorArchitecture.Cch()));
  395. IFW32FALSE_EXIT(TestReference.ClearLanguage());
  396. IFW32FALSE_EXIT(TestReference.ProbeAssembly(dwProbeAssemblyFlags, pActCtxGenCtx, CProbedAssemblyInformation::eLanguageNeutral, fFound));
  397. if (!fFound)
  398. {
  399. if (fWildcardedProcessorArchitecture || fAutoWow64Probing)
  400. IFW32FALSE_EXIT(
  401. TestReference.SetProcessorArchitecture(
  402. pszOriginalProcessorArchitecture,
  403. cchOriginalProcessorArchitecture));
  404. IFW32FALSE_EXIT(TestReference.SetLanguage(pszOriginalLanguage, cchOriginalLanguage));
  405. }
  406. }
  407. }
  408. if (!fFound)
  409. {
  410. // If we're automatically searching for wow64 assemblies and the processor architecture we just tried
  411. // was ia32-on-win64, try again with plain PROCESSOR_ARCHITECTURE_INTEL.
  412. if (fAutoWow64Probing && (wCurrentProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA32_ON_WIN64))
  413. {
  414. wCurrentProcessorArchitecture = PROCESSOR_ARCHITECTURE_INTEL;
  415. dwProbeAssemblyFlags &= ~(CProbedAssemblyInformation::ProbeAssembly_SkipPrivateAssemblies);
  416. IFW32FALSE_EXIT(::FusionpFormatProcessorArchitecture(wCurrentProcessorArchitecture, buffProcessorArchitecture));
  417. IFW32FALSE_EXIT(TestReference.SetProcessorArchitecture(buffProcessorArchitecture, buffProcessorArchitecture.Cch()));
  418. pszOriginalProcessorArchitecture = buffProcessorArchitecture;
  419. cchOriginalProcessorArchitecture = buffProcessorArchitecture.Cch();
  420. goto TryItAllAgain;
  421. }
  422. // If we're handling a processorArchitecture="*" bind and the current processor architecture hasn't fallen
  423. // back to PROCESSOR_ARCHITECTURE_UNKNOWN ( == data-only assemblies), fall back now.
  424. if (fWildcardedProcessorArchitecture && (wCurrentProcessorArchitecture != PROCESSOR_ARCHITECTURE_UNKNOWN))
  425. {
  426. wCurrentProcessorArchitecture = PROCESSOR_ARCHITECTURE_UNKNOWN;
  427. // data-only private assemblies cannot be found with processorArchitecture="*"
  428. dwProbeAssemblyFlags |= CProbedAssemblyInformation::ProbeAssembly_SkipPrivateAssemblies;
  429. IFW32FALSE_EXIT(::FusionpFormatProcessorArchitecture(wCurrentProcessorArchitecture, buffProcessorArchitecture));
  430. IFW32FALSE_EXIT(TestReference.SetProcessorArchitecture(buffProcessorArchitecture, buffProcessorArchitecture.Cch()));
  431. pszOriginalProcessorArchitecture = buffProcessorArchitecture;
  432. cchOriginalProcessorArchitecture = buffProcessorArchitecture.Cch();
  433. goto TryItAllAgain;
  434. }
  435. // If it wasn't optional, declare an error.
  436. if ((Flags & SXSP_RESOLVE_PARTIAL_REFERENCE_FLAG_OPTIONAL) == 0)
  437. {
  438. // NTRAID#NTBUG9 - 571854 - 2002/03/26 - xiaoyuw
  439. // the default value would never get used since GetAssemblyName always reset the input parameter to be NULL;
  440. PCWSTR AssemblyName = L"<error retrieving assembly name>";
  441. SIZE_T AssemblyNameCch = NUMBER_OF(L"<error retrieving assembly name>") - 1;
  442. TestReference.GetAssemblyName(&AssemblyName, &AssemblyNameCch);
  443. ::FusionpLogError(
  444. MSG_SXS_MANIFEST_PARSE_DEPENDENCY,
  445. CUnicodeString(AssemblyName, AssemblyNameCch),
  446. CEventLogLastError(ERROR_SXS_ASSEMBLY_NOT_FOUND));
  447. ORIGINATE_WIN32_FAILURE_AND_EXIT(AssemblyProbingFailed, ERROR_SXS_ASSEMBLY_NOT_FOUND);
  448. }
  449. }
  450. else
  451. IFW32FALSE_EXIT(ProbedAssemblyInformation.TakeValue(TestReference));
  452. rfFound = fFound;
  453. fSuccess = TRUE;
  454. Exit:
  455. if (!fSuccess)
  456. {
  457. CSxsPreserveLastError ple;
  458. PCWSTR pszAssemblyName = NULL;
  459. SIZE_T AssemblyNameCch = 0;
  460. PartialReference.GetAssemblyName(&pszAssemblyName, &AssemblyNameCch);
  461. ::FusionpLogError(
  462. MSG_SXS_FUNCTION_CALL_FAIL,
  463. CEventLogString(L"Resolve Partial Assembly"),
  464. (pszAssemblyName != NULL) ? CEventLogString(static_cast<PCWSTR>(pszAssemblyName)) : CEventLogString(L"Assembly Name Unknown"),
  465. CEventLogLastError(ple.LastError()));
  466. ple.Restore();
  467. }
  468. return fSuccess;
  469. }
  470. BOOL
  471. SxspResolvePartialReference(
  472. DWORD Flags,
  473. PCASSEMBLY ParsingAssemblyContext,
  474. PACTCTXGENCTX pActCtxGenCtx,
  475. const CAssemblyReference &PartialReference,
  476. CProbedAssemblyInformation &ProbedAssemblyInformation,
  477. bool &rfFound
  478. )
  479. {
  480. FN_PROLOG_WIN32
  481. CSmartPtr<CSxspResolvePartialReferenceLocals> Locals;
  482. IFW32FALSE_EXIT(Locals.Win32Allocate(__FILE__, __LINE__));
  483. IFW32FALSE_EXIT(
  484. SxspResolvePartialReference(
  485. Flags,
  486. ParsingAssemblyContext,
  487. pActCtxGenCtx,
  488. PartialReference,
  489. ProbedAssemblyInformation,
  490. rfFound,
  491. Locals
  492. ));
  493. FN_EPILOG
  494. }
  495. BOOL
  496. SxspAddManifestToActCtxGenCtx(
  497. PACTCTXGENCTX pActCtxGenCtx,
  498. CProbedAssemblyInformation &ProbedInformation,
  499. PASSEMBLY *AssemblyOut
  500. )
  501. {
  502. BOOL fSuccess = FALSE;
  503. FN_TRACE_WIN32(fSuccess);
  504. PASSEMBLY Asm = NULL;
  505. PCWSTR ProbedAssemblyName = 0;
  506. SIZE_T ProbedAssemblyNameCch = 0;
  507. if (AssemblyOut != NULL)
  508. *AssemblyOut = NULL;
  509. PARAMETER_CHECK(pActCtxGenCtx != NULL);
  510. IFW32FALSE_EXIT(ProbedInformation.GetAssemblyName(&ProbedAssemblyName, &ProbedAssemblyNameCch));
  511. // NTRAID#NTBUG9 - 571854 - 2002/03/26 - xiaoyuw:
  512. // INTERNAL_ERROR_CHECK or ASSERT should be added here
  513. // INTERNAL_ERROR_CHECK(ProbedAssemblyName != NULL && ProbedAssemblyNameCch != 0);
  514. // First, let's see if we've already found this assembly.
  515. IFW32FALSE_EXIT(::SxspFindAssemblyByName(pActCtxGenCtx, ProbedAssemblyName, ProbedAssemblyNameCch, &Asm));
  516. // Same name... if the metadata is different, we're in trouble.
  517. if (Asm != NULL)
  518. {
  519. BOOL fEqualIdentity;
  520. // Both identities should be definitions, so no need to set the ref-matches-def flag...
  521. IFW32FALSE_EXIT(
  522. ::SxsAreAssemblyIdentitiesEqual(
  523. SXS_ARE_ASSEMBLY_IDENTITIES_EQUAL_FLAG_ALLOW_REF_TO_MATCH_DEF,
  524. Asm->GetAssemblyIdentity(),
  525. ProbedInformation.GetAssemblyIdentity(),
  526. &fEqualIdentity));
  527. if (!fEqualIdentity)
  528. {
  529. PCWSTR MP1 = L"<unavailable>";
  530. PCWSTR MP2 = MP1;
  531. ProbedInformation.GetManifestPath(&MP1, NULL);
  532. Asm->m_ProbedAssemblyInformation.GetManifestPath(&MP2, NULL);
  533. Asm = NULL;
  534. ::FusionpDbgPrintEx(FUSION_DBG_LEVEL_ERROR, "SXS.DLL: Failing to add new manifest %S to activation context because it conflicts with existing %S\n", MP1, MP2);
  535. ORIGINATE_WIN32_FAILURE_AND_EXIT(VersionConflict, ERROR_SXS_VERSION_CONFLICT);
  536. }
  537. }
  538. if (Asm == NULL)
  539. {
  540. IFALLOCFAILED_EXIT(Asm = FUSION_NEW_SINGLETON(ASSEMBLY));
  541. IFW32FALSE_EXIT(::SxspInitAssembly(Asm, ProbedInformation));
  542. IFW32FALSE_EXIT(::SxspAddAssemblyToActivationContextGenerationContext(pActCtxGenCtx, Asm));
  543. }
  544. if (AssemblyOut != NULL)
  545. {
  546. *AssemblyOut = Asm;
  547. Asm = NULL;
  548. }
  549. fSuccess = TRUE;
  550. Exit:
  551. if (Asm != NULL)
  552. Asm->Release();
  553. return fSuccess;
  554. }
  555. BOOL
  556. SxspAddAssemblyToActivationContextGenerationContext(
  557. PACTCTXGENCTX pActCtxGenCtx,
  558. PASSEMBLY Asm
  559. )
  560. {
  561. BOOL fSuccess = FALSE;
  562. FN_TRACE_WIN32(fSuccess);
  563. PARAMETER_CHECK(pActCtxGenCtx != NULL);
  564. PARAMETER_CHECK(Asm != NULL);
  565. // If you hit either of these asserts, either the assembly structure has been trashed or
  566. // it's already been added to the generation context.
  567. ASSERT(Asm->m_AssemblyRosterIndex == 0);
  568. Asm->m_AssemblyRosterIndex = pActCtxGenCtx->m_NextAssemblyRosterIndex++;
  569. pActCtxGenCtx->m_AssemblyList.AddToTail(Asm);
  570. Asm->AddRef();
  571. if (pActCtxGenCtx->m_ManifestOperation != MANIFEST_OPERATION_INSTALL)
  572. {
  573. PCWSTR AssemblyName = NULL;
  574. IFW32FALSE_EXIT(Asm->GetAssemblyName(&AssemblyName, NULL));
  575. IFW32FALSE_EXIT(pActCtxGenCtx->m_AssemblyTable.Insert(AssemblyName, Asm, ERROR_SXS_DUPLICATE_ASSEMBLY_NAME));
  576. }
  577. fSuccess = TRUE;
  578. Exit:
  579. return fSuccess;
  580. }
  581. BOOL
  582. SxspFindAssemblyByName(
  583. PACTCTXGENCTX pActCtxGenCtx,
  584. PCWSTR AssemblyName,
  585. SIZE_T AssemblyNameCch,
  586. PASSEMBLY *AssemblyOut
  587. )
  588. {
  589. BOOL fSuccess = FALSE;
  590. FN_TRACE_WIN32(fSuccess);
  591. CSmallStringBuffer AssemblyNameBuffer;
  592. PASSEMBLY Result = NULL;
  593. if (AssemblyOut != NULL)
  594. *AssemblyOut = NULL;
  595. PARAMETER_CHECK(AssemblyOut != NULL);
  596. PARAMETER_CHECK(pActCtxGenCtx != NULL);
  597. // Unfortunately, we really need the string to be null terminated...
  598. IFW32FALSE_EXIT(AssemblyNameBuffer.Win32Assign(AssemblyName, AssemblyNameCch));
  599. AssemblyName = AssemblyNameBuffer;
  600. IFW32FALSE_EXIT(pActCtxGenCtx->m_AssemblyTable.Find(AssemblyName, Result));
  601. if (Result != NULL)
  602. Result->AddRef();
  603. *AssemblyOut = Result;
  604. fSuccess = TRUE;
  605. Exit:
  606. return fSuccess;
  607. }
  608. BOOL
  609. SxspAddRootManifestToActCtxGenCtx(
  610. PACTCTXGENCTX pActCtxGenCtx,
  611. PCSXS_GENERATE_ACTIVATION_CONTEXT_PARAMETERS Parameters
  612. )
  613. {
  614. FN_PROLOG_WIN32
  615. CProbedAssemblyInformation AssemblyInfo;
  616. PARAMETER_CHECK(Parameters != NULL);
  617. PARAMETER_CHECK(pActCtxGenCtx != NULL);
  618. #define IS_NT_DOS_PATH(_x) (IS_PATH_SEPARATOR_U((_x)[0]) && ((_x)[1] == L'?') && ((_x)[2] == L'?') && IS_PATH_SEPARATOR_U((_x)[3]))
  619. PARAMETER_CHECK((Parameters->AssemblyDirectory == NULL) || (IS_NT_DOS_PATH(Parameters->AssemblyDirectory) == FALSE));
  620. PARAMETER_CHECK((Parameters->AssemblyDirectory == NULL) || (IS_NT_DOS_PATH(Parameters->AssemblyDirectory) == FALSE));
  621. PARAMETER_CHECK((Parameters->Manifest.Path == NULL) || (IS_NT_DOS_PATH(Parameters->Manifest.Path) == FALSE));
  622. PARAMETER_CHECK((Parameters->Policy.Path == NULL) || (IS_NT_DOS_PATH(Parameters->Policy.Path) == FALSE));
  623. IFW32FALSE_EXIT(AssemblyInfo.Initialize(pActCtxGenCtx));
  624. IFW32FALSE_EXIT(AssemblyInfo.SetManifestPath(
  625. ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE,
  626. Parameters->Manifest.Path,
  627. (Parameters->Manifest.Path != NULL) ? ::wcslen(Parameters->Manifest.Path) : 0));
  628. ASSERT(Parameters->Manifest.Stream != NULL);
  629. IFW32FALSE_EXIT(AssemblyInfo.SetManifestStream(Parameters->Manifest.Stream));
  630. IFW32FALSE_EXIT(AssemblyInfo.SetManifestFlags(ASSEMBLY_MANIFEST_FILETYPE_STREAM));
  631. IFW32FALSE_EXIT(AssemblyInfo.SetPolicyPath(
  632. ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE,
  633. Parameters->Policy.Path,
  634. (Parameters->Policy.Path != NULL) ? ::wcslen(Parameters->Policy.Path) : 0));
  635. IFW32FALSE_EXIT(AssemblyInfo.SetPolicyStream(Parameters->Policy.Stream));
  636. IFW32FALSE_EXIT(AssemblyInfo.SetPolicyFlags(ASSEMBLY_POLICY_FILETYPE_STREAM));
  637. IFW32FALSE_EXIT(::SxspAddManifestToActCtxGenCtx(pActCtxGenCtx, AssemblyInfo, NULL));
  638. FN_EPILOG
  639. #undef IS_NT_DOS_PATH
  640. }
  641. BOOL
  642. SxspInitAssembly(
  643. PASSEMBLY Asm,
  644. CProbedAssemblyInformation &AssemblyInfo
  645. )
  646. {
  647. BOOL fSuccess = FALSE;
  648. FN_TRACE_WIN32(fSuccess);
  649. PARAMETER_CHECK(Asm != NULL);
  650. IFW32FALSE_EXIT(Asm->m_ProbedAssemblyInformation.InitializeTakeValue(AssemblyInfo));
  651. Asm->m_Incorporated = FALSE;
  652. Asm->m_ManifestVersionMajor = 0;
  653. Asm->m_ManifestVersionMinor = 0;
  654. fSuccess = TRUE;
  655. Exit:
  656. return fSuccess;
  657. }
  658. class CSxspIncorporateAssemblyLocals
  659. {
  660. public:
  661. #if FUSION_XML_TREE
  662. SXS_XML_STRING LocalStringArray[128];
  663. PSXS_XML_STRING ActualStringArray;
  664. #endif
  665. STATSTG statstg;
  666. ACTCTXCTB_ASSEMBLY_CONTEXT AssemblyContext;
  667. CStringBuffer TextuallyEncodedIdentityBuffer;
  668. CFileStream ProbeFileTypeStream;
  669. CFileStream FileStream;
  670. };
  671. BOOL
  672. SxspIncorporateAssembly(
  673. PACTCTXGENCTX pActCtxGenCtx,
  674. PASSEMBLY Asm,
  675. CSxspIncorporateAssemblyLocals *Locals
  676. )
  677. {
  678. BOOL fSuccess = FALSE;
  679. FN_TRACE_WIN32(fSuccess);
  680. HRESULT hr = 0;
  681. ULONG i = 0;
  682. ACTCTXCTB_ASSEMBLY_CONTEXT &AssemblyContext = Locals->AssemblyContext;
  683. const bool fInstalling = (pActCtxGenCtx->m_ManifestOperation == MANIFEST_OPERATION_INSTALL);
  684. ULONG ManifestType = (Asm->m_ProbedAssemblyInformation.GetManifestFlags() & ASSEMBLY_MANIFEST_FILETYPE_MASK);
  685. CImpersonate impersonate(pActCtxGenCtx->m_ImpersonationData);
  686. SXS_POLICY_SOURCE s;
  687. #if FUSION_XML_TREE
  688. PSXS_XML_STRING ActualStringArray = Locals->LocalStringArray;
  689. #endif
  690. STATSTG &statstg = Locals->statstg;
  691. // declaration order here is partially deliberate, to control cleanup order.
  692. // normally, declaration order is determined by not declaring until you have
  693. // the data to initialize with the ctor, but the use of goto messes that up
  694. CFileStream &FileStream = Locals->FileStream;
  695. CSmartPtr<CResourceStream> ResourceStream;
  696. CSmartPtr<CTeeStreamWithHash> TeeStreamForManifestInstall;
  697. #if FUSION_PRECOMPILED_MANIFEST
  698. CSmartPtr<CPrecompiledManifestWriterStream> pcmWriterStream;
  699. #endif
  700. CNodeFactory *pNodeFactory = NULL;
  701. CSmartRef<IXMLParser> pIXMLParser;
  702. PASSEMBLY_IDENTITY AssemblyIdentity = NULL;
  703. CStringBuffer &TextuallyEncodedIdentityBuffer = Locals->TextuallyEncodedIdentityBuffer;
  704. PCWSTR ManifestPath = NULL;
  705. PARAMETER_CHECK(Asm != NULL);
  706. PARAMETER_CHECK(!Asm->m_Incorporated);
  707. PARAMETER_CHECK(pActCtxGenCtx != NULL);
  708. // set flags
  709. AssemblyContext.Flags = 0;
  710. s = Asm->m_ProbedAssemblyInformation.GetPolicySource();
  711. if ( s == SXS_POLICY_SYSTEM_POLICY)
  712. AssemblyContext.Flags |= ACTCTXCTB_ASSEMBLY_CONTEXT_ASSEMBLY_POLICY_APPLIED;
  713. else if (s == SXS_POLICY_ROOT_POLICY)
  714. AssemblyContext.Flags |= ACTCTXCTB_ASSEMBLY_CONTEXT_ROOT_POLICY_APPLIED;
  715. if (Asm->IsRoot())
  716. AssemblyContext.Flags |= ACTCTXCTB_ASSEMBLY_CONTEXT_IS_ROOT_ASSEMBLY;
  717. if (Asm->m_ProbedAssemblyInformation.IsPrivateAssembly())
  718. AssemblyContext.Flags |= ACTCTXCTB_ASSEMBLY_CONTEXT_IS_PRIVATE_ASSEMBLY;
  719. if (Asm->m_ProbedAssemblyInformation.GetAssemblyIdentity() != NULL)
  720. {
  721. // Convert the identity into a somewhat human-readable form that we can log etc.
  722. IFW32FALSE_EXIT(
  723. ::SxspGenerateTextualIdentity(
  724. 0,
  725. Asm->m_ProbedAssemblyInformation.GetAssemblyIdentity(),
  726. TextuallyEncodedIdentityBuffer));
  727. AssemblyContext.TextuallyEncodedIdentity = TextuallyEncodedIdentityBuffer;
  728. AssemblyContext.TextuallyEncodedIdentityCch = TextuallyEncodedIdentityBuffer.Cch();
  729. }
  730. else
  731. {
  732. AssemblyContext.TextuallyEncodedIdentity = L"<identity unavailable>";
  733. AssemblyContext.TextuallyEncodedIdentityCch = 22;
  734. }
  735. // copy assembly-identity info
  736. IFW32FALSE_EXIT(::SxsDuplicateAssemblyIdentity(SXS_DUPLICATE_ASSEMBLY_IDENTITY_FLAG_ALLOW_NULL, Asm->m_ProbedAssemblyInformation.GetAssemblyIdentity(), &AssemblyIdentity));
  737. AssemblyContext.AssemblyIdentity = AssemblyIdentity; // assign to pointer-to-const in the struct; can't pass struct member pointer directly
  738. IFW32FALSE_EXIT(Asm->m_ProbedAssemblyInformation.GetManifestPath(&AssemblyContext.ManifestPath, &AssemblyContext.ManifestPathCch));
  739. AssemblyContext.ManifestPathType = Asm->GetManifestPathType();
  740. IFW32FALSE_EXIT(Asm->m_ProbedAssemblyInformation.GetPolicyPath(AssemblyContext.PolicyPath, AssemblyContext.PolicyPathCch));
  741. AssemblyContext.PolicyPathType = Asm->GetPolicyPathType();
  742. AssemblyContext.AssemblyRosterIndex = Asm->m_AssemblyRosterIndex;
  743. if (fInstalling)
  744. {
  745. IFW32FALSE_EXIT(TeeStreamForManifestInstall.Win32Allocate(__FILE__, __LINE__));
  746. AssemblyContext.TeeStreamForManifestInstall = TeeStreamForManifestInstall;
  747. AssemblyContext.InstallationInfo = pActCtxGenCtx->m_InstallationContext.InstallSource;
  748. AssemblyContext.SecurityMetaData = pActCtxGenCtx->m_InstallationContext.SecurityMetaData;
  749. AssemblyContext.InstallReferenceData = pActCtxGenCtx->m_InstallationContext.InstallReferenceData;
  750. #if FUSION_PRECOMPILED_MANIFEST
  751. IFW32FALSE_EXIT(pcmWriterStream.Win32Allocate(__FILE__, __LINE__);
  752. AssemblyContext.pcmWriterStream = pcmWriterStream ;
  753. #endif
  754. }
  755. else
  756. {
  757. AssemblyContext.SecurityMetaData = NULL;
  758. AssemblyContext.TeeStreamForManifestInstall = NULL;
  759. AssemblyContext.InstallationInfo = NULL;
  760. #if FUSION_PRECOMPILED_MANIFEST
  761. AssemblyContext.pcmWriterStream = NULL;
  762. #endif
  763. }
  764. if (pActCtxGenCtx->m_pNodeFactory == NULL)
  765. {
  766. IFALLOCFAILED_EXIT(pActCtxGenCtx->m_pNodeFactory = new CNodeFactory);
  767. pActCtxGenCtx->m_pNodeFactory->AddRef(); // faked function
  768. }
  769. else
  770. pActCtxGenCtx->m_pNodeFactory->ResetParseState();
  771. IFW32FALSE_EXIT(pActCtxGenCtx->m_pNodeFactory->Initialize(pActCtxGenCtx, Asm, &AssemblyContext));
  772. pNodeFactory = pActCtxGenCtx->m_pNodeFactory;
  773. ASSERT(pNodeFactory != NULL);
  774. // Everyone's ready; let's get the XML parser:
  775. IFW32FALSE_EXIT(::SxspGetXMLParser(IID_IXMLParser, (LPVOID *) &pIXMLParser));
  776. IFCOMFAILED_EXIT(pIXMLParser->SetFactory(pNodeFactory));
  777. //
  778. // open the file or map the resource into memory
  779. //
  780. IStream* Stream; // deliberatly not "smart", we don't refcount it
  781. Stream = NULL;
  782. { // scope for impersonation for file open
  783. IFW32FALSE_EXIT(impersonate.Impersonate());
  784. if (ManifestType == ASSEMBLY_MANIFEST_FILETYPE_AUTO_DETECT)
  785. {
  786. //
  787. // decide between xml in its own text file or a resource
  788. // in a "portable executable" by checking for the portable executable
  789. // signature, "MZ".
  790. //
  791. BYTE buffer[2] = {0,0};
  792. ULONG cbRead = 0;
  793. CFileStream &ProbeFileTypeStream = Locals->ProbeFileTypeStream;
  794. IFW32FALSE_EXIT(Asm->m_ProbedAssemblyInformation.GetManifestPath(&ManifestPath, NULL));
  795. IFW32FALSE_EXIT(
  796. ProbeFileTypeStream.OpenForRead(
  797. ManifestPath,
  798. CImpersonationData(),
  799. FILE_SHARE_READ,
  800. OPEN_EXISTING,
  801. FILE_FLAG_SEQUENTIAL_SCAN));
  802. IFCOMFAILED_EXIT(ProbeFileTypeStream.Read(buffer, 2, &cbRead));
  803. if (cbRead != 2)
  804. ORIGINATE_WIN32_FAILURE_AND_EXIT(ManifestLessThanTwoBytesLong, ERROR_SXS_MANIFEST_FORMAT_ERROR);
  805. IFW32FALSE_EXIT(ProbeFileTypeStream.Close());
  806. // MS-DOS stub, Mark Zbikowski
  807. if (buffer[0] == 'M' && buffer[1] == 'Z')
  808. {
  809. // should we do further checking, like that PE\0\0 occurs
  810. // where the MS-DOS header says it is?
  811. ManifestType = ASSEMBLY_MANIFEST_FILETYPE_RESOURCE;
  812. }
  813. else
  814. {
  815. ManifestType = ASSEMBLY_MANIFEST_FILETYPE_FILE;
  816. }
  817. }
  818. switch (ManifestType)
  819. {
  820. case ASSEMBLY_MANIFEST_FILETYPE_RESOURCE:
  821. {
  822. if (ManifestPath == NULL)
  823. IFW32FALSE_EXIT(Asm->m_ProbedAssemblyInformation.GetManifestPath(&ManifestPath, NULL));
  824. IFW32FALSE_EXIT(ResourceStream.Win32Allocate(__FILE__, __LINE__));
  825. IFW32FALSE_EXIT(ResourceStream->Initialize(ManifestPath, MAKEINTRESOURCEW(RT_MANIFEST)));
  826. Stream = ResourceStream;
  827. break;
  828. }
  829. case ASSEMBLY_MANIFEST_FILETYPE_FILE:
  830. {
  831. if (ManifestPath == NULL)
  832. IFW32FALSE_EXIT(Asm->m_ProbedAssemblyInformation.GetManifestPath(&ManifestPath, NULL));
  833. IFW32FALSE_EXIT(
  834. FileStream.OpenForRead(
  835. ManifestPath,
  836. CImpersonationData(),
  837. FILE_SHARE_READ,
  838. OPEN_EXISTING,
  839. FILE_FLAG_SEQUENTIAL_SCAN));
  840. Stream = &FileStream;
  841. break;
  842. }
  843. case ASSEMBLY_MANIFEST_FILETYPE_STREAM:
  844. Stream = Asm->m_ProbedAssemblyInformation.GetManifestStream();
  845. break;
  846. default:
  847. ASSERT2(FALSE, "unknown manifest file type");
  848. break;
  849. }
  850. IFW32FALSE_EXIT(impersonate.Unimpersonate());
  851. }
  852. //
  853. // Optionally "tee" the manifest so it gets copied into
  854. // the store while we read it, buffering until we know where in
  855. // the store it goes. The manifest itself is not referenced
  856. // in the manifest.
  857. //
  858. if (fInstalling)
  859. {
  860. IFW32FALSE_EXIT(TeeStreamForManifestInstall->InitCryptHash(CALG_SHA1));
  861. TeeStreamForManifestInstall->SetSource(Stream);
  862. Stream = TeeStreamForManifestInstall;
  863. }
  864. //
  865. // We get E_NOTIMPL on the OutOfProcessMemoryStreams in the AppCompat case.
  866. //
  867. IFCOMFAILED_EXIT(((hr = Stream->Stat(&statstg, STATFLAG_NONAME)) != E_NOTIMPL) ? hr : NOERROR);
  868. if (hr == E_NOTIMPL)
  869. {
  870. statstg.mtime.dwLowDateTime = 0;
  871. statstg.mtime.dwHighDateTime = 0;
  872. }
  873. IFW32FALSE_EXIT(
  874. pNodeFactory->SetParseType(
  875. XML_FILE_TYPE_MANIFEST,
  876. Asm->m_ProbedAssemblyInformation.GetManifestPathType(),
  877. Asm->m_ProbedAssemblyInformation.GetManifestPath(),
  878. statstg.mtime));
  879. INTERNAL_ERROR_CHECK(Stream != NULL);
  880. IFCOMFAILED_EXIT(pIXMLParser->SetInput(Stream));
  881. IFCOMFAILED_EXIT(pIXMLParser->Run(-1));
  882. IFW32FALSE_EXIT(FileStream.Close());
  883. #if FUSION_PRECOMPILED_MANIFEST
  884. IFW32FALSE_EXIT((AssemblyContext.pcmWriterStream == NULL) || (pcmWriterStream.Close()));
  885. #endif
  886. // Tell the contributors we're done parsing this file
  887. for (i=0; i<pActCtxGenCtx->m_ContributorCount; i++)
  888. IFW32FALSE_EXIT(
  889. pActCtxGenCtx->m_Contributors[i].Fire_ParseEnding(
  890. pActCtxGenCtx,
  891. &AssemblyContext));
  892. #if FUSION_XML_TREE
  893. // Now let's fill in the document's string table.
  894. StringTableEntryCount = pNodeFactory->m_ParseTreeStringPool.GetEntryCount() + 1;
  895. if (StringTableEntryCount > NUMBER_OF(Locals->LocalStringArray))
  896. IFALLOCFAILED_EXIT(ActualStringArray = FUSION_NEW_ARRAY(SXS_XML_STRING, StringTableEntryCount));
  897. IFW32FALSE_EXIT(pNodeFactory->m_ParseTreeStringPool.FillInStringArray(StringTableEntryCount, ActualStringArray, EntriesFilledIn));
  898. // The size should have been an exact match.
  899. ASSERT(EntriesFilledIn == StringTableEntryCount);
  900. pNodeFactory->m_XmlDocument.StringCount = EntriesFilledIn;
  901. pNodeFactory->m_XmlDocument.Strings = ActualStringArray;
  902. ::SxspDumpXmlTree(0, &(pNodeFactory->m_XmlDocument));
  903. pNodeFactory->m_XmlDocument.StringCount = 0;
  904. pNodeFactory->m_XmlDocument.Strings = NULL;
  905. if (ActualStringArray != Locals->LocalStringArray)
  906. {
  907. FUSION_DELETE_ARRAY(ActualStringArray);
  908. ActualStringArray = NULL;
  909. }
  910. #endif // FUSION_XML_TREE
  911. Asm->m_Incorporated = TRUE;
  912. fSuccess = TRUE;
  913. Exit:
  914. // And tell them we're done.
  915. for (i=0; i<pActCtxGenCtx->m_ContributorCount; i++)
  916. pActCtxGenCtx->m_Contributors[i].Fire_ParseEnded(pActCtxGenCtx, &AssemblyContext);
  917. return fSuccess;
  918. }
  919. BOOL
  920. SxspIncorporateAssembly(
  921. PACTCTXGENCTX pActCtxGenCtx,
  922. PASSEMBLY Asm
  923. )
  924. {
  925. FN_PROLOG_WIN32
  926. CSmartPtr<CSxspIncorporateAssemblyLocals> Locals;
  927. PARAMETER_CHECK(Asm != NULL);
  928. PARAMETER_CHECK(!Asm->m_Incorporated);
  929. PARAMETER_CHECK(pActCtxGenCtx != NULL);
  930. IFW32FALSE_EXIT(Locals.Win32Allocate(__FILE__, __LINE__));
  931. IFW32FALSE_EXIT(::SxspIncorporateAssembly(pActCtxGenCtx, Asm, Locals));
  932. FN_EPILOG
  933. }
  934. BOOL
  935. SxspEnqueueAssemblyReference(
  936. PACTCTXGENCTX pActCtxGenCtx,
  937. PASSEMBLY SourceAssembly,
  938. PCASSEMBLY_IDENTITY Identity,
  939. bool Optional,
  940. bool MetadataSatellite
  941. )
  942. {
  943. FN_PROLOG_WIN32
  944. CSmartPtr<CPendingAssembly> PendingAssembly;
  945. PARAMETER_CHECK(Identity != NULL);
  946. PARAMETER_CHECK(pActCtxGenCtx != NULL);
  947. IFW32FALSE_EXIT(PendingAssembly.Win32Allocate(__FILE__, __LINE__));
  948. IFW32FALSE_EXIT(PendingAssembly->Initialize(SourceAssembly, Identity, Optional, MetadataSatellite));
  949. pActCtxGenCtx->m_PendingAssemblyList.AddToTail(PendingAssembly.Detach());
  950. FN_EPILOG
  951. }
  952. class CSxspProcessPendingAssembliesLocals
  953. {
  954. public:
  955. CSmallStringBuffer buffName;
  956. CProbedAssemblyInformation MuiAssemblyFound;
  957. CProbedAssemblyInformation AssemblyFound;
  958. };
  959. BOOL
  960. SxspProcessPendingAssemblies(
  961. PACTCTXGENCTX pActCtxGenCtx,
  962. CSxspProcessPendingAssembliesLocals *Locals
  963. )
  964. {
  965. FN_PROLOG_WIN32
  966. CPendingAssembly *EntryToDelete = NULL;
  967. CSmartPtrWithNamedDestructor<ASSEMBLY_IDENTITY, SxsDestroyAssemblyIdentity> MuiAssemblyIdentity;
  968. CDequeIterator<CPendingAssembly, offsetof(CPendingAssembly, m_Linkage)> Iter(&pActCtxGenCtx->m_PendingAssemblyList);
  969. PARAMETER_CHECK(pActCtxGenCtx != NULL);
  970. for (Iter.Reset(); Iter.More(); Iter.Next())
  971. {
  972. bool fFound = false;
  973. CAssemblyReference TargetAssemblyRef;
  974. CProbedAssemblyInformation &AssemblyFound = Locals->AssemblyFound;
  975. AssemblyFound.Reinitialize();
  976. CSmartRef<ASSEMBLY> Assembly;
  977. if (EntryToDelete != NULL)
  978. {
  979. pActCtxGenCtx->m_PendingAssemblyList.Remove(EntryToDelete);
  980. FUSION_DELETE_SINGLETON(EntryToDelete);
  981. }
  982. EntryToDelete = NULL;
  983. IFW32FALSE_EXIT(AssemblyFound.Initialize(pActCtxGenCtx));
  984. IFW32FALSE_EXIT(TargetAssemblyRef.Initialize(Iter->GetIdentity()));
  985. IFW32FALSE_EXIT(
  986. ::SxspResolvePartialReference(
  987. Iter->IsOptional() ? SXSP_RESOLVE_PARTIAL_REFERENCE_FLAG_OPTIONAL : 0,
  988. Iter->SourceAssembly(),
  989. pActCtxGenCtx,
  990. TargetAssemblyRef,
  991. AssemblyFound,
  992. fFound));
  993. INTERNAL_ERROR_CHECK(fFound || Iter->IsOptional());
  994. if (fFound)
  995. {
  996. PCASSEMBLY_IDENTITY pAssemblyIdentity = NULL;
  997. PCWSTR szLanguage;
  998. SIZE_T cchLanguage;
  999. IFW32FALSE_EXIT(::SxspAddManifestToActCtxGenCtx(pActCtxGenCtx, AssemblyFound, &Assembly));
  1000. // Note that AssemblyFound is no longer intact; this is to avoid duplication of
  1001. // the assembly identity inside the SxspAddManifestToActCtxGenCtx() call.
  1002. if (Iter->IsMetadataSatellite())
  1003. Iter->SourceAssembly()->m_MetadataSatelliteRosterIndex = Assembly->m_AssemblyRosterIndex;
  1004. // If it's a worldwide assembly, we want to auto-probe for the MUI assembly
  1005. IFW32FALSE_EXIT(
  1006. ::SxspGetAssemblyIdentityAttributeValue(
  1007. SXSP_GET_ASSEMBLY_IDENTITY_ATTRIBUTE_VALUE_FLAG_NOT_FOUND_RETURNS_NULL,
  1008. Assembly->m_ProbedAssemblyInformation.GetAssemblyIdentity(),
  1009. &s_IdentityAttribute_language,
  1010. &szLanguage,
  1011. &cchLanguage));
  1012. if (cchLanguage == 0)
  1013. {
  1014. CSmallStringBuffer &buffName = Locals->buffName;
  1015. PCWSTR szName;
  1016. SIZE_T cchName;
  1017. CProbedAssemblyInformation &MuiAssemblyFound = Locals->MuiAssemblyFound;
  1018. MuiAssemblyFound.Reinitialize();
  1019. CAssemblyReference MuiAssemblyRef;
  1020. ::SxsDestroyAssemblyIdentity(MuiAssemblyIdentity.Detach());
  1021. IFW32FALSE_EXIT(
  1022. ::SxsDuplicateAssemblyIdentity(
  1023. 0,
  1024. Assembly->m_ProbedAssemblyInformation.GetAssemblyIdentity(), // PCASSEMBLY_IDENTITY Source,
  1025. &MuiAssemblyIdentity));
  1026. IFW32FALSE_EXIT(
  1027. ::SxspSetAssemblyIdentityAttributeValue(
  1028. SXSP_SET_ASSEMBLY_IDENTITY_ATTRIBUTE_VALUE_FLAG_OVERWRITE_EXISTING,
  1029. MuiAssemblyIdentity,
  1030. &s_IdentityAttribute_language,
  1031. L"*",
  1032. 1));
  1033. IFW32FALSE_EXIT(
  1034. ::SxspGetAssemblyIdentityAttributeValue(
  1035. 0,
  1036. MuiAssemblyIdentity,
  1037. &s_IdentityAttribute_name,
  1038. &szName,
  1039. &cchName));
  1040. IFW32FALSE_EXIT(buffName.Win32Assign(szName, cchName));
  1041. IFW32FALSE_EXIT(buffName.Win32Append(L".mui", 4));
  1042. IFW32FALSE_EXIT(
  1043. ::SxspSetAssemblyIdentityAttributeValue(
  1044. SXSP_SET_ASSEMBLY_IDENTITY_ATTRIBUTE_VALUE_FLAG_OVERWRITE_EXISTING,
  1045. MuiAssemblyIdentity,
  1046. &s_IdentityAttribute_name,
  1047. buffName,
  1048. buffName.Cch()));
  1049. IFW32FALSE_EXIT(MuiAssemblyFound.Initialize(pActCtxGenCtx));
  1050. IFW32FALSE_EXIT(MuiAssemblyRef.Initialize(MuiAssemblyIdentity));
  1051. IFW32FALSE_EXIT(
  1052. ::SxspResolvePartialReference(
  1053. SXSP_RESOLVE_PARTIAL_REFERENCE_FLAG_OPTIONAL |
  1054. SXSP_RESOLVE_PARTIAL_REFERENCE_FLAG_SKIP_WORLDWIDE,
  1055. Iter->SourceAssembly(),
  1056. pActCtxGenCtx,
  1057. MuiAssemblyRef,
  1058. MuiAssemblyFound,
  1059. fFound));
  1060. if (fFound)
  1061. IFW32FALSE_EXIT(::SxspAddManifestToActCtxGenCtx(pActCtxGenCtx, MuiAssemblyFound, NULL));
  1062. }
  1063. }
  1064. EntryToDelete = Iter;
  1065. }
  1066. if (EntryToDelete != NULL)
  1067. {
  1068. pActCtxGenCtx->m_PendingAssemblyList.Remove(EntryToDelete);
  1069. FUSION_DELETE_SINGLETON(EntryToDelete);
  1070. }
  1071. FN_EPILOG
  1072. }
  1073. BOOL
  1074. SxspProcessPendingAssemblies(
  1075. PACTCTXGENCTX pActCtxGenCtx
  1076. )
  1077. {
  1078. FN_PROLOG_WIN32
  1079. CSmartPtr<CSxspProcessPendingAssembliesLocals> Locals;
  1080. IFW32FALSE_EXIT(Locals.Win32Allocate(__FILE__, __LINE__));
  1081. IFW32FALSE_EXIT(::SxspProcessPendingAssemblies(pActCtxGenCtx, Locals));
  1082. FN_EPILOG
  1083. }
  1084. BOOL
  1085. SxspCloseManifestGraph(
  1086. PACTCTXGENCTX pActCtxGenCtx
  1087. )
  1088. {
  1089. FN_PROLOG_WIN32
  1090. CDequeIterator<ASSEMBLY, offsetof(ASSEMBLY, m_Linkage)> Iter(&pActCtxGenCtx->m_AssemblyList);
  1091. PARAMETER_CHECK(pActCtxGenCtx != NULL);
  1092. // We need to just walk the list of assemblies, incorporating any that aren't already
  1093. // incorporated into the actctx data. New ones found during incorporation are appended
  1094. // to the end of the list, so we should complete everything with a single walk.
  1095. for (Iter.Reset(); Iter.More(); Iter.Next())
  1096. {
  1097. if (!Iter->m_Incorporated)
  1098. {
  1099. IFW32FALSE_EXIT(::SxspIncorporateAssembly(pActCtxGenCtx, Iter));
  1100. }
  1101. else
  1102. {
  1103. PCWSTR AssemblyName = L"<assembly name unavailable>";
  1104. PCWSTR ManifestPath = L"<manifest path unavailable>";
  1105. Iter->m_ProbedAssemblyInformation.GetAssemblyName(&AssemblyName, NULL);
  1106. Iter->m_ProbedAssemblyInformation.GetManifestPath(&ManifestPath, NULL);
  1107. #if DBG
  1108. ::FusionpDbgPrintEx(FUSION_DBG_LEVEL_INFO, "SXS.DLL: Skipping already incorporated assembly %S (manifest: %S)\n", AssemblyName, ManifestPath);
  1109. #endif
  1110. }
  1111. IFW32FALSE_EXIT(::SxspProcessPendingAssemblies(pActCtxGenCtx));
  1112. }
  1113. FN_EPILOG
  1114. }
  1115. BOOL
  1116. SxspBuildActCtxData(
  1117. PACTCTXGENCTX pActCtxGenCtx,
  1118. PHANDLE SectionHandle
  1119. )
  1120. {
  1121. FN_PROLOG_WIN32
  1122. CActivationContextGenerationContextContributor *Ctb = NULL;
  1123. SIZE_T SectionTotalSize = 0;
  1124. SIZE_T TotalHeaderSize = 0;
  1125. SIZE_T AssemblyRosterSize = 0;
  1126. ULONG SectionCount = 0;
  1127. ULONG ExtendedSectionCount = 0;
  1128. ULONG NonExtendedSectionCount = 0;
  1129. CSmartArrayPtr<GUID> ExtendedSectionGuids;
  1130. ULONG ExtensionGuidCount = 0;
  1131. PACTIVATION_CONTEXT_DATA ActCtxData = NULL;
  1132. CMappedViewOfFile VoidActCtxData;
  1133. CFileMapping TempMappingHandle;
  1134. BYTE *Cursor = NULL;
  1135. ULONG i;
  1136. CDequeIterator<ASSEMBLY, offsetof(ASSEMBLY, m_Linkage)> AssemblyIter(&pActCtxGenCtx->m_AssemblyList);
  1137. PACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_HEADER AssemblyRosterHeader = NULL;
  1138. PACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_ENTRY AssemblyRosterEntry = NULL;
  1139. PCACTIVATION_CONTEXT_STRING_SECTION_HEADER AssemblyInformationSection = NULL; // we use this after the main part of
  1140. // processing to fill in the assembly roster
  1141. PARAMETER_CHECK(pActCtxGenCtx != NULL);
  1142. INTERNAL_ERROR_CHECK(pActCtxGenCtx->m_ManifestOperation == MANIFEST_OPERATION_GENERATE_ACTIVATION_CONTEXT);
  1143. // Let's see how big this whole thing is going to be now.
  1144. for (i=0; i<pActCtxGenCtx->m_ContributorCount; i++)
  1145. {
  1146. Ctb = &pActCtxGenCtx->m_Contributors[i];
  1147. IFW32FALSE_EXIT(Ctb->Fire_AllParsingDone(pActCtxGenCtx));
  1148. IFW32FALSE_EXIT(Ctb->Fire_GetSectionSize(pActCtxGenCtx));
  1149. if (Ctb->SectionSize() > ULONG_MAX)
  1150. {
  1151. ::FusionpDbgPrintEx(
  1152. FUSION_DBG_LEVEL_ERROR,
  1153. "SXS.DLL: Contributor %S wants more than ULONG_MAX bytes for its section; failing activation context creation.\n",
  1154. Ctb->Name());
  1155. ORIGINATE_WIN32_FAILURE_AND_EXIT(ContributorNeedsMoreThan2ToThe32ndBytes, ERROR_INSUFFICIENT_BUFFER);
  1156. }
  1157. SectionTotalSize += Ctb->SectionSize();
  1158. if (Ctb->SectionSize() != 0)
  1159. {
  1160. SectionCount++;
  1161. if (Ctb->IsExtendedSection())
  1162. ExtendedSectionCount++;
  1163. else
  1164. NonExtendedSectionCount++;
  1165. }
  1166. }
  1167. ASSERT(SectionCount == (ExtendedSectionCount + NonExtendedSectionCount));
  1168. // If we had any extended sections, we need to figure out how many
  1169. // unique extension GUIDs were present.
  1170. ExtensionGuidCount = 0;
  1171. if (ExtendedSectionCount != 0)
  1172. {
  1173. // There may only be one GUID with 1000 instances, but for the sake of
  1174. // simplicity, we'll just allocate an array equal in size to the number
  1175. // of extended sections, and do a linear search to find dups. This
  1176. // is a clear candidate for rewriting if the extensibility story
  1177. // takes off. -mgrier 2/24/2000
  1178. IFW32FALSE_EXIT(ExtendedSectionGuids.Win32Allocate(ExtendedSectionCount, __FILE__, __LINE__));
  1179. // IFALLOCFAILED_EXIT(ExtendedSectionGuids = FUSION_NEW_ARRAY(GUID, ExtendedSectionCount));
  1180. for (i=0; i<pActCtxGenCtx->m_ContributorCount; i++)
  1181. {
  1182. Ctb = &pActCtxGenCtx->m_Contributors[i];
  1183. if ((Ctb->SectionSize() != 0) &&
  1184. Ctb->IsExtendedSection())
  1185. {
  1186. ULONG j;
  1187. for (j=0; j<ExtensionGuidCount; j++)
  1188. {
  1189. if (ExtendedSectionGuids[j] == Ctb->ExtensionGuid())
  1190. break;
  1191. }
  1192. if (j == ExtensionGuidCount)
  1193. ExtendedSectionGuids[ExtensionGuidCount++] = Ctb->ExtensionGuid();
  1194. }
  1195. }
  1196. }
  1197. // Figure out the entire size. SectionTotalSize already includes all the
  1198. // particular data from the sections; now we need to add in space for the
  1199. // headers etc.
  1200. TotalHeaderSize = 0;
  1201. // The header for the whole thing
  1202. TotalHeaderSize += sizeof(ACTIVATION_CONTEXT_DATA);
  1203. if (NonExtendedSectionCount != 0)
  1204. {
  1205. // The header for the default section TOC
  1206. TotalHeaderSize += sizeof(ACTIVATION_CONTEXT_DATA_TOC_HEADER);
  1207. // The entry for each non-extended section entry in the TOC. For now we'll
  1208. // just put the entries in whatever order they're in in the contributor list.
  1209. // the code is in place to do the linear searches and we can optimize this
  1210. // later.
  1211. TotalHeaderSize += (sizeof(ACTIVATION_CONTEXT_DATA_TOC_ENTRY) * NonExtendedSectionCount);
  1212. }
  1213. if (ExtensionGuidCount != 0)
  1214. {
  1215. ULONG j;
  1216. // The header for the extension GUID TOC
  1217. TotalHeaderSize += sizeof(ACTIVATION_CONTEXT_DATA_EXTENDED_TOC_HEADER);
  1218. // The entry for each extension GUID
  1219. TotalHeaderSize += (sizeof(ACTIVATION_CONTEXT_DATA_EXTENDED_TOC_ENTRY) * ExtensionGuidCount);
  1220. for (j=0; j<ExtensionGuidCount; j++)
  1221. {
  1222. ULONG SectionCountForThisExtension = 0;
  1223. for (j=0; j<pActCtxGenCtx->m_ContributorCount; j++)
  1224. {
  1225. Ctb = &pActCtxGenCtx->m_Contributors[j];
  1226. if ((Ctb->SectionSize() != 0) &&
  1227. Ctb->IsExtendedSection() &&
  1228. (Ctb->ExtensionGuid() == ExtendedSectionGuids[j]))
  1229. SectionCountForThisExtension++;
  1230. }
  1231. TotalHeaderSize += sizeof(ACTIVATION_CONTEXT_DATA_TOC_HEADER);
  1232. TotalHeaderSize += (sizeof(ACTIVATION_CONTEXT_DATA_TOC_ENTRY) * SectionCountForThisExtension);
  1233. }
  1234. }
  1235. SectionTotalSize += TotalHeaderSize;
  1236. // Allocate space for the assembly roster and the one dead entry at the beginning of the array.
  1237. AssemblyRosterSize =
  1238. sizeof(ACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_HEADER)
  1239. + sizeof(ACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_ENTRY)
  1240. + (sizeof(ACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_ENTRY) * pActCtxGenCtx->m_AssemblyList.GetEntryCount());
  1241. SectionTotalSize += AssemblyRosterSize;
  1242. if (SectionTotalSize > ULONG_MAX)
  1243. {
  1244. ::FusionpDbgPrintEx(
  1245. FUSION_DBG_LEVEL_ERROR,
  1246. "SXS.DLL: Total size of activation context exceeds ULONG_MAX; failing activation context creation.\n");
  1247. ORIGINATE_WIN32_FAILURE_AND_EXIT(SectionSizeTotalMoreThan2ToThe32nd, ERROR_INSUFFICIENT_BUFFER);
  1248. goto Exit;
  1249. }
  1250. ::FusionpDbgPrintEx(
  1251. FUSION_DBG_LEVEL_ACTCTX,
  1252. "SXS.DLL: Creating %lu byte file mapping\n", static_cast<ULONG>(SectionTotalSize));
  1253. IFW32NULL_EXIT(
  1254. TempMappingHandle.Win32CreateFileMapping(
  1255. INVALID_HANDLE_VALUE, // Pagefile backed section
  1256. PAGE_READWRITE,
  1257. SectionTotalSize));
  1258. IFW32NULL_EXIT(VoidActCtxData.Win32MapViewOfFile(TempMappingHandle, FILE_MAP_WRITE));
  1259. ActCtxData = reinterpret_cast<PACTIVATION_CONTEXT_DATA>(static_cast<PVOID>(VoidActCtxData));
  1260. ActCtxData->Magic = ACTIVATION_CONTEXT_DATA_MAGIC;
  1261. ActCtxData->HeaderSize = sizeof(ACTIVATION_CONTEXT_DATA);
  1262. ActCtxData->FormatVersion = ACTIVATION_CONTEXT_DATA_FORMAT_WHISTLER;
  1263. ActCtxData->TotalSize = static_cast<ULONG>(SectionTotalSize);
  1264. ActCtxData->Flags = 0;
  1265. if (pActCtxGenCtx->m_NoInherit)
  1266. ActCtxData->Flags |= ACTIVATION_CONTEXT_FLAG_NO_INHERIT;
  1267. Cursor = (BYTE *) (ActCtxData + 1);
  1268. AssemblyRosterHeader = (PACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_HEADER) Cursor;
  1269. Cursor = (BYTE *) (AssemblyRosterHeader + 1);
  1270. AssemblyRosterHeader->HeaderSize = sizeof(ACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_HEADER);
  1271. AssemblyRosterHeader->HashAlgorithm = FUSION_HASH_ALGORITHM;
  1272. AssemblyRosterHeader->EntryCount = static_cast<ULONG>(pActCtxGenCtx->m_AssemblyList.GetEntryCount() + 1);
  1273. AssemblyRosterHeader->FirstEntryOffset = static_cast<LONG>(((LONG_PTR) Cursor) - ((LONG_PTR) ActCtxData));
  1274. AssemblyRosterEntry = (PACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_ENTRY) Cursor;
  1275. Cursor = (BYTE *) (AssemblyRosterEntry + AssemblyRosterHeader->EntryCount);
  1276. // First assembly roster entry is a blank one for index 0
  1277. AssemblyRosterEntry[0].Flags = ACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_ENTRY_INVALID;
  1278. AssemblyRosterEntry[0].AssemblyNameLength = 0;
  1279. AssemblyRosterEntry[0].AssemblyNameOffset = 0;
  1280. AssemblyRosterEntry[0].PseudoKey = 0;
  1281. // Fill in the roster with bogus data to start with; we'll fill it in for real after
  1282. // we've found the assembly information section.
  1283. for (AssemblyIter.Reset(), i = 1; AssemblyIter.More(); AssemblyIter.Next(), i++)
  1284. {
  1285. AssemblyRosterEntry[i].Flags = ACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_ENTRY_INVALID;
  1286. if (AssemblyIter->IsRoot())
  1287. AssemblyRosterEntry[i].Flags |= ACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_ENTRY_ROOT;
  1288. }
  1289. ActCtxData->AssemblyRosterOffset = static_cast<LONG>(((LONG_PTR) AssemblyRosterHeader) - ((LONG_PTR) ActCtxData));
  1290. if (NonExtendedSectionCount != 0)
  1291. {
  1292. PACTIVATION_CONTEXT_DATA_TOC_HEADER Toc = (PACTIVATION_CONTEXT_DATA_TOC_HEADER) Cursor;
  1293. PACTIVATION_CONTEXT_DATA_TOC_ENTRY Entry = (PACTIVATION_CONTEXT_DATA_TOC_ENTRY) (Toc + 1);
  1294. ULONG iEntry = 0;
  1295. ULONG j;
  1296. ULONG LastSectionId;
  1297. Toc->HeaderSize = sizeof(ACTIVATION_CONTEXT_DATA_TOC_HEADER);
  1298. Toc->EntryCount = NonExtendedSectionCount;
  1299. Toc->FirstEntryOffset = static_cast<LONG>(((LONG_PTR) Entry) - ((LONG_PTR) ActCtxData));
  1300. Cursor = (BYTE *) (Entry + NonExtendedSectionCount);
  1301. // Since we sorted the providers prior to building the array, we can set the
  1302. // inorder bit so that we at least do a binary search at runtime.
  1303. // We'll assume it's dense also; if we find out that it isn't while we're
  1304. // building, we'll clear the dense bit.
  1305. Toc->Flags = ACTIVATION_CONTEXT_DATA_TOC_HEADER_INORDER | ACTIVATION_CONTEXT_DATA_TOC_HEADER_DENSE;
  1306. for (j=0; j<pActCtxGenCtx->m_ContributorCount; j++)
  1307. {
  1308. Ctb = &pActCtxGenCtx->m_Contributors[j];
  1309. LastSectionId = 0;
  1310. if ((Ctb->SectionSize() != 0) &&
  1311. !Ctb->IsExtendedSection())
  1312. {
  1313. if (iEntry != 0)
  1314. {
  1315. if (Ctb->SectionId() != (LastSectionId + 1))
  1316. Toc->Flags &= ~ACTIVATION_CONTEXT_DATA_TOC_HEADER_DENSE;
  1317. }
  1318. LastSectionId = Ctb->SectionId();
  1319. Entry->Id = Ctb->SectionId();
  1320. Entry->Offset = static_cast<LONG>(((LONG_PTR) Cursor) - ((LONG_PTR) ActCtxData));
  1321. Entry->Length = static_cast<ULONG>(Ctb->SectionSize());
  1322. Entry->Format = Ctb->SectionFormat();
  1323. IFW32FALSE_EXIT(Ctb->Fire_GetSectionData(pActCtxGenCtx, Cursor));
  1324. // We have special knowledge about the assembly metadata section; we reference it
  1325. // in the assembly roster.
  1326. if (Ctb->SectionId() == ACTIVATION_CONTEXT_SECTION_ASSEMBLY_INFORMATION)
  1327. AssemblyInformationSection = (PCACTIVATION_CONTEXT_STRING_SECTION_HEADER) Cursor;
  1328. Cursor = (BYTE *) (((ULONG_PTR) Cursor) + Ctb->SectionSize());
  1329. Entry++;
  1330. iEntry++;
  1331. }
  1332. }
  1333. ActCtxData->DefaultTocOffset = static_cast<LONG>(((LONG_PTR) Toc) - ((LONG_PTR) ActCtxData));
  1334. }
  1335. else
  1336. ActCtxData->DefaultTocOffset = 0;
  1337. if (ExtensionGuidCount != 0)
  1338. {
  1339. ULONG j;
  1340. PACTIVATION_CONTEXT_DATA_EXTENDED_TOC_HEADER ExtToc = (PACTIVATION_CONTEXT_DATA_EXTENDED_TOC_HEADER) Cursor;
  1341. PACTIVATION_CONTEXT_DATA_EXTENDED_TOC_ENTRY ExtTocEntry = (PACTIVATION_CONTEXT_DATA_EXTENDED_TOC_ENTRY) (ExtToc + 1);
  1342. Cursor = (BYTE *) (ExtTocEntry + ExtensionGuidCount);
  1343. ExtToc->HeaderSize = sizeof(ACTIVATION_CONTEXT_DATA_EXTENDED_TOC_HEADER);
  1344. ExtToc->EntryCount = ExtensionGuidCount;
  1345. ExtToc->FirstEntryOffset = static_cast<LONG>(((LONG_PTR) ExtTocEntry) - ((LONG_PTR) ActCtxData));
  1346. ExtToc->Flags = 0;
  1347. for (j=0; j<ExtensionGuidCount; j++)
  1348. {
  1349. ULONG k;
  1350. ULONG SectionCountForThisExtension = 0;
  1351. PACTIVATION_CONTEXT_DATA_TOC_HEADER Toc = (PACTIVATION_CONTEXT_DATA_TOC_HEADER) Cursor;
  1352. PACTIVATION_CONTEXT_DATA_TOC_ENTRY Entry = (PACTIVATION_CONTEXT_DATA_TOC_ENTRY) (Toc + 1);
  1353. ExtTocEntry->ExtensionGuid = ExtendedSectionGuids[i];
  1354. for (k=0; k<pActCtxGenCtx->m_ContributorCount; k++)
  1355. {
  1356. Ctb = &pActCtxGenCtx->m_Contributors[k];
  1357. if ((Ctb->SectionSize() != 0) &&
  1358. Ctb->IsExtendedSection() &&
  1359. (Ctb->ExtensionGuid() == ExtendedSectionGuids[j]))
  1360. {
  1361. SectionCountForThisExtension++;
  1362. }
  1363. }
  1364. Cursor = (BYTE *) (Entry + SectionCountForThisExtension);
  1365. Toc->HeaderSize = sizeof(ACTIVATION_CONTEXT_DATA_TOC_HEADER);
  1366. Toc->EntryCount = SectionCountForThisExtension;
  1367. Toc->FirstEntryOffset = static_cast<LONG>(((LONG_PTR) Entry) - ((LONG_PTR) ActCtxData));
  1368. Toc->Flags = 0;
  1369. for (k=0; k<pActCtxGenCtx->m_ContributorCount; k++)
  1370. {
  1371. Ctb = &pActCtxGenCtx->m_Contributors[k];
  1372. if ((Ctb->SectionSize() != 0) &&
  1373. Ctb->IsExtendedSection() &&
  1374. (Ctb->ExtensionGuid() == ExtendedSectionGuids[k]) &&
  1375. (Ctb->SectionId() != 0) )
  1376. {
  1377. SIZE_T SectionSize = Ctb->SectionSize();
  1378. Entry->Id = Ctb->SectionId();
  1379. Entry->Offset = static_cast<LONG>(((LONG_PTR) Cursor) - ((LONG_PTR) ActCtxData));
  1380. Entry->Length = static_cast<ULONG>(SectionSize);
  1381. Entry->Format = Ctb->SectionFormat();
  1382. IFW32FALSE_EXIT(Ctb->Fire_GetSectionData(pActCtxGenCtx, Cursor));
  1383. Cursor = (BYTE *) (((ULONG_PTR) Cursor) + SectionSize);
  1384. Entry++;
  1385. }
  1386. }
  1387. }
  1388. ActCtxData->ExtendedTocOffset = static_cast<LONG>(((LONG_PTR) ExtToc) - ((LONG_PTR) ActCtxData));
  1389. }
  1390. else
  1391. ActCtxData->ExtendedTocOffset = 0;
  1392. ASSERT(AssemblyInformationSection != NULL);
  1393. // Go back and fill in the assembly roster...
  1394. if (AssemblyInformationSection != NULL)
  1395. {
  1396. PCACTIVATION_CONTEXT_STRING_SECTION_ENTRY Entries = (PCACTIVATION_CONTEXT_STRING_SECTION_ENTRY)
  1397. (((ULONG_PTR) AssemblyInformationSection) + AssemblyInformationSection->ElementListOffset);
  1398. LONG_PTR SectionOffset = ((LONG_PTR) AssemblyInformationSection) - ((LONG_PTR) ActCtxData);
  1399. AssemblyRosterHeader->HashAlgorithm = AssemblyInformationSection->HashAlgorithm;
  1400. AssemblyRosterHeader->AssemblyInformationSectionOffset = static_cast<ULONG>(SectionOffset);
  1401. // If there are 3 assemblies, there must be 3 entries in the section and 4 roster entries
  1402. // (counting the bogus entry 0).
  1403. ASSERT(AssemblyInformationSection->ElementCount == (AssemblyRosterHeader->EntryCount - 1));
  1404. if (AssemblyInformationSection->ElementCount != (AssemblyRosterHeader->EntryCount - 1))
  1405. {
  1406. ::FusionpSetLastWin32Error(ERROR_INTERNAL_ERROR);
  1407. goto Exit;
  1408. }
  1409. for (i=0; i<AssemblyInformationSection->ElementCount; i++)
  1410. {
  1411. ULONG iRoster = Entries[i].AssemblyRosterIndex;
  1412. ASSERT(iRoster != 0);
  1413. ASSERT(iRoster < AssemblyRosterHeader->EntryCount);
  1414. if ((iRoster == 0) ||
  1415. (iRoster >= AssemblyRosterHeader->EntryCount))
  1416. {
  1417. ::FusionpSetLastWin32Error(ERROR_INTERNAL_ERROR);
  1418. goto Exit;
  1419. }
  1420. // Make sure that we're not repeating an index somehow...
  1421. ASSERT(AssemblyRosterEntry[iRoster].Flags & ACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_ENTRY_INVALID);
  1422. if ((AssemblyRosterEntry[iRoster].Flags & ACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_ENTRY_INVALID) == 0)
  1423. {
  1424. ::FusionpSetLastWin32Error(ERROR_INTERNAL_ERROR);
  1425. goto Exit;
  1426. }
  1427. // Turn off the invalid flag...
  1428. AssemblyRosterEntry[iRoster].Flags &= ~ACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_ENTRY_INVALID;
  1429. // Point to the data already in the string section header
  1430. AssemblyRosterEntry[iRoster].AssemblyNameLength = Entries[i].KeyLength;
  1431. if (Entries[i].KeyOffset != 0)
  1432. AssemblyRosterEntry[iRoster].AssemblyNameOffset = static_cast<LONG>(Entries[i].KeyOffset + SectionOffset);
  1433. else
  1434. AssemblyRosterEntry[iRoster].AssemblyNameOffset = 0;
  1435. AssemblyRosterEntry[iRoster].AssemblyInformationLength = Entries[i].Length;
  1436. AssemblyRosterEntry[iRoster].AssemblyInformationOffset = static_cast<LONG>(Entries[i].Offset + SectionOffset);
  1437. AssemblyRosterEntry[iRoster].PseudoKey = Entries[i].PseudoKey;
  1438. }
  1439. }
  1440. else
  1441. {
  1442. // the assembly metadata section provider should have contributed *something*
  1443. ::FusionpSetLastWin32Error(ERROR_INTERNAL_ERROR);
  1444. goto Exit;
  1445. }
  1446. if (::FusionpDbgWouldPrintAtFilterLevel(FUSION_DBG_LEVEL_ACTCTX))
  1447. {
  1448. CTinyStringBuffer buffPrefix;
  1449. ::SxspDbgPrintActivationContextData(FUSION_DBG_LEVEL_ACTCTX, ActCtxData, buffPrefix);
  1450. }
  1451. IFW32FALSE_EXIT(VoidActCtxData.Win32Close());
  1452. *SectionHandle = TempMappingHandle.Detach();
  1453. FN_EPILOG
  1454. }
  1455. CPendingAssembly::CPendingAssembly() :
  1456. m_SourceAssembly(NULL),
  1457. m_Identity(NULL),
  1458. m_Optional(false),
  1459. m_MetadataSatellite(false)
  1460. {
  1461. }
  1462. CPendingAssembly::~CPendingAssembly()
  1463. {
  1464. if (m_Identity != NULL)
  1465. {
  1466. ::SxsDestroyAssemblyIdentity(m_Identity);
  1467. m_Identity = NULL;
  1468. }
  1469. }
  1470. BOOL
  1471. CPendingAssembly::Initialize(
  1472. PASSEMBLY Assembly,
  1473. PCASSEMBLY_IDENTITY Identity,
  1474. bool Optional,
  1475. bool MetadataSatellite
  1476. )
  1477. {
  1478. BOOL fSuccess = FALSE;
  1479. FN_TRACE_WIN32(fSuccess);
  1480. INTERNAL_ERROR_CHECK(m_Identity == NULL);
  1481. PARAMETER_CHECK(Identity != NULL);
  1482. IFW32FALSE_EXIT(::SxsDuplicateAssemblyIdentity(0, Identity, &m_Identity));
  1483. m_SourceAssembly = Assembly;
  1484. m_Optional = Optional;
  1485. m_MetadataSatellite = MetadataSatellite;
  1486. fSuccess = TRUE;
  1487. Exit:
  1488. return fSuccess;
  1489. }