366 lines
11 KiB
C++
366 lines
11 KiB
C++
|
/*++
|
||
|
|
||
|
Copyright (c) Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
clrclassinfo.cpp
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
CLR 'surrogate' contributor for Win32-CLR interop assemblies
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Jon Wiswall (jonwis) March, 2002 (heavily borrowed from comclass.cpp)
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "stdinc.h"
|
||
|
#include <windows.h>
|
||
|
#include "sxsp.h"
|
||
|
|
||
|
DECLARE_STD_ATTRIBUTE_NAME_DESCRIPTOR(clsid);
|
||
|
DECLARE_STD_ATTRIBUTE_NAME_DESCRIPTOR(name);
|
||
|
DECLARE_STD_ATTRIBUTE_NAME_DESCRIPTOR(runtimeVersion);
|
||
|
|
||
|
#define ALLOCATE_BUFFER_SPACE(_bytesNeeded, _bufferCursor, _bytesLeft, _bytesWritten, _typeName, _ptr) \
|
||
|
do { \
|
||
|
if (_bytesLeft < (_bytesNeeded)) \
|
||
|
ORIGINATE_WIN32_FAILURE_AND_EXIT(NoRoom, ERROR_INSUFFICIENT_BUFFER); \
|
||
|
_bytesLeft -= (_bytesNeeded); \
|
||
|
_bytesWritten += (_bytesNeeded); \
|
||
|
_ptr = (_typeName) _bufferCursor; \
|
||
|
_bufferCursor = (PVOID) (((ULONG_PTR) _bufferCursor) + (_bytesNeeded)); \
|
||
|
} while (0)
|
||
|
|
||
|
#define ALLOCATE_BUFFER_SPACE_TYPE(_typeName, _bufferCursor, _bytesLeft, _bytesWritten, _ptr) \
|
||
|
ALLOCATE_BUFFER_SPACE(sizeof(_typeName), _bufferCursor, _bytesLeft, _bytesWritten, _typeName *, _ptr)
|
||
|
|
||
|
typedef struct _CLR_GLOBAL_CONTEXT *PCLR_GLOBAL_CONTEXT;
|
||
|
typedef struct _CLR_SURROGATE_ENTRY *PCLR_SURROGATE_ENTRY;
|
||
|
|
||
|
typedef struct _CLR_GLOBAL_CONTEXT
|
||
|
{
|
||
|
_CLR_GLOBAL_CONTEXT() { }
|
||
|
|
||
|
CSmallStringBuffer m_FileNameBuffer;
|
||
|
PCLR_SURROGATE_ENTRY m_SurrogateList;
|
||
|
ULONG m_SurrogateListCount;
|
||
|
|
||
|
private:
|
||
|
_CLR_GLOBAL_CONTEXT(const _CLR_GLOBAL_CONTEXT &);
|
||
|
void operator =(const _CLR_GLOBAL_CONTEXT &);
|
||
|
} CLR_GLOBAL_CONTEXT;
|
||
|
|
||
|
typedef struct _CLR_SURROGATE_ENTRY
|
||
|
{
|
||
|
public:
|
||
|
_CLR_SURROGATE_ENTRY() { }
|
||
|
|
||
|
PCLR_SURROGATE_ENTRY m_Next;
|
||
|
PCLR_GLOBAL_CONTEXT m_GlobalContext;
|
||
|
GUID m_ReferenceClsid;
|
||
|
CSmallStringBuffer m_TypeName;
|
||
|
CSmallStringBuffer m_RuntimeVersion;
|
||
|
|
||
|
private:
|
||
|
_CLR_SURROGATE_ENTRY(const _CLR_SURROGATE_ENTRY &);
|
||
|
void operator =(const _CLR_SURROGATE_ENTRY &);
|
||
|
} CLR_SURROGATE_ENTRY;
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
SxspClrSurrogateAddSurrogate(
|
||
|
PACTCTXCTB_CBELEMENTPARSED SurrogateParsed,
|
||
|
PCLR_GLOBAL_CONTEXT pGlobalContext,
|
||
|
PGUID_SECTION_GENERATION_CONTEXT pGsGenCtx
|
||
|
);
|
||
|
|
||
|
|
||
|
VOID
|
||
|
WINAPI
|
||
|
SxspClrInteropContributorCallback(
|
||
|
PACTCTXCTB_CALLBACK_DATA Data
|
||
|
)
|
||
|
{
|
||
|
FN_TRACE();
|
||
|
|
||
|
PGUID_SECTION_GENERATION_CONTEXT GSGenContext = (PGUID_SECTION_GENERATION_CONTEXT) Data->Header.ActCtxGenContext;
|
||
|
PCLR_GLOBAL_CONTEXT ClrGlobalContext = NULL;
|
||
|
|
||
|
if (GSGenContext != NULL)
|
||
|
ClrGlobalContext = (PCLR_GLOBAL_CONTEXT)SxsGetGuidSectionGenerationContextCallbackContext(GSGenContext);
|
||
|
|
||
|
switch (Data->Header.Reason)
|
||
|
{
|
||
|
case ACTCTXCTB_CBREASON_GETSECTIONDATA:
|
||
|
Data->GetSectionData.Success = FALSE;
|
||
|
INTERNAL_ERROR_CHECK(GSGenContext != NULL);
|
||
|
INTERNAL_ERROR_CHECK(Data->Header.ManifestOperation == MANIFEST_OPERATION_GENERATE_ACTIVATION_CONTEXT);
|
||
|
IFW32FALSE_EXIT(::SxsGetGuidSectionGenerationContextSectionData(GSGenContext, Data->GetSectionData.SectionSize, Data->GetSectionData.SectionDataStart, NULL));
|
||
|
Data->GetSectionData.Success = TRUE;
|
||
|
break;
|
||
|
|
||
|
case ACTCTXCTB_CBREASON_ACTCTXGENBEGINNING:
|
||
|
Data->GenBeginning.Success = FALSE;
|
||
|
|
||
|
INTERNAL_ERROR_CHECK(ClrGlobalContext == NULL);
|
||
|
INTERNAL_ERROR_CHECK(GSGenContext == NULL);
|
||
|
|
||
|
IFALLOCFAILED_EXIT(ClrGlobalContext = FUSION_NEW_SINGLETON(CLR_GLOBAL_CONTEXT));
|
||
|
|
||
|
ClrGlobalContext->m_SurrogateList = NULL;
|
||
|
ClrGlobalContext->m_SurrogateListCount = 0;
|
||
|
|
||
|
IFW32FALSE_EXIT(
|
||
|
::SxsInitGuidSectionGenerationContext(
|
||
|
&GSGenContext,
|
||
|
ACTIVATION_CONTEXT_DATA_CLR_SURROGATE_FORMAT_WHISTLER,
|
||
|
&::SxspClrInteropGuidSectionGenerationCallback,
|
||
|
ClrGlobalContext));
|
||
|
|
||
|
ClrGlobalContext = NULL;
|
||
|
|
||
|
Data->Header.ActCtxGenContext = GSGenContext;
|
||
|
Data->GenBeginning.Success = TRUE;
|
||
|
|
||
|
break;
|
||
|
|
||
|
case ACTCTXCTB_CBREASON_ACTCTXGENENDED:
|
||
|
if (GSGenContext != NULL)
|
||
|
::SxsDestroyGuidSectionGenerationContext(GSGenContext);
|
||
|
|
||
|
FUSION_DELETE_SINGLETON(ClrGlobalContext);
|
||
|
ClrGlobalContext = NULL;
|
||
|
break;
|
||
|
|
||
|
case ACTCTXCTB_CBREASON_ALLPARSINGDONE:
|
||
|
Data->AllParsingDone.Success = FALSE;
|
||
|
|
||
|
#if 0
|
||
|
if (GSGenContext != NULL)
|
||
|
IFW32FALSE_EXIT(::SxsDoneModifyingGuidSectionGenerationContext(GSGenContext));
|
||
|
#endif
|
||
|
|
||
|
Data->AllParsingDone.Success = TRUE;
|
||
|
break;
|
||
|
|
||
|
case ACTCTXCTB_CBREASON_GETSECTIONSIZE:
|
||
|
Data->GetSectionSize.Success = FALSE;
|
||
|
INTERNAL_ERROR_CHECK(Data->Header.ManifestOperation == MANIFEST_OPERATION_GENERATE_ACTIVATION_CONTEXT);
|
||
|
INTERNAL_ERROR_CHECK(GSGenContext != NULL);
|
||
|
IFW32FALSE_EXIT(::SxsGetGuidSectionGenerationContextSectionSize(GSGenContext, &Data->GetSectionSize.SectionSize));
|
||
|
Data->GetSectionSize.Success = TRUE;
|
||
|
break;
|
||
|
|
||
|
case ACTCTXCTB_CBREASON_ELEMENTPARSED:
|
||
|
{
|
||
|
ULONG MappedValue = 0;
|
||
|
bool fFound = false;
|
||
|
|
||
|
enum MappedValues {
|
||
|
eClrSurrogate,
|
||
|
};
|
||
|
|
||
|
static const WCHAR ELEMENT_PATH_BUILTIN_CLR_SURROGATE[] = L"urn:schemas-microsoft-com:asm.v1^assembly!urn:schemas-microsoft-com:asm.v1^clrSurrogate";
|
||
|
|
||
|
static const ELEMENT_PATH_MAP_ENTRY s_rgEntries[] =
|
||
|
{
|
||
|
{ 2, ELEMENT_PATH_BUILTIN_CLR_SURROGATE, NUMBER_OF(ELEMENT_PATH_BUILTIN_CLR_SURROGATE)-1, eClrSurrogate },
|
||
|
};
|
||
|
|
||
|
Data->ElementParsed.Success = FALSE;
|
||
|
IFW32FALSE_EXIT(::SxspProcessElementPathMap(
|
||
|
Data->ElementParsed.ParseContext,
|
||
|
s_rgEntries,
|
||
|
NUMBER_OF(s_rgEntries),
|
||
|
MappedValue,
|
||
|
fFound));
|
||
|
|
||
|
if (!fFound)
|
||
|
{
|
||
|
Data->ElementParsed.Success = TRUE;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
switch (MappedValue) {
|
||
|
case eClrSurrogate:
|
||
|
if (SxspClrSurrogateAddSurrogate(&Data->ElementParsed, ClrGlobalContext, GSGenContext))
|
||
|
Data->ElementParsed.Success = TRUE;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
FN_EPILOG
|
||
|
}
|
||
|
|
||
|
BOOL
|
||
|
SxspClrSurrogateAddSurrogate(
|
||
|
PACTCTXCTB_CBELEMENTPARSED SurrogateParsed,
|
||
|
PCLR_GLOBAL_CONTEXT pGlobalContext,
|
||
|
PGUID_SECTION_GENERATION_CONTEXT pGsGenCtx
|
||
|
)
|
||
|
{
|
||
|
FN_PROLOG_WIN32;
|
||
|
CSmallStringBuffer RuntimeVersionBuffer;
|
||
|
CSmallStringBuffer SurrogateClassNameBuffer;
|
||
|
CSmallStringBuffer ClsidBuffer;
|
||
|
GUID SurrogateIdent = GUID_NULL;
|
||
|
bool fFound = false;
|
||
|
SIZE_T cbWritten;
|
||
|
PCLR_SURROGATE_ENTRY Entry;
|
||
|
bool fFileContextSelfAllocated = false;
|
||
|
|
||
|
INTERNAL_ERROR_CHECK(pGlobalContext);
|
||
|
|
||
|
IFW32FALSE_EXIT(::SxspGetAttributeValue(
|
||
|
0,
|
||
|
&s_AttributeName_runtimeVersion,
|
||
|
SurrogateParsed,
|
||
|
fFound,
|
||
|
sizeof(RuntimeVersionBuffer),
|
||
|
&RuntimeVersionBuffer,
|
||
|
cbWritten,
|
||
|
NULL, 0));
|
||
|
|
||
|
IFW32FALSE_EXIT(::SxspGetAttributeValue(
|
||
|
SXSP_GET_ATTRIBUTE_VALUE_FLAG_REQUIRED_ATTRIBUTE,
|
||
|
&s_AttributeName_name,
|
||
|
SurrogateParsed,
|
||
|
fFound,
|
||
|
sizeof(SurrogateClassNameBuffer),
|
||
|
&SurrogateClassNameBuffer,
|
||
|
cbWritten,
|
||
|
NULL, 0));
|
||
|
INTERNAL_ERROR_CHECK(fFound);
|
||
|
|
||
|
IFW32FALSE_EXIT(::SxspGetAttributeValue(
|
||
|
SXSP_GET_ATTRIBUTE_VALUE_FLAG_REQUIRED_ATTRIBUTE,
|
||
|
&s_AttributeName_clsid,
|
||
|
SurrogateParsed,
|
||
|
fFound,
|
||
|
sizeof(ClsidBuffer),
|
||
|
&ClsidBuffer,
|
||
|
cbWritten,
|
||
|
NULL, 0));
|
||
|
INTERNAL_ERROR_CHECK(fFound);
|
||
|
|
||
|
IFW32FALSE_EXIT(SxspParseGUID(ClsidBuffer, ClsidBuffer.Cch(), SurrogateIdent));
|
||
|
|
||
|
//
|
||
|
// If we were doing something other than generating an actctx, then we can leap out.
|
||
|
//
|
||
|
if (SurrogateParsed->Header.ManifestOperation != MANIFEST_OPERATION_GENERATE_ACTIVATION_CONTEXT)
|
||
|
FN_SUCCESSFUL_EXIT();
|
||
|
|
||
|
IFALLOCFAILED_EXIT(Entry = FUSION_NEW_SINGLETON(CLR_SURROGATE_ENTRY));
|
||
|
|
||
|
Entry->m_ReferenceClsid = SurrogateIdent;
|
||
|
IFW32FALSE_EXIT(Entry->m_RuntimeVersion.Win32Assign(RuntimeVersionBuffer));
|
||
|
IFW32FALSE_EXIT(Entry->m_TypeName.Win32Assign(SurrogateClassNameBuffer));
|
||
|
|
||
|
IFW32FALSE_EXIT(::SxsAddGuidToGuidSectionGenerationContext(
|
||
|
pGsGenCtx,
|
||
|
&SurrogateIdent,
|
||
|
Entry,
|
||
|
SurrogateParsed->AssemblyContext->AssemblyRosterIndex,
|
||
|
ERROR_SXS_DUPLICATE_CLSID));
|
||
|
|
||
|
Entry->m_Next = pGlobalContext->m_SurrogateList;
|
||
|
pGlobalContext->m_SurrogateList = Entry->m_Next;
|
||
|
pGlobalContext->m_SurrogateListCount++;
|
||
|
|
||
|
FN_EPILOG;
|
||
|
}
|
||
|
|
||
|
BOOL WINAPI
|
||
|
SxspClrInteropGuidSectionGenerationCallback(
|
||
|
PVOID Context,
|
||
|
ULONG Reason,
|
||
|
PVOID CallbackData
|
||
|
)
|
||
|
{
|
||
|
FN_PROLOG_WIN32
|
||
|
|
||
|
PCLR_GLOBAL_CONTEXT ClrGlobalContext = (PCLR_GLOBAL_CONTEXT) Context;
|
||
|
INTERNAL_ERROR_CHECK(CallbackData != NULL);
|
||
|
|
||
|
switch (Reason)
|
||
|
{
|
||
|
case GUID_SECTION_GENERATION_CONTEXT_CALLBACK_REASON_ENTRYDELETED:
|
||
|
{
|
||
|
INTERNAL_ERROR_CHECK( ClrGlobalContext != NULL );
|
||
|
|
||
|
PGUID_SECTION_GENERATION_CONTEXT_CBDATA_ENTRYDELETED CBData =
|
||
|
(PGUID_SECTION_GENERATION_CONTEXT_CBDATA_ENTRYDELETED) CallbackData;
|
||
|
PCLR_SURROGATE_ENTRY Entry = (PCLR_SURROGATE_ENTRY) CBData->DataContext;
|
||
|
|
||
|
if (Entry != NULL)
|
||
|
{
|
||
|
FUSION_DELETE_SINGLETON(Entry);
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case GUID_SECTION_GENERATION_CONTEXT_CALLBACK_REASON_GETDATASIZE:
|
||
|
{
|
||
|
PGUID_SECTION_GENERATION_CONTEXT_CBDATA_GETDATASIZE CBData =
|
||
|
(PGUID_SECTION_GENERATION_CONTEXT_CBDATA_GETDATASIZE) CallbackData;
|
||
|
PCLR_SURROGATE_ENTRY Entry = (PCLR_SURROGATE_ENTRY) CBData->DataContext;
|
||
|
|
||
|
INTERNAL_ERROR_CHECK(!Entry->m_TypeName.IsEmpty());
|
||
|
|
||
|
CBData->DataSize = sizeof(ACTIVATION_CONTEXT_DATA_CLR_SURROGATE);
|
||
|
CBData->DataSize += (Entry->m_RuntimeVersion.Cch() + 1) * sizeof(WCHAR);
|
||
|
CBData->DataSize += (Entry->m_TypeName.Cch() + 1) * sizeof(WCHAR);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
case GUID_SECTION_GENERATION_CONTEXT_CALLBACK_REASON_GETDATA:
|
||
|
{
|
||
|
PGUID_SECTION_GENERATION_CONTEXT_CBDATA_GETDATA CBData =
|
||
|
(PGUID_SECTION_GENERATION_CONTEXT_CBDATA_GETDATA) CallbackData;
|
||
|
PCLR_SURROGATE_ENTRY Entry = (PCLR_SURROGATE_ENTRY) CBData->DataContext;
|
||
|
PACTIVATION_CONTEXT_DATA_CLR_SURROGATE Info;
|
||
|
PVOID Cursor = CBData->Buffer;
|
||
|
|
||
|
SIZE_T BytesLeft = CBData->BufferSize;
|
||
|
SIZE_T BytesWritten = 0;
|
||
|
|
||
|
ALLOCATE_BUFFER_SPACE_TYPE(ACTIVATION_CONTEXT_DATA_CLR_SURROGATE, Cursor, BytesLeft, BytesWritten, Info);
|
||
|
|
||
|
Info->Size = sizeof(ACTIVATION_CONTEXT_DATA_CLR_SURROGATE);
|
||
|
Info->Flags = 0;
|
||
|
Info->SurrogateIdent = Entry->m_ReferenceClsid;
|
||
|
|
||
|
IFW32FALSE_EXIT(Entry->m_RuntimeVersion.Win32CopyIntoBuffer(
|
||
|
(PWSTR*)&Cursor,
|
||
|
&BytesLeft,
|
||
|
&BytesWritten,
|
||
|
Info,
|
||
|
&Info->VersionOffset,
|
||
|
&Info->VersionLength));
|
||
|
|
||
|
IFW32FALSE_EXIT(Entry->m_TypeName.Win32CopyIntoBuffer(
|
||
|
(PWSTR*)&Cursor,
|
||
|
&BytesLeft,
|
||
|
&BytesWritten,
|
||
|
Info,
|
||
|
&Info->TypeNameOffset,
|
||
|
&Info->TypeNameLength));
|
||
|
|
||
|
CBData->BytesWritten = BytesWritten;
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
FN_EPILOG
|
||
|
}
|
||
|
|