internal static Attribute GetCustomAttribute(RuntimeMethodInfo method)
{
if ((method.Attributes & MethodAttributes.PinvokeImpl) == 0)
return null;
MetadataImport scope = method.Module.ModuleHandle.GetMetadataImport();
string entryPoint, dllName = null;
int token = method.MetadataToken;
PInvokeAttributes flags = 0;
scope.GetPInvokeMap(token, out flags, out entryPoint, out dllName);
CharSet charSet = CharSet.None;
switch (flags & PInvokeAttributes.CharSetMask)
{
case PInvokeAttributes.CharSetNotSpec: charSet = CharSet.None; break;
case PInvokeAttributes.CharSetAnsi: charSet = CharSet.Ansi; break;
case PInvokeAttributes.CharSetUnicode: charSet = CharSet.Unicode; break;
case PInvokeAttributes.CharSetAuto: charSet = CharSet.Auto; break;
default: ASSERT.UNREACHABLE(); break;
}
CallingConvention callingConvention = CallingConvention.Cdecl;
switch (flags & PInvokeAttributes.CallConvMask)
{
case PInvokeAttributes.CallConvWinapi :callingConvention = CallingConvention.Winapi; break;
case PInvokeAttributes.CallConvCdecl :callingConvention = CallingConvention.Cdecl; break;
case PInvokeAttributes.CallConvStdcall :callingConvention = CallingConvention.StdCall; break;
case PInvokeAttributes.CallConvThiscall :callingConvention = CallingConvention.ThisCall; break;
case PInvokeAttributes.CallConvFastcall :callingConvention = CallingConvention.FastCall; break;
default: ASSERT.UNREACHABLE(); break;
}
bool exactSpelling = (flags & PInvokeAttributes.NoMangle) != 0;
bool setLastError = (flags & PInvokeAttributes.SupportsLastError) != 0;
bool bestFitMapping = (flags & PInvokeAttributes.BestFitMask) == PInvokeAttributes.BestFitEnabled;
bool throwOnUnmappableChar = (flags & PInvokeAttributes.ThrowOnUnmappableCharMask) == PInvokeAttributes.ThrowOnUnmappableCharEnabled;
bool preserveSig = (method.GetMethodImplementationFlags() & MethodImplAttributes.PreserveSig) != 0;
return new DllImportAttribute(
dllName, entryPoint, charSet, exactSpelling, setLastError, preserveSig,
callingConvention, bestFitMapping, throwOnUnmappableChar);
}