694 lines
22 KiB
C++
694 lines
22 KiB
C++
|
#include "stdinc.h"
|
||
|
|
||
|
|
||
|
typedef CFusionArray<BYTE> CStackBackingBuffer;
|
||
|
|
||
|
#define WRITE_INTO_BUFFER(cursor, target, length, source, leftover) \
|
||
|
(target) = (cursor); \
|
||
|
RtlCopyMemory(cursor, source, length); \
|
||
|
leftover -= (length); \
|
||
|
INTERNAL_ERROR_CHECK((length % sizeof(WCHAR) == 0)); \
|
||
|
(cursor) = (PWSTR)(((ULONG_PTR)(cursor)) + length); \
|
||
|
*(cursor)++ = UNICODE_NULL;
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
SxspLookupAssemblyIdentityInActCtx(
|
||
|
HANDLE hActCtx,
|
||
|
ULONG ulRosterIndex,
|
||
|
CStringBuffer &TargetString
|
||
|
)
|
||
|
{
|
||
|
FN_PROLOG_WIN32;
|
||
|
|
||
|
SIZE_T cbRequired = 0;
|
||
|
bool fMoreSpaceRequired = false;
|
||
|
CStackBackingBuffer TargetRegion;
|
||
|
PCACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION pDetailedInfo = NULL;
|
||
|
|
||
|
TargetString.Clear();
|
||
|
|
||
|
IFW32FALSE_EXIT_UNLESS2(
|
||
|
QueryActCtxW(
|
||
|
0,
|
||
|
hActCtx,
|
||
|
(PVOID)&ulRosterIndex,
|
||
|
AssemblyDetailedInformationInActivationContext,
|
||
|
TargetRegion.GetArrayPtr(),
|
||
|
TargetRegion.GetSize(),
|
||
|
&cbRequired),
|
||
|
LIST_1(ERROR_INSUFFICIENT_BUFFER),
|
||
|
fMoreSpaceRequired);
|
||
|
|
||
|
if (fMoreSpaceRequired)
|
||
|
{
|
||
|
IFW32FALSE_EXIT(TargetRegion.Win32SetSize(cbRequired, CStackBackingBuffer::eSetSizeModeExact));
|
||
|
|
||
|
IFW32FALSE_EXIT(
|
||
|
QueryActCtxW(
|
||
|
0,
|
||
|
hActCtx,
|
||
|
(PVOID)&ulRosterIndex,
|
||
|
AssemblyDetailedInformationInActivationContext,
|
||
|
TargetRegion.GetArrayPtr(),
|
||
|
TargetRegion.GetSize(),
|
||
|
&cbRequired));
|
||
|
}
|
||
|
|
||
|
pDetailedInfo = (PCACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION)TargetRegion.GetArrayPtr();
|
||
|
IFW32FALSE_EXIT(TargetString.Win32Assign(
|
||
|
pDetailedInfo->lpAssemblyEncodedAssemblyIdentity,
|
||
|
pDetailedInfo->ulEncodedAssemblyIdentityLength / sizeof(WCHAR)));
|
||
|
|
||
|
FN_EPILOG;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
WINAPI
|
||
|
SxsFindClrClassInformation(
|
||
|
DWORD dwFlags,
|
||
|
PVOID pvSearchData,
|
||
|
HANDLE hActivationContext,
|
||
|
PVOID pvDataBuffer,
|
||
|
SIZE_T cbDataBuffer,
|
||
|
PSIZE_T pcbDataBufferWrittenOrRequired
|
||
|
)
|
||
|
{
|
||
|
FN_PROLOG_WIN32;
|
||
|
|
||
|
SIZE_T cbRequired = 0;
|
||
|
CStringBuffer AssemblyIdentity;
|
||
|
CFusionActCtxScope ActivationScope;
|
||
|
CFusionActCtxHandle UsedHandleDuringSearch;
|
||
|
GUID GuidToSearch;
|
||
|
ACTCTX_SECTION_KEYED_DATA KeyedData = {sizeof(KeyedData)};
|
||
|
PSXS_CLR_CLASS_INFORMATION pOutputStruct = NULL;
|
||
|
PCACTIVATION_CONTEXT_DATA_COM_SERVER_REDIRECTION pComServerRedirect = NULL;
|
||
|
PCACTIVATION_CONTEXT_DATA_COM_SERVER_REDIRECTION_SHIM pClrShim = NULL;
|
||
|
|
||
|
if (pcbDataBufferWrittenOrRequired)
|
||
|
*pcbDataBufferWrittenOrRequired = 0;
|
||
|
|
||
|
PARAMETER_CHECK(pcbDataBufferWrittenOrRequired != NULL);
|
||
|
PARAMETER_CHECK(pvSearchData != NULL);
|
||
|
PARAMETER_CHECK(pvDataBuffer || (cbDataBuffer == 0));
|
||
|
IFINVALID_FLAGS_EXIT_WIN32(dwFlags,
|
||
|
SXS_FIND_CLR_CLASS_SEARCH_PROGID |
|
||
|
SXS_FIND_CLR_CLASS_SEARCH_GUID |
|
||
|
SXS_FIND_CLR_CLASS_ACTIVATE_ACTCTX |
|
||
|
SXS_FIND_CLR_CLASS_GET_IDENTITY |
|
||
|
SXS_FIND_CLR_CLASS_GET_PROGID |
|
||
|
SXS_FIND_CLR_CLASS_GET_RUNTIME_VERSION |
|
||
|
SXS_FIND_CLR_CLASS_GET_TYPE_NAME);
|
||
|
|
||
|
//
|
||
|
// Can't be both... I'm sure there's a logic thing I could do smarter here, but ohwell.
|
||
|
//
|
||
|
if ((dwFlags & SXS_FIND_CLR_CLASS_SEARCH_PROGID) && (dwFlags & SXS_FIND_CLR_CLASS_SEARCH_GUID))
|
||
|
{
|
||
|
ORIGINATE_WIN32_FAILURE_AND_EXIT(CantSearchBothProgidAndGuid, ERROR_INVALID_PARAMETER);
|
||
|
}
|
||
|
//
|
||
|
// But it has to be at least one of these.
|
||
|
//
|
||
|
else if ((dwFlags & (SXS_FIND_CLR_CLASS_SEARCH_PROGID | SXS_FIND_CLR_CLASS_SEARCH_GUID)) == 0)
|
||
|
{
|
||
|
ORIGINATE_WIN32_FAILURE_AND_EXIT(MustHaveAtLeastOneSearchTypeSet, ERROR_INVALID_PARAMETER);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Activate if necessary
|
||
|
//
|
||
|
if (dwFlags & SXS_FIND_CLR_CLASS_ACTIVATE_ACTCTX)
|
||
|
{
|
||
|
IFW32FALSE_EXIT(ActivationScope.Win32Activate(hActivationContext));
|
||
|
AddRefActCtx(hActivationContext);
|
||
|
UsedHandleDuringSearch = hActivationContext;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
IFW32FALSE_EXIT(GetCurrentActCtx(&UsedHandleDuringSearch));
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Aha, they wanted a progid search
|
||
|
//
|
||
|
if (dwFlags & SXS_FIND_CLR_CLASS_SEARCH_PROGID)
|
||
|
{
|
||
|
PCACTIVATION_CONTEXT_DATA_COM_PROGID_REDIRECTION pProgidFound = NULL;
|
||
|
|
||
|
IFW32FALSE_EXIT(
|
||
|
FindActCtxSectionStringW(
|
||
|
0,
|
||
|
NULL,
|
||
|
ACTIVATION_CONTEXT_SECTION_COM_PROGID_REDIRECTION,
|
||
|
(LPCWSTR)pvSearchData,
|
||
|
&KeyedData));
|
||
|
|
||
|
pProgidFound = (PCACTIVATION_CONTEXT_DATA_COM_PROGID_REDIRECTION)KeyedData.lpData;
|
||
|
GuidToSearch = *(LPGUID)(((ULONG_PTR)KeyedData.lpSectionBase) + pProgidFound->ConfiguredClsidOffset);
|
||
|
}
|
||
|
//
|
||
|
// They handed us a GUID instead
|
||
|
//
|
||
|
else if (dwFlags & SXS_FIND_CLR_CLASS_SEARCH_GUID)
|
||
|
{
|
||
|
GuidToSearch = *(LPGUID)pvSearchData;
|
||
|
}
|
||
|
//
|
||
|
// Hmm.. we validated these flags above, how could we possibly get here?
|
||
|
//
|
||
|
else
|
||
|
{
|
||
|
INTERNAL_ERROR_CHECK(FALSE);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Now that we've got the guids, let's look in the GUID clr class table for more information
|
||
|
//
|
||
|
RtlZeroMemory(&KeyedData, sizeof(KeyedData));
|
||
|
KeyedData.cbSize = sizeof(KeyedData);
|
||
|
IFW32FALSE_EXIT(
|
||
|
FindActCtxSectionGuid(
|
||
|
0,
|
||
|
NULL,
|
||
|
ACTIVATION_CONTEXT_SECTION_COM_SERVER_REDIRECTION,
|
||
|
&GuidToSearch,
|
||
|
&KeyedData));
|
||
|
|
||
|
pComServerRedirect = (PCACTIVATION_CONTEXT_DATA_COM_SERVER_REDIRECTION)KeyedData.lpData;
|
||
|
|
||
|
//
|
||
|
// What do we want to do here if you've asked for a CLR class and yet there's no surrogate
|
||
|
// information??
|
||
|
//
|
||
|
if (pComServerRedirect->ShimDataOffset == 0)
|
||
|
{
|
||
|
ORIGINATE_WIN32_FAILURE_AND_EXIT(ThisGuidIsNotAClrClass, ERROR_SXS_KEY_NOT_FOUND);
|
||
|
}
|
||
|
|
||
|
pClrShim = (PCACTIVATION_CONTEXT_DATA_COM_SERVER_REDIRECTION_SHIM)(((ULONG_PTR)pComServerRedirect) + pComServerRedirect->ShimDataOffset);
|
||
|
|
||
|
//
|
||
|
// Now we've got all the stuff we need. Calculate the required size of things.
|
||
|
//
|
||
|
cbRequired = sizeof(SXS_CLR_CLASS_INFORMATION);
|
||
|
|
||
|
if ((dwFlags & SXS_FIND_CLR_CLASS_GET_PROGID) && (pComServerRedirect->ProgIdLength > 0))
|
||
|
cbRequired += pComServerRedirect->ProgIdLength + sizeof(WCHAR);
|
||
|
|
||
|
if (dwFlags & SXS_FIND_CLR_CLASS_GET_IDENTITY)
|
||
|
{
|
||
|
IFW32FALSE_EXIT(
|
||
|
SxspLookupAssemblyIdentityInActCtx(
|
||
|
UsedHandleDuringSearch,
|
||
|
KeyedData.ulAssemblyRosterIndex,
|
||
|
AssemblyIdentity));
|
||
|
|
||
|
if (AssemblyIdentity.Cch() > 0) {
|
||
|
cbRequired += (AssemblyIdentity.Cch() + 1) * sizeof(WCHAR);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ((dwFlags & SXS_FIND_CLR_CLASS_GET_RUNTIME_VERSION) && (pClrShim->ShimVersionLength > 0))
|
||
|
cbRequired += pClrShim->ShimVersionLength + sizeof(WCHAR);
|
||
|
|
||
|
if ((dwFlags & SXS_FIND_CLR_CLASS_GET_TYPE_NAME) && (pClrShim->TypeLength > 0))
|
||
|
cbRequired += pClrShim->TypeLength + sizeof(WCHAR);
|
||
|
|
||
|
//
|
||
|
// Is there enough space in the outbound buffer?
|
||
|
//
|
||
|
if (cbRequired <= cbDataBuffer)
|
||
|
{
|
||
|
PWSTR pwszCursor;
|
||
|
SIZE_T cbRemaining = cbDataBuffer;
|
||
|
|
||
|
pOutputStruct = (PSXS_CLR_CLASS_INFORMATION)pvDataBuffer;
|
||
|
pwszCursor = (PWSTR)(pOutputStruct + 1);
|
||
|
cbRemaining -= sizeof(SXS_CLR_CLASS_INFORMATION);
|
||
|
|
||
|
pOutputStruct->ReferenceClsid = GuidToSearch;
|
||
|
pOutputStruct->dwFlags = 0;
|
||
|
pOutputStruct->dwSize = sizeof(*pOutputStruct);
|
||
|
pOutputStruct->ulThreadingModel = pComServerRedirect->ThreadingModel;
|
||
|
pOutputStruct->ulType = pClrShim->Type;
|
||
|
|
||
|
if (dwFlags & SXS_FIND_CLR_CLASS_GET_IDENTITY)
|
||
|
{
|
||
|
SIZE_T cbWritten;
|
||
|
pOutputStruct->pcwszImplementingAssembly = pwszCursor;
|
||
|
|
||
|
IFW32FALSE_EXIT(
|
||
|
AssemblyIdentity.Win32CopyIntoBuffer(
|
||
|
&pwszCursor,
|
||
|
&cbRemaining,
|
||
|
&cbWritten,
|
||
|
NULL,
|
||
|
NULL,
|
||
|
NULL));
|
||
|
}
|
||
|
else
|
||
|
pOutputStruct->pcwszImplementingAssembly = NULL;
|
||
|
|
||
|
if (dwFlags & SXS_FIND_CLR_CLASS_GET_PROGID)
|
||
|
{
|
||
|
WRITE_INTO_BUFFER(
|
||
|
pwszCursor,
|
||
|
pOutputStruct->pcwszProgId,
|
||
|
pComServerRedirect->ProgIdLength,
|
||
|
(PVOID)(((ULONG_PTR)pComServerRedirect) + pComServerRedirect->ProgIdOffset),
|
||
|
cbRemaining);
|
||
|
}
|
||
|
else
|
||
|
pOutputStruct->pcwszProgId = NULL;
|
||
|
|
||
|
|
||
|
if (dwFlags & SXS_FIND_CLR_CLASS_GET_RUNTIME_VERSION)
|
||
|
{
|
||
|
WRITE_INTO_BUFFER(
|
||
|
pwszCursor,
|
||
|
pOutputStruct->pcwszRuntimeVersion,
|
||
|
pClrShim->ShimVersionLength,
|
||
|
(PVOID)(((ULONG_PTR)pClrShim) + pClrShim->ShimVersionLength),
|
||
|
cbRemaining);
|
||
|
}
|
||
|
else
|
||
|
pOutputStruct->pcwszRuntimeVersion = NULL;
|
||
|
|
||
|
if (dwFlags & SXS_FIND_CLR_CLASS_GET_TYPE_NAME)
|
||
|
{
|
||
|
WRITE_INTO_BUFFER(
|
||
|
pwszCursor,
|
||
|
pOutputStruct->pcwszTypeName,
|
||
|
pClrShim->TypeLength,
|
||
|
(PVOID)(((ULONG_PTR)pClrShim) + pClrShim->TypeOffset),
|
||
|
cbRemaining);
|
||
|
}
|
||
|
else
|
||
|
pOutputStruct->pcwszTypeName = NULL;
|
||
|
|
||
|
*pcbDataBufferWrittenOrRequired = cbRequired;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*pcbDataBufferWrittenOrRequired = cbRequired;
|
||
|
ORIGINATE_WIN32_FAILURE_AND_EXIT(NotEnoughSpaceInOutboundBuffer, ERROR_INSUFFICIENT_BUFFER);
|
||
|
}
|
||
|
|
||
|
FN_EPILOG;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
WINAPI
|
||
|
SxsFindClrSurrogateInformation(
|
||
|
DWORD dwFlags,
|
||
|
LPGUID lpGuidToFind,
|
||
|
HANDLE hActivationContext,
|
||
|
PVOID pvDataBuffer,
|
||
|
SIZE_T cbDataBuffer,
|
||
|
PSIZE_T pcbDataBufferWrittenOrRequired
|
||
|
)
|
||
|
{
|
||
|
FN_PROLOG_WIN32;
|
||
|
|
||
|
SIZE_T cbRequired = 0;
|
||
|
PSXS_CLR_SURROGATE_INFORMATION pOutputStruct = NULL;
|
||
|
PCACTIVATION_CONTEXT_DATA_CLR_SURROGATE pSurrogateInfo = NULL;
|
||
|
ACTCTX_SECTION_KEYED_DATA KeyedData = {sizeof(KeyedData)};
|
||
|
CFusionActCtxScope ActCtxScope;
|
||
|
CFusionActCtxHandle UsedActivationContext;
|
||
|
CStringBuffer AssemblyIdentity;
|
||
|
|
||
|
if (pcbDataBufferWrittenOrRequired != NULL)
|
||
|
*pcbDataBufferWrittenOrRequired = 0;
|
||
|
|
||
|
//
|
||
|
// The data buffer has to be present, or the data buffer size has to be zero,
|
||
|
// and the written-or-required value must be present as well.
|
||
|
//
|
||
|
PARAMETER_CHECK(pvDataBuffer || (cbDataBuffer == 0));
|
||
|
PARAMETER_CHECK(pcbDataBufferWrittenOrRequired != NULL);
|
||
|
IFINVALID_FLAGS_EXIT_WIN32(dwFlags,
|
||
|
SXS_FIND_CLR_SURROGATE_USE_ACTCTX |
|
||
|
SXS_FIND_CLR_SURROGATE_GET_IDENTITY |
|
||
|
SXS_FIND_CLR_SURROGATE_GET_RUNTIME_VERSION |
|
||
|
SXS_FIND_CLR_SURROGATE_GET_TYPE_NAME);
|
||
|
|
||
|
//
|
||
|
// Steps we take here:
|
||
|
// - Activate the actctx if required.
|
||
|
// - Find the surrogate that corresponds to this progid
|
||
|
// - Calculate required size of data
|
||
|
// - If there's enough space, then start copying into the output blob
|
||
|
// - Otherwise, set the "required" size and error out with ERROR_INSUFFICIENT_BUFFER
|
||
|
//
|
||
|
|
||
|
|
||
|
//
|
||
|
// If we were told to use the actctx, then activate it over this function,
|
||
|
// and get a reference to it into UsedActivationContext so we can query with
|
||
|
// it later.
|
||
|
//
|
||
|
if (dwFlags & SXS_FIND_CLR_SURROGATE_USE_ACTCTX)
|
||
|
{
|
||
|
IFW32FALSE_EXIT(ActCtxScope.Win32Activate(hActivationContext));
|
||
|
AddRefActCtx(hActivationContext);
|
||
|
UsedActivationContext = hActivationContext;
|
||
|
}
|
||
|
//
|
||
|
// Otherwise, grab the current actctx and go to town. This addrefs the activation
|
||
|
// context, so we can let UsedActivationContext's destructor release it on the
|
||
|
// exit path.
|
||
|
//
|
||
|
else
|
||
|
{
|
||
|
IFW32FALSE_EXIT(GetCurrentActCtx(&UsedActivationContext));
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Initially, we require at least this amount of space.
|
||
|
//
|
||
|
cbRequired += sizeof(SXS_CLR_SURROGATE_INFORMATION);
|
||
|
IFW32FALSE_EXIT(
|
||
|
FindActCtxSectionGuid(
|
||
|
0,
|
||
|
NULL,
|
||
|
ACTIVATION_CONTEXT_SECTION_CLR_SURROGATES,
|
||
|
lpGuidToFind,
|
||
|
&KeyedData));
|
||
|
|
||
|
//
|
||
|
// Start totalling up the size
|
||
|
//
|
||
|
pSurrogateInfo = (PCACTIVATION_CONTEXT_DATA_CLR_SURROGATE)KeyedData.lpData;
|
||
|
|
||
|
if ((dwFlags & SXS_FIND_CLR_SURROGATE_GET_TYPE_NAME) && (pSurrogateInfo->TypeNameLength > 0))
|
||
|
cbRequired += pSurrogateInfo->TypeNameLength + sizeof(WCHAR);
|
||
|
|
||
|
if ((dwFlags & SXS_FIND_CLR_SURROGATE_GET_RUNTIME_VERSION) && (pSurrogateInfo->VersionLength > 0))
|
||
|
cbRequired += pSurrogateInfo->VersionLength + sizeof(WCHAR);
|
||
|
|
||
|
if (dwFlags & SXS_FIND_CLR_SURROGATE_GET_IDENTITY)
|
||
|
{
|
||
|
IFW32FALSE_EXIT(
|
||
|
SxspLookupAssemblyIdentityInActCtx(
|
||
|
UsedActivationContext,
|
||
|
KeyedData.ulAssemblyRosterIndex,
|
||
|
AssemblyIdentity));
|
||
|
|
||
|
if (AssemblyIdentity.Cch() > 0)
|
||
|
{
|
||
|
cbRequired += (AssemblyIdentity.Cch() + 1) * sizeof(WCHAR);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Go stomp the gathered data into the right places
|
||
|
//
|
||
|
if (cbRequired <= cbDataBuffer)
|
||
|
{
|
||
|
PWSTR pwszOutputCursor;
|
||
|
SIZE_T cbRemaining = cbDataBuffer;
|
||
|
SIZE_T cbWritten = 0;
|
||
|
|
||
|
pOutputStruct = (PSXS_CLR_SURROGATE_INFORMATION)pvDataBuffer;
|
||
|
pwszOutputCursor = (PWSTR)(pOutputStruct + 1);
|
||
|
|
||
|
pOutputStruct->cbSize = sizeof(SXS_CLR_SURROGATE_INFORMATION);
|
||
|
pOutputStruct->dwFlags = 0;
|
||
|
pOutputStruct->SurrogateIdent = pSurrogateInfo->SurrogateIdent;
|
||
|
|
||
|
//
|
||
|
// Write things into the output buffer
|
||
|
//
|
||
|
if (dwFlags & SXS_FIND_CLR_SURROGATE_GET_IDENTITY)
|
||
|
{
|
||
|
pOutputStruct->pcwszImplementingAssembly = pwszOutputCursor;
|
||
|
|
||
|
IFW32FALSE_EXIT(
|
||
|
AssemblyIdentity.Win32CopyIntoBuffer(
|
||
|
&pwszOutputCursor,
|
||
|
&cbRemaining,
|
||
|
&cbWritten,
|
||
|
NULL, NULL, NULL));
|
||
|
}
|
||
|
else
|
||
|
pOutputStruct->pcwszImplementingAssembly = NULL;
|
||
|
|
||
|
|
||
|
if (dwFlags & SXS_FIND_CLR_SURROGATE_GET_TYPE_NAME)
|
||
|
{
|
||
|
WRITE_INTO_BUFFER(
|
||
|
pwszOutputCursor,
|
||
|
pOutputStruct->pcwszSurrogateType,
|
||
|
pSurrogateInfo->TypeNameLength,
|
||
|
(PVOID)(((ULONG_PTR)pSurrogateInfo) + pSurrogateInfo->TypeNameOffset),
|
||
|
cbRemaining);
|
||
|
}
|
||
|
else
|
||
|
pOutputStruct->pcwszSurrogateType = NULL;
|
||
|
|
||
|
if (dwFlags & SXS_FIND_CLR_SURROGATE_GET_RUNTIME_VERSION)
|
||
|
{
|
||
|
WRITE_INTO_BUFFER(
|
||
|
pwszOutputCursor,
|
||
|
pOutputStruct->pcwszRuntimeVersion,
|
||
|
pSurrogateInfo->VersionLength,
|
||
|
(PVOID)(((ULONG_PTR)pSurrogateInfo) + pSurrogateInfo->VersionOffset),
|
||
|
cbRemaining);
|
||
|
}
|
||
|
else
|
||
|
pOutputStruct->pcwszRuntimeVersion = NULL;
|
||
|
|
||
|
*pcbDataBufferWrittenOrRequired = cbRequired;
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*pcbDataBufferWrittenOrRequired = cbRequired;
|
||
|
ORIGINATE_WIN32_FAILURE_AND_EXIT(NotEnoughSpaceInOutputBuffer, ERROR_INSUFFICIENT_BUFFER);
|
||
|
}
|
||
|
|
||
|
FN_EPILOG;
|
||
|
}
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
WINAPI
|
||
|
SxsLookupClrGuid(
|
||
|
DWORD dwFlags,
|
||
|
LPGUID pClsid,
|
||
|
HANDLE hActCtx,
|
||
|
PVOID pvOutputBuffer,
|
||
|
SIZE_T cbOutputBuffer,
|
||
|
PSIZE_T pcbOutputBuffer
|
||
|
)
|
||
|
{
|
||
|
FN_PROLOG_WIN32;
|
||
|
|
||
|
if (pcbOutputBuffer)
|
||
|
*pcbOutputBuffer = 0;
|
||
|
|
||
|
CStackBackingBuffer BackingBuffer;
|
||
|
DWORD dwLastError;
|
||
|
SIZE_T cbRequired = 0;
|
||
|
PSXS_GUID_INFORMATION_CLR pOutputTarget = NULL;
|
||
|
PCWSTR pcwszRuntimeVersion = NULL;
|
||
|
PCWSTR pcwszTypeName = NULL;
|
||
|
PCWSTR pcwszAssemblyName = NULL;
|
||
|
SIZE_T cchRuntimeVersion = 0;
|
||
|
SIZE_T cchTypeName = 0;
|
||
|
SIZE_T cchAssemblyName = 0;
|
||
|
|
||
|
enum {
|
||
|
eFoundSurrogate,
|
||
|
eFoundClrClass,
|
||
|
eNotFound
|
||
|
} FoundThingType = eNotFound;
|
||
|
|
||
|
PARAMETER_CHECK(pcbOutputBuffer != NULL);
|
||
|
PARAMETER_CHECK(pvOutputBuffer || (cbOutputBuffer == 0));
|
||
|
IFINVALID_FLAGS_EXIT_WIN32(dwFlags,
|
||
|
SXS_LOOKUP_CLR_GUID_USE_ACTCTX |
|
||
|
SXS_LOOKUP_CLR_GUID_FIND_SURROGATE |
|
||
|
SXS_LOOKUP_CLR_GUID_FIND_CLR_CLASS |
|
||
|
SXS_LOOKUP_CLR_GUID_FIND_ANY);
|
||
|
//
|
||
|
// Nothing found yet, let's look into the surrogate data tables first
|
||
|
//
|
||
|
if ((FoundThingType == eNotFound) && ((dwFlags & SXS_LOOKUP_CLR_GUID_FIND_SURROGATE) != 0))
|
||
|
{
|
||
|
IFW32FALSE_EXIT_UNLESS3(
|
||
|
SxsFindClrSurrogateInformation(
|
||
|
SXS_FIND_CLR_SURROGATE_GET_ALL | ((dwFlags & SXS_LOOKUP_CLR_GUID_USE_ACTCTX) ? SXS_FIND_CLR_SURROGATE_USE_ACTCTX : 0),
|
||
|
pClsid,
|
||
|
hActCtx,
|
||
|
BackingBuffer.GetArrayPtr(),
|
||
|
BackingBuffer.GetSize(),
|
||
|
&cbRequired),
|
||
|
LIST_3(ERROR_SXS_SECTION_NOT_FOUND, ERROR_SXS_KEY_NOT_FOUND, ERROR_INSUFFICIENT_BUFFER),
|
||
|
dwLastError);
|
||
|
|
||
|
//
|
||
|
// If we found the key and section, but the buffer was too small, resize and try again
|
||
|
//
|
||
|
if (dwLastError == ERROR_INSUFFICIENT_BUFFER)
|
||
|
{
|
||
|
IFW32FALSE_EXIT(BackingBuffer.Win32SetSize(cbRequired, CStackBackingBuffer::eSetSizeModeExact));
|
||
|
|
||
|
IFW32FALSE_EXIT_UNLESS3(
|
||
|
SxsFindClrSurrogateInformation(
|
||
|
SXS_FIND_CLR_SURROGATE_GET_ALL | ((dwFlags & SXS_LOOKUP_CLR_GUID_USE_ACTCTX) ? SXS_FIND_CLR_SURROGATE_USE_ACTCTX : 0),
|
||
|
pClsid,
|
||
|
hActCtx,
|
||
|
BackingBuffer.GetArrayPtr(),
|
||
|
BackingBuffer.GetSize(),
|
||
|
&cbRequired),
|
||
|
LIST_2(ERROR_SXS_SECTION_NOT_FOUND, ERROR_SXS_KEY_NOT_FOUND),
|
||
|
dwLastError);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Great - we either succeeded during the first call, or we succeeded after
|
||
|
// resizing our buffers. Gather information, set the type, and continue.
|
||
|
//
|
||
|
if (dwLastError == ERROR_SUCCESS)
|
||
|
{
|
||
|
//
|
||
|
// At this point, BackingBuffer contains goop about a CLR surrogate. Ensure that
|
||
|
// our output buffer is large enough, and then fill it out.
|
||
|
//
|
||
|
PCSXS_CLR_SURROGATE_INFORMATION pSurrogateInfo =
|
||
|
(PCSXS_CLR_SURROGATE_INFORMATION)BackingBuffer.GetArrayPtr();
|
||
|
|
||
|
pcwszAssemblyName = pSurrogateInfo->pcwszImplementingAssembly;
|
||
|
pcwszTypeName = pSurrogateInfo->pcwszSurrogateType;
|
||
|
pcwszRuntimeVersion = pSurrogateInfo->pcwszRuntimeVersion;
|
||
|
FoundThingType = eFoundSurrogate;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// We've yet to find anything, and the flags say we can look up a clr class
|
||
|
//
|
||
|
if ((FoundThingType == eNotFound) && ((dwFlags & SXS_LOOKUP_CLR_GUID_FIND_CLR_CLASS) != 0))
|
||
|
{
|
||
|
IFW32FALSE_EXIT_UNLESS3(
|
||
|
SxsFindClrClassInformation(
|
||
|
SXS_FIND_CLR_CLASS_SEARCH_GUID | SXS_FIND_CLR_CLASS_GET_ALL,
|
||
|
(PVOID)pClsid,
|
||
|
hActCtx,
|
||
|
BackingBuffer.GetArrayPtr(),
|
||
|
BackingBuffer.GetSize(),
|
||
|
&cbRequired),
|
||
|
LIST_3(ERROR_INSUFFICIENT_BUFFER, ERROR_SXS_SECTION_NOT_FOUND, ERROR_SXS_KEY_NOT_FOUND),
|
||
|
dwLastError);
|
||
|
|
||
|
if (dwLastError == ERROR_INSUFFICIENT_BUFFER)
|
||
|
{
|
||
|
IFW32FALSE_EXIT(BackingBuffer.Win32SetSize(cbRequired, CStackBackingBuffer::eSetSizeModeExact));
|
||
|
|
||
|
IFW32FALSE_EXIT_UNLESS3(
|
||
|
SxsFindClrClassInformation(
|
||
|
SXS_FIND_CLR_CLASS_SEARCH_GUID | SXS_FIND_CLR_CLASS_GET_ALL,
|
||
|
(PVOID)pClsid,
|
||
|
hActCtx,
|
||
|
BackingBuffer.GetArrayPtr(),
|
||
|
BackingBuffer.GetSize(),
|
||
|
&cbRequired),
|
||
|
LIST_2(ERROR_SXS_SECTION_NOT_FOUND, ERROR_SXS_KEY_NOT_FOUND),
|
||
|
dwLastError);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// We succeeded, either after the first query, or after resizing.
|
||
|
//
|
||
|
if (dwLastError == ERROR_SUCCESS)
|
||
|
{
|
||
|
PCSXS_CLR_CLASS_INFORMATION pClassInfo =
|
||
|
(PCSXS_CLR_CLASS_INFORMATION)BackingBuffer.GetArrayPtr();
|
||
|
FoundThingType = eFoundClrClass;
|
||
|
pcwszAssemblyName = pClassInfo->pcwszImplementingAssembly;
|
||
|
pcwszRuntimeVersion = pClassInfo->pcwszRuntimeVersion;
|
||
|
pcwszTypeName = pClassInfo->pcwszTypeName;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// If we got to this point and didn't find anything, then error out with a reasonable
|
||
|
// error code.
|
||
|
//
|
||
|
if (FoundThingType == eNotFound)
|
||
|
{
|
||
|
ORIGINATE_WIN32_FAILURE_AND_EXIT(DidntFindObject, ERROR_NOT_FOUND);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Calculate some sizes - string lengths, etc.
|
||
|
//
|
||
|
cbRequired = sizeof(SXS_GUID_INFORMATION_CLR);
|
||
|
cchAssemblyName = StringLength(pcwszAssemblyName);
|
||
|
cchRuntimeVersion = StringLength(pcwszRuntimeVersion);
|
||
|
cchTypeName = StringLength(pcwszTypeName);
|
||
|
cbRequired += (cchAssemblyName + cchRuntimeVersion + cchTypeName + 3) * sizeof(WCHAR);
|
||
|
|
||
|
//
|
||
|
// If there was enough space, start stomping data into the output buffer
|
||
|
//
|
||
|
if (cbRequired <= cbOutputBuffer)
|
||
|
{
|
||
|
PWSTR pwszCursor;
|
||
|
pOutputTarget = (PSXS_GUID_INFORMATION_CLR)pvOutputBuffer;
|
||
|
pwszCursor = (PWSTR)(pOutputTarget + 1);
|
||
|
|
||
|
pOutputTarget->cbSize = sizeof(*pOutputTarget);
|
||
|
pOutputTarget->dwFlags = 0;
|
||
|
|
||
|
switch (FoundThingType) {
|
||
|
case eFoundClrClass:
|
||
|
pOutputTarget->dwFlags |= SXS_GUID_INFORMATION_CLR_FLAG_IS_CLASS;
|
||
|
break;
|
||
|
case eFoundSurrogate:
|
||
|
pOutputTarget->dwFlags |= SXS_GUID_INFORMATION_CLR_FLAG_IS_SURROGATE;
|
||
|
break;
|
||
|
default:
|
||
|
INTERNAL_ERROR_CHECK(FALSE);
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// This grossness is unfortunately required.
|
||
|
//
|
||
|
pOutputTarget->pcwszAssemblyIdentity = pwszCursor;
|
||
|
wcscpy(pwszCursor, pcwszAssemblyName);
|
||
|
pwszCursor += cchAssemblyName + 1;
|
||
|
|
||
|
pOutputTarget->pcwszRuntimeVersion= pwszCursor;
|
||
|
wcscpy(pwszCursor, pcwszRuntimeVersion);
|
||
|
pwszCursor += cchRuntimeVersion+ 1;
|
||
|
|
||
|
pOutputTarget->pcwszTypeName = pwszCursor;
|
||
|
wcscpy(pwszCursor, pcwszTypeName);
|
||
|
pwszCursor += cchTypeName + 1;
|
||
|
|
||
|
*pcbOutputBuffer = cbRequired;
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
*pcbOutputBuffer = cbRequired;
|
||
|
|
||
|
ORIGINATE_WIN32_FAILURE_AND_EXIT(NotEnoughSpaceInOutputBuffer, ERROR_INSUFFICIENT_BUFFER);
|
||
|
}
|
||
|
|
||
|
FN_EPILOG;
|
||
|
}
|
||
|
|