in src/InstrumentationEngine/TypeCreator.cpp [60:324]
HRESULT MicrosoftInstrumentationEngine::CTypeCreator::FromSignature(_In_ DWORD cbBuffer, _In_ const BYTE* pCorSignature, _Out_ IType ** ppType, _Out_opt_ DWORD* pdwSigSize)
{
IfNullRetPointer(pCorSignature);
IfNullRetPointer(pdwSigSize);
IfNullRetPointer(ppType);
if (cbBuffer == 0)
{
return E_INVALIDARG;
}
*ppType = nullptr;
*pdwSigSize = 0;
HRESULT hr = S_OK;
PCCOR_SIGNATURE currentSignature = pCorSignature;
CorElementType sigElement = ELEMENT_TYPE_END;
DWORD currentSize = 1;
CComPtr<IType> createdType;
switch ((sigElement = static_cast<CorElementType>(*currentSignature)))
{
case ELEMENT_TYPE_VOID:
case ELEMENT_TYPE_BOOLEAN:
case ELEMENT_TYPE_CHAR:
case ELEMENT_TYPE_I1:
case ELEMENT_TYPE_U1:
case ELEMENT_TYPE_I2:
case ELEMENT_TYPE_U2:
case ELEMENT_TYPE_I4:
case ELEMENT_TYPE_U4:
case ELEMENT_TYPE_I8:
case ELEMENT_TYPE_U8:
case ELEMENT_TYPE_R4:
case ELEMENT_TYPE_R8:
case ELEMENT_TYPE_I:
case ELEMENT_TYPE_U:
case ELEMENT_TYPE_STRING:
case ELEMENT_TYPE_OBJECT:
case ELEMENT_TYPE_TYPEDBYREF:
{
createdType.Attach(new CSimpleType(sigElement));
if (createdType == nullptr)
{
return E_OUTOFMEMORY;
}
}
break;
case ELEMENT_TYPE_CLASS:
case ELEMENT_TYPE_VALUETYPE:
{
mdToken tokenValue;
currentSize += CorSigUncompressToken(¤tSignature[currentSize], &tokenValue);
IfFailRet(FromToken(sigElement, tokenValue, &createdType));
}
break;
case ELEMENT_TYPE_PTR:
case ELEMENT_TYPE_BYREF:
case ELEMENT_TYPE_SZARRAY:
{
DWORD newSize;
CComPtr<IType> relatedType;
IfFailRet(FromSignature(cbBuffer - currentSize, ¤tSignature[currentSize], &relatedType, &newSize));
createdType.Attach(new CCompositeType(sigElement, relatedType));
if (createdType == nullptr)
{
return E_OUTOFMEMORY;
}
currentSize += newSize;
}
break;
case ELEMENT_TYPE_FNPTR:
{
CComPtr<IType> pReturnType;
ULONG convention = IMAGE_CEE_CS_CALLCONV_MAX;
CComPtr<IEnumTypes> pEnumTypes;
DWORD genericCount = 0;
DWORD newSize = 0;
IfFailRet(ParseMethodSignature(
¤tSignature[currentSize],
cbBuffer - currentSize,
&convention,
&pReturnType,
&pEnumTypes,
&genericCount,
&newSize));
currentSize += newSize;
vector<CComPtr<IType>> parameterTypes;
ULONG cTypes;
CComPtr<IType> pType;
while (S_OK == (hr = pEnumTypes->Next(1, &pType, &cTypes)))
{
parameterTypes.push_back(pType);
pType.Release();
}
IfFailRet(hr);
hr = S_OK;
createdType.Attach(new CFunctionType((CorCallingConvention)convention, pReturnType, parameterTypes, genericCount));
if (createdType == nullptr)
{
return E_OUTOFMEMORY;
}
}
break;
case ELEMENT_TYPE_ARRAY:
{
DWORD newSize;
CComPtr<IType> relatedType;
IfFailRet(FromSignature(cbBuffer - currentSize, ¤tSignature[currentSize], &relatedType, &newSize));
currentSize += newSize;
IfFailRet(cbBuffer > currentSize ? S_OK : E_UNEXPECTED);
ULONG rank;
ULONG sizeCount;
ULONG boundsCount;
currentSize += CorSigUncompressData(¤tSignature[currentSize], &rank);
currentSize += CorSigUncompressData(¤tSignature[currentSize], &sizeCount);
std::vector<ULONG> counts(sizeCount);
for (ULONG iSizeIndex = 0; iSizeIndex < sizeCount; iSizeIndex++)
{
ULONG count;
currentSize += CorSigUncompressData(¤tSignature[currentSize], &count);
counts[iSizeIndex] = count;
}
currentSize += CorSigUncompressData(¤tSignature[currentSize], &boundsCount);
std::vector<ULONG> bounds(boundsCount);
for (ULONG iBoundIndex = 0; iBoundIndex < boundsCount; iBoundIndex++)
{
ULONG bound;
currentSize += CorSigUncompressData(¤tSignature[currentSize], &bound);
bounds[iBoundIndex] = bound;
}
createdType.Attach(new CArrayType(relatedType, rank, counts, bounds));
if (createdType == nullptr)
{
return E_OUTOFMEMORY;
}
}
break;
case ELEMENT_TYPE_MVAR:
case ELEMENT_TYPE_VAR:
{
ULONG position;
currentSize += CorSigUncompressData(¤tSignature[currentSize], &position);
createdType.Attach(new CGenericParameterType(sigElement, position));
if (createdType == nullptr)
{
return E_OUTOFMEMORY;
}
}
break;
case ELEMENT_TYPE_GENERICINST:
{
DWORD newSize;
CComPtr<IType> relatedType;
IfFailRet(FromSignature(cbBuffer - currentSize, ¤tSignature[currentSize], &relatedType, &newSize));
currentSize += newSize;
IfFailRet(cbBuffer > currentSize ? S_OK : E_UNEXPECTED);
ULONG argumentCount = 0;
currentSize += CorSigUncompressData(¤tSignature[currentSize], &argumentCount);
std::vector<IType*> parameters;
for (ULONG i = 0; i < argumentCount; i++)
{
IType* parameterType = nullptr;
IfFailRet(FromSignature(cbBuffer - currentSize, ¤tSignature[currentSize], ¶meterType, &newSize));
currentSize += newSize;
IfFailRet(cbBuffer >= currentSize ? S_OK : E_UNEXPECTED);
parameters.push_back(parameterType);
}
createdType.Attach(new CGenericInstance(relatedType, parameters));
for (IType* parameter : parameters)
{
parameter->Release();
}
if (createdType == nullptr)
{
return E_OUTOFMEMORY;
}
}
break;
case ELEMENT_TYPE_PINNED:
{
DWORD newSize = 0;
IfFailRet(FromSignature(cbBuffer - currentSize, ¤tSignature[currentSize], &createdType, &newSize));
static_cast<CType*>(createdType.p)->SetIsPinned(true);
currentSize += newSize;
}
break;
case ELEMENT_TYPE_SENTINEL:
{
DWORD newSize = 0;
IfFailRet(FromSignature(cbBuffer - currentSize, ¤tSignature[currentSize], &createdType, &newSize));
static_cast<CType*>(createdType.p)->SetIsSentinel(true);
currentSize += newSize;
}
break;
case ELEMENT_TYPE_CMOD_REQD:
case ELEMENT_TYPE_CMOD_OPT:
{
mdToken token = mdTokenNil;
currentSize += CorSigUncompressToken(¤tSignature[currentSize], &token);
std::vector<CComPtr<IType>> modifiers;
CComPtr<IType> pModifierType;
pModifierType.Attach(new CModifierType(sigElement, token));
if (pModifierType == nullptr)
{
return E_OUTOFMEMORY;
}
modifiers.push_back(pModifierType);
CorElementType modifierElementType = (CorElementType)currentSignature[currentSize];
while ((modifierElementType == ELEMENT_TYPE_CMOD_REQD) || (modifierElementType == ELEMENT_TYPE_CMOD_OPT))
{
++currentSize;
mdToken tokenInner = mdTokenNil;
currentSize += CorSigUncompressToken(¤tSignature[currentSize], &tokenInner);
CComPtr<IType> pNextModifierType;
pNextModifierType.Attach(new CModifierType(modifierElementType, tokenInner));
if (pNextModifierType == nullptr)
{
return E_OUTOFMEMORY;
}
modifiers.push_back(pNextModifierType);
modifierElementType = (CorElementType)currentSignature[currentSize];
}
DWORD newSize = 0;
IfFailRet(FromSignature(cbBuffer - currentSize, ¤tSignature[currentSize], &createdType, &newSize));
currentSize += newSize;
static_cast<CType*>(createdType.p)->SetModifers(modifiers);
}
break;
default:
CLogging::LogError(_T("Unexpected element type %d. This usually indicates a signature parsing bug"), sigElement);
return E_NOTIMPL;
}
if (createdType)
{
*ppType = createdType.Detach();
*pdwSigSize = currentSize;
hr = S_OK;
}
else
{
CLogging::LogError(_T("Type %d is not yet supported"), sigElement);
hr = E_FAIL;
}
return hr;
}