2990 lines
99 KiB
C++
2990 lines
99 KiB
C++
#include "stdinc.h"
|
|
#include "actctxgenctx.h"
|
|
|
|
#define DEFINE_ATTRIBUTE(attributeName, attributeType, typePrefix) \
|
|
{ \
|
|
L ## #attributeName, \
|
|
offsetof(CNodeFactory, m_ ## typePrefix ## _ ## attributeName), \
|
|
offsetof(CNodeFactory, m_f ## attributeName ## _ ## Present), \
|
|
&CNodeFactory::XMLParser_Parse_ ## attributeType \
|
|
},
|
|
|
|
const static ASSEMBLY_VERSION assemblyVersion0 = {0,0,0,0};
|
|
|
|
typedef enum _in_xml_tag_when_identity_generated_{
|
|
SXS_IN_INVALID_XML_TAG_WHEN_ASSEMBLY_IDENTITY_GENERATED,
|
|
SXS_IN_ASSEMBLY_TAG,
|
|
SXS_IN_DEPENDENCY_TAG
|
|
}SXS_IN_XML_TAG_WHEN_IDENTITY_GENERATED;
|
|
|
|
static
|
|
VOID
|
|
SxspDbgPrintXmlNodeInfo(
|
|
ULONG Level,
|
|
XML_NODE_INFO *pNode
|
|
);
|
|
|
|
static
|
|
PCSTR
|
|
SxspFormatXmlNodeType(
|
|
DWORD dwType
|
|
);
|
|
|
|
struct EventIdErrorPair
|
|
{
|
|
DWORD dwEventId;
|
|
LONG nError;
|
|
};
|
|
|
|
const static EventIdErrorPair eventIdToErrorMap[] =
|
|
{
|
|
#include "Messages.hi" // generated from .x file, like .mc
|
|
};
|
|
|
|
// deliberately no extra paranetheses here
|
|
#define NODEFACTORY_STRING_AND_LENGTH(x) x, NUMBER_OF(x) - 1
|
|
|
|
const static SXS_NAME_LENGTH_PAIR IgnoredAttributesInDependencyTagForIdentity[]={
|
|
//maybe more later
|
|
{ NODEFACTORY_STRING_AND_LENGTH(L"Description") }
|
|
};
|
|
|
|
const DWORD IGNORED_ATTRIBUTE_NUM_IN_DEPENDENCY_TAG = NUMBER_OF(IgnoredAttributesInDependencyTagForIdentity);
|
|
|
|
DECLARE_STD_ATTRIBUTE_NAME_DESCRIPTOR(baseInterface);
|
|
DECLARE_STD_ATTRIBUTE_NAME_DESCRIPTOR(clsid);
|
|
DECLARE_STD_ATTRIBUTE_NAME_DESCRIPTOR(description);
|
|
DECLARE_STD_ATTRIBUTE_NAME_DESCRIPTOR(flags);
|
|
DECLARE_STD_ATTRIBUTE_NAME_DESCRIPTOR(hash);
|
|
DECLARE_STD_ATTRIBUTE_NAME_DESCRIPTOR(hashalg);
|
|
DECLARE_STD_ATTRIBUTE_NAME_DESCRIPTOR(helpdir);
|
|
DECLARE_STD_ATTRIBUTE_NAME_DESCRIPTOR(iid);
|
|
DECLARE_STD_ATTRIBUTE_NAME_DESCRIPTOR(language);
|
|
DECLARE_STD_ATTRIBUTE_NAME_DESCRIPTOR(loadFrom);
|
|
DECLARE_STD_ATTRIBUTE_NAME_DESCRIPTOR(manifestVersion);
|
|
DECLARE_STD_ATTRIBUTE_NAME_DESCRIPTOR(metadataSatellite);
|
|
DECLARE_STD_ATTRIBUTE_NAME_DESCRIPTOR(name);
|
|
DECLARE_STD_ATTRIBUTE_NAME_DESCRIPTOR(newVersion);
|
|
DECLARE_STD_ATTRIBUTE_NAME_DESCRIPTOR(numMethods);
|
|
DECLARE_STD_ATTRIBUTE_NAME_DESCRIPTOR(oldVersion);
|
|
DECLARE_STD_ATTRIBUTE_NAME_DESCRIPTOR(optional);
|
|
DECLARE_STD_ATTRIBUTE_NAME_DESCRIPTOR(processorArchitecture);
|
|
DECLARE_STD_ATTRIBUTE_NAME_DESCRIPTOR(progid);
|
|
DECLARE_STD_ATTRIBUTE_NAME_DESCRIPTOR(proxyStubClsid32);
|
|
DECLARE_STD_ATTRIBUTE_NAME_DESCRIPTOR(publicKeyToken);
|
|
DECLARE_STD_ATTRIBUTE_NAME_DESCRIPTOR(publicKey);
|
|
DECLARE_STD_ATTRIBUTE_NAME_DESCRIPTOR(resourceid);
|
|
DECLARE_STD_ATTRIBUTE_NAME_DESCRIPTOR(runtimeVersion);
|
|
DECLARE_STD_ATTRIBUTE_NAME_DESCRIPTOR(size);
|
|
DECLARE_STD_ATTRIBUTE_NAME_DESCRIPTOR(threadingModel);
|
|
DECLARE_STD_ATTRIBUTE_NAME_DESCRIPTOR(tlbid);
|
|
DECLARE_STD_ATTRIBUTE_NAME_DESCRIPTOR(type);
|
|
DECLARE_STD_ATTRIBUTE_NAME_DESCRIPTOR(version);
|
|
DECLARE_STD_ATTRIBUTE_NAME_DESCRIPTOR(versioned);
|
|
|
|
// How to interpret the parser worker rules here:
|
|
//
|
|
// First, the state of the parser must match m_xps for the rule to be considered.
|
|
// If the value eNotParsing is in the table, it matches any current parser
|
|
// state. Use this to globally ignore some particular tag type when
|
|
// combined with a NULL m_pszTag and NULL m_pfn.
|
|
// Second, the type of the tag from the XML parser must match m_dwType.
|
|
// If m_pszTag is not NULL, a case-insensitive comparison is done between the
|
|
// string m_pszTag points to and the tag from the XML parser. An m_pszTag
|
|
// value of NULL matches any tag.
|
|
// If the three criteria match, the worker function is called. The worker function
|
|
// pointer may be NULL, in which case no action is taken. (This is useful for
|
|
// callbacks from the parser about XML_WHITESPACE where we don't really have to do
|
|
// anything at all.)
|
|
//
|
|
|
|
#define DEFINE_TAG_WORKER_IGNOREALLOFTYPE(dwType) { CNodeFactory::eNotParsing, (dwType), NULL, NULL, NULL, 0, 0, 0, NULL }
|
|
|
|
//
|
|
// Notes on use of the DEFINE_TAG_WORKER_ELEMENT() macro:
|
|
//
|
|
// The first parameter, sourceState, is part of the name of a XMLParseState
|
|
// enumeration value. It is concatenated onto "eParsing" to form the name of
|
|
// the state which the rule will match.
|
|
//
|
|
// The second parameter is both the text of the tag to match and is used to
|
|
// form the name of the function to invoke if the rule matches. The tag is
|
|
// compared case-insensitively, and the name of the member function invoked
|
|
// is XMLParser_Element_ followed by the sourceState string followed by another
|
|
// underscore, followed by the tagName string. So, for example, the following
|
|
// rule:
|
|
//
|
|
// DEFINE_TAG_WORKER_ELEMENT(DepAssy, Version)
|
|
//
|
|
// says that when the parser is in the eParsingDepAssy state and a "Version"
|
|
// tag is found, call the function CNodeFactory::XMLParser_Element_DepAssy_Version().
|
|
//
|
|
|
|
#define DEFINE_TAG_WORKER_ELEMENT(sourceState, tagName) \
|
|
{ \
|
|
CNodeFactory::eParsing_ ## sourceState, \
|
|
XML_ELEMENT, \
|
|
SXS_ASSEMBLY_MANIFEST_STD_NAMESPACE, \
|
|
L ## #tagName, \
|
|
s_rg_ ## sourceState ## _ ## tagName ## _attributes, \
|
|
NUMBER_OF(SXS_ASSEMBLY_MANIFEST_STD_NAMESPACE) - 1, \
|
|
NUMBER_OF(L ## #tagName) - 1, \
|
|
NUMBER_OF(s_rg_ ## sourceState ## _ ## tagName ## _attributes), \
|
|
&CNodeFactory::XMLParser_Element_ ## sourceState ## _ ## tagName, \
|
|
CNodeFactory::eParsing_ ## sourceState ## _ ## tagName \
|
|
}
|
|
|
|
#define DEFINE_TAG_WORKER_ELEMENT_NOCB(sourceState, tagName) \
|
|
{ \
|
|
CNodeFactory::eParsing_ ## sourceState, \
|
|
XML_ELEMENT, \
|
|
SXS_ASSEMBLY_MANIFEST_STD_NAMESPACE, \
|
|
L ## #tagName, \
|
|
s_rg_ ## sourceState ## _ ## tagName ## _attributes, \
|
|
NUMBER_OF(SXS_ASSEMBLY_MANIFEST_STD_NAMESPACE) - 1, \
|
|
NUMBER_OF(L ## #tagName) - 1, \
|
|
NUMBER_OF(s_rg_ ## sourceState ## _ ## tagName ## _attributes), \
|
|
NULL, \
|
|
CNodeFactory::eParsing_ ## sourceState ## _ ## tagName \
|
|
}
|
|
|
|
#define DEFINE_TAG_WORKER_ELEMENT_NONS(sourceState, tagName) \
|
|
{ \
|
|
CNodeFactory::eParsing_ ## sourceState, \
|
|
XML_ELEMENT, \
|
|
NULL, \
|
|
L ## #tagName, \
|
|
s_rg_ ## sourceState ## _ ## tagName ## _attributes, \
|
|
0, \
|
|
NUMBER_OF(L ## #tagName) - 1, \
|
|
NUMBER_OF(s_rg_ ## sourceState ## _ ## tagName ## _attributes), \
|
|
&CNodeFactory::XMLParser_Element_ ## sourceState ## _ ## tagName, \
|
|
CNodeFactory::eParsing_ ## sourceState ## _ ## tagName \
|
|
}
|
|
|
|
#define BEGIN_ELEMENT_LEGAL_ATTRIBUTES(_element) \
|
|
const static ELEMENT_LEGAL_ATTRIBUTE s_rg_ ## _element ## _attributes[] = { \
|
|
{ ELEMENT_LEGAL_ATTRIBUTE_FLAG_IGNORE, NULL, NULL },
|
|
|
|
#define DEFINE_ELEMENT_NONS_REQUIRED_ATTRIBUTE(attributeName, validatorFlags, validator) { ELEMENT_LEGAL_ATTRIBUTE_FLAG_REQUIRED, &s_AttributeName_ ## attributeName, validator, validatorFlags },
|
|
#define DEFINE_ELEMENT_NONS_OPTIONAL_ATTRIBUTE(attributeName, validatorFlags, validator) { 0, &s_AttributeName_ ## attributeName, validator, validatorFlags },
|
|
|
|
#define END_ELEMENT_LEGAL_ATTRIBUTES(_element) };
|
|
|
|
BEGIN_ELEMENT_LEGAL_ATTRIBUTES(doc_assembly)
|
|
DEFINE_ELEMENT_NONS_REQUIRED_ATTRIBUTE(manifestVersion, 0, NULL)
|
|
END_ELEMENT_LEGAL_ATTRIBUTES(doc_assembly)
|
|
|
|
BEGIN_ELEMENT_LEGAL_ATTRIBUTES(doc_assembly_description)
|
|
END_ELEMENT_LEGAL_ATTRIBUTES(doc_assembly_description)
|
|
|
|
BEGIN_ELEMENT_LEGAL_ATTRIBUTES(doc_assembly_noInherit)
|
|
END_ELEMENT_LEGAL_ATTRIBUTES(doc_assembly_noInherit)
|
|
|
|
BEGIN_ELEMENT_LEGAL_ATTRIBUTES(doc_assembly_noInheritable)
|
|
END_ELEMENT_LEGAL_ATTRIBUTES(doc_assembly_noInheritable)
|
|
|
|
BEGIN_ELEMENT_LEGAL_ATTRIBUTES(doc_assembly_assemblyIdentity)
|
|
DEFINE_ELEMENT_NONS_REQUIRED_ATTRIBUTE(name, 0, NULL)
|
|
DEFINE_ELEMENT_NONS_REQUIRED_ATTRIBUTE(version, 0, NULL)
|
|
DEFINE_ELEMENT_NONS_OPTIONAL_ATTRIBUTE(type, 0, NULL)
|
|
DEFINE_ELEMENT_NONS_OPTIONAL_ATTRIBUTE(processorArchitecture, SXSP_VALIDATE_PROCESSOR_ARCHITECTURE_ATTRIBUTE_FLAG_WILDCARD_ALLOWED, &::SxspValidateProcessorArchitectureAttribute)
|
|
DEFINE_ELEMENT_NONS_OPTIONAL_ATTRIBUTE(publicKeyToken, 0, NULL)
|
|
DEFINE_ELEMENT_NONS_OPTIONAL_ATTRIBUTE(language, 0, &::SxspValidateLanguageAttribute)
|
|
DEFINE_ELEMENT_NONS_OPTIONAL_ATTRIBUTE(publicKey, 0, NULL)
|
|
END_ELEMENT_LEGAL_ATTRIBUTES(doc_assembly_assemblyIdentity)
|
|
|
|
BEGIN_ELEMENT_LEGAL_ATTRIBUTES(doc_assembly_dependency)
|
|
DEFINE_ELEMENT_NONS_OPTIONAL_ATTRIBUTE(optional, 0, &::SxspValidateBoolAttribute)
|
|
END_ELEMENT_LEGAL_ATTRIBUTES(doc_assembly_dependency)
|
|
|
|
BEGIN_ELEMENT_LEGAL_ATTRIBUTES(doc_assembly_dependency_dependentAssembly)
|
|
END_ELEMENT_LEGAL_ATTRIBUTES(doc_assembly_dependency_dependentAssembly)
|
|
|
|
BEGIN_ELEMENT_LEGAL_ATTRIBUTES(doc_assembly_dependency_dependentAssembly_assemblyIdentity)
|
|
DEFINE_ELEMENT_NONS_REQUIRED_ATTRIBUTE(name, 0, NULL)
|
|
DEFINE_ELEMENT_NONS_OPTIONAL_ATTRIBUTE(type, 0, NULL)
|
|
DEFINE_ELEMENT_NONS_OPTIONAL_ATTRIBUTE(version, 0, NULL)
|
|
DEFINE_ELEMENT_NONS_OPTIONAL_ATTRIBUTE(processorArchitecture, SXSP_VALIDATE_PROCESSOR_ARCHITECTURE_ATTRIBUTE_FLAG_WILDCARD_ALLOWED, &::SxspValidateProcessorArchitectureAttribute)
|
|
DEFINE_ELEMENT_NONS_OPTIONAL_ATTRIBUTE(publicKeyToken, 0, NULL)
|
|
DEFINE_ELEMENT_NONS_OPTIONAL_ATTRIBUTE(language, SXSP_VALIDATE_LANGUAGE_ATTRIBUTE_FLAG_WILDCARD_ALLOWED, &::SxspValidateLanguageAttribute)
|
|
END_ELEMENT_LEGAL_ATTRIBUTES(doc_assembly_dependency_dependentAssembly_assemblyIdentity)
|
|
|
|
BEGIN_ELEMENT_LEGAL_ATTRIBUTES(doc_assembly_dependency_dependentAssembly_bindingRedirect)
|
|
DEFINE_ELEMENT_NONS_REQUIRED_ATTRIBUTE(oldVersion, 0, NULL)
|
|
DEFINE_ELEMENT_NONS_REQUIRED_ATTRIBUTE(newVersion, 0, NULL)
|
|
END_ELEMENT_LEGAL_ATTRIBUTES(doc_assembly_dependency_dependentAssembly_bindingRedirect)
|
|
|
|
BEGIN_ELEMENT_LEGAL_ATTRIBUTES(doc_assembly_file)
|
|
DEFINE_ELEMENT_NONS_REQUIRED_ATTRIBUTE(name, 0, NULL)
|
|
DEFINE_ELEMENT_NONS_OPTIONAL_ATTRIBUTE(hash, 0, NULL)
|
|
DEFINE_ELEMENT_NONS_OPTIONAL_ATTRIBUTE(hashalg, 0, NULL)
|
|
DEFINE_ELEMENT_NONS_OPTIONAL_ATTRIBUTE(loadFrom, 0, NULL)
|
|
DEFINE_ELEMENT_NONS_OPTIONAL_ATTRIBUTE(size, 0, &::SxspValidateUnsigned64Attribute)
|
|
END_ELEMENT_LEGAL_ATTRIBUTES(doc_assembly_file)
|
|
|
|
BEGIN_ELEMENT_LEGAL_ATTRIBUTES(doc_assembly_file_comClass)
|
|
DEFINE_ELEMENT_NONS_REQUIRED_ATTRIBUTE(clsid, 0, &::SxspValidateGuidAttribute)
|
|
DEFINE_ELEMENT_NONS_OPTIONAL_ATTRIBUTE(threadingModel, 0, NULL)
|
|
DEFINE_ELEMENT_NONS_OPTIONAL_ATTRIBUTE(progid, 0, NULL)
|
|
DEFINE_ELEMENT_NONS_OPTIONAL_ATTRIBUTE(tlbid, 0, &::SxspValidateGuidAttribute)
|
|
DEFINE_ELEMENT_NONS_OPTIONAL_ATTRIBUTE(description, 0, NULL)
|
|
END_ELEMENT_LEGAL_ATTRIBUTES(doc_assembly_file_comClass)
|
|
|
|
BEGIN_ELEMENT_LEGAL_ATTRIBUTES(doc_assembly_file_comClass_progid)
|
|
END_ELEMENT_LEGAL_ATTRIBUTES(doc_assembly_file_comClass_progid)
|
|
|
|
BEGIN_ELEMENT_LEGAL_ATTRIBUTES(doc_assembly_clrClass)
|
|
DEFINE_ELEMENT_NONS_REQUIRED_ATTRIBUTE(name, 0, NULL)
|
|
DEFINE_ELEMENT_NONS_REQUIRED_ATTRIBUTE(clsid, 0, &::SxspValidateGuidAttribute)
|
|
DEFINE_ELEMENT_NONS_OPTIONAL_ATTRIBUTE(progid, 0, NULL)
|
|
DEFINE_ELEMENT_NONS_OPTIONAL_ATTRIBUTE(tlbid, 0, &::SxspValidateGuidAttribute)
|
|
DEFINE_ELEMENT_NONS_OPTIONAL_ATTRIBUTE(description, 0, NULL)
|
|
DEFINE_ELEMENT_NONS_OPTIONAL_ATTRIBUTE(runtimeVersion, 0, NULL)
|
|
DEFINE_ELEMENT_NONS_OPTIONAL_ATTRIBUTE(threadingModel, 0, NULL)
|
|
END_ELEMENT_LEGAL_ATTRIBUTES(doc_assembly_clrClass)
|
|
|
|
BEGIN_ELEMENT_LEGAL_ATTRIBUTES(doc_assembly_clrSurrogate)
|
|
DEFINE_ELEMENT_NONS_REQUIRED_ATTRIBUTE(clsid, 0, &::SxspValidateGuidAttribute)
|
|
DEFINE_ELEMENT_NONS_REQUIRED_ATTRIBUTE(name, 0, NULL)
|
|
DEFINE_ELEMENT_NONS_OPTIONAL_ATTRIBUTE(runtimeVersion, 0, NULL)
|
|
END_ELEMENT_LEGAL_ATTRIBUTES(doc_assembly_file_clrSurrogate)
|
|
|
|
|
|
BEGIN_ELEMENT_LEGAL_ATTRIBUTES(doc_assembly_clrClass_progid)
|
|
END_ELEMENT_LEGAL_ATTRIBUTES(doc_assembly_clrClass_progid)
|
|
|
|
BEGIN_ELEMENT_LEGAL_ATTRIBUTES(doc_assembly_file_comInterfaceProxyStub)
|
|
DEFINE_ELEMENT_NONS_REQUIRED_ATTRIBUTE(iid, 0, &::SxspValidateGuidAttribute)
|
|
DEFINE_ELEMENT_NONS_OPTIONAL_ATTRIBUTE(tlbid, 0, &::SxspValidateGuidAttribute)
|
|
DEFINE_ELEMENT_NONS_OPTIONAL_ATTRIBUTE(name, 0, NULL)
|
|
DEFINE_ELEMENT_NONS_OPTIONAL_ATTRIBUTE(numMethods, 0, NULL)
|
|
DEFINE_ELEMENT_NONS_OPTIONAL_ATTRIBUTE(baseInterface, 0, &::SxspValidateGuidAttribute)
|
|
DEFINE_ELEMENT_NONS_OPTIONAL_ATTRIBUTE(proxyStubClsid32, 0, &::SxspValidateGuidAttribute)
|
|
DEFINE_ELEMENT_NONS_OPTIONAL_ATTRIBUTE(threadingModel, 0, NULL)
|
|
END_ELEMENT_LEGAL_ATTRIBUTES(doc_assembly_file_comInterfaceProxyStub)
|
|
|
|
BEGIN_ELEMENT_LEGAL_ATTRIBUTES(doc_assembly_file_typelib)
|
|
DEFINE_ELEMENT_NONS_REQUIRED_ATTRIBUTE(tlbid, 0, &::SxspValidateGuidAttribute)
|
|
DEFINE_ELEMENT_NONS_REQUIRED_ATTRIBUTE(version, 0, NULL)
|
|
DEFINE_ELEMENT_NONS_REQUIRED_ATTRIBUTE(helpdir, 0, NULL)
|
|
DEFINE_ELEMENT_NONS_OPTIONAL_ATTRIBUTE(resourceid, 0, NULL)
|
|
DEFINE_ELEMENT_NONS_OPTIONAL_ATTRIBUTE(flags, 0, NULL)
|
|
END_ELEMENT_LEGAL_ATTRIBUTES(doc_assembly_file_typelib)
|
|
|
|
BEGIN_ELEMENT_LEGAL_ATTRIBUTES(doc_assembly_file_windowClass)
|
|
DEFINE_ELEMENT_NONS_OPTIONAL_ATTRIBUTE(versioned, 0, &::SxspValidateBoolAttribute)
|
|
END_ELEMENT_LEGAL_ATTRIBUTES(doc_assembly_file_windowClass)
|
|
|
|
BEGIN_ELEMENT_LEGAL_ATTRIBUTES(doc_assembly_comInterfaceExternalProxyStub)
|
|
DEFINE_ELEMENT_NONS_REQUIRED_ATTRIBUTE(iid, 0, &::SxspValidateGuidAttribute)
|
|
DEFINE_ELEMENT_NONS_REQUIRED_ATTRIBUTE(name, 0, NULL)
|
|
DEFINE_ELEMENT_NONS_OPTIONAL_ATTRIBUTE(proxyStubClsid32, 0, &::SxspValidateGuidAttribute)
|
|
DEFINE_ELEMENT_NONS_OPTIONAL_ATTRIBUTE(tlbid, 0, &::SxspValidateGuidAttribute)
|
|
DEFINE_ELEMENT_NONS_OPTIONAL_ATTRIBUTE(numMethods, 0, NULL)
|
|
DEFINE_ELEMENT_NONS_OPTIONAL_ATTRIBUTE(baseInterface, 0, &::SxspValidateGuidAttribute)
|
|
END_ELEMENT_LEGAL_ATTRIBUTES(doc_assembly_comInterfaceExternalProxyStub)
|
|
|
|
BEGIN_ELEMENT_LEGAL_ATTRIBUTES(doc_configuration)
|
|
END_ELEMENT_LEGAL_ATTRIBUTES(doc_configuration)
|
|
|
|
BEGIN_ELEMENT_LEGAL_ATTRIBUTES(doc_configuration_windows)
|
|
END_ELEMENT_LEGAL_ATTRIBUTES(doc_configuration_windows)
|
|
|
|
BEGIN_ELEMENT_LEGAL_ATTRIBUTES(doc_configuration_windows_assemblyBinding)
|
|
END_ELEMENT_LEGAL_ATTRIBUTES(doc_configuration_windows_assemblyBinding)
|
|
|
|
BEGIN_ELEMENT_LEGAL_ATTRIBUTES(doc_configuration_windows_assemblyBinding_assemblyIdentity)
|
|
DEFINE_ELEMENT_NONS_REQUIRED_ATTRIBUTE(name, 0, NULL)
|
|
DEFINE_ELEMENT_NONS_REQUIRED_ATTRIBUTE(version, 0, NULL)
|
|
DEFINE_ELEMENT_NONS_OPTIONAL_ATTRIBUTE(type, 0, NULL)
|
|
DEFINE_ELEMENT_NONS_OPTIONAL_ATTRIBUTE(processorArchitecture, 0, &::SxspValidateProcessorArchitectureAttribute)
|
|
DEFINE_ELEMENT_NONS_OPTIONAL_ATTRIBUTE(publicKeyToken, 0, NULL)
|
|
DEFINE_ELEMENT_NONS_OPTIONAL_ATTRIBUTE(language, 0, &::SxspValidateLanguageAttribute)
|
|
END_ELEMENT_LEGAL_ATTRIBUTES(doc_configuration_windows_assemblyBinding_assemblyIdentity)
|
|
|
|
BEGIN_ELEMENT_LEGAL_ATTRIBUTES(doc_configuration_windows_assemblyBinding_dependentAssembly)
|
|
END_ELEMENT_LEGAL_ATTRIBUTES(doc_configuration_windows_assemblyBinding_dependentAssembly)
|
|
|
|
BEGIN_ELEMENT_LEGAL_ATTRIBUTES(doc_configuration_windows_assemblyBinding_dependentAssembly_assemblyIdentity)
|
|
DEFINE_ELEMENT_NONS_REQUIRED_ATTRIBUTE(name, 0, NULL)
|
|
DEFINE_ELEMENT_NONS_REQUIRED_ATTRIBUTE(processorArchitecture, 0, &::SxspValidateProcessorArchitectureAttribute)
|
|
DEFINE_ELEMENT_NONS_OPTIONAL_ATTRIBUTE(type, 0, NULL)
|
|
DEFINE_ELEMENT_NONS_OPTIONAL_ATTRIBUTE(publicKeyToken, 0, NULL)
|
|
DEFINE_ELEMENT_NONS_OPTIONAL_ATTRIBUTE(language, 0, &::SxspValidateLanguageAttribute)
|
|
END_ELEMENT_LEGAL_ATTRIBUTES(doc_configuration_windows_assemblyBinding_dependentAssembly_assemblyIdentity)
|
|
|
|
BEGIN_ELEMENT_LEGAL_ATTRIBUTES(doc_configuration_windows_assemblyBinding_dependentAssembly_bindingRedirect)
|
|
DEFINE_ELEMENT_NONS_REQUIRED_ATTRIBUTE(oldVersion, 0, NULL)
|
|
DEFINE_ELEMENT_NONS_REQUIRED_ATTRIBUTE(newVersion, 0, NULL)
|
|
END_ELEMENT_LEGAL_ATTRIBUTES(doc_configuration_windows_assemblyBinding_dependentAssembly_bindingRedirect)
|
|
|
|
static const struct
|
|
{
|
|
CNodeFactory::XMLParseState m_xpsOld;
|
|
DWORD m_dwType;
|
|
PCWSTR m_pszNamespace;
|
|
PCWSTR m_pszName;
|
|
PCELEMENT_LEGAL_ATTRIBUTE m_prgLegalAttributes;
|
|
UCHAR m_cchNamespace; // We use UCHAR here just for greater data density. Changing this and rebuilding
|
|
UCHAR m_cchName; // this module should work fine if you really need namespaces or names longer than
|
|
// 255 characters.
|
|
UCHAR m_cLegalAttributes;
|
|
CNodeFactory::XMLParserWorkerFunctionPtr m_pfn;
|
|
CNodeFactory::XMLParseState m_xpsNew;
|
|
} s_rgWorkers[] =
|
|
{
|
|
DEFINE_TAG_WORKER_IGNOREALLOFTYPE(XML_WHITESPACE),
|
|
DEFINE_TAG_WORKER_IGNOREALLOFTYPE(XML_COMMENT),
|
|
DEFINE_TAG_WORKER_ELEMENT(doc, assembly),
|
|
DEFINE_TAG_WORKER_ELEMENT(doc_assembly, assemblyIdentity),
|
|
DEFINE_TAG_WORKER_ELEMENT_NOCB(doc_assembly, description),
|
|
DEFINE_TAG_WORKER_ELEMENT(doc_assembly, noInherit),
|
|
DEFINE_TAG_WORKER_ELEMENT(doc_assembly, noInheritable),
|
|
DEFINE_TAG_WORKER_ELEMENT(doc_assembly, dependency),
|
|
DEFINE_TAG_WORKER_ELEMENT(doc_assembly_dependency, dependentAssembly),
|
|
DEFINE_TAG_WORKER_ELEMENT(doc_assembly_dependency_dependentAssembly, assemblyIdentity),
|
|
DEFINE_TAG_WORKER_ELEMENT(doc_assembly_dependency_dependentAssembly, bindingRedirect),
|
|
DEFINE_TAG_WORKER_ELEMENT_NOCB(doc_assembly, file),
|
|
DEFINE_TAG_WORKER_ELEMENT_NOCB(doc_assembly_file, comClass),
|
|
DEFINE_TAG_WORKER_ELEMENT_NOCB(doc_assembly_file_comClass, progid),
|
|
DEFINE_TAG_WORKER_ELEMENT_NOCB(doc_assembly, clrClass),
|
|
DEFINE_TAG_WORKER_ELEMENT_NOCB(doc_assembly_clrClass, progid),
|
|
DEFINE_TAG_WORKER_ELEMENT_NOCB(doc_assembly_file, comInterfaceProxyStub),
|
|
DEFINE_TAG_WORKER_ELEMENT_NOCB(doc_assembly_file, typelib),
|
|
DEFINE_TAG_WORKER_ELEMENT_NOCB(doc_assembly_file, windowClass),
|
|
DEFINE_TAG_WORKER_ELEMENT_NOCB(doc_assembly, clrSurrogate),
|
|
DEFINE_TAG_WORKER_ELEMENT_NOCB(doc_assembly, comInterfaceExternalProxyStub),
|
|
|
|
// All app config productions go here, just for neatness
|
|
DEFINE_TAG_WORKER_ELEMENT_NONS(doc, configuration),
|
|
DEFINE_TAG_WORKER_ELEMENT_NONS(doc_configuration, windows),
|
|
DEFINE_TAG_WORKER_ELEMENT(doc_configuration_windows, assemblyBinding),
|
|
DEFINE_TAG_WORKER_ELEMENT(doc_configuration_windows_assemblyBinding, assemblyIdentity),
|
|
DEFINE_TAG_WORKER_ELEMENT(doc_configuration_windows_assemblyBinding, dependentAssembly),
|
|
DEFINE_TAG_WORKER_ELEMENT(doc_configuration_windows_assemblyBinding_dependentAssembly, assemblyIdentity),
|
|
DEFINE_TAG_WORKER_ELEMENT(doc_configuration_windows_assemblyBinding_dependentAssembly, bindingRedirect),
|
|
};
|
|
|
|
BOOL
|
|
SxspIsNamespaceDeclaration(XML_NODE_INFO *pNodeInfo)
|
|
{
|
|
FN_TRACE();
|
|
|
|
ASSERT(pNodeInfo->dwType == XML_ATTRIBUTE);
|
|
if (pNodeInfo->ulLen >= 5)
|
|
{ // "xmlns" : prefix for namespace declaration, default ns or non-default ns
|
|
if ((pNodeInfo->pwcText[0] == L'x') &&
|
|
(pNodeInfo->pwcText[1] == L'm') &&
|
|
(pNodeInfo->pwcText[2] == L'l') &&
|
|
(pNodeInfo->pwcText[3] == L'n') &&
|
|
(pNodeInfo->pwcText[4] == L's'))
|
|
{
|
|
if (pNodeInfo->ulLen == 5) // like xmlns="", default ns declaration
|
|
return TRUE;
|
|
else
|
|
if (pNodeInfo->pwcText[5] == L':')
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
//In this function, two tasks:
|
|
// 1) verify PublicKey and StrongName
|
|
// 2) create AssemblyIdentity based on xmlnode array
|
|
// 3) for (name, processorArchitecure, version. langid) they would be unique with SXS_ASSEMBLY_MANIFEST_STD_NAMESPACE
|
|
// 4) if there are dup triples {nsURL, name, value), only one is count, this is done with SxsCreateAssemblyIdentity
|
|
BOOL
|
|
SxspCreateAssemblyIdentityFromIdentityElement(
|
|
DWORD Flags,
|
|
PCACTCTXCTB_PARSE_CONTEXT ParseContext,
|
|
ULONG Type,
|
|
PASSEMBLY_IDENTITY *AssemblyIdentityOut,
|
|
DWORD cNumRecs,
|
|
PCSXS_NODE_INFO prgNodeInfo
|
|
)
|
|
{
|
|
BOOL fSuccess = FALSE;
|
|
FN_TRACE_WIN32(fSuccess);
|
|
|
|
DWORD i;
|
|
PASSEMBLY_IDENTITY AssemblyIdentity = NULL;
|
|
CStringBuffer buffValue;
|
|
|
|
if (AssemblyIdentityOut != NULL)
|
|
*AssemblyIdentityOut = NULL;
|
|
|
|
PARAMETER_CHECK((Flags & ~(SXSP_CREATE_ASSEMBLY_IDENTITY_FROM_IDENTITY_TAG_FLAG_VERIFY_PUBLIC_KEY_IF_PRESENT)) == 0);
|
|
PARAMETER_CHECK((Type == ASSEMBLY_IDENTITY_TYPE_DEFINITION) || (Type == ASSEMBLY_IDENTITY_TYPE_REFERENCE));
|
|
PARAMETER_CHECK(AssemblyIdentityOut != NULL);
|
|
PARAMETER_CHECK(prgNodeInfo != NULL);
|
|
PARAMETER_CHECK(prgNodeInfo[0].Type == XML_ELEMENT);
|
|
|
|
IFW32FALSE_EXIT(::SxsCreateAssemblyIdentity(0, Type, &AssemblyIdentity, 0, NULL));
|
|
|
|
i = 1;
|
|
while (i<cNumRecs)
|
|
{
|
|
ULONG j;
|
|
INTERNAL_ERROR_CHECK(prgNodeInfo[i].Type == XML_ATTRIBUTE);
|
|
|
|
buffValue.Clear();
|
|
|
|
j = i + 1;
|
|
|
|
while ((j < cNumRecs) && (prgNodeInfo[j].Type == XML_PCDATA))
|
|
{
|
|
IFW32FALSE_EXIT(buffValue.Win32Append(prgNodeInfo[j].pszText, prgNodeInfo[j].cchText));
|
|
|
|
j++;
|
|
}
|
|
|
|
// if this is a special attribute, we'll handle it ... specially.
|
|
if ((prgNodeInfo[i].NamespaceStringBuf.Cch() == 0) &&
|
|
(::FusionpCompareStrings(
|
|
SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_PUBLIC_KEY,
|
|
SXS_ASSEMBLY_IDENTITY_STD_ATTRIBUTE_NAME_PUBLIC_KEY_CCH,
|
|
prgNodeInfo[i].pszText,
|
|
prgNodeInfo[i].cchText,
|
|
false) == 0))
|
|
{// ignore publicKey if it appears in assembly identity
|
|
}
|
|
else
|
|
{
|
|
ASSEMBLY_IDENTITY_ATTRIBUTE Attribute;
|
|
|
|
Attribute.Flags = 0;
|
|
Attribute.NamespaceCch = prgNodeInfo[i].NamespaceStringBuf.Cch();
|
|
Attribute.Namespace = prgNodeInfo[i].NamespaceStringBuf;
|
|
Attribute.NameCch = prgNodeInfo[i].cchText;
|
|
Attribute.Name = prgNodeInfo[i].pszText;
|
|
Attribute.ValueCch = buffValue.Cch();
|
|
Attribute.Value = buffValue;
|
|
|
|
IFW32FALSE_EXIT(::SxsInsertAssemblyIdentityAttribute(0, AssemblyIdentity, &Attribute));
|
|
}
|
|
|
|
i = j;
|
|
}
|
|
|
|
*AssemblyIdentityOut = AssemblyIdentity;
|
|
AssemblyIdentity = NULL;
|
|
|
|
fSuccess = TRUE;
|
|
Exit:
|
|
if (AssemblyIdentity != NULL)
|
|
::SxsDestroyAssemblyIdentity(AssemblyIdentity);
|
|
return fSuccess;
|
|
}
|
|
|
|
CNodeFactory::CNodeFactory()
|
|
: m_ActCtxGenCtx(NULL),
|
|
m_Assembly(NULL),
|
|
m_fFirstCreateNodeCall(true),
|
|
m_cUnknownChildDepth(0),
|
|
m_xpsParseState(eParsing_doc),
|
|
m_fAssemblyFound(false),
|
|
m_fIdentityFound(false),
|
|
m_AssemblyContext(NULL),
|
|
m_CurrentPolicyDependentAssemblyIdentity(NULL),
|
|
m_CurrentPolicyStatement(NULL),
|
|
m_IntuitedParseType(eActualParseType_Undetermined),
|
|
m_pApplicationPolicyTable(NULL),
|
|
m_fNoInheritableFound(false)
|
|
{
|
|
m_ParseContext.XMLElementDepth = 0;
|
|
m_ParseContext.ElementPath = NULL;
|
|
m_ParseContext.ElementPathCch = 0;
|
|
m_ParseContext.ElementName = NULL;
|
|
m_ParseContext.ElementPathCch = 0;
|
|
m_ParseContext.ElementHash = 0;
|
|
}
|
|
|
|
CNodeFactory::~CNodeFactory()
|
|
{
|
|
CSxsPreserveLastError ple;
|
|
|
|
if ((m_CurrentPolicyStatement != NULL) &&
|
|
(m_CurrentPolicyDependentAssemblyIdentity != NULL) &&
|
|
(m_pApplicationPolicyTable != NULL))
|
|
{
|
|
if (m_pApplicationPolicyTable->Find(m_buffCurrentApplicationPolicyIdentityKey, m_CurrentPolicyStatement))
|
|
m_CurrentPolicyStatement = NULL;
|
|
}
|
|
|
|
FUSION_DELETE_SINGLETON(m_CurrentPolicyStatement);
|
|
|
|
if (m_CurrentPolicyDependentAssemblyIdentity != NULL)
|
|
::SxsDestroyAssemblyIdentity(m_CurrentPolicyDependentAssemblyIdentity);
|
|
|
|
if (m_Assembly != NULL)
|
|
{
|
|
m_Assembly->Release();
|
|
m_Assembly = NULL;
|
|
}
|
|
|
|
ple.Restore();
|
|
}
|
|
|
|
BOOL
|
|
CNodeFactory::Initialize(
|
|
PACTCTXGENCTX ActCtxGenCtx,
|
|
PASSEMBLY Assembly,
|
|
PACTCTXCTB_ASSEMBLY_CONTEXT AssemblyContext
|
|
)
|
|
{
|
|
BOOL fSuccess = FALSE;
|
|
FN_TRACE_WIN32(fSuccess);
|
|
|
|
PARAMETER_CHECK(Assembly != NULL);
|
|
|
|
#if FUSION_XML_TREE
|
|
IFW32FALSE_EXIT(m_ParseTreeStringPool.Initialize());
|
|
#endif // FUSION_XML_TREE
|
|
|
|
IFW32FALSE_EXIT(m_XMLNamespaceManager.Initialize());
|
|
|
|
m_ActCtxGenCtx = ActCtxGenCtx;
|
|
|
|
Assembly->AddRef();
|
|
if (m_Assembly != NULL)
|
|
m_Assembly->Release();
|
|
m_Assembly = Assembly;
|
|
|
|
m_AssemblyContext = AssemblyContext;
|
|
m_ParseContext.AssemblyContext = AssemblyContext;
|
|
m_ParseContext.ErrorCallbacks.MissingRequiredAttribute = &CNodeFactory::ParseErrorCallback_MissingRequiredAttribute;
|
|
m_ParseContext.ErrorCallbacks.AttributeNotAllowed = &CNodeFactory::ParseErrorCallback_AttributeNotAllowed;
|
|
m_ParseContext.ErrorCallbacks.InvalidAttributeValue = &CNodeFactory::ParseErrorCallback_InvalidAttributeValue;
|
|
m_ParseContext.SourceFilePathType = AssemblyContext->ManifestPathType;
|
|
m_ParseContext.SourceFile = AssemblyContext->ManifestPath;
|
|
m_ParseContext.SourceFileCch = AssemblyContext->ManifestPathCch;
|
|
m_ParseContext.LineNumber = 0;
|
|
|
|
#if FUSION_XML_TREE
|
|
m_XmlDocument.Flags = 0;
|
|
m_XmlDocument.StringCount = 0;
|
|
m_XmlDocument.Strings = NULL;
|
|
InitializeListHead(&m_XmlDocument.ElementListHead);
|
|
m_CurrentNode = NULL;
|
|
m_CurrentParent = NULL;
|
|
#endif // FUSION_XML_TREE
|
|
|
|
fSuccess = TRUE;
|
|
Exit:
|
|
return fSuccess;
|
|
}
|
|
|
|
VOID
|
|
CNodeFactory::ResetParseState()
|
|
{
|
|
m_fFirstCreateNodeCall = true;
|
|
m_fAssemblyFound = false;
|
|
m_fIdentityFound = false;
|
|
m_fNoInheritableFound = false;
|
|
|
|
FUSION_DELETE_SINGLETON(m_CurrentPolicyStatement);
|
|
m_CurrentPolicyStatement = NULL;
|
|
|
|
::SxsDestroyAssemblyIdentity(m_CurrentPolicyDependentAssemblyIdentity);
|
|
m_CurrentPolicyDependentAssemblyIdentity = NULL;
|
|
}
|
|
|
|
HRESULT
|
|
CNodeFactory::QueryInterface(
|
|
REFIID riid,
|
|
LPVOID *ppvObj
|
|
)
|
|
{
|
|
HRESULT hr = NOERROR;
|
|
FN_TRACE_HR(hr);
|
|
IUnknown *pIUnknown = NULL;
|
|
|
|
if (ppvObj != NULL)
|
|
*ppvObj = NULL;
|
|
|
|
if (ppvObj == NULL)
|
|
{
|
|
hr = E_POINTER;
|
|
goto Exit;
|
|
}
|
|
|
|
if (riid == __uuidof(this))
|
|
pIUnknown = this;
|
|
else if ((riid == IID_IUnknown) ||
|
|
(riid == IID_IXMLNodeFactory))
|
|
pIUnknown = static_cast<IXMLNodeFactory *>(this);
|
|
else
|
|
{
|
|
::FusionpDbgPrintEx(
|
|
FUSION_DBG_LEVEL_ERROR,
|
|
"SXS.DLL: Node factory asked for unknown interface\n");
|
|
|
|
hr = E_NOINTERFACE;
|
|
goto Exit;
|
|
}
|
|
|
|
pIUnknown->AddRef();
|
|
*ppvObj = pIUnknown;
|
|
hr = NOERROR;
|
|
Exit:
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CNodeFactory::NotifyEvent(
|
|
IXMLNodeSource *pSource,
|
|
XML_NODEFACTORY_EVENT iEvt
|
|
)
|
|
{
|
|
return NOERROR;
|
|
}
|
|
|
|
HRESULT
|
|
CNodeFactory::ConvertXMLNodeInfoToSXSNodeInfo(
|
|
const XML_NODE_INFO *pNodeInfo,
|
|
SXS_NODE_INFO &rSXSNodeInfo
|
|
)
|
|
{
|
|
HRESULT hr = NOERROR;
|
|
FN_TRACE_HR(hr);
|
|
|
|
INTERNAL_ERROR_CHECK(pNodeInfo != NULL);
|
|
|
|
rSXSNodeInfo.Size = pNodeInfo->dwSize;
|
|
rSXSNodeInfo.Type = pNodeInfo->dwType;
|
|
|
|
switch (pNodeInfo->dwType)
|
|
{
|
|
case XML_ELEMENT:
|
|
{
|
|
SIZE_T cchNamespacePrefix;
|
|
IFCOMFAILED_EXIT(
|
|
m_XMLNamespaceManager.Map(
|
|
0,
|
|
pNodeInfo,
|
|
&rSXSNodeInfo.NamespaceStringBuf,
|
|
&cchNamespacePrefix));
|
|
|
|
// +1 to skip colon
|
|
rSXSNodeInfo.pszText = pNodeInfo->pwcText + ((cchNamespacePrefix != 0) ? (cchNamespacePrefix + 1) : 0);
|
|
rSXSNodeInfo.cchText = pNodeInfo->ulLen - ((cchNamespacePrefix != 0) ? (cchNamespacePrefix + 1) : 0);
|
|
|
|
break;
|
|
}
|
|
|
|
case XML_ATTRIBUTE:
|
|
{
|
|
SIZE_T cchNamespacePrefix;
|
|
// if this is a namespace definition, ignore
|
|
const PCWSTR pwcText = pNodeInfo->pwcText;
|
|
if ((pwcText[0] == L'x') &&
|
|
(pwcText[1] == L'm') &&
|
|
(pwcText[2] == L'l') &&
|
|
(pwcText[3] == L'n') &&
|
|
(pwcText[4] == L's') &&
|
|
((pwcText[5] == L':') ||
|
|
(pwcText[5] == L'=')))
|
|
{
|
|
rSXSNodeInfo.pszText = pNodeInfo->pwcText;
|
|
rSXSNodeInfo.cchText = pNodeInfo->ulLen;
|
|
}
|
|
else
|
|
{
|
|
IFCOMFAILED_EXIT(
|
|
m_XMLNamespaceManager.Map(
|
|
CXMLNamespaceManager::eMapFlag_DoNotApplyDefaultNamespace,
|
|
pNodeInfo,
|
|
&rSXSNodeInfo.NamespaceStringBuf,
|
|
&cchNamespacePrefix));
|
|
|
|
// +1 to skip colon
|
|
rSXSNodeInfo.pszText = pNodeInfo->pwcText + ((cchNamespacePrefix != 0) ? (cchNamespacePrefix + 1) : 0);
|
|
rSXSNodeInfo.cchText = pNodeInfo->ulLen - ((cchNamespacePrefix != 0) ? (cchNamespacePrefix + 1) : 0);
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
// Otherwise we'll assume there's no namespace processing to do...
|
|
rSXSNodeInfo.NamespaceStringBuf.Clear();
|
|
rSXSNodeInfo.pszText = pNodeInfo->pwcText;
|
|
rSXSNodeInfo.cchText = pNodeInfo->ulLen;
|
|
break;
|
|
}
|
|
|
|
FN_EPILOG
|
|
}
|
|
|
|
HRESULT
|
|
CNodeFactory::BeginChildren(
|
|
IXMLNodeSource *pSource,
|
|
XML_NODE_INFO *pNodeInfo
|
|
)
|
|
{
|
|
HRESULT hr = NOERROR;
|
|
FN_TRACE_HR(hr);
|
|
|
|
ULONG i;
|
|
SXS_NODE_INFO SXSNodeInfo;
|
|
|
|
IFCOMFAILED_EXIT(m_XMLNamespaceManager.OnBeginChildren(pSource, pNodeInfo));
|
|
|
|
IFCOMFAILED_EXIT(this->ConvertXMLNodeInfoToSXSNodeInfo(pNodeInfo, SXSNodeInfo));
|
|
for (i=0; i<m_ActCtxGenCtx->m_ContributorCount; i++)
|
|
{
|
|
IFW32FALSE_EXIT(
|
|
m_ActCtxGenCtx->m_Contributors[i].Fire_BeginChildren(
|
|
m_ActCtxGenCtx,
|
|
m_AssemblyContext,
|
|
&m_ParseContext,
|
|
&SXSNodeInfo));
|
|
}
|
|
|
|
FN_EPILOG
|
|
}
|
|
|
|
HRESULT
|
|
CNodeFactory::EndChildren(
|
|
IXMLNodeSource *pSource,
|
|
BOOL Empty,
|
|
XML_NODE_INFO *pNodeInfo
|
|
)
|
|
{
|
|
HRESULT hr = NOERROR;
|
|
FN_TRACE_HR(hr);
|
|
ULONG i;
|
|
PWSTR Bang;
|
|
SXS_NODE_INFO SXSNodeInfo;
|
|
|
|
// Short-circuit PIs, XML-decls, whitespace and comments
|
|
if ((pNodeInfo->dwType == XML_PI) ||
|
|
(pNodeInfo->dwType == XML_XMLDECL) ||
|
|
(pNodeInfo->dwType == XML_COMMENT) ||
|
|
(pNodeInfo->dwType == XML_WHITESPACE))
|
|
{
|
|
hr = NOERROR;
|
|
goto Exit;
|
|
}
|
|
|
|
IFCOMFAILED_EXIT(m_XMLNamespaceManager.OnEndChildren(pSource, Empty, pNodeInfo));
|
|
// We hit the end of something; if we're skipping stuff, we're one level back towards
|
|
// paying attention.
|
|
if (m_cUnknownChildDepth != 0)
|
|
{
|
|
m_cUnknownChildDepth--;
|
|
}
|
|
else
|
|
{
|
|
ULONG j;
|
|
|
|
for (j=0; j<NUMBER_OF(s_rgWorkers); j++)
|
|
{
|
|
if (s_rgWorkers[j].m_xpsNew == m_xpsParseState)
|
|
{
|
|
m_xpsParseState = s_rgWorkers[j].m_xpsOld;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (j == NUMBER_OF(s_rgWorkers))
|
|
{
|
|
::FusionpDbgPrintEx(
|
|
FUSION_DBG_LEVEL_ERROR,
|
|
"SXS.DLL: %s() called when we were not expecting it. m_xpsParseState = %d\n", __FUNCTION__, m_xpsParseState);
|
|
|
|
INTERNAL_ERROR_CHECK(FALSE);
|
|
// Hey, how the heck did we get here?
|
|
}
|
|
|
|
// One time end-of-manifest checks...
|
|
if (m_xpsParseState == eParsing_doc)
|
|
{
|
|
switch (m_ParseType)
|
|
{
|
|
default:
|
|
INTERNAL_ERROR_CHECK(false);
|
|
break;
|
|
|
|
case XML_FILE_TYPE_COMPONENT_CONFIGURATION:
|
|
case XML_FILE_TYPE_APPLICATION_CONFIGURATION:
|
|
break;
|
|
|
|
case XML_FILE_TYPE_MANIFEST:
|
|
// If this is not the root assembly, this is not a noInherit actctx and the noInheritable
|
|
// element was not found, issue an error.
|
|
if (((m_AssemblyContext->Flags & ACTCTXCTB_ASSEMBLY_CONTEXT_IS_ROOT_ASSEMBLY) == 0) &&
|
|
m_ActCtxGenCtx->m_NoInherit &&
|
|
!m_fNoInheritableFound)
|
|
{
|
|
this->LogParseError(MSG_SXS_NOINHERIT_REQUIRES_NOINHERITABLE);
|
|
ORIGINATE_WIN32_FAILURE_AND_EXIT(NoInheritRequiresNoInheritable, ERROR_SXS_MANIFEST_PARSE_ERROR);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
#if FUSION_XML_TREE
|
|
m_CurrentParent = const_cast<PSXS_XML_NODE>(m_CurrentParent->Parent);
|
|
#endif // FUSION_XML_TREE
|
|
|
|
if (pNodeInfo->dwType != XML_XMLDECL)
|
|
{
|
|
IFCOMFAILED_EXIT(this->ConvertXMLNodeInfoToSXSNodeInfo(pNodeInfo, SXSNodeInfo));
|
|
|
|
for (i=0; i<m_ActCtxGenCtx->m_ContributorCount; i++)
|
|
{
|
|
IFW32FALSE_EXIT(
|
|
m_ActCtxGenCtx->m_Contributors[i].Fire_EndChildren(
|
|
m_ActCtxGenCtx,
|
|
m_AssemblyContext,
|
|
&m_ParseContext,
|
|
Empty,
|
|
&SXSNodeInfo));
|
|
}
|
|
|
|
INTERNAL_ERROR_CHECK(m_ParseContext.XMLElementDepth != 0);
|
|
|
|
m_ParseContext.XMLElementDepth--;
|
|
Bang = wcsrchr(m_buffElementPath, L'!');
|
|
|
|
INTERNAL_ERROR_CHECK(((Bang == NULL) == (m_ParseContext.XMLElementDepth == 0)));
|
|
|
|
if (Bang != NULL)
|
|
{
|
|
m_buffElementPath.Left(Bang - m_buffElementPath);
|
|
m_ParseContext.ElementPathCch = m_buffElementPath.Cch();
|
|
m_ParseContext.ElementPath = m_buffElementPath;
|
|
m_ParseContext.ElementName = wcsrchr(m_buffElementPath, L'!');
|
|
if (m_ParseContext.ElementName == NULL)
|
|
{
|
|
m_ParseContext.ElementName = m_buffElementPath;
|
|
m_ParseContext.ElementNameCch = m_buffElementPath.Cch();
|
|
}
|
|
else
|
|
{
|
|
m_ParseContext.ElementName++;
|
|
m_ParseContext.ElementNameCch = m_buffElementPath.Cch() - (m_ParseContext.ElementName - m_buffElementPath);
|
|
}
|
|
|
|
IFW32FALSE_ORIGINATE_AND_EXIT(
|
|
::SxspHashString(
|
|
m_buffElementPath,
|
|
m_ParseContext.ElementPathCch,
|
|
&m_ParseContext.ElementHash,
|
|
false));
|
|
}
|
|
else
|
|
{
|
|
m_buffElementPath.Clear();
|
|
m_ParseContext.ElementPath = NULL;
|
|
m_ParseContext.ElementPathCch = 0;
|
|
m_ParseContext.ElementName = NULL;
|
|
m_ParseContext.ElementNameCch = 0;
|
|
m_ParseContext.ElementHash = 0;
|
|
m_ParseContext.XMLElementDepth = 0;
|
|
}
|
|
}
|
|
|
|
hr = NOERROR;
|
|
|
|
Exit:
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CNodeFactory::Error(
|
|
IXMLNodeSource *pSource,
|
|
HRESULT hrErrorCode,
|
|
USHORT cNumRecs,
|
|
XML_NODE_INFO **apNodeInfo
|
|
)
|
|
{
|
|
CSxsPreserveLastError ple;
|
|
::FusionpConvertCOMFailure(hrErrorCode);
|
|
::FusionpSetLastErrorFromHRESULT(hrErrorCode);
|
|
this->LogParseError(MSG_SXS_WIN32_ERROR_MSG_WHEN_PARSING_MANIFEST, CEventLogLastError());
|
|
ple.Restore();
|
|
return NOERROR;
|
|
}
|
|
|
|
HRESULT
|
|
CNodeFactory::FirstCreateNodeCall(
|
|
IXMLNodeSource *pSource,
|
|
PVOID pNodeParent,
|
|
USHORT NodeCount,
|
|
const SXS_NODE_INFO *prgNodeInfo
|
|
)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
FN_TRACE_HR(hr);
|
|
ULONG i;
|
|
const static WCHAR rgch1_0[] = L"1.0";
|
|
const static UNICODE_STRING ustr1_0 = CONSTANT_UNICODE_STRING(rgch1_0);
|
|
bool fGotGoodManifestVersion = false;
|
|
bool fGotAnyManifestVersion = false;
|
|
|
|
// It's our first IXMLNodeFactory::CreateNode() call. This had better
|
|
// be an <ASSEMBLY MANIFESTVERSION="1.0" ...> deal.
|
|
|
|
for (i=0; i<NodeCount; i++)
|
|
{
|
|
if (prgNodeInfo[i].Type == XML_ELEMENT)
|
|
{
|
|
INTERNAL_ERROR_CHECK(i == 0);
|
|
|
|
switch (m_ParseType)
|
|
{
|
|
default:
|
|
INTERNAL_ERROR_CHECK(false);
|
|
break;
|
|
|
|
case XML_FILE_TYPE_MANIFEST:
|
|
case XML_FILE_TYPE_COMPONENT_CONFIGURATION:
|
|
if ((prgNodeInfo[i].cchText != (NUMBER_OF(SXS_ASSEMBLY_MANIFEST_STD_ELEMENT_NAME_ASSEMBLY) - 1)) ||
|
|
(prgNodeInfo[i].NamespaceStringBuf.Cch() != (NUMBER_OF(SXS_ASSEMBLY_MANIFEST_STD_NAMESPACE) - 1)) ||
|
|
(memcmp(prgNodeInfo[i].pszText, SXS_ASSEMBLY_MANIFEST_STD_ELEMENT_NAME_ASSEMBLY, prgNodeInfo[i].cchText * sizeof(WCHAR)) != 0) ||
|
|
(memcmp(prgNodeInfo[i].NamespaceStringBuf, SXS_ASSEMBLY_MANIFEST_STD_NAMESPACE, prgNodeInfo[i].NamespaceStringBuf.Cch() * sizeof(WCHAR)) != 0))
|
|
{
|
|
IFCOMFAILED_EXIT(this->LogParseError(MSG_SXS_MANIFEST_INCORRECT_ROOT_ELEMENT));
|
|
}
|
|
break;
|
|
|
|
case XML_FILE_TYPE_APPLICATION_CONFIGURATION:
|
|
if ((prgNodeInfo[i].cchText != SXS_APPLICATION_CONFIGURATION_MANIFEST_STD_ELEMENT_NAME_CONFIGURATION_CCH) ||
|
|
(prgNodeInfo[i].NamespaceStringBuf.Cch() != 0) ||
|
|
(memcmp(prgNodeInfo[i].pszText, SXS_APPLICATION_CONFIGURATION_MANIFEST_STD_ELEMENT_NAME_CONFIGURATION,
|
|
SXS_APPLICATION_CONFIGURATION_MANIFEST_STD_ELEMENT_NAME_CONFIGURATION_CCH * sizeof(WCHAR)) != 0))
|
|
{
|
|
IFCOMFAILED_EXIT(this->LogParseError(MSG_SXS_MANIFEST_INCORRECT_ROOT_ELEMENT));
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else if (prgNodeInfo[i].Type == XML_ATTRIBUTE)
|
|
{
|
|
if ((prgNodeInfo[i].cchText == (NUMBER_OF(SXS_ASSEMBLY_MANIFEST_STD_ATTRIBUTE_NAME_MANIFEST_VERSION) - 1)) &&
|
|
(prgNodeInfo[i].NamespaceStringBuf.Cch() == 0) &&
|
|
(memcmp(prgNodeInfo[i].pszText, SXS_ASSEMBLY_MANIFEST_STD_ATTRIBUTE_NAME_MANIFEST_VERSION, prgNodeInfo[i].cchText * sizeof(WCHAR)) == 0))
|
|
{
|
|
fGotAnyManifestVersion = true;
|
|
|
|
ULONG j = i + 1;
|
|
|
|
if (j < NodeCount)
|
|
{
|
|
if (prgNodeInfo[j].Type == XML_PCDATA)
|
|
{
|
|
if (prgNodeInfo[j].cchText == 3)
|
|
{
|
|
if (memcmp(prgNodeInfo[j].pszText, L"1.0", prgNodeInfo[j].cchText * sizeof(WCHAR)) == 0)
|
|
{
|
|
fGotGoodManifestVersion = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((m_ParseType == XML_FILE_TYPE_MANIFEST) ||
|
|
(m_ParseType == XML_FILE_TYPE_COMPONENT_CONFIGURATION))
|
|
{
|
|
if (fGotAnyManifestVersion)
|
|
{
|
|
if (!fGotGoodManifestVersion)
|
|
IFCOMFAILED_EXIT(this->LogParseError(MSG_SXS_MANIFEST_VERSION_ERROR));
|
|
}
|
|
else
|
|
IFCOMFAILED_EXIT(this->LogParseError(MSG_SXS_MANIFEST_VERSION_MISSING));
|
|
}
|
|
|
|
m_Assembly->m_ManifestVersionMajor = 1;
|
|
m_Assembly->m_ManifestVersionMinor = 0;
|
|
|
|
hr = NOERROR;
|
|
|
|
Exit:
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CNodeFactory::CreateNode(
|
|
IXMLNodeSource *pSource,
|
|
PVOID pNodeParent,
|
|
USHORT NodeCount,
|
|
XML_NODE_INFO **apNodeInfo
|
|
)
|
|
{
|
|
HRESULT hr = NOERROR;
|
|
FN_TRACE_HR(hr);
|
|
|
|
ULONG i;
|
|
PSXS_XML_NODE pXmlNode = NULL;
|
|
PSXS_NODE_INFO pSXSNodeInfo = NULL;
|
|
SIZE_T cchTemp;
|
|
|
|
m_ParseContext.LineNumber = pSource->GetLineNumber();
|
|
|
|
INTERNAL_ERROR_CHECK(NodeCount != 0);
|
|
|
|
#if DBG
|
|
::FusionpDbgPrintEx(
|
|
FUSION_DBG_LEVEL_NODEFACTORY,
|
|
"SXS.DLL: " __FUNCTION__ "() entered\n"
|
|
" m_ParseContext.XMLElementDepth = %lu\n",
|
|
m_ParseContext.XMLElementDepth);
|
|
|
|
for (i=0; i<NodeCount; i++)
|
|
::SxspDbgPrintXmlNodeInfo(FUSION_DBG_LEVEL_NODEFACTORY, apNodeInfo[i]);
|
|
#endif
|
|
|
|
// Short-circuit PIs, XML-decls, whitespace and comments
|
|
if ((apNodeInfo[0]->dwType == XML_PI) ||
|
|
(apNodeInfo[0]->dwType == XML_XMLDECL) ||
|
|
(apNodeInfo[0]->dwType == XML_COMMENT) ||
|
|
(apNodeInfo[0]->dwType == XML_WHITESPACE))
|
|
{
|
|
hr = NOERROR;
|
|
goto Exit;
|
|
}
|
|
|
|
IFCOMFAILED_EXIT(m_XMLNamespaceManager.OnCreateNode(pSource, pNodeParent, NodeCount, apNodeInfo));
|
|
|
|
IFALLOCFAILED_EXIT(pSXSNodeInfo = new SXS_NODE_INFO[NodeCount]);
|
|
for (i=0; i<NodeCount; i++)
|
|
IFCOMFAILED_EXIT(this->ConvertXMLNodeInfoToSXSNodeInfo(apNodeInfo[i], pSXSNodeInfo[i]));
|
|
|
|
if (m_fFirstCreateNodeCall)
|
|
{
|
|
if ((apNodeInfo[0]->dwType == XML_COMMENT) ||
|
|
(apNodeInfo[0]->dwType == XML_XMLDECL) ||
|
|
(apNodeInfo[0]->dwType == XML_WHITESPACE))
|
|
{
|
|
hr = S_OK;
|
|
goto Cont;
|
|
}
|
|
|
|
m_fFirstCreateNodeCall = FALSE;
|
|
IFCOMFAILED_EXIT(this->FirstCreateNodeCall(pSource, pNodeParent, NodeCount, pSXSNodeInfo));
|
|
}
|
|
|
|
Cont:
|
|
if (m_cUnknownChildDepth == 0)
|
|
{
|
|
for (i=0; i<NUMBER_OF(s_rgWorkers); i++)
|
|
{
|
|
bool fTemp = false;
|
|
|
|
if ((s_rgWorkers[i].m_xpsOld == eNotParsing) ||
|
|
(m_xpsParseState == s_rgWorkers[i].m_xpsOld))
|
|
fTemp = true;
|
|
|
|
const bool fParseStateMatches = fTemp;
|
|
|
|
fTemp = false;
|
|
|
|
if (fParseStateMatches)
|
|
{
|
|
if (s_rgWorkers[i].m_dwType == apNodeInfo[0]->dwType)
|
|
fTemp = true;
|
|
}
|
|
|
|
const bool fTypeMatches = fTemp;
|
|
|
|
fTemp = false;
|
|
|
|
if (fTypeMatches)
|
|
{
|
|
if (s_rgWorkers[i].m_cchName == 0)
|
|
fTemp = true;
|
|
else
|
|
{
|
|
if (s_rgWorkers[i].m_cchNamespace == pSXSNodeInfo[0].NamespaceStringBuf.Cch())
|
|
{
|
|
if (s_rgWorkers[i].m_cchName == pSXSNodeInfo[0].cchText)
|
|
{
|
|
if (::FusionpCompareStrings(
|
|
s_rgWorkers[i].m_pszNamespace,
|
|
s_rgWorkers[i].m_cchNamespace,
|
|
pSXSNodeInfo[0].NamespaceStringBuf,
|
|
pSXSNodeInfo[0].NamespaceStringBuf.Cch(),
|
|
false) == 0)
|
|
{
|
|
if (::FusionpCompareStrings(
|
|
s_rgWorkers[i].m_pszName,
|
|
s_rgWorkers[i].m_cchName,
|
|
pSXSNodeInfo[0].pszText,
|
|
pSXSNodeInfo[0].cchText,
|
|
false) == 0)
|
|
{
|
|
fTemp = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (fTemp)
|
|
{
|
|
m_xpsParseState = s_rgWorkers[i].m_xpsNew;
|
|
|
|
IFW32FALSE_EXIT(
|
|
this->ValidateElementAttributes(
|
|
pSXSNodeInfo,
|
|
NodeCount,
|
|
s_rgWorkers[i].m_prgLegalAttributes,
|
|
s_rgWorkers[i].m_cLegalAttributes));
|
|
|
|
if (s_rgWorkers[i].m_pfn != NULL)
|
|
IFW32FALSE_EXIT((this->*s_rgWorkers[i].m_pfn)(NodeCount, pSXSNodeInfo));
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i == NUMBER_OF(s_rgWorkers))
|
|
{
|
|
bool fEquals;
|
|
|
|
// If we hit an unrecognized element and its namespace is the one we own, error!
|
|
IFW32FALSE_EXIT(
|
|
pSXSNodeInfo[0].NamespaceStringBuf.Win32Equals(
|
|
SXS_ASSEMBLY_MANIFEST_STD_NAMESPACE,
|
|
SXS_ASSEMBLY_MANIFEST_STD_NAMESPACE_CCH,
|
|
fEquals,
|
|
false));
|
|
|
|
if (fEquals)
|
|
{
|
|
this->LogParseError(
|
|
MSG_SXS_MANIFEST_ELEMENT_USED_IN_INVALID_CONTEXT,
|
|
CUnicodeString(apNodeInfo[0]->pwcText, apNodeInfo[0]->ulLen),
|
|
CUnicodeString(m_ParseContext.ElementName, m_ParseContext.ElementNameCch));
|
|
|
|
ORIGINATE_WIN32_FAILURE_AND_EXIT(ElementInInvalidContext, ERROR_SXS_MANIFEST_PARSE_ERROR);
|
|
}
|
|
|
|
// For an unknown child element, the built-in XML parsing should start to ignore the subtree at this point.
|
|
if (apNodeInfo[0]->dwType == XML_ELEMENT)
|
|
m_cUnknownChildDepth = 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if ((NodeCount != 0) &&
|
|
(apNodeInfo[0]->dwType == XML_ELEMENT))
|
|
{
|
|
CUnicodeString s(apNodeInfo[0]->pwcText, apNodeInfo[0]->ulLen);
|
|
|
|
// We're handling an unknown series of elements; increment the depth.
|
|
m_cUnknownChildDepth++;
|
|
}
|
|
}
|
|
|
|
// Fire the right callbacks for XML_ELEMENT, XML_PCDATA and XML_CDATA nodes:
|
|
switch (apNodeInfo[0]->dwType)
|
|
{
|
|
case XML_ELEMENT:
|
|
#if defined(MSG_SXS_MANIFEST_PARSE_NO_INHERIT_CHILDREN_NOT_ALLOWED)
|
|
if (m_cUnknownChildDepth != 0 && m_xpsParseState == eParsing_doc_assembly_noInherit)
|
|
{
|
|
hr = this->LogParseError(MSG_SXS_MANIFEST_PARSE_NO_INHERIT_CHILDREN_NOT_ALLOWED);
|
|
goto Exit;
|
|
}
|
|
#endif
|
|
|
|
if (m_buffElementPath.Cch() != 0)
|
|
IFW32FALSE_EXIT(m_buffElementPath.Win32Append(L"!", 1));
|
|
|
|
cchTemp = m_buffElementPath.Cch();
|
|
|
|
if (pSXSNodeInfo[0].NamespaceStringBuf.Cch() != 0)
|
|
{
|
|
IFW32FALSE_EXIT(m_buffElementPath.Win32Append(pSXSNodeInfo[0].NamespaceStringBuf));
|
|
IFW32FALSE_EXIT(m_buffElementPath.Win32Append(L"^", 1));
|
|
}
|
|
|
|
IFW32FALSE_EXIT(m_buffElementPath.Win32Append(pSXSNodeInfo[0].pszText, pSXSNodeInfo[0].cchText));
|
|
|
|
m_ParseContext.ElementPathCch = m_buffElementPath.Cch();
|
|
m_ParseContext.ElementPath = m_buffElementPath;
|
|
m_ParseContext.ElementName = static_cast<PCWSTR>(m_buffElementPath) + cchTemp;
|
|
m_ParseContext.ElementNameCch = m_buffElementPath.Cch() - cchTemp;
|
|
|
|
IFW32FALSE_EXIT(::SxspHashString(m_buffElementPath, m_buffElementPath.Cch(), &m_ParseContext.ElementHash, true));
|
|
|
|
m_ParseContext.XMLElementDepth++;
|
|
|
|
for (i=0; i<m_ActCtxGenCtx->m_ContributorCount; i++)
|
|
{
|
|
IFW32FALSE_EXIT(
|
|
m_ActCtxGenCtx->m_Contributors[i].Fire_ElementParsed(
|
|
m_ActCtxGenCtx,
|
|
m_AssemblyContext,
|
|
&m_ParseContext,
|
|
NodeCount,
|
|
pSXSNodeInfo));
|
|
}
|
|
|
|
break;
|
|
|
|
case XML_PCDATA:
|
|
for (i=0; i<m_ActCtxGenCtx->m_ContributorCount; i++)
|
|
{
|
|
IFW32FALSE_EXIT(
|
|
m_ActCtxGenCtx->m_Contributors[i].Fire_PCDATAParsed(
|
|
m_ActCtxGenCtx,
|
|
m_AssemblyContext,
|
|
&m_ParseContext,
|
|
apNodeInfo[0]->pwcText,
|
|
apNodeInfo[0]->ulLen));
|
|
}
|
|
|
|
break;
|
|
|
|
case XML_CDATA:
|
|
for (i=0; i<m_ActCtxGenCtx->m_ContributorCount; i++)
|
|
{
|
|
IFW32FALSE_EXIT(
|
|
m_ActCtxGenCtx->m_Contributors[i].Fire_CDATAParsed(
|
|
m_ActCtxGenCtx,
|
|
m_AssemblyContext,
|
|
&m_ParseContext,
|
|
apNodeInfo[0]->pwcText,
|
|
apNodeInfo[0]->ulLen));
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
#if FUSION_XML_TREE
|
|
IFCOMFAILED_EXIT(this->CreateXmlNode(m_CurrentParent, NodeCount, apNodeInfo, pXmlNode));
|
|
|
|
// If we don't get a node back, just ignore it...
|
|
if (pXmlNode != NULL)
|
|
{
|
|
if (m_CurrentParent == NULL)
|
|
{
|
|
// Only XML Decls, PIs and the root document are at depth 0 or 1...
|
|
ASSERT(m_ParseContext.XMLElementDepth <= 1);
|
|
InsertTailList(&m_XmlDocument.ElementListHead, &pXmlNode->SiblingLink);
|
|
}
|
|
else
|
|
{
|
|
ASSERT(m_ParseContext.XMLElementDepth >= 1);
|
|
InsertTailList(&m_CurrentParent->Element.ChildListHead, &pXmlNode->SiblingLink);
|
|
}
|
|
|
|
if ((pXmlNode->Type != SXS_XML_NODE_TYPE_CDATA) &&
|
|
(pXmlNode->Type != SXS_XML_NODE_TYPE_PCDATA))
|
|
m_CurrentParent = pXmlNode;
|
|
|
|
pXmlNode = NULL;
|
|
}
|
|
#endif
|
|
|
|
hr = NOERROR;
|
|
|
|
Exit:
|
|
if (pSXSNodeInfo != NULL)
|
|
FUSION_DELETE_ARRAY(pSXSNodeInfo);
|
|
|
|
if (pXmlNode != NULL)
|
|
FUSION_DELETE_SINGLETON(pXmlNode);
|
|
|
|
return hr;
|
|
}
|
|
|
|
#if FUSION_XML_TREE
|
|
HRESULT
|
|
CNodeFactory::CreateXmlNode(
|
|
PSXS_XML_NODE pParent,
|
|
ULONG cNodes,
|
|
XML_NODE_INFO **prgpNodes,
|
|
PSXS_XML_NODE &rpNewNode
|
|
)
|
|
{
|
|
HRESULT hr = NOERROR;
|
|
FN_TRACE_HR(hr);
|
|
ULONG i;
|
|
ULONG cAttributes = 0;
|
|
ULONG iAttribute = 0;
|
|
PSXS_XML_NODE pNewNode = NULL;
|
|
PSXS_XML_ATTRIBUTE pAttribute = NULL;
|
|
CStringBuffer buffAttributeValue;
|
|
|
|
// Handle XML_ELEMENT vs. XML_CDATA vs. XML_PCDATA...
|
|
switch (prgpNodes[0]->dwType)
|
|
{
|
|
case XML_XMLDECL:
|
|
// <?xml version="1.0" ?> elements come through looking like normal XML_ELEMENT
|
|
// nodes with things broken into the XML_ATTRIBUTE followed by their value...
|
|
|
|
// First, let's count up the attributes...
|
|
|
|
for (i=0; i<cNodes; i++)
|
|
{
|
|
if (prgpNodes[i]->dwType == XML_ATTRIBUTE)
|
|
cAttributes++;
|
|
}
|
|
|
|
// Now let's allocate the SXS_XML_NODE plus the right number of SXS_XML_ATTRIBUTEs
|
|
IFALLOCFAILED_EXIT(hr, pNewNode = reinterpret_cast<PSXS_XML_NODE>(FUSION_RAW_ALLOC(sizeof(SXS_XML_NODE) + (cAttributes * sizeof(SXS_XML_ATTRIBUTE)), SXS_XML_NODE)));
|
|
pAttribute = reinterpret_cast<PSXS_XML_ATTRIBUTE>(pNewNode + 1);
|
|
|
|
pNewNode->Flags = 0;
|
|
pNewNode->Type = SXS_XML_NODE_TYPE_XML_DECL;
|
|
pNewNode->Parent = pParent;
|
|
pNewNode->XMLDecl.AttributeCount = cAttributes;
|
|
pNewNode->XMLDecl.Attributes = pAttribute;
|
|
|
|
for (i=0; i<cNodes; i++)
|
|
{
|
|
ULONG j;
|
|
const WCHAR *prgwch1;
|
|
const WCHAR *prgwch2;
|
|
ULONG ulPK1, ulPK2;
|
|
ULONG ulPos1, ulPos2;
|
|
ULONG cch;
|
|
|
|
switch (prgpNodes[i]->dwType)
|
|
{
|
|
case XML_XMLDECL:
|
|
INTERNAL_ERROR_CHECK(i == 0);
|
|
break;
|
|
|
|
case XML_ATTRIBUTE:
|
|
INTERNAL_ERROR_CHECK(iAttribute < cAttributes);
|
|
|
|
ulPKl = ::FusionpHashUnicodeStringCaseSensitive(prgpNodes[i]->pwcText, prgpNodes[i]->ulLen);
|
|
IFW32FALSE_EXIT(m_ParseTreeStringPool.Canonicalize(prgpNodes[i]->pwcText, prgpNodes[i]->ulLen, ulPK1, ulPos1, prgwch1));
|
|
|
|
i++;
|
|
buffAttributeValue.Clear();
|
|
cch = 0;
|
|
|
|
while ((i < cNodes) && (prgpNodes[i]->dwType == XML_PCDATA))
|
|
{
|
|
IFCOMFAILED_EXIT(buffAttributeValue.Append(prgpNodes[i]->pwcText, prgpNodes[i]->ulLen));
|
|
cch += prgpNodes[i]->ulLen;
|
|
i++;
|
|
}
|
|
|
|
// Gets incremented on the next iteration of the outer loop, so back up one...
|
|
i--;
|
|
|
|
IFW32FALSE_EXIT(::FusionpHashUnicodeString(buffAttributeValue, cch, &ulPK2, false));
|
|
IFW32FALSE_EXIT(m_ParseTreeStringPool.Canonicalize(buffAttributeValue, cch, ulPK2, ulPos2, prgwch2));
|
|
|
|
pAttribute[iAttribute].Flags = 0;
|
|
pAttribute[iAttribute].NamespaceString = 0;
|
|
pAttribute[iAttribute].NameString = ulPos1;
|
|
pAttribute[iAttribute].ValueString = ulPos2;
|
|
iAttribute++;
|
|
break;
|
|
}
|
|
}
|
|
|
|
ASSERT(iAttribute == cAttributes);
|
|
|
|
break;
|
|
|
|
case XML_ELEMENT:
|
|
// First, let's count up the attributes...
|
|
|
|
for (i=0; i<cNodes; i++)
|
|
{
|
|
if (prgpNodes[i]->dwType == XML_ATTRIBUTE)
|
|
cAttributes++;
|
|
}
|
|
|
|
// Now let's allocate the SXS_XML_NODE plus the right number of SXS_XML_ATTRIBUTEs
|
|
IFALLOCFAILED_EXIT(hr, pNewNode = reinterpret_cast<PSXS_XML_NODE>(FUSION_RAW_ALLOC(sizeof(SXS_XML_NODE) + (cAttributes * sizeof(SXS_XML_ATTRIBUTE)), SXS_XML_NODE)));
|
|
pAttribute = reinterpret_cast<PSXS_XML_ATTRIBUTE>(pNewNode + 1);
|
|
|
|
pNewNode->Flags = 0;
|
|
pNewNode->Type = SXS_XML_NODE_TYPE_ELEMENT;
|
|
pNewNode->Element.NamespaceString = 0;
|
|
pNewNode->Element.NameString = 0;
|
|
pNewNode->Parent = pParent;
|
|
pNewNode->Element.AttributeCount = cAttributes;
|
|
pNewNode->Element.Attributes = pAttribute;
|
|
InitializeListHead(&pNewNode->Element.ChildListHead);
|
|
|
|
for (i=0; i<cNodes; i++)
|
|
{
|
|
ULONG j;
|
|
const WCHAR *prgwch1;
|
|
const WCHAR *prgwch2;
|
|
ULONG ulPK1, ulPK2;
|
|
ULONG ulPos1, ulPos2;
|
|
ULONG cch;
|
|
|
|
switch (prgpNodes[i]->dwType)
|
|
{
|
|
case XML_ELEMENT:
|
|
INTERNAL_ERROR_CHECK(i == 0);
|
|
IFW32FALSE_EXIT(::FusionpHashUnicodeString(prgpNodes[0]->pwcText, prgpNodes[0]->ulLen, &ulPK1, false));
|
|
IFW32FALSE_EXIT(m_ParseTreeStringPool.Canonicalize(prgpNodes[0]->pwcText, prgpNodes[0]->ulLen, ulPK1, ulPos1, prgwch1));
|
|
pNewNode->Element.NamespaceString = 0;
|
|
pNewNode->Element.NameString = ulPos1;
|
|
break;
|
|
|
|
case XML_ATTRIBUTE:
|
|
INTERNAL_ERROR_CHECK(iAttribute < cAttributes);
|
|
|
|
IFW32FALSE_EXIT(::FusionpHashUnicodeString(prgpNodes[i]->pwcText, prgpNodes[i]->ulLen, &ulPK1, false));
|
|
IFW32FALSE_EXIT(m_ParseTreeStringPool.Canonicalize(prgpNodes[i]->pwcText, prgpNodes[i]->ulLen, ulPK1, ulPos1, prgwch1));
|
|
|
|
i++;
|
|
buffAttributeValue.Clear();
|
|
cch = 0;
|
|
|
|
while ((i < cNodes) && (prgpNodes[i]->dwType == XML_PCDATA))
|
|
{
|
|
IFCOMFAILED_EXIT(buffAttributeValue.Append(prgpNodes[i]->pwcText, prgpNodes[i]->ulLen));
|
|
cch += prgpNodes[i]->ulLen;
|
|
i++;
|
|
}
|
|
|
|
// Gets incremented on the next iteration of the outer loop, so back up one...
|
|
i--;
|
|
|
|
IFW32FALSE_EXIT(::FusionpHashUnicodeString(buffAttributeValue, cch, &ulPK2, false));
|
|
IFW32FALSE_EXIT(m_ParseTreeStringPool.Canonicalize(buffAttributeValue, cch, ulPK2, ulPos2, prgwch2));
|
|
|
|
pAttribute[iAttribute].Flags = 0;
|
|
pAttribute[iAttribute].NamespaceString = 0;
|
|
pAttribute[iAttribute].NameString = ulPos1;
|
|
pAttribute[iAttribute].ValueString = ulPos2;
|
|
iAttribute++;
|
|
break;
|
|
}
|
|
}
|
|
|
|
ASSERT(iAttribute == cAttributes);
|
|
|
|
break;
|
|
|
|
case XML_CDATA:
|
|
{
|
|
ULONG ulPK;
|
|
ULONG ulPos;
|
|
const WCHAR *prgwch;
|
|
|
|
IFW32FALSE_EXIT(::FusionpHashUnicodeString(prgpNodes[0]->pwcText, prgpNodes[0]->ulLen, &ulPK, false));
|
|
IFW32FALSE_EXIT(m_ParseTreeStringPool.Canonicalize(prgpNodes[0]->pwcText, prgpNodes[0]->ulLen, ulPK, ulPos, prgwch));
|
|
|
|
// Now let's allocate the SXS_XML_NODE
|
|
IFALLOCFAILED_EXIT(hr, pNewNode = reinterpret_cast<PSXS_XML_NODE>(FUSION_RAW_ALLOC(sizeof(SXS_XML_NODE), SXS_XML_NODE)));
|
|
pNewNode->Flags = 0;
|
|
pNewNode->Type = SXS_XML_NODE_TYPE_CDATA;
|
|
pNewNode->Parent = pParent;
|
|
pNewNode->CDataString = ulPos;
|
|
break;
|
|
}
|
|
|
|
case XML_PCDATA:
|
|
{
|
|
ULONG ulPK;
|
|
ULONG ulPos;
|
|
const WCHAR *prgwch;
|
|
|
|
IFW32FALSE_EXIT(::FusionpHashUnicodeString(prgpNodes[0]->pwcText, prgpNodes[0]->ulLen, &ulPK, false));
|
|
IFW32FALSE_EXIT(m_ParseTreeStringPool.Canonicalize(prgpNodes[0]->pwcText, prgpNodes[0]->ulLen, ulPK, ulPos, prgwch));
|
|
|
|
// Now let's allocate the SXS_XML_NODE
|
|
IFALLOCFAILED_EXIT(hr, pNewNode = reinterpret_cast<PSXS_XML_NODE>(FUSION_RAW_ALLOC(sizeof(SXS_XML_NODE), SXS_XML_NODE)));
|
|
pNewNode->Flags = 0;
|
|
pNewNode->Type = SXS_XML_NODE_TYPE_PCDATA;
|
|
pNewNode->Parent = pParent;
|
|
pNewNode->PCDataString = ulPos;
|
|
break;
|
|
}
|
|
}
|
|
|
|
rpNewNode = pNewNode;
|
|
pNewNode = NULL;
|
|
|
|
hr = NOERROR;
|
|
Exit:
|
|
FUSION_RAW_DEALLOC(pNewNode);
|
|
|
|
return hr;
|
|
}
|
|
#endif // FUSION_XML_TREE
|
|
|
|
BOOL
|
|
CNodeFactory::SetParseType(
|
|
ULONG ParseType,
|
|
ULONG PathType,
|
|
const CBaseStringBuffer &Path,
|
|
const FILETIME &rftLastWriteTime
|
|
)
|
|
{
|
|
BOOL fSuccess = FALSE;
|
|
FN_TRACE_WIN32(fSuccess);
|
|
|
|
PARAMETER_CHECK(
|
|
(ParseType == XML_FILE_TYPE_MANIFEST) ||
|
|
(ParseType == XML_FILE_TYPE_APPLICATION_CONFIGURATION) ||
|
|
(ParseType == XML_FILE_TYPE_COMPONENT_CONFIGURATION));
|
|
|
|
PARAMETER_CHECK(PathType == ACTIVATION_CONTEXT_PATH_TYPE_WIN32_FILE);
|
|
|
|
IFW32FALSE_EXIT(m_buffCurrentFileName.Win32Assign(Path));
|
|
|
|
m_ParseContext.SourceFilePathType = PathType;
|
|
m_ParseContext.SourceFile = m_buffCurrentFileName;
|
|
m_ParseContext.SourceFileCch = m_buffCurrentFileName.Cch();
|
|
m_ParseContext.SourceFileLastWriteTime = rftLastWriteTime;
|
|
|
|
m_ParseType = ParseType;
|
|
|
|
fSuccess = TRUE;
|
|
Exit:
|
|
return fSuccess;
|
|
}
|
|
|
|
BOOL
|
|
CNodeFactory::XMLParser_Element_doc_assembly(
|
|
USHORT cNumRecs,
|
|
PCSXS_NODE_INFO prgNodeInfo
|
|
)
|
|
{
|
|
BOOL fSuccess = FALSE;
|
|
FN_TRACE_WIN32(fSuccess);
|
|
ULONG i;
|
|
|
|
ASSERT(cNumRecs != 0);
|
|
ASSERT(prgNodeInfo != NULL);
|
|
|
|
if (m_fAssemblyFound)
|
|
{
|
|
CUnicodeString s;
|
|
PCWSTR ManifestPath;
|
|
IFW32FALSE_EXIT(m_Assembly->GetManifestPath(&ManifestPath, NULL));
|
|
s = ManifestPath;
|
|
this->LogParseError(MSG_SXS_MANIFEST_MULTIPLE_TOP_ASSEMBLY, &s);
|
|
goto Exit;
|
|
}
|
|
|
|
m_fAssemblyFound = true;
|
|
|
|
m_fMetadataSatelliteAlreadyFound = false;
|
|
|
|
// Now let's tell all the contributors that we're about to begin a parsing session.
|
|
for (i=0; i<m_ActCtxGenCtx->m_ContributorCount; i++)
|
|
{
|
|
IFW32FALSE_EXIT(m_ActCtxGenCtx->m_Contributors[i].Fire_ParseBeginning(
|
|
m_ActCtxGenCtx,
|
|
m_AssemblyContext,
|
|
0, // FileFlags
|
|
m_ParseType,
|
|
m_ParseContext.SourceFilePathType,
|
|
m_ParseContext.SourceFile,
|
|
m_ParseContext.SourceFileCch,
|
|
m_ParseContext.SourceFileLastWriteTime,
|
|
m_Assembly->m_ManifestVersionMajor,
|
|
m_Assembly->m_ManifestVersionMinor,
|
|
m_Assembly->m_MetadataSatelliteRosterIndex));
|
|
}
|
|
|
|
fSuccess = TRUE;
|
|
Exit:
|
|
return fSuccess;
|
|
}
|
|
|
|
BOOL
|
|
CNodeFactory::XMLParser_Element_doc_assembly_assemblyIdentity(
|
|
USHORT cNumRecs,
|
|
PCSXS_NODE_INFO prgNodeInfo
|
|
)
|
|
{
|
|
BOOL fSuccess = FALSE;
|
|
FN_TRACE_WIN32(fSuccess);
|
|
PASSEMBLY_IDENTITY AssemblyIdentity = NULL;
|
|
const BOOL fGeneratingActCtx = (m_ActCtxGenCtx->m_ManifestOperation == MANIFEST_OPERATION_GENERATE_ACTIVATION_CONTEXT);
|
|
ULONG i;
|
|
DWORD dwValidateFlags = 0;
|
|
|
|
if (m_fIdentityFound)
|
|
{
|
|
this->LogParseError(MSG_SXS_MULTIPLE_IDENTITY, CEventLogString(prgNodeInfo[0].pszText, prgNodeInfo[0].cchText));
|
|
|
|
::FusionpDbgPrintEx(
|
|
FUSION_DBG_LEVEL_ERROR,
|
|
"SXS.DLL: Manifest %ls has multiple identities\n", static_cast<PCWSTR>(m_buffCurrentFileName));
|
|
ORIGINATE_WIN32_FAILURE_AND_EXIT(
|
|
MultipleIdentities,
|
|
ERROR_SXS_MANIFEST_PARSE_ERROR);
|
|
}
|
|
|
|
m_fIdentityFound = true;
|
|
|
|
IFW32FALSE_EXIT(
|
|
::SxspCreateAssemblyIdentityFromIdentityElement(
|
|
0, // DWORD Flags,
|
|
&m_ParseContext,
|
|
ASSEMBLY_IDENTITY_TYPE_DEFINITION, // ULONG Type,
|
|
&AssemblyIdentity, // PASSEMBLY_IDENTITY *AssemblyIdentityOut,
|
|
cNumRecs,
|
|
prgNodeInfo));
|
|
|
|
// If the identity that was created is a policy statement, then we
|
|
// set the internal parse type to our special 'intuited' parse type
|
|
// for later checks of missing attributes and whatnot. This does
|
|
// duplicate work in ValidateAssembly that does the same thing, but
|
|
// we need to preemptively set this parse type before we go validating.
|
|
|
|
// if (m_IntuitedParseType == eActualParseType_Undetermined)
|
|
{
|
|
BOOL fIsPolicy = FALSE;
|
|
IFW32FALSE_EXIT(::SxspDetermineAssemblyType(AssemblyIdentity, fIsPolicy));
|
|
|
|
if (fIsPolicy)
|
|
m_IntuitedParseType = eActualParseType_PolicyManifest;
|
|
else
|
|
m_IntuitedParseType = eActualParseType_Manifest;
|
|
}
|
|
|
|
if ((m_IntuitedParseType == eActualParseType_Manifest) ||
|
|
(m_IntuitedParseType == eActualParseType_PolicyManifest) ||
|
|
(m_ParseType == XML_FILE_TYPE_MANIFEST) ||
|
|
(m_ParseType == XML_FILE_TYPE_COMPONENT_CONFIGURATION))
|
|
{
|
|
dwValidateFlags = eValidateIdentity_VersionRequired;
|
|
}
|
|
|
|
IFW32FALSE_EXIT(
|
|
this->ValidateIdentity(
|
|
dwValidateFlags,
|
|
ASSEMBLY_IDENTITY_TYPE_DEFINITION,
|
|
AssemblyIdentity));
|
|
|
|
if (fGeneratingActCtx)
|
|
{
|
|
if (m_Assembly->IsRoot())
|
|
{
|
|
// If we're generating the actctx and this is the root assembly, it's possible
|
|
// that we got to it by a filesystem path (e.g. private assembly) rather than
|
|
// an actual reference, so we need to fix up the assembly's identity information
|
|
// appropriately.
|
|
IFW32FALSE_EXIT(m_Assembly->m_Information.SetProbedIdentity(AssemblyIdentity));
|
|
}
|
|
else
|
|
{
|
|
// If we're generating the actctx and this isn't the root assembly, we need to verify
|
|
// that it's the right one.
|
|
BOOL fEqual;
|
|
IFW32FALSE_EXIT(
|
|
::SxsAreAssemblyIdentitiesEqual(
|
|
SXS_ARE_ASSEMBLY_IDENTITIES_EQUAL_FLAG_ALLOW_REF_TO_MATCH_DEF,
|
|
m_Assembly->GetAssemblyIdentity(),
|
|
AssemblyIdentity,
|
|
&fEqual));
|
|
|
|
if (!fEqual)
|
|
{
|
|
this->LogParseError(MSG_SXS_COMPONENT_MANIFEST_PROBED_IDENTITY_MISMATCH);
|
|
// LogParseError sets the last error appropriate to the message logged
|
|
goto Exit;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (m_IntuitedParseType == eActualParseType_PolicyManifest)
|
|
{
|
|
IFALLOCFAILED_EXIT(m_CurrentPolicyStatement = new CPolicyStatement);
|
|
IFW32FALSE_EXIT(m_CurrentPolicyStatement->Initialize());
|
|
}
|
|
|
|
// Tell everyone that we're sure who we are...
|
|
for (i=0; i<m_ActCtxGenCtx->m_ContributorCount; i++)
|
|
{
|
|
IFW32FALSE_EXIT(
|
|
m_ActCtxGenCtx->m_Contributors[i].Fire_IdentityDetermined(
|
|
m_ActCtxGenCtx,
|
|
m_AssemblyContext,
|
|
&m_ParseContext,
|
|
AssemblyIdentity));
|
|
}
|
|
|
|
// fix up assembly and assembly context so we know where to copy to
|
|
// also save the manifest
|
|
IFW32FALSE_EXIT(m_Assembly->m_Information.SetAssemblyIdentity(AssemblyIdentity));
|
|
if (m_AssemblyContext->AssemblyIdentity != NULL)
|
|
::SxsDestroyAssemblyIdentity(const_cast<PASSEMBLY_IDENTITY>(m_AssemblyContext->AssemblyIdentity));
|
|
|
|
m_AssemblyContext->AssemblyIdentity = AssemblyIdentity;
|
|
AssemblyIdentity = NULL;
|
|
|
|
fSuccess = TRUE;
|
|
|
|
Exit:
|
|
if (AssemblyIdentity != NULL)
|
|
::SxsDestroyAssemblyIdentity(AssemblyIdentity);
|
|
|
|
return fSuccess;
|
|
}
|
|
|
|
BOOL
|
|
CNodeFactory::XMLParser_Element_doc_assembly_noInherit(
|
|
USHORT cNumRecs,
|
|
PCSXS_NODE_INFO prgNodeInfo
|
|
)
|
|
{
|
|
BOOL fSuccess = FALSE;
|
|
FN_TRACE_WIN32(fSuccess);
|
|
|
|
INTERNAL_ERROR_CHECK(
|
|
(m_ParseType == XML_FILE_TYPE_MANIFEST) ||
|
|
(m_ParseType == XML_FILE_TYPE_APPLICATION_CONFIGURATION) ||
|
|
(m_ParseType == XML_FILE_TYPE_COMPONENT_CONFIGURATION));
|
|
|
|
switch (m_ParseType)
|
|
{
|
|
case XML_FILE_TYPE_MANIFEST:
|
|
if (cNumRecs != 1)
|
|
{
|
|
this->LogParseError(MSG_SXS_MANIFEST_PARSE_NO_INHERIT_ATTRIBUTES_NOT_ALLOWED);
|
|
goto Exit;
|
|
}
|
|
if (m_ActCtxGenCtx->m_NoInherit)
|
|
{
|
|
this->LogParseError(MSG_SXS_MANIFEST_PARSE_MULTIPLE_NO_INHERIT);
|
|
goto Exit;
|
|
}
|
|
if (m_fIdentityFound)
|
|
{
|
|
this->LogParseError(
|
|
MSG_SXS_MANIFEST_ELEMENT_MUST_OCCUR_BEFORE,
|
|
CEventLogString(L"noInherit"),
|
|
CEventLogString(L"assemblyIdentity"));
|
|
goto Exit;
|
|
}
|
|
|
|
m_ActCtxGenCtx->m_NoInherit = true;
|
|
break;
|
|
|
|
case XML_FILE_TYPE_APPLICATION_CONFIGURATION:
|
|
this->LogParseError(MSG_SXS_POLICY_PARSE_NO_INHERIT_NOT_ALLOWED);
|
|
goto Exit;
|
|
|
|
default:
|
|
::FusionpSetLastWin32Error(ERROR_INTERNAL_ERROR);
|
|
goto Exit;
|
|
}
|
|
|
|
fSuccess = TRUE;
|
|
Exit:
|
|
return fSuccess;
|
|
}
|
|
|
|
BOOL
|
|
CNodeFactory::XMLParser_Element_doc_assembly_noInheritable(
|
|
USHORT cNumRecs,
|
|
PCSXS_NODE_INFO prgNodeInfo
|
|
)
|
|
{
|
|
BOOL fSuccess = FALSE;
|
|
FN_TRACE_WIN32(fSuccess);
|
|
|
|
INTERNAL_ERROR_CHECK(
|
|
(m_ParseType == XML_FILE_TYPE_MANIFEST) ||
|
|
(m_ParseType == XML_FILE_TYPE_APPLICATION_CONFIGURATION) ||
|
|
(m_ParseType == XML_FILE_TYPE_COMPONENT_CONFIGURATION));
|
|
|
|
switch (m_ParseType)
|
|
{
|
|
case XML_FILE_TYPE_MANIFEST:
|
|
if (cNumRecs != 1)
|
|
{
|
|
this->LogParseError(MSG_SXS_MANIFEST_PARSE_NO_INHERIT_ATTRIBUTES_NOT_ALLOWED);
|
|
goto Exit;
|
|
}
|
|
|
|
if (m_fNoInheritableFound)
|
|
{
|
|
this->LogParseError(MSG_SXS_MANIFEST_PARSE_MULTIPLE_NOINHERITABLE);
|
|
goto Exit;
|
|
}
|
|
if (m_fIdentityFound)
|
|
{
|
|
this->LogParseError(
|
|
MSG_SXS_MANIFEST_ELEMENT_MUST_OCCUR_BEFORE,
|
|
CEventLogString(L"noInheritable"),
|
|
CEventLogString(L"assemblyIdentity"));
|
|
goto Exit;
|
|
}
|
|
|
|
|
|
m_fNoInheritableFound = true;
|
|
|
|
break;
|
|
|
|
case XML_FILE_TYPE_APPLICATION_CONFIGURATION:
|
|
case XML_FILE_TYPE_COMPONENT_CONFIGURATION:
|
|
this->LogParseError(MSG_SXS_POLICY_PARSE_NO_INHERIT_NOT_ALLOWED);
|
|
goto Exit;
|
|
|
|
default:
|
|
::FusionpSetLastWin32Error(ERROR_INTERNAL_ERROR);
|
|
goto Exit;
|
|
}
|
|
|
|
fSuccess = TRUE;
|
|
Exit:
|
|
return fSuccess;
|
|
}
|
|
|
|
BOOL
|
|
CNodeFactory::XMLParser_Element_doc_assembly_dependency(
|
|
USHORT cNumRecs,
|
|
PCSXS_NODE_INFO prgNodeInfo
|
|
)
|
|
{
|
|
BOOL fSuccess = FALSE;
|
|
FN_TRACE_WIN32(fSuccess);
|
|
bool fFound;
|
|
SIZE_T cb;
|
|
|
|
m_fIsDependencyOptional = false;
|
|
m_fDependencyChildHit = false;
|
|
m_fIsMetadataSatellite = false;
|
|
|
|
IFW32FALSE_EXIT(
|
|
::SxspGetAttributeValue(
|
|
0,
|
|
&s_AttributeName_optional,
|
|
prgNodeInfo,
|
|
cNumRecs,
|
|
&m_ParseContext,
|
|
fFound,
|
|
sizeof(m_fIsDependencyOptional),
|
|
&m_fIsDependencyOptional,
|
|
cb,
|
|
&::SxspValidateBoolAttribute,
|
|
0));
|
|
|
|
if (!fFound)
|
|
m_fIsDependencyOptional = false;
|
|
|
|
fSuccess = TRUE;
|
|
Exit:
|
|
return fSuccess;
|
|
}
|
|
|
|
BOOL
|
|
CNodeFactory::XMLParser_Element_doc_assembly_dependency_dependentAssembly(
|
|
USHORT cNumRecs,
|
|
PCSXS_NODE_INFO prgNodeInfo
|
|
)
|
|
{
|
|
BOOL fSuccess = FALSE;
|
|
FN_TRACE_WIN32(fSuccess);
|
|
bool fFound;
|
|
SIZE_T cb;
|
|
|
|
if (m_fDependencyChildHit == false)
|
|
{
|
|
m_fDependencyChildHit = true;
|
|
}
|
|
else
|
|
{
|
|
this->LogParseError(MSG_SXS_MANIFEST_MULTIPLE_DEPENDENTASSEMBLY_IN_DEPENDENCY);
|
|
goto Exit;
|
|
}
|
|
|
|
m_fAssemblyIdentityChildOfDependenctAssemblyHit = false;
|
|
|
|
IFW32FALSE_EXIT(
|
|
::SxspGetAttributeValue(
|
|
0,
|
|
&s_AttributeName_metadataSatellite,
|
|
prgNodeInfo,
|
|
cNumRecs,
|
|
&m_ParseContext,
|
|
fFound,
|
|
sizeof(m_fIsMetadataSatellite),
|
|
&m_fIsMetadataSatellite,
|
|
cb,
|
|
&::SxspValidateBoolAttribute,
|
|
0));
|
|
|
|
if (!fFound)
|
|
m_fIsMetadataSatellite = false;
|
|
|
|
fSuccess = TRUE;
|
|
Exit:
|
|
return fSuccess;
|
|
}
|
|
|
|
BOOL
|
|
CNodeFactory::XMLParser_Element_doc_assembly_dependency_dependentAssembly_bindingRedirect(
|
|
USHORT cNumRecs,
|
|
PCSXS_NODE_INFO prgNodeInfo
|
|
)
|
|
{
|
|
BOOL fSuccess = FALSE;
|
|
FN_TRACE_WIN32(fSuccess);
|
|
bool fFound;
|
|
bool fValid;
|
|
SIZE_T cb;
|
|
CSmallStringBuffer buffOldVersion;
|
|
CSmallStringBuffer buffNewVersion;
|
|
|
|
INTERNAL_ERROR_CHECK(m_CurrentPolicyStatement != NULL);
|
|
|
|
if (m_IntuitedParseType != eActualParseType_PolicyManifest)
|
|
{
|
|
this->LogParseError(MSG_SXS_BINDING_REDIRECTS_ONLY_IN_COMPONENT_CONFIGURATION);
|
|
goto Exit;
|
|
}
|
|
|
|
IFW32FALSE_EXIT(
|
|
::SxspGetAttributeValue(
|
|
SXSP_GET_ATTRIBUTE_VALUE_FLAG_REQUIRED_ATTRIBUTE,
|
|
&s_AttributeName_oldVersion,
|
|
prgNodeInfo,
|
|
cNumRecs,
|
|
&m_ParseContext,
|
|
fFound,
|
|
sizeof(buffOldVersion),
|
|
&buffOldVersion,
|
|
cb,
|
|
NULL,
|
|
0));
|
|
INTERNAL_ERROR_CHECK(fFound);
|
|
|
|
IFW32FALSE_EXIT(
|
|
::SxspGetAttributeValue(
|
|
SXSP_GET_ATTRIBUTE_VALUE_FLAG_REQUIRED_ATTRIBUTE,
|
|
&s_AttributeName_newVersion,
|
|
prgNodeInfo,
|
|
cNumRecs,
|
|
&m_ParseContext,
|
|
fFound,
|
|
sizeof(buffNewVersion),
|
|
&buffNewVersion,
|
|
cb,
|
|
NULL,
|
|
0));
|
|
INTERNAL_ERROR_CHECK(fFound);
|
|
|
|
IFW32FALSE_EXIT(m_CurrentPolicyStatement->AddRedirect(buffOldVersion, buffNewVersion, fValid));
|
|
|
|
if (!fValid)
|
|
{
|
|
this->LogParseError(MSG_SXS_BINDING_REDIRECT_MISSING_REQUIRED_ATTRIBUTES);
|
|
goto Exit;
|
|
}
|
|
|
|
fSuccess = TRUE;
|
|
Exit:
|
|
return fSuccess;
|
|
}
|
|
|
|
BOOL
|
|
CNodeFactory::XMLParser_Element_doc_assembly_dependency_dependentAssembly_assemblyIdentity(
|
|
USHORT cNumRecs,
|
|
PCSXS_NODE_INFO prgNodeInfo
|
|
)
|
|
{
|
|
BOOL fSuccess = FALSE;
|
|
FN_TRACE_WIN32(fSuccess);
|
|
PASSEMBLY_IDENTITY pAssemblyIdentity = NULL;
|
|
ULONG ParseType;
|
|
|
|
ASSERT(cNumRecs != 0);
|
|
ASSERT(prgNodeInfo != NULL);
|
|
|
|
// We're either parsing a manifest or a policy file; what else??
|
|
INTERNAL_ERROR_CHECK(
|
|
(m_ParseType == XML_FILE_TYPE_MANIFEST) ||
|
|
(m_ParseType == XML_FILE_TYPE_APPLICATION_CONFIGURATION) ||
|
|
(m_ParseType == XML_FILE_TYPE_COMPONENT_CONFIGURATION));
|
|
|
|
if (m_fAssemblyIdentityChildOfDependenctAssemblyHit == false)
|
|
m_fAssemblyIdentityChildOfDependenctAssemblyHit = true;
|
|
else
|
|
{
|
|
this->LogParseError(MSG_SXS_MANIFEST_MULTIPLE_ASSEMBLYIDENTITY_IN_DEPENDENCYASSEMBLY);
|
|
goto Exit;
|
|
}
|
|
|
|
switch (m_IntuitedParseType)
|
|
{
|
|
case eActualParseType_Undetermined:
|
|
ParseType = m_ParseType;
|
|
break;
|
|
case eActualParseType_PolicyManifest:
|
|
ParseType = XML_FILE_TYPE_COMPONENT_CONFIGURATION;
|
|
break;
|
|
case eActualParseType_Manifest:
|
|
ParseType = XML_FILE_TYPE_MANIFEST;
|
|
break;
|
|
default:
|
|
INTERNAL_ERROR_CHECK(FALSE);
|
|
ParseType = m_ParseType;
|
|
break;
|
|
}
|
|
switch (ParseType)
|
|
{
|
|
case XML_FILE_TYPE_MANIFEST:
|
|
IFW32FALSE_EXIT(
|
|
::SxspCreateAssemblyIdentityFromIdentityElement(
|
|
0,
|
|
&m_ParseContext,
|
|
ASSEMBLY_IDENTITY_TYPE_REFERENCE,
|
|
&pAssemblyIdentity,
|
|
cNumRecs,
|
|
prgNodeInfo));
|
|
|
|
IFW32FALSE_EXIT(
|
|
this->ValidateIdentity(
|
|
eValidateIdentity_VersionRequired | eValidateIdentity_PoliciesNotAllowed,
|
|
ASSEMBLY_IDENTITY_TYPE_REFERENCE,
|
|
pAssemblyIdentity));
|
|
|
|
// If we're not installing, process the identity...
|
|
if (m_ActCtxGenCtx->m_ManifestOperation == MANIFEST_OPERATION_GENERATE_ACTIVATION_CONTEXT)
|
|
IFW32FALSE_EXIT(::SxspEnqueueAssemblyReference(m_ActCtxGenCtx, m_Assembly, pAssemblyIdentity, m_fIsDependencyOptional, m_fIsMetadataSatellite));
|
|
|
|
break;
|
|
|
|
case XML_FILE_TYPE_COMPONENT_CONFIGURATION:
|
|
{
|
|
BOOL fValidDependencyAssemblyIdentity = FALSE;
|
|
PCWSTR pszName1 = NULL, pszName2 = NULL;
|
|
SIZE_T cchName1 = 0, cchName2 = 0;
|
|
|
|
if (m_CurrentPolicyDependentAssemblyIdentity != NULL)
|
|
{
|
|
this->LogParseError(MSG_SXS_COMPONENT_CONFIGURATION_MANIFESTS_MAY_ONLY_HAVE_ONE_DEPENDENCY);
|
|
goto Exit;
|
|
}
|
|
|
|
IFW32FALSE_EXIT(
|
|
::SxspCreateAssemblyIdentityFromIdentityElement(
|
|
0,
|
|
&m_ParseContext,
|
|
ASSEMBLY_IDENTITY_TYPE_REFERENCE,
|
|
&pAssemblyIdentity,
|
|
cNumRecs,
|
|
prgNodeInfo));
|
|
// check the name in dependency-assemblyidentity match with the name in assembly-assemblyidentity
|
|
IFW32FALSE_EXIT(
|
|
::SxspGetAssemblyIdentityAttributeValue(
|
|
SXSP_GET_ASSEMBLY_IDENTITY_ATTRIBUTE_VALUE_FLAG_NOT_FOUND_RETURNS_NULL,
|
|
m_Assembly->GetAssemblyIdentity(),
|
|
&s_IdentityAttribute_name,
|
|
&pszName1, // something in a format of "Policy.1212.1221.assemblyname"
|
|
&cchName1));
|
|
|
|
IFW32FALSE_EXIT(
|
|
::SxspGetAssemblyIdentityAttributeValue(
|
|
SXSP_GET_ASSEMBLY_IDENTITY_ATTRIBUTE_VALUE_FLAG_NOT_FOUND_RETURNS_NULL,
|
|
pAssemblyIdentity,
|
|
&s_IdentityAttribute_name,
|
|
&pszName2, // would be something as "assemblyname"
|
|
&cchName2));
|
|
|
|
if ((cchName1 > cchName2) && (cchName2 !=0))
|
|
{
|
|
if ( (*(pszName1 + (cchName1 - cchName2 -1)) == L'.') && (::FusionpCompareStrings(
|
|
pszName1 + (cchName1 - cchName2), cchName2,
|
|
pszName2, cchName2, FALSE // must be case-sensitive for values
|
|
) == 0 ))
|
|
{
|
|
fValidDependencyAssemblyIdentity = TRUE;
|
|
}
|
|
}
|
|
|
|
if (fValidDependencyAssemblyIdentity)
|
|
{
|
|
IFW32FALSE_EXIT(
|
|
this->ValidateIdentity(
|
|
eValidateIdentity_VersionNotAllowed | eValidateIdentity_PoliciesNotAllowed,
|
|
ASSEMBLY_IDENTITY_TYPE_REFERENCE,
|
|
pAssemblyIdentity));
|
|
|
|
// We'll keep track of this so that we can recognize multiple dependentAssembly elements on installation
|
|
// of policies.
|
|
m_CurrentPolicyDependentAssemblyIdentity = pAssemblyIdentity;
|
|
pAssemblyIdentity = NULL;
|
|
}
|
|
else // print a message and ignore this entry
|
|
{
|
|
::FusionpDbgPrintEx(
|
|
FUSION_DBG_LEVEL_POLICY | FUSION_DBG_LEVEL_INFO,
|
|
"SXS.DLL: unexpected assemblyidentity within dependency tag in component policy \"%ls\"\n",
|
|
m_buffCurrentFileName
|
|
);
|
|
}
|
|
} // end of this case
|
|
|
|
break;
|
|
|
|
#if 0
|
|
case XML_FILE_TYPE_APPLICATION_CONFIGURATION:
|
|
IFW32FALSE_EXIT(this->ParseElementAttributes(cNumRecs, prgpNodeInfo, NUMBER_OF(rgPolicyAttributes), rgPolicyAttributes));
|
|
|
|
if (!(m_fAssemblyNamePresent && m_fOldVersionPresent && m_fNewVersionPresent))
|
|
{
|
|
::FusionpDbgPrintEx(
|
|
FUSION_DBG_LEVEL_ERROR,
|
|
"SXS.DLL: Policy dependency tag found and either assemblyname, oldversion or newversion attributes are missing\n");
|
|
::FusionpSetLastWin32Error(ERROR_SXS_MANIFEST_PARSE_ERROR);
|
|
goto Exit;
|
|
}
|
|
|
|
break;
|
|
#endif // 0
|
|
|
|
default:
|
|
// Internal error!
|
|
INTERNAL_ERROR_CHECK(FALSE);
|
|
}
|
|
|
|
fSuccess = TRUE;
|
|
Exit:
|
|
if (pAssemblyIdentity != NULL)
|
|
::SxsDestroyAssemblyIdentity(pAssemblyIdentity);
|
|
|
|
return fSuccess;
|
|
}
|
|
|
|
BOOL
|
|
CNodeFactory::XMLParser_Element_doc_configuration(
|
|
USHORT cNumRecs,
|
|
PCSXS_NODE_INFO prgNodeInfo
|
|
)
|
|
{
|
|
BOOL fSuccess = FALSE;
|
|
FN_TRACE_WIN32(fSuccess);
|
|
ULONG i;
|
|
|
|
ASSERT(cNumRecs != 0);
|
|
ASSERT(prgNodeInfo != NULL);
|
|
|
|
if (m_fAssemblyFound)
|
|
{
|
|
CUnicodeString s;
|
|
PCWSTR ManifestPath;
|
|
IFW32FALSE_EXIT(m_Assembly->GetManifestPath(&ManifestPath, NULL));
|
|
s = ManifestPath;
|
|
this->LogParseError(MSG_SXS_MANIFEST_MULTIPLE_TOP_ASSEMBLY, &s);
|
|
goto Exit;
|
|
}
|
|
|
|
m_fAssemblyFound = true;
|
|
|
|
m_fMetadataSatelliteAlreadyFound = false;
|
|
|
|
// Now let's tell all the contributors that we're about to begin a parsing session.
|
|
for (i=0; i<m_ActCtxGenCtx->m_ContributorCount; i++)
|
|
{
|
|
IFW32FALSE_EXIT(
|
|
m_ActCtxGenCtx->m_Contributors[i].Fire_ParseBeginning(
|
|
m_ActCtxGenCtx,
|
|
m_AssemblyContext,
|
|
0, // FileFlags
|
|
m_ParseType,
|
|
m_ParseContext.SourceFilePathType,
|
|
m_ParseContext.SourceFile,
|
|
m_ParseContext.SourceFileCch,
|
|
m_ParseContext.SourceFileLastWriteTime,
|
|
m_Assembly->m_ManifestVersionMajor,
|
|
m_Assembly->m_ManifestVersionMinor,
|
|
m_Assembly->m_MetadataSatelliteRosterIndex));
|
|
}
|
|
|
|
fSuccess = TRUE;
|
|
Exit:
|
|
return fSuccess;
|
|
}
|
|
|
|
BOOL
|
|
CNodeFactory::XMLParser_Element_doc_configuration_windows(
|
|
USHORT cNumRecs,
|
|
PCSXS_NODE_INFO prgNodeInfo
|
|
)
|
|
{
|
|
BOOL fSuccess = FALSE;
|
|
FN_TRACE_WIN32(fSuccess);
|
|
|
|
fSuccess = TRUE;
|
|
// Exit:
|
|
return fSuccess;
|
|
}
|
|
|
|
BOOL
|
|
CNodeFactory::XMLParser_Element_doc_configuration_windows_assemblyBinding(
|
|
USHORT cNumRecs,
|
|
PCSXS_NODE_INFO prgNodeInfo
|
|
)
|
|
{
|
|
BOOL fSuccess = FALSE;
|
|
FN_TRACE_WIN32(fSuccess);
|
|
|
|
fSuccess = TRUE;
|
|
// Exit:
|
|
return fSuccess;
|
|
}
|
|
|
|
BOOL
|
|
CNodeFactory::XMLParser_Element_doc_configuration_windows_assemblyBinding_assemblyIdentity(
|
|
USHORT cNumRecs,
|
|
PCSXS_NODE_INFO prgNodeInfo
|
|
)
|
|
{
|
|
BOOL fSuccess = FALSE;
|
|
FN_TRACE_WIN32(fSuccess);
|
|
PASSEMBLY_IDENTITY pAssemblyIdentity = NULL;
|
|
|
|
IFW32FALSE_EXIT(
|
|
::SxspCreateAssemblyIdentityFromIdentityElement(
|
|
0,
|
|
&m_ParseContext,
|
|
ASSEMBLY_IDENTITY_TYPE_REFERENCE,
|
|
&pAssemblyIdentity,
|
|
cNumRecs,
|
|
prgNodeInfo));
|
|
|
|
IFW32FALSE_EXIT(
|
|
this->ValidateIdentity(
|
|
eValidateIdentity_VersionRequired | eValidateIdentity_PoliciesNotAllowed,
|
|
ASSEMBLY_IDENTITY_TYPE_REFERENCE,
|
|
pAssemblyIdentity));
|
|
|
|
fSuccess = TRUE;
|
|
Exit:
|
|
if (pAssemblyIdentity != NULL)
|
|
::SxsDestroyAssemblyIdentity(pAssemblyIdentity);
|
|
|
|
return fSuccess;
|
|
}
|
|
|
|
BOOL
|
|
CNodeFactory::XMLParser_Element_doc_configuration_windows_assemblyBinding_dependentAssembly(
|
|
USHORT cNumRecs,
|
|
PCSXS_NODE_INFO prgNodeInfo
|
|
)
|
|
{
|
|
BOOL fSuccess = FALSE;
|
|
FN_TRACE_WIN32(fSuccess);
|
|
|
|
fSuccess = TRUE;
|
|
// Exit:
|
|
return fSuccess;
|
|
}
|
|
|
|
BOOL
|
|
CNodeFactory::XMLParser_Element_doc_configuration_windows_assemblyBinding_dependentAssembly_assemblyIdentity(
|
|
USHORT cNumRecs,
|
|
PCSXS_NODE_INFO prgNodeInfo
|
|
)
|
|
{
|
|
BOOL fSuccess = FALSE;
|
|
FN_TRACE_WIN32(fSuccess);
|
|
PASSEMBLY_IDENTITY pAssemblyIdentity = NULL;
|
|
CPolicyStatement *pPolicyStatement = NULL;
|
|
|
|
IFW32FALSE_EXIT(
|
|
::SxspCreateAssemblyIdentityFromIdentityElement(
|
|
0,
|
|
&m_ParseContext,
|
|
ASSEMBLY_IDENTITY_TYPE_REFERENCE,
|
|
&pAssemblyIdentity,
|
|
cNumRecs,
|
|
prgNodeInfo));
|
|
|
|
IFW32FALSE_EXIT(
|
|
this->ValidateIdentity(
|
|
eValidateIdentity_VersionNotAllowed | eValidateIdentity_PoliciesNotAllowed,
|
|
ASSEMBLY_IDENTITY_TYPE_REFERENCE,
|
|
pAssemblyIdentity));
|
|
|
|
IFW32FALSE_EXIT(
|
|
::SxspGenerateTextuallyEncodedPolicyIdentityFromAssemblyIdentity(
|
|
SXSP_GENERATE_TEXTUALLY_ENCODED_POLICY_IDENTITY_FROM_ASSEMBLY_IDENTITY_FLAG_OMIT_ENTIRE_VERSION,
|
|
pAssemblyIdentity,
|
|
m_buffCurrentApplicationPolicyIdentityKey,
|
|
NULL));
|
|
|
|
IFW32FALSE_EXIT(m_ActCtxGenCtx->m_ApplicationPolicyTable.Find(m_buffCurrentApplicationPolicyIdentityKey, pPolicyStatement));
|
|
if (pPolicyStatement != NULL)
|
|
{
|
|
pPolicyStatement = NULL;
|
|
this->LogParseError(MSG_SXS_APPLICATION_CONFIGURATION_MANIFEST_MAY_ONLY_HAVE_ONE_DEPENDENTASSEMBLY_PER_IDENTITY);
|
|
goto Exit;
|
|
}
|
|
|
|
IFALLOCFAILED_EXIT(pPolicyStatement = new CPolicyStatement);
|
|
IFW32FALSE_EXIT(pPolicyStatement->Initialize());
|
|
IFW32FALSE_EXIT(m_ActCtxGenCtx->m_ApplicationPolicyTable.Insert(m_buffCurrentApplicationPolicyIdentityKey, pPolicyStatement));
|
|
m_CurrentPolicyStatement = pPolicyStatement;
|
|
pPolicyStatement = NULL;
|
|
|
|
if (m_CurrentPolicyDependentAssemblyIdentity != NULL)
|
|
{
|
|
::SxsDestroyAssemblyIdentity(m_CurrentPolicyDependentAssemblyIdentity);
|
|
m_CurrentPolicyDependentAssemblyIdentity = NULL;
|
|
}
|
|
|
|
m_CurrentPolicyDependentAssemblyIdentity = pAssemblyIdentity;
|
|
pAssemblyIdentity = NULL;
|
|
|
|
fSuccess = TRUE;
|
|
Exit:
|
|
if (pAssemblyIdentity != NULL)
|
|
::SxsDestroyAssemblyIdentity(pAssemblyIdentity);
|
|
|
|
if (pPolicyStatement != NULL)
|
|
FUSION_DELETE_SINGLETON(pPolicyStatement);
|
|
|
|
return fSuccess;
|
|
}
|
|
|
|
BOOL
|
|
CNodeFactory::XMLParser_Element_doc_configuration_windows_assemblyBinding_dependentAssembly_bindingRedirect(
|
|
USHORT cNumRecs,
|
|
PCSXS_NODE_INFO prgNodeInfo
|
|
)
|
|
{
|
|
BOOL fSuccess = FALSE;
|
|
FN_TRACE_WIN32(fSuccess);
|
|
CSmallStringBuffer buffOldVersion;
|
|
CSmallStringBuffer buffNewVersion;
|
|
bool fFound;
|
|
bool fValid;
|
|
SIZE_T cb;
|
|
|
|
if (m_CurrentPolicyStatement == NULL)
|
|
{
|
|
this->LogParseError(MSG_SXS_APPLICATION_CONFIGURATION_MANIFEST_DEPENDENTASSEMBLY_MISSING_IDENTITY);
|
|
goto Exit;
|
|
}
|
|
|
|
IFW32FALSE_EXIT(
|
|
::SxspGetAttributeValue(
|
|
SXSP_GET_ATTRIBUTE_VALUE_FLAG_REQUIRED_ATTRIBUTE,
|
|
&s_AttributeName_oldVersion,
|
|
prgNodeInfo,
|
|
cNumRecs,
|
|
&m_ParseContext,
|
|
fFound,
|
|
sizeof(buffOldVersion),
|
|
&buffOldVersion,
|
|
cb,
|
|
NULL,
|
|
0));
|
|
INTERNAL_ERROR_CHECK(fFound);
|
|
|
|
IFW32FALSE_EXIT(
|
|
::SxspGetAttributeValue(
|
|
SXSP_GET_ATTRIBUTE_VALUE_FLAG_REQUIRED_ATTRIBUTE,
|
|
&s_AttributeName_newVersion,
|
|
prgNodeInfo,
|
|
cNumRecs,
|
|
&m_ParseContext,
|
|
fFound,
|
|
sizeof(buffNewVersion),
|
|
&buffNewVersion,
|
|
cb,
|
|
NULL,
|
|
0));
|
|
INTERNAL_ERROR_CHECK(fFound);
|
|
|
|
// If either are not found, log an error
|
|
if (!fFound)
|
|
{
|
|
this->LogParseError(MSG_SXS_BINDING_REDIRECT_MISSING_REQUIRED_ATTRIBUTES);
|
|
goto Exit;
|
|
}
|
|
|
|
IFW32FALSE_EXIT(m_CurrentPolicyStatement->AddRedirect(buffOldVersion, buffNewVersion, fValid));
|
|
if (! fValid)
|
|
{
|
|
// log an error
|
|
::FusionpLogError(
|
|
MSG_SXS_POLICY_VERSION_OVERLAP,
|
|
CEventLogString(m_AssemblyContext->PolicyPath),
|
|
CEventLogString(buffOldVersion),
|
|
CEventLogString(buffNewVersion));
|
|
|
|
ORIGINATE_WIN32_FAILURE_AND_EXIT(PolicyVersionOverlap, ERROR_SXS_MANIFEST_PARSE_ERROR);
|
|
}
|
|
|
|
|
|
fSuccess = TRUE;
|
|
Exit:
|
|
return fSuccess;
|
|
}
|
|
|
|
BOOL
|
|
CNodeFactory::XMLParser_Parse_PartialAssemblyVersion(
|
|
PVOID pvDatum,
|
|
BOOL fAlreadyFound,
|
|
CBaseStringBuffer &rbuff
|
|
)
|
|
{
|
|
return reinterpret_cast<CPartialAssemblyVersion *>(pvDatum)->Parse(rbuff, rbuff.Cch());
|
|
}
|
|
|
|
BOOL
|
|
CNodeFactory::XMLParser_Parse_String(
|
|
LPVOID pvDatum,
|
|
BOOL fAlreadyFound,
|
|
CBaseStringBuffer &rbuff)
|
|
{
|
|
return ((CBaseStringBuffer *) pvDatum)->Win32Assign(rbuff);
|
|
}
|
|
|
|
BOOL
|
|
CNodeFactory::ParseElementAttributes(
|
|
USHORT cNumRecs,
|
|
XML_NODE_INFO **prgpNodeInfo,
|
|
SIZE_T cEntries,
|
|
const AttributeMapEntry *prgEntries
|
|
)
|
|
{
|
|
BOOL fSuccess = FALSE;
|
|
|
|
ULONG i, j;
|
|
|
|
for (i=1; i<cNumRecs; i++)
|
|
{
|
|
// Skip things we don't understand.
|
|
if (prgpNodeInfo[i]->dwType != XML_ATTRIBUTE)
|
|
continue;
|
|
|
|
for (j=0; j<cEntries; j++)
|
|
{
|
|
if (::FusionpCompareStrings(
|
|
prgEntries[j].m_pszAttributeName,
|
|
prgEntries[j].m_cchAttributeName,
|
|
prgpNodeInfo[i]->pwcText,
|
|
prgpNodeInfo[i]->ulLen,
|
|
false) == 0)
|
|
{
|
|
// Because attribute values may be multipart due to entity references,
|
|
// we accumulate the attibute value into buffTemp to start, and then do
|
|
// the parsing/whatever afterwards.
|
|
CStringBuffer buffTemp;
|
|
BOOL *pfIndicator = (BOOL *) (((ULONG_PTR) this) + prgEntries[j].m_offsetIndicator);
|
|
|
|
while ((++i < cNumRecs) &&
|
|
(prgpNodeInfo[i]->dwType == XML_PCDATA))
|
|
{
|
|
if (!buffTemp.Win32Append(prgpNodeInfo[i]->pwcText, prgpNodeInfo[i]->ulLen))
|
|
goto Exit;
|
|
}
|
|
|
|
// The outer for(;;) loop is going to increment i, so we need to back it up one
|
|
// place...
|
|
i--;
|
|
|
|
// Call the appropriate value type handler function...
|
|
if (prgEntries[j].m_pfn != NULL)
|
|
{
|
|
if (!((this->*(prgEntries[j].m_pfn))(((LPBYTE) this) + prgEntries[j].m_offsetData, *pfIndicator, buffTemp)))
|
|
goto Exit;
|
|
}
|
|
|
|
*pfIndicator = TRUE;
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
fSuccess = TRUE;
|
|
|
|
Exit:
|
|
return fSuccess;
|
|
}
|
|
|
|
HRESULT
|
|
CNodeFactory::LogParseError(
|
|
DWORD dwLastParseError,
|
|
const UNICODE_STRING *p1,
|
|
const UNICODE_STRING *p2,
|
|
const UNICODE_STRING *p3,
|
|
const UNICODE_STRING *p4,
|
|
const UNICODE_STRING *p5,
|
|
const UNICODE_STRING *p6,
|
|
const UNICODE_STRING *p7,
|
|
const UNICODE_STRING *p8,
|
|
const UNICODE_STRING *p9,
|
|
const UNICODE_STRING *p10,
|
|
const UNICODE_STRING *p11,
|
|
const UNICODE_STRING *p12,
|
|
const UNICODE_STRING *p13,
|
|
const UNICODE_STRING *p14,
|
|
const UNICODE_STRING *p15,
|
|
const UNICODE_STRING *p16,
|
|
const UNICODE_STRING *p17,
|
|
const UNICODE_STRING *p18,
|
|
const UNICODE_STRING *p19,
|
|
const UNICODE_STRING *p20
|
|
)
|
|
{
|
|
return
|
|
::FusionpLogParseError(
|
|
m_ParseContext.SourceFile,
|
|
m_ParseContext.SourceFileCch,
|
|
m_ParseContext.LineNumber,
|
|
dwLastParseError,
|
|
p1, p2, p3, p4, p5,
|
|
p6, p7, p8, p9, p10,
|
|
p11, p12, p13, p14, p15,
|
|
p16, p17, p18, p19, p20);
|
|
}
|
|
|
|
VOID
|
|
CNodeFactory::ParseErrorCallback_MissingRequiredAttribute(
|
|
PCACTCTXCTB_PARSE_CONTEXT ParseContext,
|
|
IN PCATTRIBUTE_NAME_DESCRIPTOR AttributeName
|
|
)
|
|
{
|
|
// CNodeFactory *pThis = (CNodeFactory *) ErrorContext;
|
|
|
|
::FusionpLogRequiredAttributeMissingParseError(
|
|
ParseContext->SourceFile,
|
|
ParseContext->SourceFileCch,
|
|
ParseContext->LineNumber,
|
|
ParseContext->ElementName,
|
|
ParseContext->ElementNameCch,
|
|
AttributeName->Name,
|
|
AttributeName->NameCch);
|
|
}
|
|
|
|
VOID
|
|
CNodeFactory::ParseErrorCallback_InvalidAttributeValue(
|
|
PCACTCTXCTB_PARSE_CONTEXT ParseContext,
|
|
IN PCATTRIBUTE_NAME_DESCRIPTOR AttributeName
|
|
)
|
|
{
|
|
// CNodeFactory *pThis = (CNodeFactory *) ErrorContext;
|
|
|
|
::FusionpLogInvalidAttributeValueParseError(
|
|
ParseContext->SourceFile,
|
|
ParseContext->SourceFileCch,
|
|
ParseContext->LineNumber,
|
|
ParseContext->ElementName,
|
|
ParseContext->ElementNameCch,
|
|
AttributeName->Name,
|
|
AttributeName->NameCch);
|
|
}
|
|
|
|
VOID
|
|
CNodeFactory::ParseErrorCallback_AttributeNotAllowed(
|
|
PCACTCTXCTB_PARSE_CONTEXT ParseContext,
|
|
IN PCATTRIBUTE_NAME_DESCRIPTOR AttributeName
|
|
)
|
|
{
|
|
// CNodeFactory *pThis = (CNodeFactory *) ErrorContext;
|
|
|
|
::FusionpLogAttributeNotAllowedParseError(
|
|
ParseContext->SourceFile,
|
|
ParseContext->SourceFileCch,
|
|
ParseContext->LineNumber,
|
|
ParseContext->ElementName,
|
|
ParseContext->ElementNameCch,
|
|
AttributeName->Name,
|
|
AttributeName->NameCch);
|
|
}
|
|
|
|
static
|
|
VOID
|
|
SxspDbgPrintXmlNodeInfo(
|
|
ULONG Level,
|
|
XML_NODE_INFO *pNode
|
|
)
|
|
{
|
|
CUnicodeString s(pNode->pwcText, pNode->ulLen);
|
|
|
|
#if DBG_SXS
|
|
::FusionpDbgPrintEx(Level, "SXS.DLL: XML_NODE_INFO at %p\n", pNode);
|
|
::FusionpDbgPrintEx(Level, " dwSize = %d\n", pNode->dwSize);
|
|
::FusionpDbgPrintEx(Level, " dwType = %d (%s)\n", pNode->dwType, SxspFormatXmlNodeType(pNode->dwType));
|
|
::FusionpDbgPrintEx(Level, " dwSubType = %d\n", pNode->dwSubType);
|
|
::FusionpDbgPrintEx(Level, " fTerminal = %d\n", pNode->fTerminal);
|
|
|
|
::FusionpDbgPrintEx(Level, " pwcText = %p (\"%wZ\")\n", pNode->pwcText, &s);
|
|
::FusionpDbgPrintEx(Level, " ulLen = %d\n", pNode->ulLen);
|
|
::FusionpDbgPrintEx(Level, " ulNsPrefixLen = %d\n", pNode->ulNsPrefixLen);
|
|
::FusionpDbgPrintEx(Level, " pNode = %p\n", pNode->pNode);
|
|
::FusionpDbgPrintEx(Level, " pReserved = %p\n", pNode->pReserved);
|
|
#else
|
|
::FusionpDbgPrintEx(Level, "SXS.DLL: XML_NODE_INFO at %p: \"%wZ\"\n", pNode, &s);
|
|
#endif
|
|
}
|
|
|
|
|
|
static
|
|
PCSTR
|
|
SxspFormatXmlNodeType(
|
|
DWORD dwType
|
|
)
|
|
{
|
|
PCSTR Result = "Unknown";
|
|
|
|
#define HANDLE_NODE_TYPE(x) case static_cast<DWORD>(x): Result = #x; break;
|
|
|
|
switch (dwType)
|
|
{
|
|
HANDLE_NODE_TYPE(XML_ELEMENT)
|
|
HANDLE_NODE_TYPE(XML_ATTRIBUTE)
|
|
HANDLE_NODE_TYPE(XML_PI)
|
|
HANDLE_NODE_TYPE(XML_XMLDECL)
|
|
HANDLE_NODE_TYPE(XML_DOCTYPE)
|
|
HANDLE_NODE_TYPE(XML_DTDATTRIBUTE)
|
|
HANDLE_NODE_TYPE(XML_ENTITYDECL)
|
|
HANDLE_NODE_TYPE(XML_ELEMENTDECL)
|
|
HANDLE_NODE_TYPE(XML_ATTLISTDECL)
|
|
HANDLE_NODE_TYPE(XML_NOTATION)
|
|
HANDLE_NODE_TYPE(XML_GROUP)
|
|
HANDLE_NODE_TYPE(XML_INCLUDESECT)
|
|
HANDLE_NODE_TYPE(XML_PCDATA)
|
|
HANDLE_NODE_TYPE(XML_CDATA)
|
|
HANDLE_NODE_TYPE(XML_IGNORESECT)
|
|
HANDLE_NODE_TYPE(XML_COMMENT)
|
|
HANDLE_NODE_TYPE(XML_ENTITYREF)
|
|
HANDLE_NODE_TYPE(XML_WHITESPACE)
|
|
HANDLE_NODE_TYPE(XML_NAME)
|
|
HANDLE_NODE_TYPE(XML_NMTOKEN)
|
|
HANDLE_NODE_TYPE(XML_STRING)
|
|
HANDLE_NODE_TYPE(XML_PEREF)
|
|
HANDLE_NODE_TYPE(XML_MODEL)
|
|
HANDLE_NODE_TYPE(XML_ATTDEF)
|
|
HANDLE_NODE_TYPE(XML_ATTTYPE)
|
|
HANDLE_NODE_TYPE(XML_ATTPRESENCE)
|
|
HANDLE_NODE_TYPE(XML_DTDSUBSET)
|
|
}
|
|
|
|
return Result;
|
|
}
|
|
|
|
BOOL
|
|
CNodeFactory::ValidateIdentity(
|
|
DWORD Flags,
|
|
ULONG Type,
|
|
PCASSEMBLY_IDENTITY AssemblyIdentity
|
|
)
|
|
{
|
|
BOOL fSuccess = FALSE;
|
|
FN_TRACE_WIN32(fSuccess);
|
|
PCWSTR pszTemp = NULL;
|
|
SIZE_T cchTemp = 0;
|
|
bool fSyntaxValid = false;
|
|
bool fError = false;
|
|
BOOL fIsPolicy;
|
|
|
|
PARAMETER_CHECK((Flags & ~(
|
|
eValidateIdentity_VersionRequired |
|
|
eValidateIdentity_PoliciesNotAllowed |
|
|
eValidateIdentity_VersionNotAllowed)) == 0);
|
|
PARAMETER_CHECK((Type == ASSEMBLY_IDENTITY_TYPE_DEFINITION) || (Type == ASSEMBLY_IDENTITY_TYPE_REFERENCE));
|
|
PARAMETER_CHECK(AssemblyIdentity != NULL);
|
|
|
|
//
|
|
// only one of these flags is allowed
|
|
//
|
|
IFINVALID_FLAGS_EXIT_WIN32(Flags,
|
|
eValidateIdentity_PoliciesNotAllowed |
|
|
eValidateIdentity_VersionNotAllowed |
|
|
eValidateIdentity_VersionRequired);
|
|
|
|
//
|
|
// Get the type of this assembly
|
|
//
|
|
IFW32FALSE_EXIT(::SxspDetermineAssemblyType(AssemblyIdentity, fIsPolicy));
|
|
|
|
//
|
|
// If it's policy, then make sure that policies are allowed. Otherwise, fail out.
|
|
//
|
|
if (fIsPolicy)
|
|
{
|
|
if (Flags & eValidateIdentity_PoliciesNotAllowed)
|
|
{
|
|
FusionpDbgPrintEx(
|
|
FUSION_DBG_LEVEL_ERROR,
|
|
"SXS.DLL: Manifest \"%ls\" (line %d) contains a type=\"win32-policy\" where it shouldn't\n",
|
|
m_ParseContext.SourceFile,
|
|
m_ParseContext.LineNumber);
|
|
|
|
fError = true;
|
|
}
|
|
else
|
|
{
|
|
m_AssemblyContext->Flags |= ACTCTXCTB_ASSEMBLY_CONTEXT_IS_SYSTEM_POLICY_INSTALLATION;
|
|
}
|
|
}
|
|
|
|
IFW32FALSE_EXIT(
|
|
::SxspGetAssemblyIdentityAttributeValue(
|
|
SXSP_GET_ASSEMBLY_IDENTITY_ATTRIBUTE_VALUE_FLAG_NOT_FOUND_RETURNS_NULL,
|
|
AssemblyIdentity,
|
|
&s_IdentityAttribute_name,
|
|
&pszTemp,
|
|
&cchTemp));
|
|
|
|
if (cchTemp == 0)
|
|
{
|
|
::FusionpDbgPrintEx(
|
|
FUSION_DBG_LEVEL_ERROR,
|
|
"SXS.DLL: Manifest \"%ls\" (line %d) is missing name attribute; report to owner of \"%ls\"\n",
|
|
m_ParseContext.SourceFile,
|
|
m_ParseContext.LineNumber,
|
|
m_ParseContext.SourceFile);
|
|
|
|
fError = true;
|
|
}
|
|
|
|
IFW32FALSE_EXIT(
|
|
::SxspGetAssemblyIdentityAttributeValue(
|
|
SXSP_GET_ASSEMBLY_IDENTITY_ATTRIBUTE_VALUE_FLAG_NOT_FOUND_RETURNS_NULL,
|
|
AssemblyIdentity,
|
|
&s_IdentityAttribute_processorArchitecture,
|
|
&pszTemp,
|
|
&cchTemp));
|
|
|
|
IFW32FALSE_EXIT(
|
|
::SxspGetAssemblyIdentityAttributeValue(
|
|
SXSP_GET_ASSEMBLY_IDENTITY_ATTRIBUTE_VALUE_FLAG_NOT_FOUND_RETURNS_NULL,
|
|
AssemblyIdentity,
|
|
&s_IdentityAttribute_version,
|
|
&pszTemp,
|
|
&cchTemp));
|
|
|
|
if (cchTemp != 0)
|
|
{
|
|
ASSEMBLY_VERSION av;
|
|
|
|
IFW32FALSE_EXIT(CFusionParser::ParseVersion(av, pszTemp, cchTemp, fSyntaxValid));
|
|
|
|
if (!fSyntaxValid)
|
|
{
|
|
::FusionpLogInvalidAttributeValueParseError(
|
|
m_ParseContext.SourceFile,
|
|
m_ParseContext.SourceFileCch,
|
|
m_ParseContext.LineNumber,
|
|
m_ParseContext.ElementName,
|
|
m_ParseContext.ElementNameCch,
|
|
s_IdentityAttribute_version);
|
|
|
|
ORIGINATE_WIN32_FAILURE_AND_EXIT(InvalidVersionNumber, ERROR_SXS_MANIFEST_PARSE_ERROR);
|
|
}
|
|
}
|
|
|
|
if ((Flags & (eValidateIdentity_VersionNotAllowed | eValidateIdentity_VersionRequired)) != 0)
|
|
{
|
|
if ((Flags & eValidateIdentity_VersionNotAllowed) != 0 && cchTemp != 0)
|
|
{
|
|
fError = true;
|
|
::FusionpDbgPrintEx(
|
|
FUSION_DBG_LEVEL_ERROR,
|
|
"SXS.DLL: Manifest \"%ls\" (line %d) has a version attribute where it may not appear; report to owner of \"%ls\"\n",
|
|
m_ParseContext.SourceFile,
|
|
m_ParseContext.LineNumber,
|
|
m_ParseContext.SourceFile);
|
|
}
|
|
else if ((Flags & eValidateIdentity_VersionRequired) != 0 && cchTemp == 0)
|
|
{
|
|
fError = true;
|
|
::FusionpDbgPrintEx(
|
|
FUSION_DBG_LEVEL_ERROR,
|
|
"SXS.DLL: Manifest \"%ls\" (line %d) is missing version attribute; report to owner of \"%ls\"\n",
|
|
m_ParseContext.SourceFile,
|
|
m_ParseContext.LineNumber,
|
|
m_ParseContext.SourceFile);
|
|
}
|
|
}
|
|
|
|
if (fError)
|
|
{
|
|
::FusionpDbgPrintEx(
|
|
FUSION_DBG_LEVEL_ERROR,
|
|
"SXS.DLL: Manifest \"%ls\" is missing required attribute or contains disallowed attribute; report to owner of \"%ls\"\n",
|
|
m_ParseContext.SourceFile,
|
|
m_ParseContext.SourceFile);
|
|
|
|
ORIGINATE_WIN32_FAILURE_AND_EXIT(InvalidIdentity, ERROR_SXS_MANIFEST_PARSE_ERROR);
|
|
}
|
|
|
|
fSuccess = TRUE;
|
|
Exit:
|
|
return fSuccess;
|
|
}
|
|
|
|
BOOL
|
|
CNodeFactory::ValidateElementAttributes(
|
|
PCSXS_NODE_INFO prgNodes,
|
|
SIZE_T cNodes,
|
|
PCELEMENT_LEGAL_ATTRIBUTE prgAttributes,
|
|
UCHAR cAttributes
|
|
)
|
|
{
|
|
FN_PROLOG_WIN32
|
|
|
|
SIZE_T i;
|
|
UCHAR j;
|
|
UCHAR cRequiredAttributes, cRequiredAttributesFound;
|
|
UCHAR rgRequiredAttributeFoundBitMask[8]; // 8 * 32 = 256
|
|
BOOL fParseFailed = FALSE;
|
|
|
|
PARAMETER_CHECK((cNodes == 0) || (prgNodes != NULL));
|
|
PARAMETER_CHECK((cAttributes == 0) || (prgAttributes != NULL));
|
|
|
|
cRequiredAttributes = 0;
|
|
cRequiredAttributesFound = 0;
|
|
|
|
for (i=0; i<cAttributes; i++)
|
|
if (prgAttributes[i].m_dwFlags & ELEMENT_LEGAL_ATTRIBUTE_FLAG_REQUIRED)
|
|
cRequiredAttributes++;
|
|
|
|
rgRequiredAttributeFoundBitMask[0] = 0;
|
|
rgRequiredAttributeFoundBitMask[1] = 0;
|
|
rgRequiredAttributeFoundBitMask[2] = 0;
|
|
rgRequiredAttributeFoundBitMask[3] = 0;
|
|
rgRequiredAttributeFoundBitMask[4] = 0;
|
|
rgRequiredAttributeFoundBitMask[5] = 0;
|
|
rgRequiredAttributeFoundBitMask[6] = 0;
|
|
rgRequiredAttributeFoundBitMask[7] = 0;
|
|
|
|
for (i=0; i<cNodes; i++)
|
|
{
|
|
if (prgNodes[i].Type == SXS_ATTRIBUTE)
|
|
{
|
|
const SIZE_T cchText = prgNodes[i].cchText;
|
|
const SIZE_T cchNamespace = prgNodes[i].NamespaceStringBuf.Cch();
|
|
const PCWSTR pszText = prgNodes[i].pszText;
|
|
|
|
// Ignore any attributes that start with xml
|
|
if ((cchText >= 3) &&
|
|
((pszText[0] == L'x') || (pszText[0] == L'X')) &&
|
|
((pszText[1] == L'm') || (pszText[1] == L'M')) &&
|
|
((pszText[2] == L'l') || (pszText[2] == L'L')))
|
|
{
|
|
continue;
|
|
}
|
|
if (cchNamespace != 0 )
|
|
{
|
|
continue;
|
|
}
|
|
|
|
for (j=0; j<cAttributes; j++)
|
|
{
|
|
if ((prgAttributes[j].m_pName != NULL) &&
|
|
(cchText == prgAttributes[j].m_pName->NameCch) &&
|
|
(cchNamespace == prgAttributes[j].m_pName->NamespaceCch) &&
|
|
(::FusionpCompareStrings(prgNodes[i].NamespaceStringBuf, cchNamespace, prgAttributes[j].m_pName->Namespace, cchNamespace, false) == 0) &&
|
|
(::FusionpCompareStrings(pszText, cchText, prgAttributes[j].m_pName->Name, cchText, false) == 0))
|
|
{
|
|
if (prgAttributes[j].m_pfnValidator != NULL)
|
|
{
|
|
CSmallStringBuffer buffValue;
|
|
bool fValid = false;
|
|
SIZE_T cb;
|
|
SIZE_T i2;
|
|
|
|
for (i2=i+1; i2<cNodes; i2++)
|
|
{
|
|
if (prgNodes[i2].Type == SXS_PCDATA)
|
|
IFW32FALSE_EXIT(buffValue.Win32Append(prgNodes[i2].pszText, prgNodes[i2].cchText));
|
|
else
|
|
break;
|
|
}
|
|
|
|
IFW32FALSE_EXIT(
|
|
(*prgAttributes[j].m_pfnValidator)(
|
|
prgAttributes[j].m_dwValidatorFlags,
|
|
buffValue,
|
|
fValid,
|
|
0,
|
|
NULL,
|
|
cb));
|
|
|
|
if (!fValid)
|
|
{
|
|
::FusionpLogInvalidAttributeValueParseError(
|
|
m_ParseContext.SourceFile,
|
|
m_ParseContext.SourceFileCch,
|
|
m_ParseContext.LineNumber,
|
|
m_ParseContext.ElementName,
|
|
m_ParseContext.ElementNameCch,
|
|
prgAttributes[j].m_pName->Name,
|
|
prgAttributes[j].m_pName->NameCch);
|
|
|
|
ORIGINATE_WIN32_FAILURE_AND_EXIT(InvalidAttributeValue, ERROR_SXS_MANIFEST_PARSE_ERROR);
|
|
}
|
|
}
|
|
|
|
if (prgAttributes[j].m_dwFlags & ELEMENT_LEGAL_ATTRIBUTE_FLAG_REQUIRED)
|
|
{
|
|
rgRequiredAttributeFoundBitMask[(j / 32)] |= (1 << (j % 32));
|
|
cRequiredAttributesFound++;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (j == cAttributes)
|
|
{
|
|
// We found an illegal attribute!!
|
|
::FusionpLogAttributeNotAllowedParseError(
|
|
m_ParseContext.SourceFile,
|
|
m_ParseContext.SourceFileCch,
|
|
m_ParseContext.LineNumber,
|
|
prgNodes[0].pszText,
|
|
prgNodes[0].cchText,
|
|
prgNodes[i].pszText,
|
|
prgNodes[i].cchText);
|
|
|
|
// We don't just go to exit here because we want to report all the bad attributes and missing attributes...
|
|
fParseFailed = TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (cRequiredAttributesFound != cRequiredAttributes)
|
|
{
|
|
for (j=0; j<cAttributes; j++)
|
|
{
|
|
if (prgAttributes[j].m_dwFlags & ELEMENT_LEGAL_ATTRIBUTE_FLAG_REQUIRED)
|
|
{
|
|
if ((rgRequiredAttributeFoundBitMask[(j / 32)] & (1 << (j % 32))) == 0)
|
|
{
|
|
::FusionpLogRequiredAttributeMissingParseError(
|
|
m_ParseContext.SourceFile,
|
|
m_ParseContext.SourceFileCch,
|
|
m_ParseContext.LineNumber,
|
|
prgNodes[0].pszText,
|
|
prgNodes[0].cchText,
|
|
prgAttributes[j].m_pName->Name,
|
|
prgAttributes[j].m_pName->NameCch);
|
|
|
|
fParseFailed = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (fParseFailed)
|
|
ORIGINATE_WIN32_FAILURE_AND_EXIT(ParseError, ERROR_SXS_MANIFEST_PARSE_ERROR);
|
|
|
|
FN_EPILOG
|
|
}
|
|
|
|
|