Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

306 lines
7.8 KiB

/*
Copyright (c) Microsoft Corporation
*/
#include "stdinc.h"
#include "fusionparser.h"
#include "policystatement.h"
#include "sxsid.h"
BOOL
CPolicyStatementRedirect::Initialize(
const CBaseStringBuffer &rbuffFromVersionRange,
const CBaseStringBuffer &rbuffToVersion,
bool &rfValid
)
{
FN_PROLOG_WIN32
PCWSTR pszDash;
CStringBuffer buffTemp;
ASSEMBLY_VERSION avFromMin = { 0 };
ASSEMBLY_VERSION avFromMax = { 0 };
ASSEMBLY_VERSION avTo = { 0 };
bool fValid;
rfValid = false;
// let's see if we have a singleton or a range...
pszDash = ::wcschr(rbuffFromVersionRange, L'-');
if (pszDash == NULL)
{
// It must be a singleton. Parse it.
IFW32FALSE_EXIT(CFusionParser::ParseVersion(avFromMin, rbuffFromVersionRange, rbuffFromVersionRange.Cch(), fValid));
if (fValid)
avFromMax = avFromMin;
}
else
{
SIZE_T cchFirstSegment = static_cast<SIZE_T>(pszDash - rbuffFromVersionRange);
IFW32FALSE_EXIT(CFusionParser::ParseVersion(avFromMin, rbuffFromVersionRange, cchFirstSegment, fValid));
if (fValid)
{
IFW32FALSE_EXIT(CFusionParser::ParseVersion(avFromMax, pszDash + 1, rbuffFromVersionRange.Cch() - (cchFirstSegment + 1), fValid));
if (avFromMin > avFromMax)
fValid = false;
}
}
if (fValid)
IFW32FALSE_EXIT(CFusionParser::ParseVersion(avTo, rbuffToVersion, rbuffToVersion.Cch(), fValid));
if (fValid)
{
// Everything parsed OK. We keep the binary/numeric form of the from range so that we can do
// fast comparisons, but we keep the string of the to version because assembly identity attributes
// are stored as strings.
IFW32FALSE_EXIT(m_NewVersion.Win32Assign(rbuffToVersion));
m_avFromMin = avFromMin;
m_avFromMax = avFromMax;
rfValid = true;
}
#if DBG
if (rfValid)
{
FusionpDbgPrintEx(FUSION_DBG_LEVEL_BINDING,
"SXS: %s New redirection found: %d.%d.%d.%d-%d.%d.%d.%d to %ls\n",
__FUNCTION__,
m_avFromMin.Major, m_avFromMin.Minor, m_avFromMin.Revision, m_avFromMin.Build,
m_avFromMax.Major, m_avFromMax.Minor, m_avFromMax.Revision, m_avFromMax.Build,
static_cast<PCWSTR>(m_NewVersion));
}
else
{
FusionpDbgPrintEx(FUSION_DBG_LEVEL_BINDING,
"SXS: %s Rejecting redirection strings '%ls' -> '%ls'\n",
static_cast<PCWSTR>(rbuffFromVersionRange),
static_cast<PCWSTR>(rbuffToVersion));
}
#endif
FN_EPILOG
}
BOOL
CPolicyStatementRedirect::TryMap(
const ASSEMBLY_VERSION &rav,
CBaseStringBuffer &TargetVersion,
bool &rfMapped
)
{
FN_PROLOG_WIN32
rfMapped = false;
if ((rav >= m_avFromMin) &&
(rav <= m_avFromMax))
{
IFW32FALSE_EXIT(TargetVersion.Win32Assign(m_NewVersion));
rfMapped = true;
}
FN_EPILOG
}
BOOL
CPolicyStatementRedirect::CheckForOverlap(
const CPolicyStatementRedirect &rRedirect,
bool &rfOverlaps
)
{
FN_PROLOG_WIN32
rfOverlaps = false;
// we can assume that the other redirect is well formed (min <= max)
if (((rRedirect.m_avFromMax >= m_avFromMin) &&
(rRedirect.m_avFromMax <= m_avFromMax)) ||
((rRedirect.m_avFromMin <= m_avFromMax) &&
(rRedirect.m_avFromMin >= m_avFromMin)))
{
rfOverlaps = true;
}
FN_EPILOG
}
//
// Implementation of CPolicyStatement
//
BOOL
CPolicyStatement::Initialize()
{
return TRUE;
}
BOOL
CPolicyStatement::AddRedirect(
const CBaseStringBuffer &rbuffFromVersion,
const CBaseStringBuffer &rbuffToVersion,
bool &rfValid
)
{
BOOL fSuccess = FALSE;
FN_TRACE_WIN32(fSuccess);
CPolicyStatementRedirect *Redirect = NULL;
CDequeIterator<CPolicyStatementRedirect, FIELD_OFFSET(CPolicyStatementRedirect, m_leLinks)> iter;
bool fOverlaps;
bool fValid = false;
rfValid = false;
// NTRAID#NTBUG9 - 591010 - 2002/03/30 - mgrier - switch to using smart pointer
IFALLOCFAILED_EXIT(Redirect = new CPolicyStatementRedirect);
IFW32FALSE_EXIT(Redirect->Initialize(rbuffFromVersion, rbuffToVersion, fValid));
if (fValid)
{
iter.Rebind(&m_Redirects);
for (iter.Reset(); iter.More(); iter.Next())
{
IFW32FALSE_EXIT(iter->CheckForOverlap(*Redirect, fOverlaps));
if (fOverlaps)
{
fValid = false;
break;
}
}
iter.Unbind();
}
if (fValid)
{
// Looks good; add it!
m_Redirects.AddToTail(Redirect);
Redirect = NULL;
rfValid = true;
}
// NTRAID#NTBUG9 - 591010 - 2002/03/30 - mgrier - Once Redirect is a smart pointer, switch
// the function epilog to FN_EPILOG
fSuccess = TRUE;
Exit:
if (Redirect != NULL)
FUSION_DELETE_SINGLETON(Redirect);
return fSuccess;
}
BOOL
CPolicyStatement::ApplyPolicy(
PASSEMBLY_IDENTITY AssemblyIdentity,
bool &rfPolicyApplied
)
{
FN_PROLOG_WIN32
PCWSTR Version = NULL;
SIZE_T VersionCch = 0;
CSmallStringBuffer VersionBuffer;
SIZE_T cchWritten = 0;
CDequeIterator<CPolicyStatementRedirect, FIELD_OFFSET(CPolicyStatementRedirect, m_leLinks)> iter;
ASSEMBLY_VERSION av;
bool fSyntaxValid;
bool fMapped = false;
#if DBG
PCWSTR Name = NULL;
SIZE_T NameCch = 0;
#endif
rfPolicyApplied = false;
PARAMETER_CHECK(AssemblyIdentity != NULL);
IFW32FALSE_EXIT(
::SxspGetAssemblyIdentityAttributeValue(
0,
AssemblyIdentity,
&s_IdentityAttribute_version,
&Version,
&VersionCch));
#if DBG
IFW32FALSE_EXIT(
::SxspGetAssemblyIdentityAttributeValue(
0,
AssemblyIdentity,
&s_IdentityAttribute_name,
&Name,
&NameCch));
#endif
IFW32FALSE_EXIT(CFusionParser::ParseVersion(av, Version, VersionCch, fSyntaxValid));
// An invalid version number should have been caught earlier.
INTERNAL_ERROR_CHECK(fSyntaxValid);
iter.Rebind(&m_Redirects);
for (iter.Reset(); iter.More(); iter.Next())
{
IFW32FALSE_EXIT(iter->TryMap(av, VersionBuffer, fMapped));
if (fMapped)
{
FusionpDbgPrintEx(
FUSION_DBG_LEVEL_BINDING,
"SXS: %s Intermediate redirection : %d.%d.%d.%d to %ls\n",
__FUNCTION__,
av.Major, av.Minor, av.Revision, av.Build,
static_cast<PCWSTR>(VersionBuffer));
break;
}
}
if (fMapped)
{
#if DBG
FusionpDbgPrintEx(
FUSION_DBG_LEVEL_BINDING,
"SXS: %s Final version redirection for %.*ls was from '%.*ls' to '%ls'\n",
__FUNCTION__,
NameCch, Name,
VersionCch, Version,
static_cast<PCWSTR>(VersionBuffer));
#endif
IFW32FALSE_EXIT(
::SxspSetAssemblyIdentityAttributeValue(
SXSP_SET_ASSEMBLY_IDENTITY_ATTRIBUTE_VALUE_FLAG_OVERWRITE_EXISTING,
AssemblyIdentity,
&s_IdentityAttribute_version,
VersionBuffer,
VersionBuffer.Cch()));
rfPolicyApplied = true;
}
#if DBG
else
{
FusionpDbgPrintEx(
FUSION_DBG_LEVEL_BINDING,
"SXS: %s No redirections for '%.*ls' found\n",
__FUNCTION__,
NameCch, Name);
}
#endif
FN_EPILOG
}