windows-nt/Source/XPSP1/NT/base/win32/fusion/id/sxsid.cpp

448 lines
14 KiB
C++
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
#include "stdinc.h"
#include <setupapi.h>
#include <sxsapi.h>
#include <stdlib.h>
#include <search.h>
#include "idp.h"
#include "sxsapi.h"
#include "sxsapi.h"
#include "sxsid.h"
ASSEMBLY_IDENTITY_ATTRIBUTE
SxsComposeAssemblyIdentityAttribute(
PCWSTR pszNamespace, SIZE_T cchNamespace,
PCWSTR pszName, SIZE_T cchName,
PCWSTR pszValue, SIZE_T cchValue)
{
ASSEMBLY_IDENTITY_ATTRIBUTE anattribute;
anattribute.Flags = 0; // reserved flags : must be 0;
anattribute.NamespaceCch = cchNamespace;
anattribute.NameCch = cchName;
anattribute.ValueCch = cchValue;
anattribute.Namespace = pszNamespace;
anattribute.Name = pszName;
anattribute.Value = pszValue;
return anattribute;
}
BOOL
SxsAssemblyIdentityIsAttributePresent(
PCASSEMBLY_IDENTITY pAssemblyIdentity,
PCWSTR pszNamespace,
SIZE_T cchNamespace,
PCWSTR pszName,
SIZE_T cchName,
BOOL & rfFound)
{
BOOL fSuccess = FALSE;
FN_TRACE_WIN32(fSuccess);
ULONG Count = 0;
ASSEMBLY_IDENTITY_ATTRIBUTE Attribute;
DWORD dwFindFlags;
PARAMETER_CHECK(pszName != NULL);
rfFound = FALSE;
if ( pAssemblyIdentity == NULL)
{
goto Done;
}
// in the case of a NULL namespace, we must set the flag, too ? xiaoyuw@09/11/00
dwFindFlags = SXS_FIND_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_NAMESPACE | SXS_FIND_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_NAME;
Attribute = SxsComposeAssemblyIdentityAttribute(pszNamespace, cchNamespace, pszName, cchName, NULL, 0);
if (pAssemblyIdentity){
IFW32FALSE_EXIT(
::SxsFindAssemblyIdentityAttribute( // find attribute by "namespace" and "name"
SXS_FIND_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_NAMESPACE |
SXS_FIND_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_NAME |
SXS_FIND_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_NOT_FOUND_SUCCEEDS,
pAssemblyIdentity,
&Attribute,
NULL,
&Count));
if ( Count >0 ) { // found
rfFound = TRUE;
}
}
Done:
fSuccess = TRUE;
Exit:
return fSuccess;
}
BOOL
SxspSetAssemblyIdentityAttributeValue(
DWORD Flags,
PASSEMBLY_IDENTITY AssemblyIdentity,
PCSXS_ASSEMBLY_IDENTITY_ATTRIBUTE_REFERENCE AttributeReference,
const WCHAR *Value,
SIZE_T ValueCch
)
{
BOOL fSuccess = FALSE;
FN_TRACE_WIN32(fSuccess);
ASSEMBLY_IDENTITY_ATTRIBUTE Attribute;
DWORD FlagsToRealInsert = 0;
PARAMETER_CHECK((Flags & ~(SXSP_SET_ASSEMBLY_IDENTITY_ATTRIBUTE_VALUE_FLAG_OVERWRITE_EXISTING)) == 0);
PARAMETER_CHECK(AssemblyIdentity != NULL);
PARAMETER_CHECK(AttributeReference != NULL);
PARAMETER_CHECK(Value != NULL || ValueCch == 0);
Attribute.Flags = 0;
Attribute.Namespace = AttributeReference->Namespace;
Attribute.NamespaceCch = AttributeReference->NamespaceCch;
Attribute.Name = AttributeReference->Name;
Attribute.NameCch = AttributeReference->NameCch;
Attribute.Value = Value;
Attribute.ValueCch = ValueCch;
if (Flags & SXSP_SET_ASSEMBLY_IDENTITY_ATTRIBUTE_VALUE_FLAG_OVERWRITE_EXISTING)
FlagsToRealInsert |= SXS_INSERT_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_OVERWRITE_EXISTING;
IFW32FALSE_EXIT(::SxsInsertAssemblyIdentityAttribute(FlagsToRealInsert, AssemblyIdentity, &Attribute));
fSuccess = TRUE;
Exit:
return fSuccess;
}
BOOL
SxspSetAssemblyIdentityAttributeValue(
DWORD Flags,
PASSEMBLY_IDENTITY AssemblyIdentity,
PCSXS_ASSEMBLY_IDENTITY_ATTRIBUTE_REFERENCE AttributeReference,
const CBaseStringBuffer &Value
)
{
BOOL fSuccess = FALSE;
FN_TRACE_WIN32(fSuccess);
IFW32FALSE_EXIT(
::SxspSetAssemblyIdentityAttributeValue(
Flags,
AssemblyIdentity,
AttributeReference,
static_cast<PCWSTR>(Value),
Value.Cch()));
fSuccess = TRUE;
Exit:
return fSuccess;
}
/////////////////////////////////////////////////////////////////////////////
// Action :
// 1. if (namespace, name) is provided, remove all attributes with such (namespace, name)
// 2. if (namespace, name, value), remove at most 1 attribute from assembly-identity
///////////////////////////////////////////////////////////////////////////////
BOOL
SxspRemoveAssemblyIdentityAttribute(
DWORD Flags,
PASSEMBLY_IDENTITY pAssemblyIdentity,
PCSXS_ASSEMBLY_IDENTITY_ATTRIBUTE_REFERENCE AttributeReference
)
{
BOOL fSuccess = FALSE;
FN_TRACE_WIN32(fSuccess);
ASSEMBLY_IDENTITY_ATTRIBUTE Attribute;
ULONG Ordinal;
ULONG Count;
DWORD dwFindAttributeFlags = 0;
PARAMETER_CHECK((Flags & ~(SXSP_REMOVE_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_NOT_FOUND_SUCCEEDS)) == 0);
PARAMETER_CHECK(pAssemblyIdentity != NULL);
PARAMETER_CHECK(AttributeReference != NULL);
Attribute.Flags = 0;
Attribute.Namespace = AttributeReference->Namespace;
Attribute.NamespaceCch = AttributeReference->NamespaceCch;
Attribute.Name = AttributeReference->Name;
Attribute.NameCch = AttributeReference->NameCch;
dwFindAttributeFlags = SXS_FIND_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_NAMESPACE | SXS_FIND_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_NAME;
// If it's OK for the attribute not to exist, set the flag in the call to find it.
if (Flags & SXSP_REMOVE_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_NOT_FOUND_SUCCEEDS)
dwFindAttributeFlags |= SXS_FIND_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_NOT_FOUND_SUCCEEDS;
IFW32FALSE_EXIT(
::SxsFindAssemblyIdentityAttribute(
dwFindAttributeFlags,
pAssemblyIdentity,
&Attribute,
&Ordinal,
&Count));
INTERNAL_ERROR_CHECK(Count <= 1);
if (Count > 0)
{
IFW32FALSE_EXIT(
::SxsRemoveAssemblyIdentityAttributesByOrdinal(
0, // DWORD Flags,
pAssemblyIdentity,
Ordinal,
Count));
}
fSuccess = TRUE;
Exit:
return fSuccess;
}
/////////////////////////////////////////////////////////////////////////////
// if no such attribure with such (namespace and name), return FALSE with
// ::SetLastError(ERROR_NOT_FOUND);
///////////////////////////////////////////////////////////////////////////////
BOOL
SxspGetAssemblyIdentityAttributeValue(
DWORD Flags,
PCASSEMBLY_IDENTITY AssemblyIdentity,
PCSXS_ASSEMBLY_IDENTITY_ATTRIBUTE_REFERENCE AttributeReference,
OUT PCWSTR *StringOut,
OUT SIZE_T *CchOut OPTIONAL
)
{
BOOL fSuccess = FALSE;
FN_TRACE_WIN32(fSuccess);
PCINTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE InternalAttribute = NULL;
ASSEMBLY_IDENTITY_ATTRIBUTE Attribute;
DWORD dwLocateFlags = SXSP_LOCATE_INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_NAMESPACE | SXSP_LOCATE_INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_MATCH_NAME;
if (StringOut != NULL)
*StringOut = NULL;
if (CchOut != NULL)
*CchOut = 0;
PARAMETER_CHECK((Flags & ~(SXSP_GET_ASSEMBLY_IDENTITY_ATTRIBUTE_VALUE_FLAG_NOT_FOUND_RETURNS_NULL)) == 0);
PARAMETER_CHECK(AssemblyIdentity != NULL);
PARAMETER_CHECK(AttributeReference != NULL);
Attribute.Flags = 0;
Attribute.Namespace = AttributeReference->Namespace;
Attribute.NamespaceCch = AttributeReference->NamespaceCch;
Attribute.Name = AttributeReference->Name;
Attribute.NameCch = AttributeReference->NameCch;
if (Flags & SXSP_GET_ASSEMBLY_IDENTITY_ATTRIBUTE_VALUE_FLAG_NOT_FOUND_RETURNS_NULL)
dwLocateFlags |= SXSP_LOCATE_INTERNAL_ASSEMBLY_IDENTITY_ATTRIBUTE_FLAG_NOT_FOUND_RETURNS_NULL;
IFW32FALSE_EXIT(
::SxspLocateInternalAssemblyIdentityAttribute(
dwLocateFlags,
AssemblyIdentity,
&Attribute,
&InternalAttribute,
NULL));
if (InternalAttribute != NULL)
{
if (StringOut != NULL)
*StringOut = InternalAttribute->Attribute.Value;
if (CchOut != NULL)
*CchOut = InternalAttribute->Attribute.ValueCch;
}
fSuccess = TRUE;
Exit:
return fSuccess;
}
BOOL
SxspGetAssemblyIdentityAttributeValue(
IN DWORD Flags,
IN PCASSEMBLY_IDENTITY AssemblyIdentity,
PCSXS_ASSEMBLY_IDENTITY_ATTRIBUTE_REFERENCE AttributeReference,
OUT CBaseStringBuffer &Value
)
{
BOOL fSuccess = FALSE;
FN_TRACE_WIN32(fSuccess);
PCWSTR String = NULL;
SIZE_T Cch = 0;
IFW32FALSE_EXIT(
::SxspGetAssemblyIdentityAttributeValue(
Flags,
AssemblyIdentity,
AttributeReference,
&String,
&Cch));
IFW32FALSE_EXIT(Value.Win32Assign(String, Cch));
fSuccess = TRUE;
Exit:
return fSuccess;
}
BOOL
SxspUpdateAssemblyIdentityHash(
DWORD dwFlags,
PASSEMBLY_IDENTITY AssemblyIdentity
)
{
BOOL fSuccess = FALSE;
FN_TRACE_WIN32(fSuccess);
PARAMETER_CHECK(dwFlags == 0);
PARAMETER_CHECK(AssemblyIdentity != NULL);
if (AssemblyIdentity->HashDirty)
{
IFW32FALSE_EXIT(::SxspHashInternalAssemblyIdentityAttributes(
0,
AssemblyIdentity->AttributeCount,
AssemblyIdentity->AttributePointerArray,
&AssemblyIdentity->Hash));
AssemblyIdentity->HashDirty = FALSE;
}
fSuccess = TRUE;
Exit:
return fSuccess;
}
BOOL
SxspEnsureAssemblyIdentityHashIsUpToDate(
DWORD dwFlags,
PCASSEMBLY_IDENTITY AssemblyIdentity
)
{
BOOL fSuccess = FALSE;
FN_TRACE_WIN32(fSuccess);
PARAMETER_CHECK(dwFlags == 0);
PARAMETER_CHECK(AssemblyIdentity != NULL);
if (AssemblyIdentity->HashDirty)
IFW32FALSE_EXIT(::SxspUpdateAssemblyIdentityHash(0, const_cast<PASSEMBLY_IDENTITY>(AssemblyIdentity)));
fSuccess = TRUE;
Exit:
return fSuccess;
}
BOOL
SxsHashAssemblyIdentity(
DWORD dwFlags,
PCASSEMBLY_IDENTITY pAssemblyIdentity,
ULONG * pulPseudoKey
)
{
BOOL fSuccess = FALSE;
FN_TRACE_WIN32(fSuccess);
ULONG ulPseudoKey;
if (pulPseudoKey)
*pulPseudoKey = 0;
PARAMETER_CHECK(dwFlags == 0);
if (pAssemblyIdentity == NULL)
ulPseudoKey = 0;
else
{
IFW32FALSE_EXIT(::SxspEnsureAssemblyIdentityHashIsUpToDate(0, pAssemblyIdentity));
ulPseudoKey = pAssemblyIdentity->Hash;
}
if (pulPseudoKey != NULL)
*pulPseudoKey = ulPseudoKey;
fSuccess = TRUE;
Exit:
return fSuccess;
}
// just to find whether Equal or Not
BOOL
SxsAreAssemblyIdentitiesEqual(
DWORD dwFlags,
PCASSEMBLY_IDENTITY pAssemblyIdentity1,
PCASSEMBLY_IDENTITY pAssemblyIdentity2,
BOOL *EqualOut
)
{
BOOL fSuccess = FALSE;
FN_TRACE_WIN32(fSuccess);
BOOL Equal = FALSE;
if (EqualOut != NULL)
*EqualOut = FALSE;
PARAMETER_CHECK((dwFlags & ~(SXS_ARE_ASSEMBLY_IDENTITIES_EQUAL_FLAG_ALLOW_REF_TO_MATCH_DEF)) == 0);
PARAMETER_CHECK(pAssemblyIdentity1 != NULL);
PARAMETER_CHECK(pAssemblyIdentity2 != NULL);
PARAMETER_CHECK(EqualOut != NULL);
// get hash for each assembly identity
IFW32FALSE_EXIT(::SxspEnsureAssemblyIdentityHashIsUpToDate(0, pAssemblyIdentity1));
IFW32FALSE_EXIT(::SxspEnsureAssemblyIdentityHashIsUpToDate(0, pAssemblyIdentity2));
// compare hash value of two identity; it's a quick way to determine they're not equal.
if (pAssemblyIdentity2->Hash == pAssemblyIdentity1->Hash)
{
// Note that two identities which differ only in their internal flags are still semantically
// equal.
if ((pAssemblyIdentity1->Flags == pAssemblyIdentity2->Flags) &&
(pAssemblyIdentity1->Hash == pAssemblyIdentity2->Hash) &&
(pAssemblyIdentity1->NamespaceCount == pAssemblyIdentity2->NamespaceCount) &&
(pAssemblyIdentity1->AttributeCount == pAssemblyIdentity2->AttributeCount))
{
if (dwFlags & SXS_ARE_ASSEMBLY_IDENTITIES_EQUAL_FLAG_ALLOW_REF_TO_MATCH_DEF)
{
if (((pAssemblyIdentity1->Type == ASSEMBLY_IDENTITY_TYPE_DEFINITION) ||
(pAssemblyIdentity1->Type == ASSEMBLY_IDENTITY_TYPE_REFERENCE)) &&
((pAssemblyIdentity2->Type == ASSEMBLY_IDENTITY_TYPE_DEFINITION) ||
(pAssemblyIdentity2->Type == ASSEMBLY_IDENTITY_TYPE_REFERENCE)))
{
// They match sufficiently...
Equal = TRUE;
}
}
else
Equal = (pAssemblyIdentity1->Type == pAssemblyIdentity2->Type);
if (Equal)
{
ULONG ComparisonResult = SXS_COMPARE_ASSEMBLY_IDENTITY_ATTRIBUTES_COMPARISON_RESULT_INVALID;
// Reset our assumption...
Equal = FALSE;
IFW32FALSE_EXIT(
::SxspCompareAssemblyIdentityAttributeLists(
0,
pAssemblyIdentity1->AttributeCount,
pAssemblyIdentity1->AttributePointerArray,
pAssemblyIdentity2->AttributePointerArray,
&ComparisonResult));
INTERNAL_ERROR_CHECK(
(ComparisonResult == SXS_COMPARE_ASSEMBLY_IDENTITY_ATTRIBUTES_COMPARISON_RESULT_LESS_THAN) ||
(ComparisonResult == SXS_COMPARE_ASSEMBLY_IDENTITY_ATTRIBUTES_COMPARISON_RESULT_EQUAL) ||
(ComparisonResult == SXS_COMPARE_ASSEMBLY_IDENTITY_ATTRIBUTES_COMPARISON_RESULT_GREATER_THAN));
if (ComparisonResult == SXS_COMPARE_ASSEMBLY_IDENTITY_ATTRIBUTES_COMPARISON_RESULT_EQUAL)
Equal = TRUE;
}
}
}
*EqualOut = Equal;
fSuccess = TRUE;
Exit:
return fSuccess;
}