Source code of Windows XP (NT5)
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.

1726 lines
65 KiB

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