|
|
/*++
Copyright (c) Microsoft Corporation
Module Name:
actctxgen.cpp
Abstract:
APIs for generating activation contexts.
Author:
Michael J. Grier (MGrier) 23-Feb-2000
Revision History: xiaoyuw 09/2000 replace attributes with assembly identity --*/
#include "stdinc.h"
#include <windows.h>
#include <sxsp.h>
#include <ole2.h>
#include <xmlparser.h>
#include "nodefactory.h"
#include <wchar.h>
#include "filestream.h"
#include "fusionhandle.h"
#include "cteestream.h"
#include "cresourcestream.h"
#include "fusionxml.h"
#include "util.h"
#include "sxsexceptionhandling.h"
#include "csxspreservelasterror.h"
#include "smartptr.h"
#include "cstreamtap.h"
#include "pendingassembly.h"
#include "actctxgenctx.h"
BOOL SxspFindAssemblyByName( PACTCTXGENCTX pActCtxGenCtx, PCWSTR AssemblyName, SIZE_T AssemblyNameCch, PASSEMBLY *AssemblyFound );
BOOL SxspAddAssemblyToActivationContextGenerationContext( PACTCTXGENCTX pActCtxGenCtx, PASSEMBLY Asm );
_ACTCTXGENCTX::_ACTCTXGENCTX() : m_Contributors(NULL), m_ContributorCount(0), m_ProcessorArchitecture(0), m_LangID(0), m_Flags(0), m_ManifestOperation(MANIFEST_OPERATION_INVALID), m_ManifestOperationFlags(0), m_NextAssemblyRosterIndex(1), m_fClsidMapInitialized(FALSE), m_InitializedContributorCount(0), m_NoInherit(false), m_pNodeFactory(NULL), m_ulFileCount(0), m_fAppApplyPublisherPolicy(SXS_PUBLISHER_POLICY_APPLY_DEFAULT), m_ApplicationDirectoryHasBeenProbedForLanguageSubdirs(false), m_ApplicationDirectoryHasSpecificLanguageSubdir(false), m_ApplicationDirectoryHasGenericLanguageSubdir(false), m_ApplicationDirectoryHasSpecificSystemLanguageSubdir(false), m_ApplicationDirectoryHasGenericSystemLanguageSubdir(false) { }
_ACTCTXGENCTX::~_ACTCTXGENCTX() { while (m_InitializedContributorCount) { m_InitializedContributorCount -= 1; CActivationContextGenerationContextContributor *Ctb = &m_Contributors[m_InitializedContributorCount];
Ctb->Fire_ParseEnded(this, NULL); Ctb->Fire_ActCtxGenEnded(this); }
FUSION_DELETE_ARRAY(m_Contributors); m_Contributors = NULL;
m_AssemblyTable.ClearNoCallback(); m_ComponentPolicyTable.ClearNoCallback(); m_PendingAssemblyList.Clear(&CPendingAssembly::DeleteYourself); m_AssemblyList.Clear(&ASSEMBLY::Release);
if (m_fClsidMapInitialized) { m_fClsidMapInitialized = false; VERIFY_NTC(m_ClsidMap.Uninitialize()); }
FUSION_DELETE_SINGLETON(m_pNodeFactory); m_pNodeFactory = NULL; }
BOOL SxspInitActCtxGenCtx( PACTCTXGENCTX pActCtxGenCtx, ULONG ulManifestOperation, DWORD dwFlags, DWORD dwManifestOperationFlags, const CImpersonationData &ImpersonationData, USHORT ProcessorArchitecture, LANGID LangId, ULONG ApplicationDirectoryPathType, SIZE_T ApplicationDirectoryCch, PCWSTR ApplicationDirectory ) { BOOL fSuccess = FALSE; FN_TRACE_WIN32(fSuccess);
PACTCTXCTB Ctb = NULL; CSxsLockCriticalSection lock(g_ActCtxCtbListCritSec); CStringBufferAccessor acc; // used for LangID String buffer
LANGID SystemLangId = ::GetSystemDefaultUILanguage(); bool fEqual = false;
PARAMETER_CHECK(pActCtxGenCtx != NULL);
PARAMETER_CHECK( (ulManifestOperation == SXSP_INIT_ACT_CTX_GEN_CTX_OPERATION_PARSE_ONLY) || (ulManifestOperation == SXSP_INIT_ACT_CTX_GEN_CTX_OPERATION_GENERATE_ACTIVATION_CONTEXT) || (ulManifestOperation == SXSP_INIT_ACT_CTX_GEN_CTX_OPERATION_INSTALL));
PARAMETER_CHECK( (ApplicationDirectoryPathType == ACTIVATION_CONTEXT_PATH_TYPE_NONE) || (ApplicationDirectoryPathType == ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE));
PARAMETER_CHECK((dwFlags & ~(SXS_GENERATE_ACTCTX_SYSTEM_DEFAULT | SXS_GENERATE_ACTCTX_APP_RUNNING_IN_SAFEMODE)) == 0); PARAMETER_CHECK((dwFlags == 0) || (dwFlags == SXS_GENERATE_ACTCTX_SYSTEM_DEFAULT) || (dwFlags == SXS_GENERATE_ACTCTX_APP_RUNNING_IN_SAFEMODE));
switch (ulManifestOperation) { case SXSP_INIT_ACT_CTX_GEN_CTX_OPERATION_PARSE_ONLY: PARAMETER_CHECK(dwManifestOperationFlags == 0); break;
case SXSP_INIT_ACT_CTX_GEN_CTX_OPERATION_GENERATE_ACTIVATION_CONTEXT: PARAMETER_CHECK(dwManifestOperationFlags == 0); break;
case SXSP_INIT_ACT_CTX_GEN_CTX_OPERATION_INSTALL: PARAMETER_CHECK( (dwManifestOperationFlags & ~( MANIFEST_OPERATION_INSTALL_FLAG_NOT_TRANSACTIONAL | MANIFEST_OPERATION_INSTALL_FLAG_NO_VERIFY | MANIFEST_OPERATION_INSTALL_FLAG_REPLACE_EXISTING | MANIFEST_OPERATION_INSTALL_FLAG_ABORT | MANIFEST_OPERATION_INSTALL_FLAG_FROM_DIRECTORY | MANIFEST_OPERATION_INSTALL_FLAG_FROM_DIRECTORY_RECURSIVE | MANIFEST_OPERATION_INSTALL_FLAG_MOVE | MANIFEST_OPERATION_INSTALL_FLAG_INCLUDE_CODEBASE | MANIFEST_OPERATION_INSTALL_FLAG_FROM_RESOURCE | MANIFEST_OPERATION_INSTALL_FLAG_INSTALLED_BY_DARWIN | MANIFEST_OPERATION_INSTALL_FLAG_INSTALLED_BY_OSSETUP | MANIFEST_OPERATION_INSTALL_FLAG_INSTALLED_BY_MIGRATION | MANIFEST_OPERATION_INSTALL_FLAG_CREATE_LOGFILE | MANIFEST_OPERATION_INSTALL_FLAG_REFERENCE_VALID | MANIFEST_OPERATION_INSTALL_FLAG_REFRESH | MANIFEST_OPERATION_INSTALL_FLAG_FROM_CABINET | MANIFEST_OPERATION_INSTALL_FLAG_APPLY_PATCHES | MANIFEST_OPERATION_INSTALL_FLAG_FORCE_LOOK_FOR_CATALOG | MANIFEST_OPERATION_INSTALL_FLAG_COMMIT)) == 0); break; }
pActCtxGenCtx->m_ProcessorArchitecture = ProcessorArchitecture; pActCtxGenCtx->m_LangID = LangId; pActCtxGenCtx->m_SystemLangID = SystemLangId;
pActCtxGenCtx->m_SpecificLanguage.Clear();
IFW32FALSE_EXIT(pActCtxGenCtx->m_ApplicationDirectoryBuffer.Win32Assign(ApplicationDirectory, ApplicationDirectoryCch)); pActCtxGenCtx->m_ApplicationDirectoryPathType = ApplicationDirectoryPathType;
IFW32FALSE_EXIT(::SxspMapLANGIDToCultures(LangId, pActCtxGenCtx->m_GenericLanguage, pActCtxGenCtx->m_SpecificLanguage)); IFW32FALSE_EXIT(::SxspMapLANGIDToCultures(SystemLangId, pActCtxGenCtx->m_GenericSystemLanguage, pActCtxGenCtx->m_SpecificSystemLanguage));
// If these match the user's language, clear them to avoid the probing later on.
IFW32FALSE_EXIT(pActCtxGenCtx->m_SpecificSystemLanguage.Win32Equals(pActCtxGenCtx->m_SpecificLanguage, fEqual, true)); if (fEqual) pActCtxGenCtx->m_SpecificSystemLanguage.Clear();
IFW32FALSE_EXIT(pActCtxGenCtx->m_GenericSystemLanguage.Win32Equals(pActCtxGenCtx->m_GenericLanguage, fEqual, true)); if (fEqual) pActCtxGenCtx->m_GenericSystemLanguage.Clear();
pActCtxGenCtx->m_ImpersonationData = ImpersonationData; pActCtxGenCtx->m_ManifestOperation = ulManifestOperation; pActCtxGenCtx->m_Flags = dwFlags; pActCtxGenCtx->m_ManifestOperationFlags = dwManifestOperationFlags; pActCtxGenCtx->m_fAppApplyPublisherPolicy = SXS_PUBLISHER_POLICY_APPLY_DEFAULT;
IFW32FALSE_EXIT(pActCtxGenCtx->m_AssemblyTable.Initialize()); IFW32FALSE_EXIT(pActCtxGenCtx->m_ComponentPolicyTable.Initialize()); IFW32FALSE_EXIT(pActCtxGenCtx->m_ApplicationPolicyTable.Initialize());
IFW32FALSE_EXIT(pActCtxGenCtx->m_ClsidMap.Initialize()); pActCtxGenCtx->m_fClsidMapInitialized = TRUE; pActCtxGenCtx->m_ClsidMappingContext.Map = &(pActCtxGenCtx->m_ClsidMap);
IFW32FALSE_EXIT(::SxspGetAssemblyRootDirectory(pActCtxGenCtx->m_AssemblyRootDirectoryBuffer)); pActCtxGenCtx->m_AssemblyRootDirectoryPathType = ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE;
lock.Lock();
IFALLOCFAILED_EXIT(pActCtxGenCtx->m_Contributors = FUSION_NEW_ARRAY(CActivationContextGenerationContextContributor, g_ActCtxCtbListCount)); pActCtxGenCtx->m_ContributorCount = g_ActCtxCtbListCount;
for ( (pActCtxGenCtx->m_InitializedContributorCount = 0), (Ctb=g_ActCtxCtbListHead); (Ctb != NULL) && (pActCtxGenCtx->m_InitializedContributorCount < g_ActCtxCtbListCount); (pActCtxGenCtx->m_InitializedContributorCount++), (Ctb = Ctb->m_Next) ) { ACTCTXCTB_CBACTCTXGENBEGINNING CBData;
CBData.Header.Reason = ACTCTXCTB_CBREASON_ACTCTXGENBEGINNING; CBData.Header.ExtensionGuid = Ctb->GetExtensionGuidPtr(); CBData.Header.SectionId = Ctb->m_SectionId; CBData.Header.ContributorContext = Ctb->m_ContributorContext; CBData.Header.ActCtxGenContext = NULL; CBData.Header.ManifestParseContext = NULL; CBData.Header.ManifestOperation = ulManifestOperation; CBData.Header.ManifestOperationFlags = dwManifestOperationFlags; CBData.Header.Flags = dwFlags; CBData.Header.pOriginalActCtxGenCtx = pActCtxGenCtx; CBData.Header.InstallationContext = &(pActCtxGenCtx->m_InstallationContext); CBData.Header.ClsidMappingContext = &(pActCtxGenCtx->m_ClsidMappingContext); CBData.ApplicationDirectory = pActCtxGenCtx->m_ApplicationDirectoryBuffer; CBData.ApplicationDirectoryCch = pActCtxGenCtx->m_ApplicationDirectoryBuffer.Cch(); CBData.ApplicationDirectoryPathType = pActCtxGenCtx->m_ApplicationDirectoryPathType; CBData.Success = TRUE;
(*(Ctb->m_CallbackFunction))((PACTCTXCTB_CALLBACK_DATA) &CBData.Header);
if (!CBData.Success) { ASSERT(::FusionpGetLastWin32Error() != ERROR_SUCCESS); if (::FusionpGetLastWin32Error() == ERROR_SUCCESS) ::FusionpSetLastWin32Error(ERROR_INTERNAL_ERROR);
goto Exit; }
IFW32FALSE_EXIT(pActCtxGenCtx->m_Contributors[pActCtxGenCtx->m_InitializedContributorCount].Initialize(Ctb, CBData.Header.ActCtxGenContext)); } // If the list count is correct, we should be both at the end of the list
// and at the max index.
ASSERT(pActCtxGenCtx->m_InitializedContributorCount == g_ActCtxCtbListCount); ASSERT(Ctb == NULL);
qsort(pActCtxGenCtx->m_Contributors, pActCtxGenCtx->m_ContributorCount, sizeof(CActivationContextGenerationContextContributor), &CActivationContextGenerationContextContributor::Compare);
fSuccess = TRUE; Exit: return fSuccess; }
BOOL SxspFireActCtxGenEnding( PACTCTXGENCTX pActCtxGenCtx ) { BOOL fSuccess = FALSE; FN_TRACE_WIN32(fSuccess); ULONG i;
PARAMETER_CHECK(pActCtxGenCtx != NULL);
for (i=0; i<pActCtxGenCtx->m_InitializedContributorCount; i++) IFW32FALSE_EXIT(pActCtxGenCtx->m_Contributors[i].Fire_ActCtxGenEnding(pActCtxGenCtx));
fSuccess = TRUE; Exit: return fSuccess; }
class CSxspResolvePartialReferenceLocals { public: CProbedAssemblyInformation TestReference; CSmallStringBuffer buffProcessorArchitecture; };
BOOL SxspResolvePartialReference( DWORD Flags, PCASSEMBLY ParsingAssemblyContext, PACTCTXGENCTX pActCtxGenCtx, const CAssemblyReference &PartialReference, CProbedAssemblyInformation &ProbedAssemblyInformation, bool &rfFound, CSxspResolvePartialReferenceLocals *Locals ) { BOOL fSuccess = FALSE; FN_TRACE_WIN32(fSuccess);
CProbedAssemblyInformation &TestReference = Locals->TestReference; CSmallStringBuffer &buffProcessorArchitecture = Locals->buffProcessorArchitecture; bool fWildcardedLanguage = false; bool fWildcardedProcessorArchitecture = false; bool fAutoWow64Probing = false; bool fHasPKToken = false; bool fFound = false; USHORT wCurrentProcessorArchitecture = PROCESSOR_ARCHITECTURE_UNKNOWN; DWORD dwProbeAssemblyFlags = 0; PCWSTR pszOriginalProcessorArchitecture = NULL; SIZE_T cchOriginalProcessorArchitecture = 0; PCWSTR pszOriginalLanguage = NULL; SIZE_T cchOriginalLanguage = 0;
fHasPKToken = false; rfFound = false;
PARAMETER_CHECK(pActCtxGenCtx != NULL); IFINVALID_FLAGS_EXIT_WIN32(Flags, SXSP_RESOLVE_PARTIAL_REFERENCE_FLAG_OPTIONAL | SXSP_RESOLVE_PARTIAL_REFERENCE_FLAG_SKIP_WORLDWIDE);
//
// A partial reference needs to have processor architecture, assembly name and
// assembly version filled in. We only probe based on langid.
//
// Copy the attributes over...
IFW32FALSE_EXIT(TestReference.Initialize(PartialReference, pActCtxGenCtx));
fWildcardedProcessorArchitecture = false; fAutoWow64Probing = false;
// Find out if we're either processing a processorArchitecture="*" bind or
// if we're supposed to do wow64 probing
IFW32FALSE_EXIT(PartialReference.IsProcessorArchitectureWildcarded(fWildcardedProcessorArchitecture));
if (pActCtxGenCtx->m_ProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA32_ON_WIN64) { IFW32FALSE_EXIT(PartialReference.IsProcessorArchitectureX86(fAutoWow64Probing)); }
if (fWildcardedProcessorArchitecture || fAutoWow64Probing) { wCurrentProcessorArchitecture = pActCtxGenCtx->m_ProcessorArchitecture; IFW32FALSE_EXIT(::FusionpFormatProcessorArchitecture(wCurrentProcessorArchitecture, buffProcessorArchitecture)); IFW32FALSE_EXIT(TestReference.SetProcessorArchitecture(buffProcessorArchitecture, buffProcessorArchitecture.Cch()));
// We do not probe for private wow64 assemblies.
if (wCurrentProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA32_ON_WIN64) dwProbeAssemblyFlags |= CProbedAssemblyInformation::ProbeAssembly_SkipPrivateAssemblies; }
IFW32FALSE_EXIT(PartialReference.GetProcessorArchitecture(pszOriginalProcessorArchitecture, cchOriginalProcessorArchitecture)); IFW32FALSE_EXIT(PartialReference.GetLanguage(pszOriginalLanguage, cchOriginalLanguage));
TryItAllAgain:
// Let's try the few languages we can.
IFW32FALSE_EXIT(PartialReference.IsLanguageWildcarded(fWildcardedLanguage)); if (!fWildcardedLanguage) { // If there's no language="*" in the dependency, let's just look for the exact match and
// call it a day.
if (fWildcardedProcessorArchitecture || fAutoWow64Probing) IFW32FALSE_EXIT(TestReference.SetProcessorArchitecture(buffProcessorArchitecture, buffProcessorArchitecture.Cch()));
IFW32FALSE_EXIT(TestReference.ProbeAssembly(dwProbeAssemblyFlags, pActCtxGenCtx, CProbedAssemblyInformation::eExplicitBind, fFound));
if ((!fFound) && (fWildcardedProcessorArchitecture || fAutoWow64Probing)) IFW32FALSE_EXIT(TestReference.SetProcessorArchitecture(pszOriginalProcessorArchitecture, cchOriginalProcessorArchitecture)); } else { // Let's try the user's language...
if (pActCtxGenCtx->m_SpecificLanguage[0] != L'\0') { // Since this is the first probe, we don't have to reset to original...
if (fWildcardedProcessorArchitecture || fAutoWow64Probing) IFW32FALSE_EXIT(TestReference.SetProcessorArchitecture(buffProcessorArchitecture, buffProcessorArchitecture.Cch())); IFW32FALSE_EXIT(TestReference.SetLanguage(pActCtxGenCtx->m_SpecificLanguage)); IFW32FALSE_EXIT(TestReference.ProbeAssembly(dwProbeAssemblyFlags, pActCtxGenCtx, CProbedAssemblyInformation::eSpecificLanguage, fFound)); if (!fFound) { if (fWildcardedProcessorArchitecture || fAutoWow64Probing) IFW32FALSE_EXIT( TestReference.SetProcessorArchitecture( pszOriginalProcessorArchitecture, cchOriginalProcessorArchitecture));
IFW32FALSE_EXIT(TestReference.SetLanguage(pszOriginalLanguage, cchOriginalLanguage)); } }
if (!fFound && (pActCtxGenCtx->m_GenericLanguage[0] != L'\0')) { // Try the user's slightly more generic version of the language...
if (fWildcardedProcessorArchitecture || fAutoWow64Probing) IFW32FALSE_EXIT(TestReference.SetProcessorArchitecture(buffProcessorArchitecture, buffProcessorArchitecture.Cch()));
IFW32FALSE_EXIT(TestReference.SetLanguage(pActCtxGenCtx->m_GenericLanguage));
IFW32FALSE_EXIT(TestReference.ProbeAssembly(dwProbeAssemblyFlags, pActCtxGenCtx, CProbedAssemblyInformation::eGenericLanguage, fFound));
if (!fFound) { if (fWildcardedProcessorArchitecture || fAutoWow64Probing) IFW32FALSE_EXIT( TestReference.SetProcessorArchitecture( pszOriginalProcessorArchitecture, cchOriginalProcessorArchitecture));
IFW32FALSE_EXIT(TestReference.SetLanguage(pszOriginalLanguage, cchOriginalLanguage)); } }
// Let's try the system's installed language...
if (!fFound && (pActCtxGenCtx->m_SpecificSystemLanguage[0] != L'\0')) { if (fWildcardedProcessorArchitecture || fAutoWow64Probing) IFW32FALSE_EXIT(TestReference.SetProcessorArchitecture(buffProcessorArchitecture, buffProcessorArchitecture.Cch())); IFW32FALSE_EXIT(TestReference.SetLanguage(pActCtxGenCtx->m_SpecificSystemLanguage)); IFW32FALSE_EXIT(TestReference.ProbeAssembly(dwProbeAssemblyFlags, pActCtxGenCtx, CProbedAssemblyInformation::eSpecificSystemLanguage, fFound)); if (!fFound) { if (fWildcardedProcessorArchitecture || fAutoWow64Probing) IFW32FALSE_EXIT( TestReference.SetProcessorArchitecture( pszOriginalProcessorArchitecture, cchOriginalProcessorArchitecture));
IFW32FALSE_EXIT(TestReference.SetLanguage(pszOriginalLanguage, cchOriginalLanguage)); } }
if (!fFound && (pActCtxGenCtx->m_GenericSystemLanguage[0] != L'\0')) { // Try the user's slightly more generic version of the language...
if (fWildcardedProcessorArchitecture || fAutoWow64Probing) IFW32FALSE_EXIT(TestReference.SetProcessorArchitecture(buffProcessorArchitecture, buffProcessorArchitecture.Cch())); IFW32FALSE_EXIT(TestReference.SetLanguage(pActCtxGenCtx->m_GenericSystemLanguage)); IFW32FALSE_EXIT(TestReference.ProbeAssembly(dwProbeAssemblyFlags, pActCtxGenCtx, CProbedAssemblyInformation::eGenericSystemLanguage, fFound)); if (!fFound) { if (fWildcardedProcessorArchitecture || fAutoWow64Probing) IFW32FALSE_EXIT( TestReference.SetProcessorArchitecture( pszOriginalProcessorArchitecture, cchOriginalProcessorArchitecture));
IFW32FALSE_EXIT(TestReference.SetLanguage(pszOriginalLanguage, cchOriginalLanguage)); } }
// If we haven't found a language specific one and the caller did not
// request us to skip the language-dependent ones, try for a language neutral
if (!fFound && ((Flags & SXSP_RESOLVE_PARTIAL_REFERENCE_FLAG_SKIP_WORLDWIDE) == 0)) { // Try with no language!
if (fWildcardedProcessorArchitecture || fAutoWow64Probing) IFW32FALSE_EXIT(TestReference.SetProcessorArchitecture(buffProcessorArchitecture, buffProcessorArchitecture.Cch())); IFW32FALSE_EXIT(TestReference.ClearLanguage()); IFW32FALSE_EXIT(TestReference.ProbeAssembly(dwProbeAssemblyFlags, pActCtxGenCtx, CProbedAssemblyInformation::eLanguageNeutral, fFound)); if (!fFound) { if (fWildcardedProcessorArchitecture || fAutoWow64Probing) IFW32FALSE_EXIT( TestReference.SetProcessorArchitecture( pszOriginalProcessorArchitecture, cchOriginalProcessorArchitecture));
IFW32FALSE_EXIT(TestReference.SetLanguage(pszOriginalLanguage, cchOriginalLanguage)); } } }
if (!fFound) { // If we're automatically searching for wow64 assemblies and the processor architecture we just tried
// was ia32-on-win64, try again with plain PROCESSOR_ARCHITECTURE_INTEL.
if (fAutoWow64Probing && (wCurrentProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA32_ON_WIN64)) { wCurrentProcessorArchitecture = PROCESSOR_ARCHITECTURE_INTEL; dwProbeAssemblyFlags &= ~(CProbedAssemblyInformation::ProbeAssembly_SkipPrivateAssemblies);
IFW32FALSE_EXIT(::FusionpFormatProcessorArchitecture(wCurrentProcessorArchitecture, buffProcessorArchitecture)); IFW32FALSE_EXIT(TestReference.SetProcessorArchitecture(buffProcessorArchitecture, buffProcessorArchitecture.Cch())); pszOriginalProcessorArchitecture = buffProcessorArchitecture; cchOriginalProcessorArchitecture = buffProcessorArchitecture.Cch(); goto TryItAllAgain; }
// If we're handling a processorArchitecture="*" bind and the current processor architecture hasn't fallen
// back to PROCESSOR_ARCHITECTURE_UNKNOWN ( == data-only assemblies), fall back now.
if (fWildcardedProcessorArchitecture && (wCurrentProcessorArchitecture != PROCESSOR_ARCHITECTURE_UNKNOWN)) { wCurrentProcessorArchitecture = PROCESSOR_ARCHITECTURE_UNKNOWN; // data-only private assemblies cannot be found with processorArchitecture="*"
dwProbeAssemblyFlags |= CProbedAssemblyInformation::ProbeAssembly_SkipPrivateAssemblies;
IFW32FALSE_EXIT(::FusionpFormatProcessorArchitecture(wCurrentProcessorArchitecture, buffProcessorArchitecture)); IFW32FALSE_EXIT(TestReference.SetProcessorArchitecture(buffProcessorArchitecture, buffProcessorArchitecture.Cch())); pszOriginalProcessorArchitecture = buffProcessorArchitecture; cchOriginalProcessorArchitecture = buffProcessorArchitecture.Cch(); goto TryItAllAgain; }
// If it wasn't optional, declare an error.
if ((Flags & SXSP_RESOLVE_PARTIAL_REFERENCE_FLAG_OPTIONAL) == 0) { // NTRAID#NTBUG9 - 571854 - 2002/03/26 - xiaoyuw
// the default value would never get used since GetAssemblyName always reset the input parameter to be NULL;
PCWSTR AssemblyName = L"<error retrieving assembly name>"; SIZE_T AssemblyNameCch = NUMBER_OF(L"<error retrieving assembly name>") - 1;
TestReference.GetAssemblyName(&AssemblyName, &AssemblyNameCch);
::FusionpLogError( MSG_SXS_MANIFEST_PARSE_DEPENDENCY, CUnicodeString(AssemblyName, AssemblyNameCch), CEventLogLastError(ERROR_SXS_ASSEMBLY_NOT_FOUND));
ORIGINATE_WIN32_FAILURE_AND_EXIT(AssemblyProbingFailed, ERROR_SXS_ASSEMBLY_NOT_FOUND); } } else IFW32FALSE_EXIT(ProbedAssemblyInformation.TakeValue(TestReference));
rfFound = fFound;
fSuccess = TRUE;
Exit: if (!fSuccess) { CSxsPreserveLastError ple; PCWSTR pszAssemblyName = NULL; SIZE_T AssemblyNameCch = 0;
PartialReference.GetAssemblyName(&pszAssemblyName, &AssemblyNameCch);
::FusionpLogError( MSG_SXS_FUNCTION_CALL_FAIL, CEventLogString(L"Resolve Partial Assembly"), (pszAssemblyName != NULL) ? CEventLogString(static_cast<PCWSTR>(pszAssemblyName)) : CEventLogString(L"Assembly Name Unknown"), CEventLogLastError(ple.LastError()));
ple.Restore(); }
return fSuccess; }
BOOL SxspResolvePartialReference( DWORD Flags, PCASSEMBLY ParsingAssemblyContext, PACTCTXGENCTX pActCtxGenCtx, const CAssemblyReference &PartialReference, CProbedAssemblyInformation &ProbedAssemblyInformation, bool &rfFound ) { FN_PROLOG_WIN32
CSmartPtr<CSxspResolvePartialReferenceLocals> Locals;
IFW32FALSE_EXIT(Locals.Win32Allocate(__FILE__, __LINE__));
IFW32FALSE_EXIT( SxspResolvePartialReference( Flags, ParsingAssemblyContext, pActCtxGenCtx, PartialReference, ProbedAssemblyInformation, rfFound, Locals ));
FN_EPILOG }
BOOL SxspAddManifestToActCtxGenCtx( PACTCTXGENCTX pActCtxGenCtx, CProbedAssemblyInformation &ProbedInformation, PASSEMBLY *AssemblyOut ) { BOOL fSuccess = FALSE; FN_TRACE_WIN32(fSuccess); PASSEMBLY Asm = NULL; PCWSTR ProbedAssemblyName = 0; SIZE_T ProbedAssemblyNameCch = 0;
if (AssemblyOut != NULL) *AssemblyOut = NULL;
PARAMETER_CHECK(pActCtxGenCtx != NULL); IFW32FALSE_EXIT(ProbedInformation.GetAssemblyName(&ProbedAssemblyName, &ProbedAssemblyNameCch));
// NTRAID#NTBUG9 - 571854 - 2002/03/26 - xiaoyuw:
// INTERNAL_ERROR_CHECK or ASSERT should be added here
// INTERNAL_ERROR_CHECK(ProbedAssemblyName != NULL && ProbedAssemblyNameCch != 0);
// First, let's see if we've already found this assembly.
IFW32FALSE_EXIT(::SxspFindAssemblyByName(pActCtxGenCtx, ProbedAssemblyName, ProbedAssemblyNameCch, &Asm)); // Same name... if the metadata is different, we're in trouble.
if (Asm != NULL) { BOOL fEqualIdentity;
// Both identities should be definitions, so no need to set the ref-matches-def flag...
IFW32FALSE_EXIT( ::SxsAreAssemblyIdentitiesEqual( SXS_ARE_ASSEMBLY_IDENTITIES_EQUAL_FLAG_ALLOW_REF_TO_MATCH_DEF, Asm->GetAssemblyIdentity(), ProbedInformation.GetAssemblyIdentity(), &fEqualIdentity));
if (!fEqualIdentity) { PCWSTR MP1 = L"<unavailable>"; PCWSTR MP2 = MP1;
ProbedInformation.GetManifestPath(&MP1, NULL); Asm->m_ProbedAssemblyInformation.GetManifestPath(&MP2, NULL);
Asm = NULL; ::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); ORIGINATE_WIN32_FAILURE_AND_EXIT(VersionConflict, ERROR_SXS_VERSION_CONFLICT); } }
if (Asm == NULL) { IFALLOCFAILED_EXIT(Asm = FUSION_NEW_SINGLETON(ASSEMBLY)); IFW32FALSE_EXIT(::SxspInitAssembly(Asm, ProbedInformation)); IFW32FALSE_EXIT(::SxspAddAssemblyToActivationContextGenerationContext(pActCtxGenCtx, Asm)); }
if (AssemblyOut != NULL) { *AssemblyOut = Asm; Asm = NULL; }
fSuccess = TRUE;
Exit: if (Asm != NULL) Asm->Release();
return fSuccess; }
BOOL SxspAddAssemblyToActivationContextGenerationContext( PACTCTXGENCTX pActCtxGenCtx, PASSEMBLY Asm ) { BOOL fSuccess = FALSE;
FN_TRACE_WIN32(fSuccess);
PARAMETER_CHECK(pActCtxGenCtx != NULL); PARAMETER_CHECK(Asm != NULL);
// If you hit either of these asserts, either the assembly structure has been trashed or
// it's already been added to the generation context.
ASSERT(Asm->m_AssemblyRosterIndex == 0); Asm->m_AssemblyRosterIndex = pActCtxGenCtx->m_NextAssemblyRosterIndex++; pActCtxGenCtx->m_AssemblyList.AddToTail(Asm); Asm->AddRef(); if (pActCtxGenCtx->m_ManifestOperation != MANIFEST_OPERATION_INSTALL) { PCWSTR AssemblyName = NULL; IFW32FALSE_EXIT(Asm->GetAssemblyName(&AssemblyName, NULL)); IFW32FALSE_EXIT(pActCtxGenCtx->m_AssemblyTable.Insert(AssemblyName, Asm, ERROR_SXS_DUPLICATE_ASSEMBLY_NAME)); }
fSuccess = TRUE; Exit: return fSuccess; }
BOOL SxspFindAssemblyByName( PACTCTXGENCTX pActCtxGenCtx, PCWSTR AssemblyName, SIZE_T AssemblyNameCch, PASSEMBLY *AssemblyOut ) { BOOL fSuccess = FALSE; FN_TRACE_WIN32(fSuccess); CSmallStringBuffer AssemblyNameBuffer; PASSEMBLY Result = NULL;
if (AssemblyOut != NULL) *AssemblyOut = NULL;
PARAMETER_CHECK(AssemblyOut != NULL); PARAMETER_CHECK(pActCtxGenCtx != NULL);
// Unfortunately, we really need the string to be null terminated...
IFW32FALSE_EXIT(AssemblyNameBuffer.Win32Assign(AssemblyName, AssemblyNameCch)); AssemblyName = AssemblyNameBuffer;
IFW32FALSE_EXIT(pActCtxGenCtx->m_AssemblyTable.Find(AssemblyName, Result));
if (Result != NULL) Result->AddRef();
*AssemblyOut = Result; fSuccess = TRUE;
Exit: return fSuccess; }
BOOL SxspAddRootManifestToActCtxGenCtx( PACTCTXGENCTX pActCtxGenCtx, PCSXS_GENERATE_ACTIVATION_CONTEXT_PARAMETERS Parameters ) { FN_PROLOG_WIN32 CProbedAssemblyInformation AssemblyInfo;
PARAMETER_CHECK(Parameters != NULL); PARAMETER_CHECK(pActCtxGenCtx != NULL);
#define IS_NT_DOS_PATH(_x) (IS_PATH_SEPARATOR_U((_x)[0]) && ((_x)[1] == L'?') && ((_x)[2] == L'?') && IS_PATH_SEPARATOR_U((_x)[3]))
PARAMETER_CHECK((Parameters->AssemblyDirectory == NULL) || (IS_NT_DOS_PATH(Parameters->AssemblyDirectory) == FALSE)); PARAMETER_CHECK((Parameters->AssemblyDirectory == NULL) || (IS_NT_DOS_PATH(Parameters->AssemblyDirectory) == FALSE)); PARAMETER_CHECK((Parameters->Manifest.Path == NULL) || (IS_NT_DOS_PATH(Parameters->Manifest.Path) == FALSE)); PARAMETER_CHECK((Parameters->Policy.Path == NULL) || (IS_NT_DOS_PATH(Parameters->Policy.Path) == FALSE));
IFW32FALSE_EXIT(AssemblyInfo.Initialize(pActCtxGenCtx)); IFW32FALSE_EXIT(AssemblyInfo.SetManifestPath( ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE, Parameters->Manifest.Path, (Parameters->Manifest.Path != NULL) ? ::wcslen(Parameters->Manifest.Path) : 0)); ASSERT(Parameters->Manifest.Stream != NULL); IFW32FALSE_EXIT(AssemblyInfo.SetManifestStream(Parameters->Manifest.Stream)); IFW32FALSE_EXIT(AssemblyInfo.SetManifestFlags(ASSEMBLY_MANIFEST_FILETYPE_STREAM));
IFW32FALSE_EXIT(AssemblyInfo.SetPolicyPath( ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE, Parameters->Policy.Path, (Parameters->Policy.Path != NULL) ? ::wcslen(Parameters->Policy.Path) : 0)); IFW32FALSE_EXIT(AssemblyInfo.SetPolicyStream(Parameters->Policy.Stream)); IFW32FALSE_EXIT(AssemblyInfo.SetPolicyFlags(ASSEMBLY_POLICY_FILETYPE_STREAM));
IFW32FALSE_EXIT(::SxspAddManifestToActCtxGenCtx(pActCtxGenCtx, AssemblyInfo, NULL));
FN_EPILOG #undef IS_NT_DOS_PATH
}
BOOL SxspInitAssembly( PASSEMBLY Asm, CProbedAssemblyInformation &AssemblyInfo ) { BOOL fSuccess = FALSE;
FN_TRACE_WIN32(fSuccess);
PARAMETER_CHECK(Asm != NULL);
IFW32FALSE_EXIT(Asm->m_ProbedAssemblyInformation.InitializeTakeValue(AssemblyInfo)); Asm->m_Incorporated = FALSE; Asm->m_ManifestVersionMajor = 0; Asm->m_ManifestVersionMinor = 0;
fSuccess = TRUE; Exit: return fSuccess; }
class CSxspIncorporateAssemblyLocals { public: #if FUSION_XML_TREE
SXS_XML_STRING LocalStringArray[128]; PSXS_XML_STRING ActualStringArray; #endif
STATSTG statstg; ACTCTXCTB_ASSEMBLY_CONTEXT AssemblyContext; CStringBuffer TextuallyEncodedIdentityBuffer; CFileStream ProbeFileTypeStream; CFileStream FileStream; };
BOOL SxspIncorporateAssembly( PACTCTXGENCTX pActCtxGenCtx, PASSEMBLY Asm, CSxspIncorporateAssemblyLocals *Locals ) { BOOL fSuccess = FALSE; FN_TRACE_WIN32(fSuccess); HRESULT hr = 0; ULONG i = 0; ACTCTXCTB_ASSEMBLY_CONTEXT &AssemblyContext = Locals->AssemblyContext; const bool fInstalling = (pActCtxGenCtx->m_ManifestOperation == MANIFEST_OPERATION_INSTALL); ULONG ManifestType = (Asm->m_ProbedAssemblyInformation.GetManifestFlags() & ASSEMBLY_MANIFEST_FILETYPE_MASK); CImpersonate impersonate(pActCtxGenCtx->m_ImpersonationData); SXS_POLICY_SOURCE s; #if FUSION_XML_TREE
PSXS_XML_STRING ActualStringArray = Locals->LocalStringArray; #endif
STATSTG &statstg = Locals->statstg;
// declaration order here is partially deliberate, to control cleanup order.
// normally, declaration order is determined by not declaring until you have
// the data to initialize with the ctor, but the use of goto messes that up
CFileStream &FileStream = Locals->FileStream; CSmartPtr<CResourceStream> ResourceStream; CSmartPtr<CTeeStreamWithHash> TeeStreamForManifestInstall;
#if FUSION_PRECOMPILED_MANIFEST
CSmartPtr<CPrecompiledManifestWriterStream> pcmWriterStream; #endif
CNodeFactory *pNodeFactory = NULL; CSmartRef<IXMLParser> pIXMLParser; PASSEMBLY_IDENTITY AssemblyIdentity = NULL;
CStringBuffer &TextuallyEncodedIdentityBuffer = Locals->TextuallyEncodedIdentityBuffer; PCWSTR ManifestPath = NULL;
PARAMETER_CHECK(Asm != NULL); PARAMETER_CHECK(!Asm->m_Incorporated); PARAMETER_CHECK(pActCtxGenCtx != NULL);
// set flags
AssemblyContext.Flags = 0; s = Asm->m_ProbedAssemblyInformation.GetPolicySource();
if ( s == SXS_POLICY_SYSTEM_POLICY) AssemblyContext.Flags |= ACTCTXCTB_ASSEMBLY_CONTEXT_ASSEMBLY_POLICY_APPLIED; else if (s == SXS_POLICY_ROOT_POLICY) AssemblyContext.Flags |= ACTCTXCTB_ASSEMBLY_CONTEXT_ROOT_POLICY_APPLIED;
if (Asm->IsRoot()) AssemblyContext.Flags |= ACTCTXCTB_ASSEMBLY_CONTEXT_IS_ROOT_ASSEMBLY;
if (Asm->m_ProbedAssemblyInformation.IsPrivateAssembly()) AssemblyContext.Flags |= ACTCTXCTB_ASSEMBLY_CONTEXT_IS_PRIVATE_ASSEMBLY;
if (Asm->m_ProbedAssemblyInformation.GetAssemblyIdentity() != NULL) { // Convert the identity into a somewhat human-readable form that we can log etc.
IFW32FALSE_EXIT( ::SxspGenerateTextualIdentity( 0, Asm->m_ProbedAssemblyInformation.GetAssemblyIdentity(), TextuallyEncodedIdentityBuffer)); AssemblyContext.TextuallyEncodedIdentity = TextuallyEncodedIdentityBuffer; AssemblyContext.TextuallyEncodedIdentityCch = TextuallyEncodedIdentityBuffer.Cch(); } else { AssemblyContext.TextuallyEncodedIdentity = L"<identity unavailable>"; AssemblyContext.TextuallyEncodedIdentityCch = 22; }
// copy assembly-identity info
IFW32FALSE_EXIT(::SxsDuplicateAssemblyIdentity(SXS_DUPLICATE_ASSEMBLY_IDENTITY_FLAG_ALLOW_NULL, Asm->m_ProbedAssemblyInformation.GetAssemblyIdentity(), &AssemblyIdentity)); AssemblyContext.AssemblyIdentity = AssemblyIdentity; // assign to pointer-to-const in the struct; can't pass struct member pointer directly
IFW32FALSE_EXIT(Asm->m_ProbedAssemblyInformation.GetManifestPath(&AssemblyContext.ManifestPath, &AssemblyContext.ManifestPathCch)); AssemblyContext.ManifestPathType = Asm->GetManifestPathType(); IFW32FALSE_EXIT(Asm->m_ProbedAssemblyInformation.GetPolicyPath(AssemblyContext.PolicyPath, AssemblyContext.PolicyPathCch)); AssemblyContext.PolicyPathType = Asm->GetPolicyPathType(); AssemblyContext.AssemblyRosterIndex = Asm->m_AssemblyRosterIndex;
if (fInstalling) { IFW32FALSE_EXIT(TeeStreamForManifestInstall.Win32Allocate(__FILE__, __LINE__)); AssemblyContext.TeeStreamForManifestInstall = TeeStreamForManifestInstall; AssemblyContext.InstallationInfo = pActCtxGenCtx->m_InstallationContext.InstallSource; AssemblyContext.SecurityMetaData = pActCtxGenCtx->m_InstallationContext.SecurityMetaData; AssemblyContext.InstallReferenceData = pActCtxGenCtx->m_InstallationContext.InstallReferenceData; #if FUSION_PRECOMPILED_MANIFEST
IFW32FALSE_EXIT(pcmWriterStream.Win32Allocate(__FILE__, __LINE__); AssemblyContext.pcmWriterStream = pcmWriterStream ; #endif
} else { AssemblyContext.SecurityMetaData = NULL; AssemblyContext.TeeStreamForManifestInstall = NULL; AssemblyContext.InstallationInfo = NULL; #if FUSION_PRECOMPILED_MANIFEST
AssemblyContext.pcmWriterStream = NULL; #endif
}
if (pActCtxGenCtx->m_pNodeFactory == NULL) { IFALLOCFAILED_EXIT(pActCtxGenCtx->m_pNodeFactory = new CNodeFactory); pActCtxGenCtx->m_pNodeFactory->AddRef(); // faked function
} else pActCtxGenCtx->m_pNodeFactory->ResetParseState();
IFW32FALSE_EXIT(pActCtxGenCtx->m_pNodeFactory->Initialize(pActCtxGenCtx, Asm, &AssemblyContext)); pNodeFactory = pActCtxGenCtx->m_pNodeFactory; ASSERT(pNodeFactory != NULL);
// Everyone's ready; let's get the XML parser:
IFW32FALSE_EXIT(::SxspGetXMLParser(IID_IXMLParser, (LPVOID *) &pIXMLParser)); IFCOMFAILED_EXIT(pIXMLParser->SetFactory(pNodeFactory));
//
// open the file or map the resource into memory
//
IStream* Stream; // deliberatly not "smart", we don't refcount it
Stream = NULL; { // scope for impersonation for file open
IFW32FALSE_EXIT(impersonate.Impersonate());
if (ManifestType == ASSEMBLY_MANIFEST_FILETYPE_AUTO_DETECT) { //
// decide between xml in its own text file or a resource
// in a "portable executable" by checking for the portable executable
// signature, "MZ".
//
BYTE buffer[2] = {0,0}; ULONG cbRead = 0; CFileStream &ProbeFileTypeStream = Locals->ProbeFileTypeStream;
IFW32FALSE_EXIT(Asm->m_ProbedAssemblyInformation.GetManifestPath(&ManifestPath, NULL)); IFW32FALSE_EXIT( ProbeFileTypeStream.OpenForRead( ManifestPath, CImpersonationData(), FILE_SHARE_READ, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN));
IFCOMFAILED_EXIT(ProbeFileTypeStream.Read(buffer, 2, &cbRead));
if (cbRead != 2) ORIGINATE_WIN32_FAILURE_AND_EXIT(ManifestLessThanTwoBytesLong, ERROR_SXS_MANIFEST_FORMAT_ERROR);
IFW32FALSE_EXIT(ProbeFileTypeStream.Close());
// MS-DOS stub, Mark Zbikowski
if (buffer[0] == 'M' && buffer[1] == 'Z') { // should we do further checking, like that PE\0\0 occurs
// where the MS-DOS header says it is?
ManifestType = ASSEMBLY_MANIFEST_FILETYPE_RESOURCE; } else { ManifestType = ASSEMBLY_MANIFEST_FILETYPE_FILE; } } switch (ManifestType) { case ASSEMBLY_MANIFEST_FILETYPE_RESOURCE: { if (ManifestPath == NULL) IFW32FALSE_EXIT(Asm->m_ProbedAssemblyInformation.GetManifestPath(&ManifestPath, NULL)); IFW32FALSE_EXIT(ResourceStream.Win32Allocate(__FILE__, __LINE__)); IFW32FALSE_EXIT(ResourceStream->Initialize(ManifestPath, MAKEINTRESOURCEW(RT_MANIFEST))); Stream = ResourceStream; break; } case ASSEMBLY_MANIFEST_FILETYPE_FILE: { if (ManifestPath == NULL) IFW32FALSE_EXIT(Asm->m_ProbedAssemblyInformation.GetManifestPath(&ManifestPath, NULL)); IFW32FALSE_EXIT( FileStream.OpenForRead( ManifestPath, CImpersonationData(), FILE_SHARE_READ, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN)); Stream = &FileStream; break; } case ASSEMBLY_MANIFEST_FILETYPE_STREAM: Stream = Asm->m_ProbedAssemblyInformation.GetManifestStream(); break; default: ASSERT2(FALSE, "unknown manifest file type"); break; }
IFW32FALSE_EXIT(impersonate.Unimpersonate()); }
//
// Optionally "tee" the manifest so it gets copied into
// the store while we read it, buffering until we know where in
// the store it goes. The manifest itself is not referenced
// in the manifest.
//
if (fInstalling) { IFW32FALSE_EXIT(TeeStreamForManifestInstall->InitCryptHash(CALG_SHA1)); TeeStreamForManifestInstall->SetSource(Stream); Stream = TeeStreamForManifestInstall; }
//
// We get E_NOTIMPL on the OutOfProcessMemoryStreams in the AppCompat case.
//
IFCOMFAILED_EXIT(((hr = Stream->Stat(&statstg, STATFLAG_NONAME)) != E_NOTIMPL) ? hr : NOERROR); if (hr == E_NOTIMPL) { statstg.mtime.dwLowDateTime = 0; statstg.mtime.dwHighDateTime = 0; }
IFW32FALSE_EXIT( pNodeFactory->SetParseType( XML_FILE_TYPE_MANIFEST, Asm->m_ProbedAssemblyInformation.GetManifestPathType(), Asm->m_ProbedAssemblyInformation.GetManifestPath(), statstg.mtime));
INTERNAL_ERROR_CHECK(Stream != NULL);
IFCOMFAILED_EXIT(pIXMLParser->SetInput(Stream)); IFCOMFAILED_EXIT(pIXMLParser->Run(-1)); IFW32FALSE_EXIT(FileStream.Close()); #if FUSION_PRECOMPILED_MANIFEST
IFW32FALSE_EXIT((AssemblyContext.pcmWriterStream == NULL) || (pcmWriterStream.Close())); #endif
// Tell the contributors we're done parsing this file
for (i=0; i<pActCtxGenCtx->m_ContributorCount; i++) IFW32FALSE_EXIT( pActCtxGenCtx->m_Contributors[i].Fire_ParseEnding( pActCtxGenCtx, &AssemblyContext));
#if FUSION_XML_TREE
// Now let's fill in the document's string table.
StringTableEntryCount = pNodeFactory->m_ParseTreeStringPool.GetEntryCount() + 1;
if (StringTableEntryCount > NUMBER_OF(Locals->LocalStringArray)) IFALLOCFAILED_EXIT(ActualStringArray = FUSION_NEW_ARRAY(SXS_XML_STRING, StringTableEntryCount));
IFW32FALSE_EXIT(pNodeFactory->m_ParseTreeStringPool.FillInStringArray(StringTableEntryCount, ActualStringArray, EntriesFilledIn)); // The size should have been an exact match.
ASSERT(EntriesFilledIn == StringTableEntryCount);
pNodeFactory->m_XmlDocument.StringCount = EntriesFilledIn; pNodeFactory->m_XmlDocument.Strings = ActualStringArray;
::SxspDumpXmlTree(0, &(pNodeFactory->m_XmlDocument));
pNodeFactory->m_XmlDocument.StringCount = 0; pNodeFactory->m_XmlDocument.Strings = NULL;
if (ActualStringArray != Locals->LocalStringArray) { FUSION_DELETE_ARRAY(ActualStringArray); ActualStringArray = NULL; } #endif // FUSION_XML_TREE
Asm->m_Incorporated = TRUE; fSuccess = TRUE;
Exit: // And tell them we're done.
for (i=0; i<pActCtxGenCtx->m_ContributorCount; i++) pActCtxGenCtx->m_Contributors[i].Fire_ParseEnded(pActCtxGenCtx, &AssemblyContext);
return fSuccess; }
BOOL SxspIncorporateAssembly( PACTCTXGENCTX pActCtxGenCtx, PASSEMBLY Asm ) { FN_PROLOG_WIN32
CSmartPtr<CSxspIncorporateAssemblyLocals> Locals;
PARAMETER_CHECK(Asm != NULL); PARAMETER_CHECK(!Asm->m_Incorporated); PARAMETER_CHECK(pActCtxGenCtx != NULL);
IFW32FALSE_EXIT(Locals.Win32Allocate(__FILE__, __LINE__));
IFW32FALSE_EXIT(::SxspIncorporateAssembly(pActCtxGenCtx, Asm, Locals));
FN_EPILOG }
BOOL SxspEnqueueAssemblyReference( PACTCTXGENCTX pActCtxGenCtx, PASSEMBLY SourceAssembly, PCASSEMBLY_IDENTITY Identity, bool Optional, bool MetadataSatellite ) { FN_PROLOG_WIN32
CSmartPtr<CPendingAssembly> PendingAssembly;
PARAMETER_CHECK(Identity != NULL); PARAMETER_CHECK(pActCtxGenCtx != NULL);
IFW32FALSE_EXIT(PendingAssembly.Win32Allocate(__FILE__, __LINE__)); IFW32FALSE_EXIT(PendingAssembly->Initialize(SourceAssembly, Identity, Optional, MetadataSatellite));
pActCtxGenCtx->m_PendingAssemblyList.AddToTail(PendingAssembly.Detach());
FN_EPILOG }
class CSxspProcessPendingAssembliesLocals { public:
CSmallStringBuffer buffName; CProbedAssemblyInformation MuiAssemblyFound; CProbedAssemblyInformation AssemblyFound; };
BOOL SxspProcessPendingAssemblies( PACTCTXGENCTX pActCtxGenCtx, CSxspProcessPendingAssembliesLocals *Locals ) { FN_PROLOG_WIN32
CPendingAssembly *EntryToDelete = NULL; CSmartPtrWithNamedDestructor<ASSEMBLY_IDENTITY, SxsDestroyAssemblyIdentity> MuiAssemblyIdentity;
CDequeIterator<CPendingAssembly, offsetof(CPendingAssembly, m_Linkage)> Iter(&pActCtxGenCtx->m_PendingAssemblyList); PARAMETER_CHECK(pActCtxGenCtx != NULL);
for (Iter.Reset(); Iter.More(); Iter.Next()) { bool fFound = false; CAssemblyReference TargetAssemblyRef; CProbedAssemblyInformation &AssemblyFound = Locals->AssemblyFound; AssemblyFound.Reinitialize(); CSmartRef<ASSEMBLY> Assembly;
if (EntryToDelete != NULL) { pActCtxGenCtx->m_PendingAssemblyList.Remove(EntryToDelete); FUSION_DELETE_SINGLETON(EntryToDelete); }
EntryToDelete = NULL;
IFW32FALSE_EXIT(AssemblyFound.Initialize(pActCtxGenCtx)); IFW32FALSE_EXIT(TargetAssemblyRef.Initialize(Iter->GetIdentity()));
IFW32FALSE_EXIT( ::SxspResolvePartialReference( Iter->IsOptional() ? SXSP_RESOLVE_PARTIAL_REFERENCE_FLAG_OPTIONAL : 0, Iter->SourceAssembly(), pActCtxGenCtx, TargetAssemblyRef, AssemblyFound, fFound));
INTERNAL_ERROR_CHECK(fFound || Iter->IsOptional());
if (fFound) { PCASSEMBLY_IDENTITY pAssemblyIdentity = NULL; PCWSTR szLanguage; SIZE_T cchLanguage;
IFW32FALSE_EXIT(::SxspAddManifestToActCtxGenCtx(pActCtxGenCtx, AssemblyFound, &Assembly));
// Note that AssemblyFound is no longer intact; this is to avoid duplication of
// the assembly identity inside the SxspAddManifestToActCtxGenCtx() call.
if (Iter->IsMetadataSatellite()) Iter->SourceAssembly()->m_MetadataSatelliteRosterIndex = Assembly->m_AssemblyRosterIndex;
// If it's a worldwide assembly, we want to auto-probe for the MUI assembly
IFW32FALSE_EXIT( ::SxspGetAssemblyIdentityAttributeValue( SXSP_GET_ASSEMBLY_IDENTITY_ATTRIBUTE_VALUE_FLAG_NOT_FOUND_RETURNS_NULL, Assembly->m_ProbedAssemblyInformation.GetAssemblyIdentity(), &s_IdentityAttribute_language, &szLanguage, &cchLanguage));
if (cchLanguage == 0) { CSmallStringBuffer &buffName = Locals->buffName; PCWSTR szName; SIZE_T cchName; CProbedAssemblyInformation &MuiAssemblyFound = Locals->MuiAssemblyFound; MuiAssemblyFound.Reinitialize(); CAssemblyReference MuiAssemblyRef;
::SxsDestroyAssemblyIdentity(MuiAssemblyIdentity.Detach());
IFW32FALSE_EXIT( ::SxsDuplicateAssemblyIdentity( 0, Assembly->m_ProbedAssemblyInformation.GetAssemblyIdentity(), // PCASSEMBLY_IDENTITY Source,
&MuiAssemblyIdentity));
IFW32FALSE_EXIT( ::SxspSetAssemblyIdentityAttributeValue( SXSP_SET_ASSEMBLY_IDENTITY_ATTRIBUTE_VALUE_FLAG_OVERWRITE_EXISTING, MuiAssemblyIdentity, &s_IdentityAttribute_language, L"*", 1));
IFW32FALSE_EXIT( ::SxspGetAssemblyIdentityAttributeValue( 0, MuiAssemblyIdentity, &s_IdentityAttribute_name, &szName, &cchName));
IFW32FALSE_EXIT(buffName.Win32Assign(szName, cchName)); IFW32FALSE_EXIT(buffName.Win32Append(L".mui", 4));
IFW32FALSE_EXIT( ::SxspSetAssemblyIdentityAttributeValue( SXSP_SET_ASSEMBLY_IDENTITY_ATTRIBUTE_VALUE_FLAG_OVERWRITE_EXISTING, MuiAssemblyIdentity, &s_IdentityAttribute_name, buffName, buffName.Cch()));
IFW32FALSE_EXIT(MuiAssemblyFound.Initialize(pActCtxGenCtx)); IFW32FALSE_EXIT(MuiAssemblyRef.Initialize(MuiAssemblyIdentity));
IFW32FALSE_EXIT( ::SxspResolvePartialReference( SXSP_RESOLVE_PARTIAL_REFERENCE_FLAG_OPTIONAL | SXSP_RESOLVE_PARTIAL_REFERENCE_FLAG_SKIP_WORLDWIDE, Iter->SourceAssembly(), pActCtxGenCtx, MuiAssemblyRef, MuiAssemblyFound, fFound));
if (fFound) IFW32FALSE_EXIT(::SxspAddManifestToActCtxGenCtx(pActCtxGenCtx, MuiAssemblyFound, NULL)); }
}
EntryToDelete = Iter; }
if (EntryToDelete != NULL) { pActCtxGenCtx->m_PendingAssemblyList.Remove(EntryToDelete); FUSION_DELETE_SINGLETON(EntryToDelete); }
FN_EPILOG }
BOOL SxspProcessPendingAssemblies( PACTCTXGENCTX pActCtxGenCtx ) { FN_PROLOG_WIN32
CSmartPtr<CSxspProcessPendingAssembliesLocals> Locals;
IFW32FALSE_EXIT(Locals.Win32Allocate(__FILE__, __LINE__)); IFW32FALSE_EXIT(::SxspProcessPendingAssemblies(pActCtxGenCtx, Locals));
FN_EPILOG }
BOOL SxspCloseManifestGraph( PACTCTXGENCTX pActCtxGenCtx ) { FN_PROLOG_WIN32
CDequeIterator<ASSEMBLY, offsetof(ASSEMBLY, m_Linkage)> Iter(&pActCtxGenCtx->m_AssemblyList); PARAMETER_CHECK(pActCtxGenCtx != NULL);
// We need to just walk the list of assemblies, incorporating any that aren't already
// incorporated into the actctx data. New ones found during incorporation are appended
// to the end of the list, so we should complete everything with a single walk.
for (Iter.Reset(); Iter.More(); Iter.Next()) { if (!Iter->m_Incorporated) { IFW32FALSE_EXIT(::SxspIncorporateAssembly(pActCtxGenCtx, Iter)); } else { PCWSTR AssemblyName = L"<assembly name unavailable>"; PCWSTR ManifestPath = L"<manifest path unavailable>"; Iter->m_ProbedAssemblyInformation.GetAssemblyName(&AssemblyName, NULL); Iter->m_ProbedAssemblyInformation.GetManifestPath(&ManifestPath, NULL); #if DBG
::FusionpDbgPrintEx(FUSION_DBG_LEVEL_INFO, "SXS.DLL: Skipping already incorporated assembly %S (manifest: %S)\n", AssemblyName, ManifestPath); #endif
}
IFW32FALSE_EXIT(::SxspProcessPendingAssemblies(pActCtxGenCtx)); }
FN_EPILOG }
BOOL SxspBuildActCtxData( PACTCTXGENCTX pActCtxGenCtx, PHANDLE SectionHandle ) { FN_PROLOG_WIN32
CActivationContextGenerationContextContributor *Ctb = NULL; SIZE_T SectionTotalSize = 0; SIZE_T TotalHeaderSize = 0; SIZE_T AssemblyRosterSize = 0; ULONG SectionCount = 0; ULONG ExtendedSectionCount = 0; ULONG NonExtendedSectionCount = 0; CSmartArrayPtr<GUID> ExtendedSectionGuids; ULONG ExtensionGuidCount = 0; PACTIVATION_CONTEXT_DATA ActCtxData = NULL; CMappedViewOfFile VoidActCtxData; CFileMapping TempMappingHandle; BYTE *Cursor = NULL; ULONG i; CDequeIterator<ASSEMBLY, offsetof(ASSEMBLY, m_Linkage)> AssemblyIter(&pActCtxGenCtx->m_AssemblyList); PACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_HEADER AssemblyRosterHeader = NULL; PACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_ENTRY AssemblyRosterEntry = NULL; PCACTIVATION_CONTEXT_STRING_SECTION_HEADER AssemblyInformationSection = NULL; // we use this after the main part of
// processing to fill in the assembly roster
PARAMETER_CHECK(pActCtxGenCtx != NULL); INTERNAL_ERROR_CHECK(pActCtxGenCtx->m_ManifestOperation == MANIFEST_OPERATION_GENERATE_ACTIVATION_CONTEXT);
// Let's see how big this whole thing is going to be now.
for (i=0; i<pActCtxGenCtx->m_ContributorCount; i++) { Ctb = &pActCtxGenCtx->m_Contributors[i];
IFW32FALSE_EXIT(Ctb->Fire_AllParsingDone(pActCtxGenCtx)); IFW32FALSE_EXIT(Ctb->Fire_GetSectionSize(pActCtxGenCtx));
if (Ctb->SectionSize() > ULONG_MAX) { ::FusionpDbgPrintEx( FUSION_DBG_LEVEL_ERROR, "SXS.DLL: Contributor %S wants more than ULONG_MAX bytes for its section; failing activation context creation.\n", Ctb->Name());
ORIGINATE_WIN32_FAILURE_AND_EXIT(ContributorNeedsMoreThan2ToThe32ndBytes, ERROR_INSUFFICIENT_BUFFER); }
SectionTotalSize += Ctb->SectionSize();
if (Ctb->SectionSize() != 0) { SectionCount++;
if (Ctb->IsExtendedSection()) ExtendedSectionCount++; else NonExtendedSectionCount++; } }
ASSERT(SectionCount == (ExtendedSectionCount + NonExtendedSectionCount));
// If we had any extended sections, we need to figure out how many
// unique extension GUIDs were present.
ExtensionGuidCount = 0;
if (ExtendedSectionCount != 0) { // There may only be one GUID with 1000 instances, but for the sake of
// simplicity, we'll just allocate an array equal in size to the number
// of extended sections, and do a linear search to find dups. This
// is a clear candidate for rewriting if the extensibility story
// takes off. -mgrier 2/24/2000
IFW32FALSE_EXIT(ExtendedSectionGuids.Win32Allocate(ExtendedSectionCount, __FILE__, __LINE__)); // IFALLOCFAILED_EXIT(ExtendedSectionGuids = FUSION_NEW_ARRAY(GUID, ExtendedSectionCount));
for (i=0; i<pActCtxGenCtx->m_ContributorCount; i++) { Ctb = &pActCtxGenCtx->m_Contributors[i];
if ((Ctb->SectionSize() != 0) && Ctb->IsExtendedSection()) { ULONG j;
for (j=0; j<ExtensionGuidCount; j++) { if (ExtendedSectionGuids[j] == Ctb->ExtensionGuid()) break; }
if (j == ExtensionGuidCount) ExtendedSectionGuids[ExtensionGuidCount++] = Ctb->ExtensionGuid(); } } }
// Figure out the entire size. SectionTotalSize already includes all the
// particular data from the sections; now we need to add in space for the
// headers etc.
TotalHeaderSize = 0;
// The header for the whole thing
TotalHeaderSize += sizeof(ACTIVATION_CONTEXT_DATA);
if (NonExtendedSectionCount != 0) { // The header for the default section TOC
TotalHeaderSize += sizeof(ACTIVATION_CONTEXT_DATA_TOC_HEADER); // The entry for each non-extended section entry in the TOC. For now we'll
// just put the entries in whatever order they're in in the contributor list.
// the code is in place to do the linear searches and we can optimize this
// later.
TotalHeaderSize += (sizeof(ACTIVATION_CONTEXT_DATA_TOC_ENTRY) * NonExtendedSectionCount); }
if (ExtensionGuidCount != 0) { ULONG j;
// The header for the extension GUID TOC
TotalHeaderSize += sizeof(ACTIVATION_CONTEXT_DATA_EXTENDED_TOC_HEADER); // The entry for each extension GUID
TotalHeaderSize += (sizeof(ACTIVATION_CONTEXT_DATA_EXTENDED_TOC_ENTRY) * ExtensionGuidCount);
for (j=0; j<ExtensionGuidCount; j++) { ULONG SectionCountForThisExtension = 0; for (j=0; j<pActCtxGenCtx->m_ContributorCount; j++) { Ctb = &pActCtxGenCtx->m_Contributors[j];
if ((Ctb->SectionSize() != 0) && Ctb->IsExtendedSection() && (Ctb->ExtensionGuid() == ExtendedSectionGuids[j])) SectionCountForThisExtension++; }
TotalHeaderSize += sizeof(ACTIVATION_CONTEXT_DATA_TOC_HEADER); TotalHeaderSize += (sizeof(ACTIVATION_CONTEXT_DATA_TOC_ENTRY) * SectionCountForThisExtension); } }
SectionTotalSize += TotalHeaderSize;
// Allocate space for the assembly roster and the one dead entry at the beginning of the array.
AssemblyRosterSize = sizeof(ACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_HEADER) + sizeof(ACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_ENTRY) + (sizeof(ACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_ENTRY) * pActCtxGenCtx->m_AssemblyList.GetEntryCount());
SectionTotalSize += AssemblyRosterSize;
if (SectionTotalSize > ULONG_MAX) { ::FusionpDbgPrintEx( FUSION_DBG_LEVEL_ERROR, "SXS.DLL: Total size of activation context exceeds ULONG_MAX; failing activation context creation.\n");
ORIGINATE_WIN32_FAILURE_AND_EXIT(SectionSizeTotalMoreThan2ToThe32nd, ERROR_INSUFFICIENT_BUFFER);
goto Exit; }
::FusionpDbgPrintEx( FUSION_DBG_LEVEL_ACTCTX, "SXS.DLL: Creating %lu byte file mapping\n", static_cast<ULONG>(SectionTotalSize));
IFW32NULL_EXIT( TempMappingHandle.Win32CreateFileMapping( INVALID_HANDLE_VALUE, // Pagefile backed section
PAGE_READWRITE, SectionTotalSize));
IFW32NULL_EXIT(VoidActCtxData.Win32MapViewOfFile(TempMappingHandle, FILE_MAP_WRITE)); ActCtxData = reinterpret_cast<PACTIVATION_CONTEXT_DATA>(static_cast<PVOID>(VoidActCtxData));
ActCtxData->Magic = ACTIVATION_CONTEXT_DATA_MAGIC; ActCtxData->HeaderSize = sizeof(ACTIVATION_CONTEXT_DATA); ActCtxData->FormatVersion = ACTIVATION_CONTEXT_DATA_FORMAT_WHISTLER; ActCtxData->TotalSize = static_cast<ULONG>(SectionTotalSize); ActCtxData->Flags = 0;
if (pActCtxGenCtx->m_NoInherit) ActCtxData->Flags |= ACTIVATION_CONTEXT_FLAG_NO_INHERIT;
Cursor = (BYTE *) (ActCtxData + 1);
AssemblyRosterHeader = (PACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_HEADER) Cursor;
Cursor = (BYTE *) (AssemblyRosterHeader + 1);
AssemblyRosterHeader->HeaderSize = sizeof(ACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_HEADER); AssemblyRosterHeader->HashAlgorithm = FUSION_HASH_ALGORITHM; AssemblyRosterHeader->EntryCount = static_cast<ULONG>(pActCtxGenCtx->m_AssemblyList.GetEntryCount() + 1); AssemblyRosterHeader->FirstEntryOffset = static_cast<LONG>(((LONG_PTR) Cursor) - ((LONG_PTR) ActCtxData));
AssemblyRosterEntry = (PACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_ENTRY) Cursor; Cursor = (BYTE *) (AssemblyRosterEntry + AssemblyRosterHeader->EntryCount);
// First assembly roster entry is a blank one for index 0
AssemblyRosterEntry[0].Flags = ACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_ENTRY_INVALID; AssemblyRosterEntry[0].AssemblyNameLength = 0; AssemblyRosterEntry[0].AssemblyNameOffset = 0; AssemblyRosterEntry[0].PseudoKey = 0;
// Fill in the roster with bogus data to start with; we'll fill it in for real after
// we've found the assembly information section.
for (AssemblyIter.Reset(), i = 1; AssemblyIter.More(); AssemblyIter.Next(), i++) { AssemblyRosterEntry[i].Flags = ACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_ENTRY_INVALID;
if (AssemblyIter->IsRoot()) AssemblyRosterEntry[i].Flags |= ACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_ENTRY_ROOT; }
ActCtxData->AssemblyRosterOffset = static_cast<LONG>(((LONG_PTR) AssemblyRosterHeader) - ((LONG_PTR) ActCtxData));
if (NonExtendedSectionCount != 0) { PACTIVATION_CONTEXT_DATA_TOC_HEADER Toc = (PACTIVATION_CONTEXT_DATA_TOC_HEADER) Cursor; PACTIVATION_CONTEXT_DATA_TOC_ENTRY Entry = (PACTIVATION_CONTEXT_DATA_TOC_ENTRY) (Toc + 1); ULONG iEntry = 0; ULONG j; ULONG LastSectionId;
Toc->HeaderSize = sizeof(ACTIVATION_CONTEXT_DATA_TOC_HEADER); Toc->EntryCount = NonExtendedSectionCount; Toc->FirstEntryOffset = static_cast<LONG>(((LONG_PTR) Entry) - ((LONG_PTR) ActCtxData));
Cursor = (BYTE *) (Entry + NonExtendedSectionCount);
// Since we sorted the providers prior to building the array, we can set the
// inorder bit so that we at least do a binary search at runtime.
// We'll assume it's dense also; if we find out that it isn't while we're
// building, we'll clear the dense bit.
Toc->Flags = ACTIVATION_CONTEXT_DATA_TOC_HEADER_INORDER | ACTIVATION_CONTEXT_DATA_TOC_HEADER_DENSE;
for (j=0; j<pActCtxGenCtx->m_ContributorCount; j++) { Ctb = &pActCtxGenCtx->m_Contributors[j];
LastSectionId = 0;
if ((Ctb->SectionSize() != 0) && !Ctb->IsExtendedSection()) { if (iEntry != 0) { if (Ctb->SectionId() != (LastSectionId + 1)) Toc->Flags &= ~ACTIVATION_CONTEXT_DATA_TOC_HEADER_DENSE; }
LastSectionId = Ctb->SectionId();
Entry->Id = Ctb->SectionId(); Entry->Offset = static_cast<LONG>(((LONG_PTR) Cursor) - ((LONG_PTR) ActCtxData)); Entry->Length = static_cast<ULONG>(Ctb->SectionSize()); Entry->Format = Ctb->SectionFormat();
IFW32FALSE_EXIT(Ctb->Fire_GetSectionData(pActCtxGenCtx, Cursor));
// We have special knowledge about the assembly metadata section; we reference it
// in the assembly roster.
if (Ctb->SectionId() == ACTIVATION_CONTEXT_SECTION_ASSEMBLY_INFORMATION) AssemblyInformationSection = (PCACTIVATION_CONTEXT_STRING_SECTION_HEADER) Cursor;
Cursor = (BYTE *) (((ULONG_PTR) Cursor) + Ctb->SectionSize()); Entry++; iEntry++; } }
ActCtxData->DefaultTocOffset = static_cast<LONG>(((LONG_PTR) Toc) - ((LONG_PTR) ActCtxData)); } else ActCtxData->DefaultTocOffset = 0;
if (ExtensionGuidCount != 0) { ULONG j; PACTIVATION_CONTEXT_DATA_EXTENDED_TOC_HEADER ExtToc = (PACTIVATION_CONTEXT_DATA_EXTENDED_TOC_HEADER) Cursor; PACTIVATION_CONTEXT_DATA_EXTENDED_TOC_ENTRY ExtTocEntry = (PACTIVATION_CONTEXT_DATA_EXTENDED_TOC_ENTRY) (ExtToc + 1);
Cursor = (BYTE *) (ExtTocEntry + ExtensionGuidCount);
ExtToc->HeaderSize = sizeof(ACTIVATION_CONTEXT_DATA_EXTENDED_TOC_HEADER); ExtToc->EntryCount = ExtensionGuidCount; ExtToc->FirstEntryOffset = static_cast<LONG>(((LONG_PTR) ExtTocEntry) - ((LONG_PTR) ActCtxData)); ExtToc->Flags = 0;
for (j=0; j<ExtensionGuidCount; j++) { ULONG k; ULONG SectionCountForThisExtension = 0; PACTIVATION_CONTEXT_DATA_TOC_HEADER Toc = (PACTIVATION_CONTEXT_DATA_TOC_HEADER) Cursor; PACTIVATION_CONTEXT_DATA_TOC_ENTRY Entry = (PACTIVATION_CONTEXT_DATA_TOC_ENTRY) (Toc + 1);
ExtTocEntry->ExtensionGuid = ExtendedSectionGuids[i];
for (k=0; k<pActCtxGenCtx->m_ContributorCount; k++) { Ctb = &pActCtxGenCtx->m_Contributors[k];
if ((Ctb->SectionSize() != 0) && Ctb->IsExtendedSection() && (Ctb->ExtensionGuid() == ExtendedSectionGuids[j])) { SectionCountForThisExtension++; } }
Cursor = (BYTE *) (Entry + SectionCountForThisExtension);
Toc->HeaderSize = sizeof(ACTIVATION_CONTEXT_DATA_TOC_HEADER); Toc->EntryCount = SectionCountForThisExtension; Toc->FirstEntryOffset = static_cast<LONG>(((LONG_PTR) Entry) - ((LONG_PTR) ActCtxData)); Toc->Flags = 0;
for (k=0; k<pActCtxGenCtx->m_ContributorCount; k++) { Ctb = &pActCtxGenCtx->m_Contributors[k];
if ((Ctb->SectionSize() != 0) && Ctb->IsExtendedSection() && (Ctb->ExtensionGuid() == ExtendedSectionGuids[k]) && (Ctb->SectionId() != 0) ) { SIZE_T SectionSize = Ctb->SectionSize();
Entry->Id = Ctb->SectionId(); Entry->Offset = static_cast<LONG>(((LONG_PTR) Cursor) - ((LONG_PTR) ActCtxData)); Entry->Length = static_cast<ULONG>(SectionSize); Entry->Format = Ctb->SectionFormat();
IFW32FALSE_EXIT(Ctb->Fire_GetSectionData(pActCtxGenCtx, Cursor));
Cursor = (BYTE *) (((ULONG_PTR) Cursor) + SectionSize); Entry++; } } }
ActCtxData->ExtendedTocOffset = static_cast<LONG>(((LONG_PTR) ExtToc) - ((LONG_PTR) ActCtxData)); } else ActCtxData->ExtendedTocOffset = 0;
ASSERT(AssemblyInformationSection != NULL); // Go back and fill in the assembly roster...
if (AssemblyInformationSection != NULL) { PCACTIVATION_CONTEXT_STRING_SECTION_ENTRY Entries = (PCACTIVATION_CONTEXT_STRING_SECTION_ENTRY) (((ULONG_PTR) AssemblyInformationSection) + AssemblyInformationSection->ElementListOffset); LONG_PTR SectionOffset = ((LONG_PTR) AssemblyInformationSection) - ((LONG_PTR) ActCtxData);
AssemblyRosterHeader->HashAlgorithm = AssemblyInformationSection->HashAlgorithm; AssemblyRosterHeader->AssemblyInformationSectionOffset = static_cast<ULONG>(SectionOffset);
// If there are 3 assemblies, there must be 3 entries in the section and 4 roster entries
// (counting the bogus entry 0).
ASSERT(AssemblyInformationSection->ElementCount == (AssemblyRosterHeader->EntryCount - 1)); if (AssemblyInformationSection->ElementCount != (AssemblyRosterHeader->EntryCount - 1)) { ::FusionpSetLastWin32Error(ERROR_INTERNAL_ERROR); goto Exit; }
for (i=0; i<AssemblyInformationSection->ElementCount; i++) { ULONG iRoster = Entries[i].AssemblyRosterIndex;
ASSERT(iRoster != 0); ASSERT(iRoster < AssemblyRosterHeader->EntryCount);
if ((iRoster == 0) || (iRoster >= AssemblyRosterHeader->EntryCount)) { ::FusionpSetLastWin32Error(ERROR_INTERNAL_ERROR); goto Exit; }
// Make sure that we're not repeating an index somehow...
ASSERT(AssemblyRosterEntry[iRoster].Flags & ACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_ENTRY_INVALID); if ((AssemblyRosterEntry[iRoster].Flags & ACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_ENTRY_INVALID) == 0) { ::FusionpSetLastWin32Error(ERROR_INTERNAL_ERROR); goto Exit; }
// Turn off the invalid flag...
AssemblyRosterEntry[iRoster].Flags &= ~ACTIVATION_CONTEXT_DATA_ASSEMBLY_ROSTER_ENTRY_INVALID;
// Point to the data already in the string section header
AssemblyRosterEntry[iRoster].AssemblyNameLength = Entries[i].KeyLength;
if (Entries[i].KeyOffset != 0) AssemblyRosterEntry[iRoster].AssemblyNameOffset = static_cast<LONG>(Entries[i].KeyOffset + SectionOffset); else AssemblyRosterEntry[iRoster].AssemblyNameOffset = 0;
AssemblyRosterEntry[iRoster].AssemblyInformationLength = Entries[i].Length; AssemblyRosterEntry[iRoster].AssemblyInformationOffset = static_cast<LONG>(Entries[i].Offset + SectionOffset); AssemblyRosterEntry[iRoster].PseudoKey = Entries[i].PseudoKey; } } else { // the assembly metadata section provider should have contributed *something*
::FusionpSetLastWin32Error(ERROR_INTERNAL_ERROR); goto Exit; }
if (::FusionpDbgWouldPrintAtFilterLevel(FUSION_DBG_LEVEL_ACTCTX)) { CTinyStringBuffer buffPrefix; ::SxspDbgPrintActivationContextData(FUSION_DBG_LEVEL_ACTCTX, ActCtxData, buffPrefix); }
IFW32FALSE_EXIT(VoidActCtxData.Win32Close()); *SectionHandle = TempMappingHandle.Detach();
FN_EPILOG }
CPendingAssembly::CPendingAssembly() : m_SourceAssembly(NULL), m_Identity(NULL), m_Optional(false), m_MetadataSatellite(false) { }
CPendingAssembly::~CPendingAssembly() { if (m_Identity != NULL) { ::SxsDestroyAssemblyIdentity(m_Identity); m_Identity = NULL; } }
BOOL CPendingAssembly::Initialize( PASSEMBLY Assembly, PCASSEMBLY_IDENTITY Identity, bool Optional, bool MetadataSatellite ) { BOOL fSuccess = FALSE; FN_TRACE_WIN32(fSuccess);
INTERNAL_ERROR_CHECK(m_Identity == NULL);
PARAMETER_CHECK(Identity != NULL);
IFW32FALSE_EXIT(::SxsDuplicateAssemblyIdentity(0, Identity, &m_Identity)); m_SourceAssembly = Assembly; m_Optional = Optional; m_MetadataSatellite = MetadataSatellite;
fSuccess = TRUE; Exit: return fSuccess; }
|