//
//
//
//
// $Revision: 2185 $
//
#pragma warning disable 1591
using System;
using System.Collections.Generic;
using Debugger.Interop.MetaData;
using Debugger.Wrappers.CorDebug;
using Debugger.Wrappers.CorSym;
namespace Debugger.Wrappers.MetaData
{
public class InterfaceImplProps
{
public uint Method;
public uint Class;
public uint Interface;
}
///
/// Wrapper for the unmanaged metadata API
///
public class MetaData: IDisposable
{
IMetaDataImport metaData;
public MetaData(ICorDebugModule pModule)
{
Guid guid = new Guid("{ 0x7dac8207, 0xd3ae, 0x4c75, { 0x9b, 0x67, 0x92, 0x80, 0x1a, 0x49, 0x7d, 0x44 } }");
metaData = (IMetaDataImport)pModule.GetMetaDataInterface(ref guid);
ResourceManager.TrackCOMObject(metaData, typeof(IMetaDataImport));
}
public ISymUnmanagedReader GetSymReader(string fullname, string searchPath)
{
try {
ISymUnmanagedBinder symBinder = new ISymUnmanagedBinder(new Debugger.Interop.CorSym.CorSymBinder_SxSClass());
return symBinder.GetReaderForFile(metaData, fullname, searchPath);
} catch {
return null;
}
}
~MetaData()
{
Dispose();
}
public void Dispose()
{
if (metaData != null) {
ResourceManager.ReleaseCOMObject(metaData, typeof(IMetaDataImport));
metaData = null;
}
}
public TypeDefProps FindTypeDefPropsByName(string name, uint typeDef_typeRef_enclosingClass_nullable)
{
return GetTypeDefProps(FindTypeDefByName2(name, typeDef_typeRef_enclosingClass_nullable));
}
public IEnumerable EnumInterfaceImplProps(uint typeDef)
{
foreach(uint token in EnumerateTokens(metaData.EnumInterfaceImpls, typeDef)) {
yield return GetInterfaceImplProps(token);
}
}
public InterfaceImplProps GetInterfaceImplProps(uint method)
{
InterfaceImplProps ret = new InterfaceImplProps();
ret.Method = method;
metaData.GetInterfaceImplProps(
ret.Method,
out ret.Class,
out ret.Interface
);
return ret;
}
public int GetGenericParamCount(uint typeDef_methodDef)
{
int count = 0;
foreach(uint genericParam in EnumGenericParams(typeDef_methodDef)) count++;
return count;
}
public uint[] EnumGenericParams(uint typeDef_methodDef)
{
return EnumerateTokens(metaData.EnumGenericParams, typeDef_methodDef);
}
const int initialBufferSize = 8;
delegate void TokenEnumerator1(ref IntPtr phEnum, T parameter, uint[] token, uint maxCount, out uint fetched);
uint[] EnumerateTokens(TokenEnumerator1 tokenEnumerator, T parameter)
{
IntPtr enumerator = IntPtr.Zero;
uint[] buffer = new uint[initialBufferSize];
uint fetched;
tokenEnumerator(ref enumerator, parameter, buffer, (uint)buffer.Length, out fetched);
if (fetched < buffer.Length) {
// The tokens did fit the buffer
Array.Resize(ref buffer, (int)fetched);
} else {
// The tokens did not fit the buffer -> Refetch
uint actualCount;
metaData.CountEnum(enumerator, out actualCount);
if (actualCount > buffer.Length) {
buffer = new uint[actualCount];
metaData.ResetEnum(enumerator, 0);
tokenEnumerator(ref enumerator, parameter, buffer, (uint)buffer.Length, out fetched);
}
}
metaData.CloseEnum(enumerator);
return buffer;
}
delegate void TokenEnumerator2(ref IntPtr phEnum, T parameter1, R parameter2, uint[] token, uint maxCount, out uint fetched);
uint[] EnumerateTokens(TokenEnumerator2 tokenEnumerator, T parameter1, R parameter2)
{
IntPtr enumerator = IntPtr.Zero;
uint[] buffer = new uint[initialBufferSize];
uint fetched;
tokenEnumerator(ref enumerator, parameter1, parameter2, buffer, (uint)buffer.Length, out fetched);
if (fetched < buffer.Length) {
// The tokens did fit the buffer
Array.Resize(ref buffer, (int)fetched);
} else {
// The tokens did not fit the buffer -> Refetch
uint actualCount;
metaData.CountEnum(enumerator, out actualCount);
if (actualCount > buffer.Length) {
buffer = new uint[actualCount];
metaData.ResetEnum(enumerator, 0);
tokenEnumerator(ref enumerator, parameter1, parameter2, buffer, (uint)buffer.Length, out fetched);
}
}
metaData.CloseEnum(enumerator);
return buffer;
}
public TypeDefProps GetTypeDefProps(uint typeToken)
{
TypeDefProps typeDefProps = new TypeDefProps();
typeDefProps.Token = typeToken;
typeDefProps.Name =
Util.GetString(delegate(uint pStringLenght, out uint stringLenght, System.IntPtr pString) {
metaData.GetTypeDefProps(typeDefProps.Token,
pString, pStringLenght, out stringLenght, // The string to get
out typeDefProps.Flags,
out typeDefProps.SuperClassToken);
});
return typeDefProps;
}
public TypeRefProps GetTypeRefProps(uint typeToken)
{
TypeRefProps typeRefProps = new TypeRefProps();
typeRefProps.Token = typeToken;
typeRefProps.Name =
Util.GetString(delegate(uint pStringLenght, out uint stringLenght, System.IntPtr pString) {
uint unused;
metaData.GetTypeRefProps(typeRefProps.Token,
out unused,
pString, pStringLenght,out stringLenght // The string to get
);
});
return typeRefProps;
}
public IEnumerable EnumFields(uint typeToken)
{
IntPtr enumerator = IntPtr.Zero;
while (true) {
uint fieldToken;
uint fieldsFetched;
metaData.EnumFields(ref enumerator, typeToken, out fieldToken, 1, out fieldsFetched);
if (fieldsFetched == 0) {
metaData.CloseEnum(enumerator);
break;
}
yield return GetFieldProps(fieldToken);
}
}
public FieldProps GetFieldProps(uint fieldToken)
{
FieldProps fieldProps = new FieldProps();
fieldProps.Token = fieldToken;
fieldProps.Name =
Util.GetString(delegate(uint pStringLenght, out uint stringLenght, System.IntPtr pString) {
uint unused;
IntPtr unusedPtr = IntPtr.Zero;
metaData.GetFieldProps(fieldProps.Token,
out fieldProps.ClassToken,
pString, pStringLenght, out stringLenght, // The string to get
out fieldProps.Flags,
IntPtr.Zero,
out unused,
out unused,
out unusedPtr,
out unused);
});
return fieldProps;
}
public IEnumerable EnumMethods(uint typeToken)
{
IntPtr enumerator = IntPtr.Zero;
while(true) {
uint methodToken;
uint methodsFetched;
metaData.EnumMethods(ref enumerator, typeToken, out methodToken, 1, out methodsFetched);
if (methodsFetched == 0) {
metaData.CloseEnum(enumerator);
break;
}
yield return GetMethodProps(methodToken);
}
}
public IEnumerable EnumProperties(uint typeToken)
{
IntPtr enumerator = IntPtr.Zero;
while(true) {
uint methodToken;
uint pcProperties;
metaData.EnumProperties(ref enumerator, typeToken, out methodToken, 1, out pcProperties);
if (pcProperties == 0) {
metaData.CloseEnum(enumerator);
break;
}
yield return GetPropertyProps(methodToken);
}
}
public IEnumerable EnumMethodsWithName(uint typeToken, string name)
{
IntPtr enumerator = IntPtr.Zero;
while(true) {
uint methodToken;
uint methodsFetched;
metaData.EnumMethodsWithName(ref enumerator, typeToken, name, out methodToken, 1, out methodsFetched);
if (methodsFetched == 0) {
metaData.CloseEnum(enumerator);
break;
}
yield return GetMethodProps(methodToken);
}
}
public unsafe PropertyProps GetPropertyProps(uint propertyToken)
{
PropertyProps propertyProps = new PropertyProps();
propertyProps.Token = propertyToken;
propertyProps.Name =
Util.GetString(delegate(uint pStringLenght, out uint stringLenght, System.IntPtr pString) {
uint sigBlobSize;
metaData.GetPropertyProps(propertyProps.Token,
out propertyProps.ClassToken,
pString, pStringLenght, out stringLenght,
out propertyProps.Flags,
IntPtr.Zero,//new IntPtr(&pSigBlob),
out sigBlobSize,
out propertyProps.TypeKind,
out propertyProps.DefaultValue,
out propertyProps.DefaultValueSize,
out propertyProps.Setter,
out propertyProps.Getter,
out propertyProps.OtherMethods,
2,
out propertyProps.OtherMethodNumTokens);
});
return propertyProps;
}
public unsafe MethodProps GetMethodProps(uint methodToken)
{
MethodProps methodProps = new MethodProps();
try
{
IntPtr sigPtr = IntPtr.Zero;
methodProps.Token = methodToken;
methodProps.Name =
Util.GetString(delegate(uint pStringLenght, out uint stringLenght, System.IntPtr pString)
{
uint sigBlobSize;
metaData.GetMethodProps(methodProps.Token,
out methodProps.ClassToken,
pString, pStringLenght, out stringLenght, // The string to get
out methodProps.Flags,
out sigPtr,//new IntPtr(&pSigBlob),
out sigBlobSize,
out methodProps.CodeRVA,
out methodProps.ImplFlags);
});
}
catch
{
}
return methodProps;
}
public IEnumerable EnumParams(uint mb)
{
IntPtr enumerator = IntPtr.Zero;
while(true) {
uint token;
uint fetched;
metaData.EnumParams(ref enumerator, mb, out token, 1, out fetched);
if (fetched == 0) {
metaData.CloseEnum(enumerator);
break;
}
yield return token;
}
}
public int GetParamCount(uint methodToken)
{
int count = 0;
foreach(uint param in EnumParams(methodToken)) count++;
return count;
}
public ParamProps GetParamForMethodIndex(uint methodToken, uint parameterSequence)
{
uint paramToken = 0;
metaData.GetParamForMethodIndex(methodToken, parameterSequence, ref paramToken);
return GetParamProps(paramToken);
}
public ParamProps GetParamProps(uint paramToken)
{
ParamProps paramProps = new ParamProps();
paramProps.Token = paramToken;
paramProps.Name =
Util.GetString(delegate(uint pStringLenght, out uint stringLenght, System.IntPtr pString) {
uint unused;
metaData.GetParamProps(paramProps.Token,
out paramProps.MethodToken,
out paramProps.ParameterSequence,
pString, pStringLenght, out stringLenght, // The string to get
out paramProps.Flags,
out unused,
IntPtr.Zero,
out unused);
});
return paramProps;
}
public uint FindTypeDefByName2(string name, uint typeDef_typeRef_enclosingClass_nullable)
{
uint typeDef;
metaData.FindTypeDefByName(name, typeDef_typeRef_enclosingClass_nullable, out typeDef);
return typeDef;
}
public TypeDefProps FindTypeDefByName(string typeName, uint enclosingClassToken)
{
uint typeDefToken;
metaData.FindTypeDefByName(typeName, enclosingClassToken, out typeDefToken);
return GetTypeDefProps(typeDefToken);
}
}
}
#pragma warning restore 1591