HRESULT FilterManager::MarkSignature( PCCOR_SIGNATURE pbSig, // [IN] point to the current byte to visit in the signature ULONG cbSig, // [IN] count of bytes available. ULONG *pcbUsed) // [OUT] count of bytes consumed. { HRESULT hr = NOERROR; // A result. ULONG cArg = 0; // count of arguments in the signature ULONG cTypes = 0; // Count of argument types in the signature. ULONG cb; // Bytes used in a sig element. ULONG cbUsed = 0; // Total bytes consumed. ULONG callingconv = IMAGE_CEE_CS_CALLCONV_MAX; // calling convention VALIDATE_SIGNATURE_LEN( CorSigUncompressData(pbSig, &callingconv) ); if ((callingconv & IMAGE_CEE_CS_CALLCONV_MASK) >= IMAGE_CEE_CS_CALLCONV_MAX) IfFailGo(META_E_BAD_SIGNATURE); // Field signature is a single element. if (isCallConv(callingconv, IMAGE_CEE_CS_CALLCONV_FIELD)) { // It is a FieldDef VALIDATE_SIGNATURE_LEN_HR( MarkFieldSignature(pbSig, cbSig - cbUsed, &cb) ); } else { // If Generic call, get count of type parameters. //@TODO: where are the type params? if (callingconv & IMAGE_CEE_CS_CALLCONV_GENERIC) { VALIDATE_SIGNATURE_LEN( CorSigUncompressData(pbSig, &cTypes) ); } // Count of arguments passed in call. VALIDATE_SIGNATURE_LEN( CorSigUncompressData(pbSig, &cArg) ); // Mark the return type, if there is one (LocalVarSig and GenericInst don't have return types). if ( !( isCallConv(callingconv, IMAGE_CEE_CS_CALLCONV_LOCAL_SIG) || isCallConv(callingconv, IMAGE_CEE_CS_CALLCONV_GENERICINST)) ) { // process the return type VALIDATE_SIGNATURE_LEN_HR( MarkFieldSignature(pbSig, cbSig - cbUsed, &cb) ); } // Iterate over the arguments, and mark each one. while (cArg--) { VALIDATE_SIGNATURE_LEN_HR( MarkFieldSignature(pbSig, cbSig - cbUsed, &cb) ); } } ErrExit: *pcbUsed = cbUsed; return hr; } // HRESULT FilterManager::MarkSignature()
// Skips past the calling convention, argument count (saving that into // *pCount), then moves past the return type. ULONG _skipMethodSignatureHeader(PCCOR_SIGNATURE sig, ULONG *pCount) { ULONG tmp; ULONG cb = 0; cb += CorSigUncompressData(&sig[0], &tmp); _ASSERTE(tmp != IMAGE_CEE_CS_CALLCONV_FIELD); cb += CorSigUncompressData(&sig[cb], pCount); cb += _skipTypeInSignature(&sig[cb]); return cb; }
// _skipFunkyModifiersInSignature will skip the modifiers that // we don't care about. Everything we care about is listed as // a case in CreateValueByType. Specifically, we care about: ULONG _skipFunkyModifiersInSignature(PCCOR_SIGNATURE sig) { ULONG cb = 0; ULONG skippedCB = 0; ULONG elementType; // Need to skip all funky modifiers in the signature to get us to // the first bit of good stuff. do { cb = CorSigUncompressData(&sig[skippedCB], &elementType); switch( elementType ) { case ELEMENT_TYPE_CMOD_REQD: case ELEMENT_TYPE_CMOD_OPT: { mdToken typeRef; skippedCB += cb; skippedCB += CorSigUncompressToken(&sig[skippedCB], &typeRef); break; } case ELEMENT_TYPE_MAX: { _ASSERTE( !"_skipFunkyModifiersInSignature:Given an invalid type!" ); break; } case ELEMENT_TYPE_MODIFIER: case ELEMENT_TYPE_PINNED: { // Since these are all followed by another ELEMENT_TYPE, // we're done. skippedCB += cb; break; } default: { // Since we didn't find any modifiers, don't skip // anything. cb = 0; break; } } } while (cb > 0); return skippedCB; }
ULONG _detectAndSkipVASentinel(PCCOR_SIGNATURE sig) { ULONG cb = 0; ULONG elementType = ELEMENT_TYPE_MAX; cb += CorSigUncompressData(sig, &elementType); if (CorIsModifierElementType((CorElementType)elementType) && (elementType == ELEMENT_TYPE_SENTINEL)) { return cb; } else { return 0; } }
//PrettyPrinting type names PCCOR_SIGNATURE PrettyPrintType( PCCOR_SIGNATURE typePtr, // type to convert, CQuickBytes *out, // where to put the pretty printed string IMDInternalImport *pIMDI, // ptr to IMDInternal class with ComSig DWORD formatFlags /*= formatILDasm*/) { mdToken tk; const char* str; int typ; CQuickBytes tmp; CQuickBytes Appendix; BOOL Reiterate; int n; do { Reiterate = FALSE; switch(typ = *typePtr++) { case ELEMENT_TYPE_VOID : str = "void"; goto APPEND; case ELEMENT_TYPE_BOOLEAN : str = "bool"; goto APPEND; case ELEMENT_TYPE_CHAR : str = "char"; goto APPEND; case ELEMENT_TYPE_I1 : str = "int8"; goto APPEND; case ELEMENT_TYPE_U1 : str = "uint8"; goto APPEND; case ELEMENT_TYPE_I2 : str = "int16"; goto APPEND; case ELEMENT_TYPE_U2 : str = "uint16"; goto APPEND; case ELEMENT_TYPE_I4 : str = "int32"; goto APPEND; case ELEMENT_TYPE_U4 : str = "uint32"; goto APPEND; case ELEMENT_TYPE_I8 : str = "int64"; goto APPEND; case ELEMENT_TYPE_U8 : str = "uint64"; goto APPEND; case ELEMENT_TYPE_R4 : str = "float32"; goto APPEND; case ELEMENT_TYPE_R8 : str = "float64"; goto APPEND; case ELEMENT_TYPE_U : str = "native uint"; goto APPEND; case ELEMENT_TYPE_I : str = "native int"; goto APPEND; case ELEMENT_TYPE_OBJECT : str = "object"; goto APPEND; case ELEMENT_TYPE_STRING : str = "string"; goto APPEND; case ELEMENT_TYPE_TYPEDBYREF : str = "typedref"; goto APPEND; APPEND: appendStr(out, (char*)str); break; case ELEMENT_TYPE_VALUETYPE : if ((formatFlags & FormatKwInNames) != 0) str = "valuetype "; else str = ""; goto DO_CLASS; case ELEMENT_TYPE_CLASS : if ((formatFlags & FormatKwInNames) != 0) str = "class "; else str = ""; goto DO_CLASS; DO_CLASS: appendStr(out, (char*)str); typePtr += CorSigUncompressToken(typePtr, &tk); if(IsNilToken(tk)) { appendStr(out, "[ERROR! NIL TOKEN]"); } else PrettyPrintClass(out, tk, pIMDI, formatFlags); break; case ELEMENT_TYPE_SZARRAY : insertStr(&Appendix,"[]"); Reiterate = TRUE; break; case ELEMENT_TYPE_ARRAY : { typePtr = PrettyPrintType(typePtr, out, pIMDI, formatFlags); unsigned rank = CorSigUncompressData(typePtr); // <TODO> what is the syntax for the rank 0 case? </TODO> if (rank == 0) { appendStr(out, "[BAD: RANK == 0!]"); } else { _ASSERTE(rank != 0); #ifdef _PREFAST_ #pragma warning(push) #pragma warning(disable:22009) // "Suppress PREfast warnings about integer overflow" // PREFAST warns about using _alloca in a loop. However when we're in this switch case we do NOT // set Reiterate to true, so we only execute through the loop once! #pragma warning(disable:6263) // "Suppress PREfast warnings about stack overflow due to _alloca in a loop." #endif int* lowerBounds = (int*) _alloca(sizeof(int)*2*rank); int* sizes = &lowerBounds[rank]; memset(lowerBounds, 0, sizeof(int)*2*rank); unsigned numSizes = CorSigUncompressData(typePtr); _ASSERTE(numSizes <= rank); unsigned i; for(i =0; i < numSizes; i++) sizes[i] = CorSigUncompressData(typePtr); unsigned numLowBounds = CorSigUncompressData(typePtr); _ASSERTE(numLowBounds <= rank); for(i = 0; i < numLowBounds; i++) typePtr+=CorSigUncompressSignedInt(typePtr,&lowerBounds[i]); appendChar(out, '['); if (rank == 1 && numSizes == 0 && numLowBounds == 0) appendStr(out, "..."); else { for(i = 0; i < rank; i++) { //if (sizes[i] != 0 || lowerBounds[i] != 0) { if (lowerBounds[i] == 0 && i < numSizes) appendStrNum(out, sizes[i]); else { if(i < numLowBounds) { appendStrNum(out, lowerBounds[i]); appendStr(out, "..."); if (/*sizes[i] != 0 && */i < numSizes) appendStrNum(out, lowerBounds[i] + sizes[i] - 1); } } } if (i < rank-1) appendChar(out, ','); } } appendChar(out, ']'); #ifdef _PREFAST_ #pragma warning(pop) #endif } } break; case ELEMENT_TYPE_VAR : appendChar(out, '!'); n = CorSigUncompressData(typePtr); appendStrNum(out, n); break; case ELEMENT_TYPE_MVAR : appendChar(out, '!'); appendChar(out, '!'); n = CorSigUncompressData(typePtr); appendStrNum(out, n); break; case ELEMENT_TYPE_FNPTR : appendStr(out, "method "); appendStr(out, "METHOD"); // was: typePtr = PrettyPrintSignature(typePtr, 0x7FFF, "*", out, pIMDI, NULL); break; case ELEMENT_TYPE_GENERICINST : { typePtr = PrettyPrintType(typePtr, out, pIMDI, formatFlags); if ((formatFlags & FormatSignature) == 0) break; if ((formatFlags & FormatAngleBrackets) != 0) appendStr(out, "<"); else appendStr(out,"["); unsigned numArgs = CorSigUncompressData(typePtr); bool needComma = false; while(numArgs--) { if (needComma) appendChar(out, ','); typePtr = PrettyPrintType(typePtr, out, pIMDI, formatFlags); needComma = true; } if ((formatFlags & FormatAngleBrackets) != 0) appendStr(out, ">"); else appendStr(out,"]"); break; } case ELEMENT_TYPE_PINNED : str = " pinned"; goto MODIFIER; case ELEMENT_TYPE_PTR : str = "*"; goto MODIFIER; case ELEMENT_TYPE_BYREF : str = "&"; goto MODIFIER; MODIFIER: insertStr(&Appendix, str); Reiterate = TRUE; break; default: case ELEMENT_TYPE_SENTINEL : case ELEMENT_TYPE_END : //_ASSERTE(!"Unknown Type"); if(typ) { char sz[64]; sprintf_s(sz,COUNTOF(sz),"/* UNKNOWN TYPE (0x%X)*/",typ); appendStr(out, sz); } break; } // end switch } while(Reiterate); if (Appendix.Size() > 0) appendStr(out,asString(&Appendix)); return(typePtr); }
HRESULT _CountBytesOfOneArg( PCCOR_SIGNATURE pbSig, ULONG *pcbTotal) // Initially, *pcbTotal contains the remaining size of the sig blob { ULONG cb; ULONG cbTotal=0; ULONG cbTotalMax; CorElementType ulElementType; ULONG ulData; ULONG ulTemp; int iData; mdToken tk; ULONG cArg; ULONG callingconv; ULONG cArgsIndex; HRESULT hr = NOERROR; if(pcbTotal==NULL) return E_FAIL; cbTotalMax = *pcbTotal; CHECK_REMAINDER; cbTotal = CorSigUncompressElementType(pbSig, &ulElementType); while (CorIsModifierElementType((CorElementType) ulElementType)) { CHECK_REMAINDER; cbTotal += CorSigUncompressElementType(&pbSig[cbTotal], &ulElementType); } switch (ulElementType) { case ELEMENT_TYPE_SZARRAY: case 0x1e /* obsolete */: // skip over base type CHECK_REMAINDER; cb = cbTotalMax - cbTotal; IfFailGo( _CountBytesOfOneArg(&pbSig[cbTotal], &cb) ); cbTotal += cb; break; case ELEMENT_TYPE_FNPTR: CHECK_REMAINDER; cbTotal += CorSigUncompressData (&pbSig[cbTotal], &callingconv); // remember number of bytes to represent the arg counts CHECK_REMAINDER; cbTotal += CorSigUncompressData (&pbSig[cbTotal], &cArg); // how many bytes to represent the return type CHECK_REMAINDER; cb = cbTotalMax - cbTotal; IfFailGo( _CountBytesOfOneArg( &pbSig[cbTotal], &cb) ); cbTotal += cb; // loop through argument for (cArgsIndex = 0; cArgsIndex < cArg; cArgsIndex++) { CHECK_REMAINDER; cb = cbTotalMax - cbTotal; IfFailGo( _CountBytesOfOneArg( &pbSig[cbTotal], &cb) ); cbTotal += cb; } break; case ELEMENT_TYPE_ARRAY: // syntax : ARRAY BaseType <rank> [i size_1... size_i] [j lowerbound_1 ... lowerbound_j] // skip over base type CHECK_REMAINDER; cb = cbTotalMax - cbTotal; IfFailGo( _CountBytesOfOneArg(&pbSig[cbTotal], &cb) ); cbTotal += cb; // Parse for the rank CHECK_REMAINDER; cbTotal += CorSigUncompressData(&pbSig[cbTotal], &ulData); // if rank == 0, we are done if (ulData == 0) break; // any size of dimension specified? CHECK_REMAINDER; cbTotal += CorSigUncompressData(&pbSig[cbTotal], &ulData); while (ulData--) { CHECK_REMAINDER; cbTotal += CorSigUncompressData(&pbSig[cbTotal], &ulTemp); } // any lower bound specified? CHECK_REMAINDER; cbTotal += CorSigUncompressData(&pbSig[cbTotal], &ulData); while (ulData--) { CHECK_REMAINDER; cbTotal += CorSigUncompressSignedInt(&pbSig[cbTotal], &iData); } break; case ELEMENT_TYPE_VALUETYPE: case ELEMENT_TYPE_CLASS: case ELEMENT_TYPE_CMOD_REQD: case ELEMENT_TYPE_CMOD_OPT: // count the bytes for the token compression CHECK_REMAINDER; cbTotal += CorSigUncompressToken(&pbSig[cbTotal], &tk); if ( ulElementType == ELEMENT_TYPE_CMOD_REQD || ulElementType == ELEMENT_TYPE_CMOD_OPT) { // skip over base type CHECK_REMAINDER; cb = cbTotalMax - cbTotal; IfFailGo( _CountBytesOfOneArg(&pbSig[cbTotal], &cb) ); cbTotal += cb; } break; default: break; } *pcbTotal = cbTotal; ErrExit: return hr; }
//***************************************************************************** // copy fixed part of VarArg signature to a buffer //***************************************************************************** HRESULT _GetFixedSigOfVarArg( // S_OK or error. PCCOR_SIGNATURE pvSigBlob, // [IN] point to a blob of COM+ method signature ULONG cbSigBlob, // [IN] size of signature CQuickBytes *pqbSig, // [OUT] output buffer for fixed part of VarArg Signature ULONG *pcbSigBlob) // [OUT] number of bytes written to the above output buffer { HRESULT hr = NOERROR; ULONG cbCalling; ULONG cbTyArgsNumber = 0; // number of bytes to store the type arg count (generics only) ULONG cbArgsNumber; // number of bytes to store the original arg count ULONG cbArgsNumberTemp; // number of bytes to store the fixed arg count ULONG cbTotal = 0; // total of number bytes for return type + all fixed arguments ULONG cbCur = 0; // index through the pvSigBlob ULONG cb; ULONG cArg; ULONG cTyArg; ULONG callingconv; ULONG cArgsIndex; CorElementType ulElementType; BYTE *pbSig; _ASSERTE (pvSigBlob && pcbSigBlob); // remember the number of bytes to represent the calling convention cbCalling = CorSigUncompressData (pvSigBlob, &callingconv); if (cbCalling == ((ULONG)(-1))) { return E_INVALIDARG; } _ASSERTE (isCallConv(callingconv, IMAGE_CEE_CS_CALLCONV_VARARG)); cbCur += cbCalling; if (callingconv & IMAGE_CEE_CS_CALLCONV_GENERIC) { cbTyArgsNumber = CorSigUncompressData(&pvSigBlob[cbCur], &cTyArg); if (cbTyArgsNumber == ((ULONG)(-1))) { return E_INVALIDARG; } cbCur += cbTyArgsNumber; } // remember number of bytes to represent the arg counts cbArgsNumber= CorSigUncompressData (&pvSigBlob[cbCur], &cArg); if (cbArgsNumber == ((ULONG)(-1))) { return E_INVALIDARG; } cbCur += cbArgsNumber; // how many bytes to represent the return type cb = cbSigBlob-cbCur; IfFailGo( _CountBytesOfOneArg( &pvSigBlob[cbCur], &cb) ); cbCur += cb; cbTotal += cb; // loop through argument until we found ELEMENT_TYPE_SENTINEL or run // out of arguments for (cArgsIndex = 0; cArgsIndex < cArg; cArgsIndex++) { _ASSERTE(cbCur < cbSigBlob); // peak the outer most ELEMENT_TYPE_* CorSigUncompressElementType (&pvSigBlob[cbCur], &ulElementType); if (ulElementType == ELEMENT_TYPE_SENTINEL) break; cb = cbSigBlob-cbCur; IfFailGo( _CountBytesOfOneArg( &pvSigBlob[cbCur], &cb) ); cbTotal += cb; cbCur += cb; } cbArgsNumberTemp = CorSigCompressData(cArgsIndex, &cArg); // now cbCalling : the number of bytes needed to store the calling convention // cbArgNumberTemp : number of bytes to store the fixed arg count // cbTotal : the number of bytes to store the ret and fixed arguments *pcbSigBlob = cbCalling + cbArgsNumberTemp + cbTotal; // resize the buffer IfFailGo( pqbSig->ReSizeNoThrow(*pcbSigBlob) ); pbSig = (BYTE *)pqbSig->Ptr(); // copy over the calling convention cb = CorSigCompressData(callingconv, pbSig); // copy over the fixed arg count cbArgsNumberTemp = CorSigCompressData(cArgsIndex, &pbSig[cb]); // copy over the fixed args + ret type memcpy(&pbSig[cb + cbArgsNumberTemp], &pvSigBlob[cbCalling + cbArgsNumber], cbTotal); ErrExit: return hr; }
unsigned SizeOfField(PCCOR_SIGNATURE *ppSig, ULONG cSig, IMDInternalImport* pImport) { unsigned ret = 0xFFFFFFFF; if(ppSig && *ppSig && cSig && pImport) { unsigned callConv = CorSigUncompressData(*ppSig); if (isCallConv(callConv, IMAGE_CEE_CS_CALLCONV_FIELD)) { mdToken tk; int typ; BOOL Reiterate; unsigned uElementNumber = 1; PCCOR_SIGNATURE pSigOrig = *ppSig; PCCOR_SIGNATURE pSigEnd = *ppSig+cSig; do { Reiterate = FALSE; switch(typ = *(*ppSig)++) { case ELEMENT_TYPE_VOID : return 0; case ELEMENT_TYPE_I1 : case ELEMENT_TYPE_U1 : case ELEMENT_TYPE_BOOLEAN : return uElementNumber; case ELEMENT_TYPE_CHAR : case ELEMENT_TYPE_I2 : case ELEMENT_TYPE_U2 : return (uElementNumber << 1); case ELEMENT_TYPE_I4 : case ELEMENT_TYPE_U4 : case ELEMENT_TYPE_R4 : return (uElementNumber << 2); case ELEMENT_TYPE_I8 : case ELEMENT_TYPE_U8 : case ELEMENT_TYPE_R8 : return (uElementNumber << 3); //case ELEMENT_TYPE_R : // return (uElementNumber * sizeof(float)); case ELEMENT_TYPE_OBJECT : case ELEMENT_TYPE_STRING : case ELEMENT_TYPE_FNPTR : case ELEMENT_TYPE_CLASS : case ELEMENT_TYPE_PTR : case ELEMENT_TYPE_BYREF : //case ELEMENT_TYPE_VAR : case ELEMENT_TYPE_U : case ELEMENT_TYPE_I : return (uElementNumber * sizeof(void*)); case ELEMENT_TYPE_TYPEDBYREF : // pair of ptrs return (uElementNumber * sizeof(void*)<<1); case ELEMENT_TYPE_VALUETYPE : *ppSig += CorSigUncompressToken(*ppSig, &tk); ret = SizeOfValueType(tk,pImport); if(ret != 0xFFFFFFFF) ret *= uElementNumber; return ret; // Modifiers or depedant types // uncomment when and if this type is supported by the Runtime //case ELEMENT_TYPE_VALUEARRAY : case ELEMENT_TYPE_ARRAY : ret = SizeOfField(ppSig, cSig-(unsigned)((*ppSig)-pSigOrig), pImport); if(ret != 0xFFFFFFFF) { unsigned rank = CorSigUncompressData(*ppSig); if (rank == 0) ret = 0xFFFFFFFF; else { int* lowerBounds = (int*) _alloca(sizeof(int)*2*rank); int* sizes = &lowerBounds[rank]; memset(lowerBounds, 0, sizeof(int)*2*rank); unsigned numSizes = CorSigUncompressData(*ppSig); _ASSERTE(numSizes <= rank); unsigned i; for(i =0; i < numSizes; i++) sizes[i] = CorSigUncompressData(*ppSig); unsigned numLowBounds = CorSigUncompressData(*ppSig); _ASSERTE(numLowBounds <= rank); for(i = 0; i < numLowBounds; i++) *ppSig+=CorSigUncompressSignedInt(*ppSig,&lowerBounds[i]); for(i = 0; i < numSizes; i++) { if (sizes[i]) uElementNumber *= sizes[i]; } ret *= uElementNumber; } } return ret; case ELEMENT_TYPE_CMOD_OPT : case ELEMENT_TYPE_CMOD_REQD : *ppSig += CorSigUncompressToken(*ppSig, &tk); case ELEMENT_TYPE_PINNED : case ELEMENT_TYPE_SZARRAY : // uElementNumber doesn't change if(*ppSig < pSigEnd) Reiterate = TRUE; break; default: case ELEMENT_TYPE_SENTINEL : case ELEMENT_TYPE_END : break; } // end switch } while(Reiterate); } // end if(CALLCONV_FIELD) } // end if(signature && import) return ret; }
// see "MetaData Unmanaged API.doc" file available inside // Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\Tool Developers Guide\docs\ // for meta data informations CParameterInfo* CParameterInfo::Parse(IN IMetaDataImport *pMetaDataImport,IN PCOR_SIGNATURE pSigParam,OUT PCOR_SIGNATURE* pNextSig) { CParameterInfo* pParameterInfo=NULL; COR_SIGNATURE SigContent; *pNextSig=0; pParameterInfo=new CParameterInfo(); if (!pParameterInfo) return NULL; //SigParam: //1) 0,N ELEMENT_TYPE_CMOD_REQD/ELEMENT_TYPE_CMOD_OPT //2) a) 0,1 TYPE_BYREF + 1 Type // or // b) 1 TYPE_TYPEDBYREF SigContent=*pSigParam; pSigParam++; switch (SigContent) { // 1) 0,N ELEMENT_TYPE_CMOD_REQD/ELEMENT_TYPE_CMOD_OPT case ELEMENT_TYPE_CMOD_REQD: case ELEMENT_TYPE_CMOD_OPT: { // in these 2 case we don't get mdToken Token; TCHAR szClassName[MAX_LENGTH]; *szClassName=0; pSigParam += CorSigUncompressToken(pSigParam,&Token); if (TypeFromToken(Token)!=mdtTypeRef) { HRESULT hr; WCHAR szName[MAX_LENGTH]; DWORD szNameSize; *szName=0; hr = pMetaDataImport->GetTypeDefProps(Token, szName, MAX_LENGTH, &szNameSize, NULL, NULL); szName[MAX_LENGTH-1]=0; if (FAILED(hr) || (szName==0) ) { wsprintfW(szName,L"ParamToken%u",Token); } #if (defined(UNICODE)||defined(_UNICODE)) _tcsncpy(szClassName,szName,MAX_LENGTH); #else wcstombs(szClassName,szName,MAX_LENGTH); #endif szClassName[MAX_LENGTH-1]=0; } _tcscpy(pParameterInfo->szName,szClassName); // get type pParameterInfo->WinAPIOverrideType=CSupportedParameters::GetParamType(pParameterInfo->szName); // get sizes pParameterInfo->StackSize=CSupportedParameters::GetParamStackSize(pParameterInfo->WinAPIOverrideType); pParameterInfo->PointedSize=CSupportedParameters::GetParamPointedSize(pParameterInfo->WinAPIOverrideType); } break; // 2) b) 1 TYPE_TYPEDBYREF case ELEMENT_TYPE_TYPEDBYREF: //A TYPEDBYREF is a simple structure of two DWORDs – one indicates the type of the parameter, the other, its value. //This struct is pushed on the stack by the caller. //So, only at runtime, is the type of the parameter actually provided. //TYPEDBYREF was originally introduced to support VB’s "refany" argument-passing technique _tcscpy(pParameterInfo->szName,_T("ULONG64")); // get type pParameterInfo->WinAPIOverrideType=PARAM_INT64; // get sizes pParameterInfo->StackSize=CSupportedParameters::GetParamStackSize(pParameterInfo->WinAPIOverrideType); pParameterInfo->PointedSize=CSupportedParameters::GetParamPointedSize(pParameterInfo->WinAPIOverrideType); break; // 2) a) 0,1 TYPE_BYREF + 1 Type case ELEMENT_TYPE_BYREF: // delete current info delete pParameterInfo; // get type infos pParameterInfo=CParameterInfo::Parse(pMetaDataImport,pSigParam,&pSigParam); if (!pParameterInfo) return NULL; _tcscat(pParameterInfo->szName,_T("*")); pParameterInfo->bPointedParameter=TRUE; // get type if (pParameterInfo->WinAPIOverrideType & EXTENDED_TYPE_FLAG_MASK) pParameterInfo->WinAPIOverrideType=PARAM_POINTER; else pParameterInfo->WinAPIOverrideType=CSupportedParameters::GetParamType(pParameterInfo->szName); pParameterInfo->StackSize=CSupportedParameters::GetParamStackSize(pParameterInfo->WinAPIOverrideType); pParameterInfo->PointedSize=CSupportedParameters::GetParamPointedSize(pParameterInfo->WinAPIOverrideType); break; ////////////////////////// // from now only Type ////////////////////////// //Type := VOID (for return type) // | Intrinsic (BOOLEAN | CHAR | I1 | U1 | I2 | U2 | I4 | U4 | I8 | U8 | R4 | R8 | I | U) // | VALUETYPE TypeDefOrRefEncoded // | CLASS TypeDefOrRefEncoded // | STRING // | OBJECT // | PTR CustomMod* VOID // | PTR CustomMod* Type // | FNPTR MethodDefSig // | FNPTR MethodRefSig // | ARRAY Type ArrayShape // | SZARRAY CustomMod* Type case ELEMENT_TYPE_VOID: // set default type pParameterInfo->WinAPIOverrideType=PARAM_VOID; _tcscpy(pParameterInfo->szName,_T("VOID")); // get sizes pParameterInfo->StackSize=CSupportedParameters::GetParamStackSize(pParameterInfo->WinAPIOverrideType); pParameterInfo->PointedSize=CSupportedParameters::GetParamPointedSize(pParameterInfo->WinAPIOverrideType); break; case ELEMENT_TYPE_BOOLEAN: // set default type pParameterInfo->WinAPIOverrideType=PARAM_BOOL; _tcscpy(pParameterInfo->szName,_T("BOOL")); // get sizes pParameterInfo->StackSize=CSupportedParameters::GetParamStackSize(pParameterInfo->WinAPIOverrideType); pParameterInfo->PointedSize=CSupportedParameters::GetParamPointedSize(pParameterInfo->WinAPIOverrideType); break; case ELEMENT_TYPE_CHAR: // set default type pParameterInfo->WinAPIOverrideType=PARAM_WCHAR; _tcscpy(pParameterInfo->szName,_T("WCHAR")); // get sizes pParameterInfo->StackSize=CSupportedParameters::GetParamStackSize(pParameterInfo->WinAPIOverrideType); pParameterInfo->PointedSize=CSupportedParameters::GetParamPointedSize(pParameterInfo->WinAPIOverrideType); break; case ELEMENT_TYPE_I1: // set default type pParameterInfo->WinAPIOverrideType=PARAM_CHAR; _tcscpy(pParameterInfo->szName,_T("SBYTE")); // get sizes pParameterInfo->StackSize=CSupportedParameters::GetParamStackSize(pParameterInfo->WinAPIOverrideType); pParameterInfo->PointedSize=CSupportedParameters::GetParamPointedSize(pParameterInfo->WinAPIOverrideType); break; case ELEMENT_TYPE_U1: // set default type pParameterInfo->WinAPIOverrideType=PARAM_BYTE; _tcscpy(pParameterInfo->szName,_T("BYTE")); // get sizes pParameterInfo->StackSize=CSupportedParameters::GetParamStackSize(pParameterInfo->WinAPIOverrideType); pParameterInfo->PointedSize=CSupportedParameters::GetParamPointedSize(pParameterInfo->WinAPIOverrideType); break; case ELEMENT_TYPE_I2: // set default type pParameterInfo->WinAPIOverrideType=PARAM_SHORT; _tcscpy(pParameterInfo->szName,_T("SHORT")); // get sizes pParameterInfo->StackSize=CSupportedParameters::GetParamStackSize(pParameterInfo->WinAPIOverrideType); pParameterInfo->PointedSize=CSupportedParameters::GetParamPointedSize(pParameterInfo->WinAPIOverrideType); break; case ELEMENT_TYPE_U2: // set default type pParameterInfo->WinAPIOverrideType=PARAM_USHORT; _tcscpy(pParameterInfo->szName,_T("USHORT")); // get sizes pParameterInfo->StackSize=CSupportedParameters::GetParamStackSize(pParameterInfo->WinAPIOverrideType); pParameterInfo->PointedSize=CSupportedParameters::GetParamPointedSize(pParameterInfo->WinAPIOverrideType); break; case ELEMENT_TYPE_I4: // set default type pParameterInfo->WinAPIOverrideType=PARAM_INT; _tcscpy(pParameterInfo->szName,_T("INT")); // get sizes pParameterInfo->StackSize=CSupportedParameters::GetParamStackSize(pParameterInfo->WinAPIOverrideType); pParameterInfo->PointedSize=CSupportedParameters::GetParamPointedSize(pParameterInfo->WinAPIOverrideType); break; case ELEMENT_TYPE_U4: // set default type pParameterInfo->WinAPIOverrideType=PARAM_UINT; _tcscpy(pParameterInfo->szName,_T("UINT")); // get sizes pParameterInfo->StackSize=CSupportedParameters::GetParamStackSize(pParameterInfo->WinAPIOverrideType); pParameterInfo->PointedSize=CSupportedParameters::GetParamPointedSize(pParameterInfo->WinAPIOverrideType); break; case ELEMENT_TYPE_I8: // set default type pParameterInfo->WinAPIOverrideType=PARAM_INT64; _tcscpy(pParameterInfo->szName,_T("INT64")); // get sizes pParameterInfo->StackSize=CSupportedParameters::GetParamStackSize(pParameterInfo->WinAPIOverrideType); pParameterInfo->PointedSize=CSupportedParameters::GetParamPointedSize(pParameterInfo->WinAPIOverrideType); break; case ELEMENT_TYPE_U8: // set default type pParameterInfo->WinAPIOverrideType=PARAM_INT64; _tcscpy(pParameterInfo->szName,_T("UINT64")); // get sizes pParameterInfo->StackSize=CSupportedParameters::GetParamStackSize(pParameterInfo->WinAPIOverrideType); pParameterInfo->PointedSize=CSupportedParameters::GetParamPointedSize(pParameterInfo->WinAPIOverrideType); break; case ELEMENT_TYPE_R4: // set default type pParameterInfo->WinAPIOverrideType=PARAM_FLOAT; _tcscpy(pParameterInfo->szName,_T("float")); // get sizes pParameterInfo->StackSize=CSupportedParameters::GetParamStackSize(pParameterInfo->WinAPIOverrideType); pParameterInfo->PointedSize=CSupportedParameters::GetParamPointedSize(pParameterInfo->WinAPIOverrideType); break; case ELEMENT_TYPE_R8: // set default type pParameterInfo->WinAPIOverrideType=PARAM_DOUBLE; _tcscpy(pParameterInfo->szName,_T("double")); // get sizes pParameterInfo->StackSize=CSupportedParameters::GetParamStackSize(pParameterInfo->WinAPIOverrideType); pParameterInfo->PointedSize=CSupportedParameters::GetParamPointedSize(pParameterInfo->WinAPIOverrideType); break; case ELEMENT_TYPE_U: // set default type pParameterInfo->WinAPIOverrideType=PARAM_UINT; _tcscpy(pParameterInfo->szName,_T("UINT")); // get sizes pParameterInfo->StackSize=CSupportedParameters::GetParamStackSize(pParameterInfo->WinAPIOverrideType); pParameterInfo->PointedSize=CSupportedParameters::GetParamPointedSize(pParameterInfo->WinAPIOverrideType); break; case ELEMENT_TYPE_I: // set default type pParameterInfo->WinAPIOverrideType=PARAM_INT; _tcscpy(pParameterInfo->szName,_T("INT")); // get sizes pParameterInfo->StackSize=CSupportedParameters::GetParamStackSize(pParameterInfo->WinAPIOverrideType); pParameterInfo->PointedSize=CSupportedParameters::GetParamPointedSize(pParameterInfo->WinAPIOverrideType); break; case ELEMENT_TYPE_OBJECT: // set default type pParameterInfo->WinAPIOverrideType=PARAM_POINTER; _tcscpy(pParameterInfo->szName,_T("PVOID")); // get sizes pParameterInfo->StackSize=CSupportedParameters::GetParamStackSize(pParameterInfo->WinAPIOverrideType); pParameterInfo->PointedSize=CSupportedParameters::GetParamPointedSize(pParameterInfo->WinAPIOverrideType); break; case ELEMENT_TYPE_STRING: // set default type pParameterInfo->WinAPIOverrideType=PARAM_NET_STRING; _tcscpy(pParameterInfo->szName,_T("string")); // get sizes pParameterInfo->StackSize=CSupportedParameters::GetParamStackSize(pParameterInfo->WinAPIOverrideType); pParameterInfo->PointedSize=CSupportedParameters::GetParamPointedSize(pParameterInfo->WinAPIOverrideType); break; case ELEMENT_TYPE_VALUETYPE: case ELEMENT_TYPE_CLASS: { HRESULT hResult=E_FAIL; mdToken Token; TCHAR szClassName[MAX_LENGTH]; WCHAR szName[MAX_LENGTH]; DWORD szNameSize; *szClassName=0; *szName=0; pSigParam+=CorSigUncompressToken(pSigParam,&Token); if ( TypeFromToken( Token ) == mdtTypeDef ) { hResult = pMetaDataImport->GetTypeDefProps( Token, szName, MAX_LENGTH, &szNameSize, NULL, NULL ); } else if ( TypeFromToken( Token ) == mdtTypeRef ) { hResult = pMetaDataImport->GetTypeRefProps(Token, NULL,szName, MAX_LENGTH, &szNameSize); } szName[MAX_LENGTH-1]=0; if (FAILED(hResult) || (szName==0) || (*szName<32) || (*szName>126) // assume readable name ) { wsprintfW(szName,L"ParamToken%u",Token); } #if (defined(UNICODE)||defined(_UNICODE)) _tcsncpy( szClassName,szName, MAX_LENGTH); #else wcstombs( szClassName, szName, MAX_LENGTH ); #endif szClassName[MAX_LENGTH-1]=0; _tcscpy(pParameterInfo->szName,szClassName); // set default type pParameterInfo->WinAPIOverrideType=PARAM_POINTER; // get sizes pParameterInfo->StackSize=CSupportedParameters::GetParamStackSize(pParameterInfo->WinAPIOverrideType); pParameterInfo->PointedSize=CSupportedParameters::GetParamPointedSize(pParameterInfo->WinAPIOverrideType); break; } case ELEMENT_TYPE_FNPTR: // set default type pParameterInfo->WinAPIOverrideType=PARAM_POINTER; _tcscpy(pParameterInfo->szName,_T("FunctionPointer")); // get sizes pParameterInfo->StackSize=CSupportedParameters::GetParamStackSize(pParameterInfo->WinAPIOverrideType); pParameterInfo->PointedSize=CSupportedParameters::GetParamPointedSize(pParameterInfo->WinAPIOverrideType); break; case ELEMENT_TYPE_SZARRAY: // The SZARRAY production describes a frequently-used, special-case of ARRAY // that's to say, a single-dimension (rank 1) array, with a zero lower bound, and no specified size // delete current info delete pParameterInfo; // get type infos pParameterInfo=CParameterInfo::Parse(pMetaDataImport,pSigParam,&pSigParam); if (!pParameterInfo) return NULL; _tcscat(pParameterInfo->szName,_T("*")); pParameterInfo->bPointedParameter=TRUE; // get type pParameterInfo->WinAPIOverrideType=CSupportedParameters::GetParamType(pParameterInfo->szName); pParameterInfo->WinAPIOverrideType|=EXTENDED_TYPE_FLAG_NET_SINGLE_DIM_ARRAY; pParameterInfo->StackSize=CSupportedParameters::GetParamStackSize(pParameterInfo->WinAPIOverrideType); pParameterInfo->PointedSize=CSupportedParameters::GetParamPointedSize(pParameterInfo->WinAPIOverrideType); break; case ELEMENT_TYPE_ARRAY: { //1) rank //2) num size //3) 0-N Sizes //4) nb low bounds //5) 0-N low bounds // //ex // Type Rank NumSizes Size* NumLoBounds LoBound* //[0..2] I4 1 1 3 0 //[,,,,,,] I4 6 0 //[0..3, 0..2,,,,] I4 6 2 4,3 0 //[1..2, 6..8] I4 2 2 2,3 2 1,6 //[5, 3..5, , ] I4 3 2 5,3 2 0,3 ULONG rank; // delete current info delete pParameterInfo; // parse element pParameterInfo=CParameterInfo::Parse(pMetaDataImport,pSigParam,&pSigParam); if (!pParameterInfo) return NULL; _tcscat(pParameterInfo->szName,_T("*")); pParameterInfo->bPointedParameter=TRUE; // get type pParameterInfo->WinAPIOverrideType=CSupportedParameters::GetParamType(pParameterInfo->szName); pParameterInfo->WinAPIOverrideType|=EXTENDED_TYPE_FLAG_NET_MULTIPLE_DIM_ARRAY; pParameterInfo->StackSize=CSupportedParameters::GetParamStackSize(pParameterInfo->WinAPIOverrideType); pParameterInfo->PointedSize=CSupportedParameters::GetParamPointedSize(pParameterInfo->WinAPIOverrideType); // we have to do parsing even if not necessary to find next signature // 1) rank rank = CorSigUncompressData((PCCOR_SIGNATURE&)pSigParam); if ( rank > 0 ) { ULONG *lower; ULONG *sizes; ULONG numsizes; ULONG arraysize=(sizeof(ULONG)*2*rank); lower=(ULONG*)_alloca(arraysize); memset(lower,0,arraysize); sizes=&lower[rank]; // 2) num size numsizes = CorSigUncompressData((PCCOR_SIGNATURE&)pSigParam); if ( numsizes <= rank ) { ULONG numlower; ULONG i; // 3) sizes for ( i = 0; i < numsizes; i++ ) sizes[i] = CorSigUncompressData((PCCOR_SIGNATURE&)pSigParam); // 4) num lower numlower = CorSigUncompressData((PCCOR_SIGNATURE&)pSigParam); if ( numlower <= rank ) { // 5) low bounds for ( i = 0; i < numlower; i++) lower[i] = CorSigUncompressData((PCCOR_SIGNATURE&)pSigParam); //// to display array size only //_tcscat( pParameterInfo->szName, "[" ); //for ( i = 0; i < rank; i++ ) //{ // if ( (sizes[i] != 0) && (lower[i] != 0) ) // { // if ( lower[i] == 0 ) // _stprintf ( pParameterInfo->szName, _T("%d"), sizes[i] ); // else // { // _stprintf( pParameterInfo->szName, _T("%d"), lower[i] ); // _tcscat( pParameterInfo->szName, _T("...") ); // if ( sizes[i] != 0 ) // _stprintf( pParameterInfo->szName, _T("%d"), (lower[i] + sizes[i] + 1) ); // } // } // if ( i < (rank - 1) ) // _tcscat( pParameterInfo->szName, _T(",") ); //} //_tcscat( pParameterInfo->szName, _T("]") ); } } } } break; case ELEMENT_TYPE_PINNED: // delete current info delete pParameterInfo; // parse element pParameterInfo=CParameterInfo::Parse(pMetaDataImport,pSigParam,&pSigParam); if (!pParameterInfo) return NULL; // _tcscat(pParameterInfo->szName,_T("pinned")); break; case ELEMENT_TYPE_PTR: // delete current info delete pParameterInfo; // get type infos pParameterInfo=CParameterInfo::Parse(pMetaDataImport,pSigParam,&pSigParam); if (!pParameterInfo) return NULL; _tcscat(pParameterInfo->szName,_T("*")); pParameterInfo->bPointedParameter=TRUE; // get type if (pParameterInfo->WinAPIOverrideType & EXTENDED_TYPE_FLAG_MASK) pParameterInfo->WinAPIOverrideType=PARAM_POINTER; else pParameterInfo->WinAPIOverrideType=CSupportedParameters::GetParamType(pParameterInfo->szName); pParameterInfo->StackSize=CSupportedParameters::GetParamStackSize(pParameterInfo->WinAPIOverrideType); pParameterInfo->PointedSize=CSupportedParameters::GetParamPointedSize(pParameterInfo->WinAPIOverrideType); break; default: case ELEMENT_TYPE_END: case ELEMENT_TYPE_SENTINEL: // set default type pParameterInfo->WinAPIOverrideType=PARAM_UNKNOWN; _tcscpy(pParameterInfo->szName,_T("Unknown")); // get sizes pParameterInfo->StackSize=CSupportedParameters::GetParamStackSize(pParameterInfo->WinAPIOverrideType); pParameterInfo->PointedSize=CSupportedParameters::GetParamPointedSize(pParameterInfo->WinAPIOverrideType); break; } // switch // fill output parameters *pNextSig=pSigParam; return pParameterInfo; }
// // _skipTypeInSignature -- skip past a type in a given signature. // Returns the number of bytes used by the type in the signature. // // ULONG _skipTypeInSignature(PCCOR_SIGNATURE sig, bool *pfPassedVarArgSentinel) { ULONG cb = 0; ULONG elementType; if (pfPassedVarArgSentinel != NULL) *pfPassedVarArgSentinel = false; cb += _skipFunkyModifiersInSignature(&sig[cb]); if (_detectAndSkipVASentinel(&sig[cb])) { cb += _detectAndSkipVASentinel(&sig[cb]); // Recursively deal with the real type. cb += _skipTypeInSignature(&sig[cb], pfPassedVarArgSentinel); if (pfPassedVarArgSentinel != NULL) *pfPassedVarArgSentinel = true; } else { cb += CorSigUncompressData(&sig[cb], &elementType); if ((elementType == ELEMENT_TYPE_CLASS) || (elementType == ELEMENT_TYPE_VALUETYPE)) { // Skip over typeref. mdToken typeRef; cb += CorSigUncompressToken(&sig[cb], &typeRef); } else if ((elementType == ELEMENT_TYPE_PTR) || (elementType == ELEMENT_TYPE_BYREF) || (elementType == ELEMENT_TYPE_PINNED) || (elementType == ELEMENT_TYPE_SZARRAY)) { // Skip over extra embedded type. cb += _skipTypeInSignature(&sig[cb]); } else if (elementType == ELEMENT_TYPE_ARRAY) { // Skip over extra embedded type. cb += _skipTypeInSignature(&sig[cb]); // Skip over rank ULONG rank; cb += CorSigUncompressData(&sig[cb], &rank); if (rank > 0) { // how many sizes? ULONG sizes; cb += CorSigUncompressData(&sig[cb], &sizes); // read out all the sizes unsigned int i; for (i = 0; i < sizes; i++) { ULONG dimSize; cb += CorSigUncompressData(&sig[cb], &dimSize); } // how many lower bounds? ULONG lowers; cb += CorSigUncompressData(&sig[cb], &lowers); // read out all the lower bounds. for (i = 0; i < lowers; i++) { int lowerBound; cb += CorSigUncompressSignedInt(&sig[cb], &lowerBound); } } } else if ( (elementType == ELEMENT_TYPE_FNPTR) ) { // We've got a method signature within this signature, // so traverse it // Run past the calling convetion, then get the // arg count, and return type ULONG cArgs; cb += _skipMethodSignatureHeader(&sig[cb], &cArgs); ULONG i; for(i = 0; i < cArgs; i++) { cb += _skipTypeInSignature(&sig[cb]); } } } return (cb); }
ULONG _sizeOfElementInstance(PCCOR_SIGNATURE sig, mdTypeDef *pmdValueClass) { ULONG cb = _skipFunkyModifiersInSignature(sig); sig = &sig[cb]; if (pmdValueClass != NULL) *pmdValueClass = mdTokenNil; switch (*sig) { case ELEMENT_TYPE_I8: case ELEMENT_TYPE_U8: case ELEMENT_TYPE_R8: return 8; case ELEMENT_TYPE_I4: case ELEMENT_TYPE_U4: case ELEMENT_TYPE_R4: #ifdef WIN32 case ELEMENT_TYPE_I: case ELEMENT_TYPE_U: #endif // WIN32 return 4; break; case ELEMENT_TYPE_I2: case ELEMENT_TYPE_U2: case ELEMENT_TYPE_CHAR: return 2; case ELEMENT_TYPE_I1: case ELEMENT_TYPE_U1: case ELEMENT_TYPE_BOOLEAN: return 1; case ELEMENT_TYPE_STRING: case ELEMENT_TYPE_PTR: case ELEMENT_TYPE_BYREF: case ELEMENT_TYPE_CLASS: case ELEMENT_TYPE_OBJECT: case ELEMENT_TYPE_FNPTR: case ELEMENT_TYPE_TYPEDBYREF: case ELEMENT_TYPE_ARRAY: case ELEMENT_TYPE_SZARRAY: return sizeof(void *); case ELEMENT_TYPE_VOID: return 0; case ELEMENT_TYPE_END: case ELEMENT_TYPE_CMOD_REQD: case ELEMENT_TYPE_CMOD_OPT: _ASSERTE(!"Asked for the size of an element that doesn't have a size!"); return 0; case ELEMENT_TYPE_VALUETYPE: if (pmdValueClass != NULL) { PCCOR_SIGNATURE sigTemp = &sig[cb]; ULONG Ignore; cb += CorSigUncompressData(sigTemp, &Ignore); sigTemp = &sig[cb]; *pmdValueClass=CorSigUncompressToken(sigTemp); } return 0; default: if ( _detectAndSkipVASentinel(sig)) { cb += _detectAndSkipVASentinel(sig); return _sizeOfElementInstance(&sig[cb]); } _ASSERTE( !"_sizeOfElementInstance given bogus value to size!" ); return 0; } }
//***************************************************************************** // walk one type and mark tokens embedded in the signature //***************************************************************************** HRESULT FilterManager::MarkFieldSignature( PCCOR_SIGNATURE pbSig, // [IN] point to the current byte to visit in the signature ULONG cbSig, // [IN] count of bytes available. ULONG *pcbUsed) // [OUT] count of bytes consumed. { HRESULT hr = NOERROR; // A result. ULONG cb; // Bytes in one signature element. ULONG cbUsed = 0; // Total bytes consumed from signature. CorElementType ulElementType; // ELEMENT_TYPE_xxx from signature. ULONG ulData; // Some data (like a count) from the signature. ULONG ulTemp; // Unused data. mdToken token; // A token from the signature. int iData; // Integer data from signature. VALIDATE_SIGNATURE_LEN( CorSigUncompressElementType(pbSig, &ulElementType) ); // Skip the modifiers... while (CorIsModifierElementType((CorElementType) ulElementType)) { VALIDATE_SIGNATURE_LEN( CorSigUncompressElementType(pbSig, &ulElementType) ); } // Examine the signature element switch (ulElementType) { case ELEMENT_TYPE_SZARRAY: // syntax: SZARRAY <BaseType> // conver the base type for the SZARRAY or GENERICARRAY VALIDATE_SIGNATURE_LEN_HR( MarkFieldSignature(pbSig, cbSig - cbUsed, &cb) ); break; case ELEMENT_TYPE_CMOD_REQD: case ELEMENT_TYPE_CMOD_OPT: // syntax: {CMOD_REQD|CMOD_OPT} <token> <signature> // now get the embedded token VALIDATE_SIGNATURE_LEN( CorSigUncompressToken(pbSig, &token) ); // Mark the token IfFailGo( Mark(token) ); // mark the base type VALIDATE_SIGNATURE_LEN_HR( MarkFieldSignature(pbSig, cbSig - cbUsed, &cb) ); break; case ELEMENT_TYPE_VAR: case ELEMENT_TYPE_MVAR: // syntax: VAR <index> VALIDATE_SIGNATURE_LEN( CorSigUncompressData(pbSig, &ulData) ); break; case ELEMENT_TYPE_ARRAY: // syntax: ARRAY BaseType <rank> [i size_1... size_i] [j lowerbound_1 ... lowerbound_j] VALIDATE_SIGNATURE_LEN_HR( MarkFieldSignature(pbSig, cbSig - cbUsed, &cb) ); // Parse for the rank VALIDATE_SIGNATURE_LEN( CorSigUncompressData(pbSig, &ulData) ); // if rank == 0, we are done if (ulData == 0) break; // Any size of dimension specified? VALIDATE_SIGNATURE_LEN( CorSigUncompressData(pbSig, &ulData) ); // Consume sizes of dimension. while (ulData--) { VALIDATE_SIGNATURE_LEN( CorSigUncompressData(pbSig, &ulTemp) ); } // Any lower bounds specified? VALIDATE_SIGNATURE_LEN( CorSigUncompressData(pbSig, &ulData) ); // Consume lower bounds. while (ulData--) { VALIDATE_SIGNATURE_LEN( CorSigUncompressSignedInt(pbSig, &iData) ); } break; case ELEMENT_TYPE_FNPTR: // function pointer is followed by another complete signature VALIDATE_SIGNATURE_LEN_HR( MarkSignature(pbSig, cbSig - cbUsed, &cb) ); break; case ELEMENT_TYPE_VALUETYPE: case ELEMENT_TYPE_CLASS: // syntax: {CLASS | VALUECLASS} <token> VALIDATE_SIGNATURE_LEN( CorSigUncompressToken(pbSig, &token) ); // Mark it. IfFailGo( Mark(token) ); break; case ELEMENT_TYPE_GENERICINST: // syntax: ELEMENT_TYPE_GEENRICINST <ELEMENT_TYPE_CLASS | ELEMENT_TYPE_VALUECLASS> <token> <n> <n params> VALIDATE_SIGNATURE_LEN_HR( MarkFieldSignature(pbSig, cbSig - cbUsed, &cb) ); // Get the number of generic parameters VALIDATE_SIGNATURE_LEN( CorSigUncompressData(pbSig, &ulData) ); // Get the generic parameters while (ulData--) { VALIDATE_SIGNATURE_LEN_HR( MarkFieldSignature(pbSig, cbSig - cbUsed, &cb) ); } break; default: // If valid element (I4, etc), great. Otherwise, return error. if ((ulElementType >= ELEMENT_TYPE_MAX) || (ulElementType == ELEMENT_TYPE_PTR) || (ulElementType == ELEMENT_TYPE_BYREF) || (ulElementType == ELEMENT_TYPE_VALUEARRAY_UNSUPPORTED)) { IfFailGo(META_E_BAD_SIGNATURE); } break; } ErrExit: *pcbUsed = cbUsed; return hr; } // HRESULT FilterManager::MarkFieldSignature()