333 lines
12 KiB
C++
333 lines
12 KiB
C++
#include "stdinc.h"
|
|
#include "Sxsp.h"
|
|
|
|
DECLARE_STD_ATTRIBUTE_NAME_DESCRIPTOR(name);
|
|
DECLARE_STD_ATTRIBUTE_NAME_DESCRIPTOR(versioned);
|
|
|
|
typedef struct _WINDOW_CLASS_CONTEXT
|
|
{
|
|
_WINDOW_CLASS_CONTEXT() { }
|
|
|
|
CStringBuffer m_FileNameBuffer;
|
|
bool m_Versioned;
|
|
private:
|
|
_WINDOW_CLASS_CONTEXT(const _WINDOW_CLASS_CONTEXT &);
|
|
void operator =(const _WINDOW_CLASS_CONTEXT &);
|
|
|
|
} WINDOW_CLASS_CONTEXT, *PWINDOW_CLASS_CONTEXT;
|
|
|
|
typedef struct _WINDOW_CLASS_ENTRY
|
|
{
|
|
_WINDOW_CLASS_ENTRY() { }
|
|
|
|
CStringBuffer m_FileNameBuffer;
|
|
CStringBuffer m_VersionSpecificWindowClassNameBuffer;
|
|
|
|
private:
|
|
_WINDOW_CLASS_ENTRY(const _WINDOW_CLASS_ENTRY &);
|
|
void operator =(const _WINDOW_CLASS_ENTRY &);
|
|
} WINDOW_CLASS_ENTRY, *PWINDOW_CLASS_ENTRY;
|
|
|
|
VOID
|
|
SxspWindowClassRedirectionContributorCallback(
|
|
PACTCTXCTB_CALLBACK_DATA Data
|
|
)
|
|
{
|
|
FN_TRACE();
|
|
PSTRING_SECTION_GENERATION_CONTEXT SSGenContext = (PSTRING_SECTION_GENERATION_CONTEXT) Data->Header.ActCtxGenContext;
|
|
PWINDOW_CLASS_CONTEXT WindowClassContext = NULL;
|
|
PWINDOW_CLASS_ENTRY Entry = NULL; // deleted on exit if not NULL
|
|
|
|
if (SSGenContext != NULL)
|
|
WindowClassContext = (PWINDOW_CLASS_CONTEXT) ::SxsGetStringSectionGenerationContextCallbackContext(SSGenContext);
|
|
|
|
switch (Data->Header.Reason)
|
|
{
|
|
case ACTCTXCTB_CBREASON_ACTCTXGENBEGINNING:
|
|
{
|
|
Data->GenBeginning.Success = FALSE;
|
|
|
|
INTERNAL_ERROR_CHECK(WindowClassContext == NULL);
|
|
|
|
if (Data->Header.ManifestOperation == MANIFEST_OPERATION_GENERATE_ACTIVATION_CONTEXT)
|
|
{
|
|
IFALLOCFAILED_EXIT(WindowClassContext = new WINDOW_CLASS_CONTEXT);
|
|
|
|
if (!::SxsInitStringSectionGenerationContext(
|
|
&SSGenContext,
|
|
ACTIVATION_CONTEXT_DATA_WINDOW_CLASS_REDIRECTION_FORMAT_WHISTLER,
|
|
TRUE,
|
|
&::SxspWindowClassRedirectionStringSectionGenerationCallback,
|
|
WindowClassContext))
|
|
{
|
|
FUSION_DELETE_SINGLETON(WindowClassContext);
|
|
WindowClassContext = NULL;
|
|
goto Exit;
|
|
}
|
|
|
|
Data->Header.ActCtxGenContext = SSGenContext;
|
|
}
|
|
|
|
Data->GenBeginning.Success = TRUE;
|
|
break;
|
|
}
|
|
|
|
case ACTCTXCTB_CBREASON_ACTCTXGENENDED:
|
|
if (SSGenContext != NULL)
|
|
::SxsDestroyStringSectionGenerationContext(SSGenContext);
|
|
FUSION_DELETE_SINGLETON(WindowClassContext);
|
|
break;
|
|
|
|
case ACTCTXCTB_CBREASON_ALLPARSINGDONE:
|
|
{
|
|
Data->AllParsingDone.Success = FALSE;
|
|
if (SSGenContext != NULL)
|
|
IFW32FALSE_EXIT(::SxsDoneModifyingStringSectionGenerationContext(SSGenContext));
|
|
Data->AllParsingDone.Success = TRUE;
|
|
break;
|
|
}
|
|
|
|
case ACTCTXCTB_CBREASON_GETSECTIONSIZE:
|
|
{
|
|
Data->GetSectionSize.Success = FALSE;
|
|
INTERNAL_ERROR_CHECK( SSGenContext );
|
|
IFW32FALSE_EXIT(::SxsGetStringSectionGenerationContextSectionSize(SSGenContext, &Data->GetSectionSize.SectionSize));
|
|
Data->GetSectionSize.Success = TRUE;
|
|
break;
|
|
}
|
|
|
|
case ACTCTXCTB_CBREASON_PCDATAPARSED:
|
|
{
|
|
Data->PCDATAParsed.Success = FALSE;
|
|
|
|
if ((Data->Header.ManifestOperation == MANIFEST_OPERATION_GENERATE_ACTIVATION_CONTEXT) &&
|
|
(Data->PCDATAParsed.ParseContext->XMLElementDepth == 3) &&
|
|
(::FusionpCompareStrings(
|
|
Data->PCDATAParsed.ParseContext->ElementPath,
|
|
Data->PCDATAParsed.ParseContext->ElementPathCch,
|
|
L"urn:schemas-microsoft-com:asm.v1^assembly!urn:schemas-microsoft-com:asm.v1^file!urn:schemas-microsoft-com:asm.v1^windowClass",
|
|
NUMBER_OF(L"urn:schemas-microsoft-com:asm.v1^assembly!urn:schemas-microsoft-com:asm.v1^file!urn:schemas-microsoft-com:asm.v1^windowClass") - 1,
|
|
false) == 0))
|
|
{
|
|
SIZE_T VersionCch;
|
|
PCWSTR pwszVersion = NULL;
|
|
|
|
INTERNAL_ERROR_CHECK2(
|
|
WindowClassContext != NULL,
|
|
"Window class context NULL while processing windowClass element");
|
|
|
|
IFALLOCFAILED_EXIT(Entry = new WINDOW_CLASS_ENTRY);
|
|
|
|
IFW32FALSE_EXIT(Entry->m_FileNameBuffer.Win32Assign(WindowClassContext->m_FileNameBuffer));
|
|
|
|
IFW32FALSE_EXIT(::SxspGetAssemblyIdentityAttributeValue(0, Data->ElementParsed.AssemblyContext->AssemblyIdentity, &s_IdentityAttribute_version, &pwszVersion, &VersionCch));
|
|
|
|
if (WindowClassContext->m_Versioned)
|
|
{
|
|
IFW32FALSE_EXIT(Entry->m_VersionSpecificWindowClassNameBuffer.Win32Assign(pwszVersion, VersionCch));
|
|
IFW32FALSE_EXIT(Entry->m_VersionSpecificWindowClassNameBuffer.Win32Append(L"!", 1));
|
|
}
|
|
|
|
IFW32FALSE_EXIT(Entry->m_VersionSpecificWindowClassNameBuffer.Win32Append(Data->PCDATAParsed.Text, Data->PCDATAParsed.TextCch));
|
|
|
|
IFW32FALSE_EXIT(
|
|
::SxsAddStringToStringSectionGenerationContext(
|
|
(PSTRING_SECTION_GENERATION_CONTEXT) Data->Header.ActCtxGenContext,
|
|
Data->PCDATAParsed.Text,
|
|
Data->PCDATAParsed.TextCch,
|
|
Entry,
|
|
Data->PCDATAParsed.AssemblyContext->AssemblyRosterIndex,
|
|
ERROR_SXS_DUPLICATE_WINDOWCLASS_NAME));
|
|
|
|
// Prevent deletion in exit path...
|
|
Entry = NULL;
|
|
}
|
|
|
|
// Everything's groovy!
|
|
Data->PCDATAParsed.Success = TRUE;
|
|
break;
|
|
}
|
|
|
|
|
|
case ACTCTXCTB_CBREASON_ELEMENTPARSED:
|
|
{
|
|
Data->ElementParsed.Success = FALSE;
|
|
|
|
if ((Data->ElementParsed.ParseContext->XMLElementDepth == 2) &&
|
|
(::FusionpCompareStrings(
|
|
Data->ElementParsed.ParseContext->ElementPath,
|
|
Data->ElementParsed.ParseContext->ElementPathCch,
|
|
L"urn:schemas-microsoft-com:asm.v1^assembly!urn:schemas-microsoft-com:asm.v1^file",
|
|
NUMBER_OF(L"urn:schemas-microsoft-com:asm.v1^assembly!urn:schemas-microsoft-com:asm.v1^file") - 1,
|
|
false) == 0))
|
|
{
|
|
CStringBuffer FileNameBuffer;
|
|
bool fFound = false;
|
|
SIZE_T cb;
|
|
|
|
// capture the name of the file we're parsing...
|
|
|
|
IFW32FALSE_EXIT(
|
|
::SxspGetAttributeValue(
|
|
0,
|
|
&s_AttributeName_name,
|
|
&Data->ElementParsed,
|
|
fFound,
|
|
sizeof(FileNameBuffer),
|
|
&FileNameBuffer,
|
|
cb,
|
|
NULL,
|
|
0));
|
|
|
|
// If there's no NAME attribute, someone else will puke; we'll handle it
|
|
// gracefully.
|
|
if (fFound)
|
|
{
|
|
if (Data->Header.ManifestOperation == MANIFEST_OPERATION_GENERATE_ACTIVATION_CONTEXT)
|
|
{
|
|
INTERNAL_ERROR_CHECK(WindowClassContext != NULL);
|
|
IFW32FALSE_EXIT(WindowClassContext->m_FileNameBuffer.Win32Assign(FileNameBuffer));
|
|
}
|
|
}
|
|
}
|
|
else if ((Data->ElementParsed.ParseContext->XMLElementDepth == 3) &&
|
|
(::FusionpCompareStrings(
|
|
Data->ElementParsed.ParseContext->ElementPath,
|
|
Data->ElementParsed.ParseContext->ElementPathCch,
|
|
L"urn:schemas-microsoft-com:asm.v1^assembly!urn:schemas-microsoft-com:asm.v1^file!urn:schemas-microsoft-com:asm.v1^windowClass",
|
|
NUMBER_OF(L"urn:schemas-microsoft-com:asm.v1^assembly!urn:schemas-microsoft-com:asm.v1^file!urn:schemas-microsoft-com:asm.v1^windowClass") - 1,
|
|
false) == 0))
|
|
{
|
|
bool fVersioned = true;
|
|
bool fFound = false;
|
|
SIZE_T cbBytesWritten;
|
|
|
|
IFW32FALSE_EXIT(
|
|
::SxspGetAttributeValue(
|
|
0,
|
|
&s_AttributeName_versioned,
|
|
&Data->ElementParsed,
|
|
fFound,
|
|
sizeof(fVersioned),
|
|
&fVersioned,
|
|
cbBytesWritten,
|
|
&::SxspValidateBoolAttribute,
|
|
0));
|
|
|
|
if (!fFound)
|
|
fVersioned = true;
|
|
|
|
if (Data->Header.ManifestOperation == MANIFEST_OPERATION_GENERATE_ACTIVATION_CONTEXT)
|
|
{
|
|
INTERNAL_ERROR_CHECK(WindowClassContext != NULL);
|
|
WindowClassContext->m_Versioned = fVersioned;
|
|
}
|
|
|
|
}
|
|
|
|
// Everything's groovy!
|
|
Data->ElementParsed.Success = TRUE;
|
|
break;
|
|
}
|
|
|
|
case ACTCTXCTB_CBREASON_GETSECTIONDATA:
|
|
Data->GetSectionData.Success = FALSE;
|
|
INTERNAL_ERROR_CHECK(SSGenContext != NULL);
|
|
IFW32FALSE_EXIT(
|
|
::SxsGetStringSectionGenerationContextSectionData(
|
|
SSGenContext,
|
|
Data->GetSectionData.SectionSize,
|
|
Data->GetSectionData.SectionDataStart,
|
|
NULL));
|
|
Data->GetSectionData.Success = TRUE;
|
|
break;
|
|
}
|
|
|
|
Exit:
|
|
;
|
|
}
|
|
|
|
BOOL
|
|
SxspWindowClassRedirectionStringSectionGenerationCallback(
|
|
PVOID Context,
|
|
ULONG Reason,
|
|
PVOID CallbackData
|
|
)
|
|
{
|
|
BOOL fSuccess = FALSE;
|
|
FN_TRACE_WIN32(fSuccess);
|
|
|
|
switch (Reason)
|
|
{
|
|
case STRING_SECTION_GENERATION_CONTEXT_CALLBACK_REASON_ENTRYDELETED:
|
|
{
|
|
PSTRING_SECTION_GENERATION_CONTEXT_CBDATA_ENTRYDELETED CBData =
|
|
(PSTRING_SECTION_GENERATION_CONTEXT_CBDATA_ENTRYDELETED) CallbackData;
|
|
PWINDOW_CLASS_ENTRY Entry = (PWINDOW_CLASS_ENTRY) CBData->DataContext;
|
|
FUSION_DELETE_SINGLETON(Entry);
|
|
break;
|
|
}
|
|
|
|
case STRING_SECTION_GENERATION_CONTEXT_CALLBACK_REASON_GETDATASIZE:
|
|
{
|
|
PSTRING_SECTION_GENERATION_CONTEXT_CBDATA_GETDATASIZE CBData =
|
|
(PSTRING_SECTION_GENERATION_CONTEXT_CBDATA_GETDATASIZE) CallbackData;
|
|
PWINDOW_CLASS_ENTRY Entry = (PWINDOW_CLASS_ENTRY) CBData->DataContext;
|
|
|
|
CBData->DataSize = sizeof(ACTIVATION_CONTEXT_DATA_WINDOW_CLASS_REDIRECTION);
|
|
CBData->DataSize += ((Entry->m_FileNameBuffer.Cch() + 1 +
|
|
Entry->m_VersionSpecificWindowClassNameBuffer.Cch() + 1) * sizeof(WCHAR));
|
|
break;
|
|
}
|
|
|
|
case STRING_SECTION_GENERATION_CONTEXT_CALLBACK_REASON_GETDATA:
|
|
{
|
|
PSTRING_SECTION_GENERATION_CONTEXT_CBDATA_GETDATA CBData =
|
|
(PSTRING_SECTION_GENERATION_CONTEXT_CBDATA_GETDATA) CallbackData;
|
|
PWINDOW_CLASS_ENTRY Entry = (PWINDOW_CLASS_ENTRY) CBData->DataContext;
|
|
PACTIVATION_CONTEXT_DATA_WINDOW_CLASS_REDIRECTION Info;
|
|
|
|
SIZE_T BytesLeft = CBData->BufferSize;
|
|
SIZE_T BytesWritten = 0;
|
|
PWSTR Cursor;
|
|
|
|
Info = (PACTIVATION_CONTEXT_DATA_WINDOW_CLASS_REDIRECTION) CBData->Buffer;
|
|
Cursor = (PWSTR) (Info + 1);
|
|
|
|
if (BytesLeft < sizeof(ACTIVATION_CONTEXT_DATA_WINDOW_CLASS_REDIRECTION))
|
|
{
|
|
::FusionpSetLastWin32Error(ERROR_INSUFFICIENT_BUFFER);
|
|
goto Exit;
|
|
}
|
|
|
|
BytesWritten += sizeof(ACTIVATION_CONTEXT_DATA_WINDOW_CLASS_REDIRECTION);
|
|
BytesLeft -= sizeof(ACTIVATION_CONTEXT_DATA_WINDOW_CLASS_REDIRECTION);
|
|
|
|
Info->Size = sizeof(ACTIVATION_CONTEXT_DATA_WINDOW_CLASS_REDIRECTION);
|
|
Info->Flags = 0;
|
|
|
|
IFW32FALSE_EXIT(Entry->m_VersionSpecificWindowClassNameBuffer.Win32CopyIntoBuffer(
|
|
&Cursor,
|
|
&BytesLeft,
|
|
&BytesWritten,
|
|
Info,
|
|
&Info->VersionSpecificClassNameOffset,
|
|
&Info->VersionSpecificClassNameLength));
|
|
|
|
IFW32FALSE_EXIT(Entry->m_FileNameBuffer.Win32CopyIntoBuffer(
|
|
&Cursor,
|
|
&BytesLeft,
|
|
&BytesWritten,
|
|
CBData->SectionHeader,
|
|
&Info->DllNameOffset,
|
|
&Info->DllNameLength));
|
|
|
|
CBData->BytesWritten = BytesWritten;
|
|
}
|
|
}
|
|
|
|
fSuccess = TRUE;
|
|
Exit:
|
|
return fSuccess;
|
|
}
|