// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
#if !SILVERLIGHT // ComObject
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using ComTypes = System.Runtime.InteropServices.ComTypes;
namespace System.Management.Automation.ComInterop
{
internal static class ComRuntimeHelpers
{
[SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes")]
[SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference", MessageId = "1#")]
public static void CheckThrowException(int hresult, ref ExcepInfo excepInfo, ComMethodDesc method, object[] args, uint argErr)
{
if (Utils.Succeeded(hresult))
{
return;
}
Exception parameterException = null;
switch (hresult)
{
case ComHresults.DISP_E_BADPARAMCOUNT:
// The number of elements provided to DISPPARAMS is different from the number of arguments
// accepted by the method or property.
parameterException = Error.DispBadParamCount(method.Name, args.Length - 1);
ThrowWrappedInvocationException(method, parameterException);
break;
case ComHresults.DISP_E_BADVARTYPE:
// One of the arguments in rgvarg is not a valid variant type.
break;
case ComHresults.DISP_E_EXCEPTION:
// The application needs to raise an exception. In this case, the structure passed in pExcepInfo
// should be filled in.
throw excepInfo.GetException();
case ComHresults.DISP_E_MEMBERNOTFOUND:
// The requested member does not exist, or the call to Invoke tried to set the value of a
// read-only property.
throw Error.DispMemberNotFound(method.Name);
case ComHresults.DISP_E_NONAMEDARGS:
// This implementation of IDispatch does not support named arguments.
throw Error.DispNoNamedArgs(method.Name);
case ComHresults.DISP_E_OVERFLOW:
// One of the arguments in rgvarg could not be coerced to the specified type.
throw Error.DispOverflow(method.Name);
case ComHresults.DISP_E_PARAMNOTFOUND:
break;
case ComHresults.DISP_E_TYPEMISMATCH:
// The index within rgvarg of the first parameter with the incorrect
// type is returned in the puArgErr parameter.
//
// But: Arguments are stored in pDispParams->rgvarg in reverse order, so the first
// parameter is the one with the highest index in the array
// https://msdn.microsoft.com/library/aa912367.aspx
argErr = ((uint)args.Length) - argErr - 2;
// One or more of the arguments could not be coerced.
Type destinationType = null;
if (argErr >= method.ParameterInformation.Length)
{
destinationType = method.InputType;
}
else
{
destinationType = method.ParameterInformation[argErr].parameterType;
}
object originalValue = args[argErr + 1];
// If this is a put, use the InputType and the last argument
if (method.IsPropertyPut || method.IsPropertyPutRef)
{
destinationType = method.InputType;
originalValue = args[args.Length - 1];
}
string originalValueString = originalValue.ToString();
string originalTypeName = Microsoft.PowerShell.ToStringCodeMethods.Type(originalValue.GetType(), true);
// ByRef arguments should be displayed in the error message as a PSReference
if (destinationType == typeof(object) && method.ParameterInformation[argErr].isByRef)
{
destinationType = typeof(PSReference);
}
string destinationTypeName = Microsoft.PowerShell.ToStringCodeMethods.Type(destinationType, true);
parameterException = Error.DispTypeMismatch(method.Name, originalValueString, originalTypeName, destinationTypeName);
ThrowWrappedInvocationException(method, parameterException);
break;
case ComHresults.DISP_E_UNKNOWNINTERFACE:
// The interface identifier passed in riid is not IID_NULL.
break;
case ComHresults.DISP_E_UNKNOWNLCID:
// The member being invoked interprets string arguments according to the LCID, and the
// LCID is not recognized.
break;
case ComHresults.DISP_E_PARAMNOTOPTIONAL:
// A required parameter was omitted.
throw Error.DispParamNotOptional(method.Name);
}
Marshal.ThrowExceptionForHR(hresult);
}
private static void ThrowWrappedInvocationException(ComMethodDesc method, Exception parameterException)
{
if ((method.InvokeKind & ComTypes.INVOKEKIND.INVOKE_FUNC) ==
ComTypes.INVOKEKIND.INVOKE_FUNC)
{
throw new MethodException(parameterException.Message, parameterException);
}
if (method.IsPropertyGet)
{
throw new GetValueInvocationException(parameterException.Message, parameterException);
}
if (method.IsPropertyPut || method.IsPropertyPutRef)
{
throw new SetValueInvocationException(parameterException.Message, parameterException);
}
throw parameterException;
}
internal static void GetInfoFromType(ComTypes.ITypeInfo typeInfo, out string name, out string documentation)
{
int dwHelpContext;
string strHelpFile;
typeInfo.GetDocumentation(-1, out name, out documentation, out dwHelpContext, out strHelpFile);
}
internal static string GetNameOfMethod(ComTypes.ITypeInfo typeInfo, int memid)
{
int cNames;
string[] rgNames = new string[1];
typeInfo.GetNames(memid, rgNames, 1, out cNames);
return rgNames[0];
}
internal static string GetNameOfLib(ComTypes.ITypeLib typeLib)
{
string name;
string strDocString;
int dwHelpContext;
string strHelpFile;
typeLib.GetDocumentation(-1, out name, out strDocString, out dwHelpContext, out strHelpFile);
return name;
}
internal static string GetNameOfType(ComTypes.ITypeInfo typeInfo)
{
string name;
string documentation;
GetInfoFromType(typeInfo, out name, out documentation);
return name;
}
///
/// Look for typeinfo using IDispatch.GetTypeInfo.
///
///
///
/// Some COM objects just dont expose typeinfo. In these cases, this method will return null.
/// Some COM objects do intend to expose typeinfo, but may not be able to do so if the type-library is not properly
/// registered. This will be considered as acceptable or as an error condition depending on throwIfMissingExpectedTypeInfo
///
internal static ComTypes.ITypeInfo GetITypeInfoFromIDispatch(IDispatch dispatch, bool throwIfMissingExpectedTypeInfo)
{
uint typeCount;
int hresult = dispatch.TryGetTypeInfoCount(out typeCount);
if ((hresult == ComHresults.E_NOTIMPL) || (hresult == ComHresults.E_NOINTERFACE))
{
return null;
}
else
{
Marshal.ThrowExceptionForHR(hresult);
}
Debug.Assert(typeCount <= 1);
if (typeCount == 0)
{
return null;
}
IntPtr typeInfoPtr = IntPtr.Zero;
hresult = dispatch.TryGetTypeInfo(0, 0, out typeInfoPtr);
if (!Utils.Succeeded(hresult))
{
CheckIfMissingTypeInfoIsExpected(hresult, throwIfMissingExpectedTypeInfo);
return null;
}
if (typeInfoPtr == IntPtr.Zero)
{ // be defensive against components that return IntPtr.Zero
if (throwIfMissingExpectedTypeInfo)
{
Marshal.ThrowExceptionForHR(ComHresults.E_FAIL);
}
return null;
}
ComTypes.ITypeInfo typeInfo = null;
try
{
typeInfo = Marshal.GetObjectForIUnknown(typeInfoPtr) as ComTypes.ITypeInfo;
}
finally
{
Marshal.Release(typeInfoPtr);
}
return typeInfo;
}
///
/// This method should be called when typeinfo is not available for an object. The function
/// will check if the typeinfo is expected to be missing. This can include error cases where
/// the same error is guaranteed to happen all the time, on all machines, under all circumstances.
/// In such cases, we just have to operate without the typeinfo.
///
/// However, if accessing the typeinfo is failing in a transient way, we might want to throw
/// an exception so that we will eagerly predictably indicate the problem.
///
private static void CheckIfMissingTypeInfoIsExpected(int hresult, bool throwIfMissingExpectedTypeInfo)
{
Debug.Assert(!Utils.Succeeded(hresult));
// Word.Basic always returns this because of an incorrect implementation of IDispatch.GetTypeInfo
// Any implementation that returns E_NOINTERFACE is likely to do so in all environments
if (hresult == ComHresults.E_NOINTERFACE)
{
return;
}
// This assert is potentially over-restrictive since COM components can behave in quite unexpected ways.
// However, asserting the common expected cases ensures that we find out about the unexpected scenarios, and
// can investigate the scenarios to ensure that there is no bug in our own code.
Debug.Assert(hresult == ComHresults.TYPE_E_LIBNOTREGISTERED);
if (throwIfMissingExpectedTypeInfo)
{
Marshal.ThrowExceptionForHR(hresult);
}
}
[SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes")]
internal static ComTypes.TYPEATTR GetTypeAttrForTypeInfo(ComTypes.ITypeInfo typeInfo)
{
IntPtr pAttrs = IntPtr.Zero;
typeInfo.GetTypeAttr(out pAttrs);
// GetTypeAttr should never return null, this is just to be safe
if (pAttrs == IntPtr.Zero)
{
throw Error.CannotRetrieveTypeInformation();
}
try
{
return (ComTypes.TYPEATTR)Marshal.PtrToStructure(pAttrs, typeof(ComTypes.TYPEATTR));
}
finally
{
typeInfo.ReleaseTypeAttr(pAttrs);
}
}
[SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes")]
internal static ComTypes.TYPELIBATTR GetTypeAttrForTypeLib(ComTypes.ITypeLib typeLib)
{
IntPtr pAttrs = IntPtr.Zero;
typeLib.GetLibAttr(out pAttrs);
// GetTypeAttr should never return null, this is just to be safe
if (pAttrs == IntPtr.Zero)
{
throw Error.CannotRetrieveTypeInformation();
}
try
{
return (ComTypes.TYPELIBATTR)Marshal.PtrToStructure(pAttrs, typeof(ComTypes.TYPELIBATTR));
}
finally
{
typeLib.ReleaseTLibAttr(pAttrs);
}
}
public static BoundDispEvent CreateComEvent(object rcw, Guid sourceIid, int dispid)
{
return new BoundDispEvent(rcw, sourceIid, dispid);
}
public static DispCallable CreateDispCallable(IDispatchComObject dispatch, ComMethodDesc method)
{
return new DispCallable(dispatch, method.Name, method.DispId);
}
}
///
/// This class contains methods that either cannot be expressed in C#, or which require writing unsafe code.
/// Callers of these methods need to use them extremely carefully as incorrect use could cause GC-holes
/// and other problems.
///
internal static class UnsafeMethods
{
[System.Runtime.Versioning.ResourceExposure(System.Runtime.Versioning.ResourceScope.None)]
[System.Runtime.Versioning.ResourceConsumption(System.Runtime.Versioning.ResourceScope.Process, System.Runtime.Versioning.ResourceScope.Process)]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1060:MovePInvokesToNativeMethodsClass")] // TODO: fix
[DllImport("oleaut32.dll", PreserveSig = false)]
internal static extern void VariantClear(IntPtr variant);
[System.Runtime.Versioning.ResourceExposure(System.Runtime.Versioning.ResourceScope.Machine)]
[System.Runtime.Versioning.ResourceConsumption(System.Runtime.Versioning.ResourceScope.Machine, System.Runtime.Versioning.ResourceScope.Machine)]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1060:MovePInvokesToNativeMethodsClass")] // TODO: fix
[DllImport("oleaut32.dll", PreserveSig = false)]
internal static extern ComTypes.ITypeLib LoadRegTypeLib(ref Guid clsid, short majorVersion, short minorVersion, int lcid);
#region public members
private static readonly MethodInfo s_convertByrefToPtr = Create_ConvertByrefToPtr();
public delegate IntPtr ConvertByrefToPtrDelegate(ref T value);
private static readonly ConvertByrefToPtrDelegate s_convertVariantByrefToPtr = (ConvertByrefToPtrDelegate)Delegate.CreateDelegate(typeof(ConvertByrefToPtrDelegate), s_convertByrefToPtr.MakeGenericMethod(typeof(Variant)));
private static MethodInfo Create_ConvertByrefToPtr()
{
// We dont use AssemblyGen.DefineMethod since that can create a anonymously-hosted DynamicMethod which cannot contain unverifiable code.
var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("ComSnippets"), AssemblyBuilderAccess.Run);
var moduleBuilder = assemblyBuilder.DefineDynamicModule("ComSnippets");
var type = moduleBuilder.DefineType("Type$ConvertByrefToPtr", TypeAttributes.Public);
Type[] paramTypes = new Type[] { typeof(Variant).MakeByRefType() };
MethodBuilder mb = type.DefineMethod("ConvertByrefToPtr", MethodAttributes.Public | MethodAttributes.Static, typeof(IntPtr), paramTypes);
GenericTypeParameterBuilder[] typeParams = mb.DefineGenericParameters("T");
typeParams[0].SetGenericParameterAttributes(GenericParameterAttributes.NotNullableValueTypeConstraint);
mb.SetSignature(typeof(IntPtr), null, null, new Type[] { typeParams[0].MakeByRefType() }, null, null);
ILGenerator method = mb.GetILGenerator();
method.Emit(OpCodes.Ldarg_0);
method.Emit(OpCodes.Conv_I);
method.Emit(OpCodes.Ret);
return type.CreateType().GetMethod("ConvertByrefToPtr");
}
#region Generated Convert ByRef Delegates
// *** BEGIN GENERATED CODE ***
// generated by function: gen_ConvertByrefToPtrDelegates from: generate_comdispatch.py
private static readonly ConvertByrefToPtrDelegate s_convertSByteByrefToPtr = (ConvertByrefToPtrDelegate)Delegate.CreateDelegate(typeof(ConvertByrefToPtrDelegate), s_convertByrefToPtr.MakeGenericMethod(typeof(sbyte)));
private static readonly ConvertByrefToPtrDelegate s_convertInt16ByrefToPtr = (ConvertByrefToPtrDelegate)Delegate.CreateDelegate(typeof(ConvertByrefToPtrDelegate), s_convertByrefToPtr.MakeGenericMethod(typeof(Int16)));
private static readonly ConvertByrefToPtrDelegate s_convertInt32ByrefToPtr = (ConvertByrefToPtrDelegate)Delegate.CreateDelegate(typeof(ConvertByrefToPtrDelegate), s_convertByrefToPtr.MakeGenericMethod(typeof(Int32)));
private static readonly ConvertByrefToPtrDelegate s_convertInt64ByrefToPtr = (ConvertByrefToPtrDelegate)Delegate.CreateDelegate(typeof(ConvertByrefToPtrDelegate), s_convertByrefToPtr.MakeGenericMethod(typeof(Int64)));
private static readonly ConvertByrefToPtrDelegate s_convertByteByrefToPtr = (ConvertByrefToPtrDelegate)Delegate.CreateDelegate(typeof(ConvertByrefToPtrDelegate), s_convertByrefToPtr.MakeGenericMethod(typeof(byte)));
private static readonly ConvertByrefToPtrDelegate s_convertUInt16ByrefToPtr = (ConvertByrefToPtrDelegate)Delegate.CreateDelegate(typeof(ConvertByrefToPtrDelegate), s_convertByrefToPtr.MakeGenericMethod(typeof(UInt16)));
private static readonly ConvertByrefToPtrDelegate s_convertUInt32ByrefToPtr = (ConvertByrefToPtrDelegate)Delegate.CreateDelegate(typeof(ConvertByrefToPtrDelegate), s_convertByrefToPtr.MakeGenericMethod(typeof(UInt32)));
private static readonly ConvertByrefToPtrDelegate s_convertUInt64ByrefToPtr = (ConvertByrefToPtrDelegate)Delegate.CreateDelegate(typeof(ConvertByrefToPtrDelegate), s_convertByrefToPtr.MakeGenericMethod(typeof(UInt64)));
private static readonly ConvertByrefToPtrDelegate s_convertIntPtrByrefToPtr = (ConvertByrefToPtrDelegate)Delegate.CreateDelegate(typeof(ConvertByrefToPtrDelegate), s_convertByrefToPtr.MakeGenericMethod(typeof(IntPtr)));
private static readonly ConvertByrefToPtrDelegate s_convertUIntPtrByrefToPtr = (ConvertByrefToPtrDelegate)Delegate.CreateDelegate(typeof(ConvertByrefToPtrDelegate), s_convertByrefToPtr.MakeGenericMethod(typeof(UIntPtr)));
private static readonly ConvertByrefToPtrDelegate s_convertSingleByrefToPtr = (ConvertByrefToPtrDelegate)Delegate.CreateDelegate(typeof(ConvertByrefToPtrDelegate), s_convertByrefToPtr.MakeGenericMethod(typeof(Single)));
private static readonly ConvertByrefToPtrDelegate s_convertDoubleByrefToPtr = (ConvertByrefToPtrDelegate)Delegate.CreateDelegate(typeof(ConvertByrefToPtrDelegate), s_convertByrefToPtr.MakeGenericMethod(typeof(double)));
private static readonly ConvertByrefToPtrDelegate s_convertDecimalByrefToPtr = (ConvertByrefToPtrDelegate)Delegate.CreateDelegate(typeof(ConvertByrefToPtrDelegate), s_convertByrefToPtr.MakeGenericMethod(typeof(decimal)));
// *** END GENERATED CODE ***
#endregion
#region Generated Outer ConvertByrefToPtr
// *** BEGIN GENERATED CODE ***
// generated by function: gen_ConvertByrefToPtr from: generate_comdispatch.py
[SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
public static IntPtr ConvertSByteByrefToPtr(ref sbyte value) { return s_convertSByteByrefToPtr(ref value); }
[SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
public static IntPtr ConvertInt16ByrefToPtr(ref Int16 value) { return s_convertInt16ByrefToPtr(ref value); }
[SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
public static IntPtr ConvertInt32ByrefToPtr(ref Int32 value) { return s_convertInt32ByrefToPtr(ref value); }
[SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
public static IntPtr ConvertInt64ByrefToPtr(ref Int64 value) { return s_convertInt64ByrefToPtr(ref value); }
[SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
public static IntPtr ConvertByteByrefToPtr(ref byte value) { return s_convertByteByrefToPtr(ref value); }
[SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
public static IntPtr ConvertUInt16ByrefToPtr(ref UInt16 value) { return s_convertUInt16ByrefToPtr(ref value); }
[SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
public static IntPtr ConvertUInt32ByrefToPtr(ref UInt32 value) { return s_convertUInt32ByrefToPtr(ref value); }
[SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
public static IntPtr ConvertUInt64ByrefToPtr(ref UInt64 value) { return s_convertUInt64ByrefToPtr(ref value); }
[SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
public static IntPtr ConvertIntPtrByrefToPtr(ref IntPtr value) { return s_convertIntPtrByrefToPtr(ref value); }
[SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
public static IntPtr ConvertUIntPtrByrefToPtr(ref UIntPtr value) { return s_convertUIntPtrByrefToPtr(ref value); }
[SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
public static IntPtr ConvertSingleByrefToPtr(ref Single value) { return s_convertSingleByrefToPtr(ref value); }
[SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
public static IntPtr ConvertDoubleByrefToPtr(ref double value) { return s_convertDoubleByrefToPtr(ref value); }
[SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
public static IntPtr ConvertDecimalByrefToPtr(ref Decimal value) { return s_convertDecimalByrefToPtr(ref value); }
// *** END GENERATED CODE ***
#endregion
[SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
public static IntPtr ConvertVariantByrefToPtr(ref Variant value) { return s_convertVariantByrefToPtr(ref value); }
internal static Variant GetVariantForObject(object obj)
{
Variant variant = default(Variant);
if (obj == null)
{
return variant;
}
InitVariantForObject(obj, ref variant);
return variant;
}
internal static void InitVariantForObject(object obj, ref Variant variant)
{
Debug.Assert(obj != null);
// GetNativeVariantForObject is very expensive for values that marshal as VT_DISPATCH
// also is is extremely common scenario when object at hand is an RCW.
// Therefore we are going to test for IDispatch before defaulting to GetNativeVariantForObject.
IDispatch disp = obj as IDispatch;
if (disp != null)
{
variant.AsDispatch = obj;
return;
}
System.Runtime.InteropServices.Marshal.GetNativeVariantForObject(obj, ConvertVariantByrefToPtr(ref variant));
}
[Obsolete("do not use this method", true)]
public static object GetObjectForVariant(Variant variant)
{
IntPtr ptr = UnsafeMethods.ConvertVariantByrefToPtr(ref variant);
return System.Runtime.InteropServices.Marshal.GetObjectForNativeVariant(ptr);
}
[Obsolete("do not use this method", true)]
public static int IUnknownRelease(IntPtr interfacePointer)
{
return s_IUnknownRelease(interfacePointer);
}
[Obsolete("do not use this method", true)]
public static void IUnknownReleaseNotZero(IntPtr interfacePointer)
{
if (interfacePointer != IntPtr.Zero)
{
IUnknownRelease(interfacePointer);
}
}
[SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference")]
[Obsolete("do not use this method", true)]
public static int IDispatchInvoke(
IntPtr dispatchPointer,
int memberDispId,
ComTypes.INVOKEKIND flags,
ref ComTypes.DISPPARAMS dispParams,
out Variant result,
out ExcepInfo excepInfo,
out uint argErr
)
{
int hresult = s_IDispatchInvoke(
dispatchPointer,
memberDispId,
flags,
ref dispParams,
out result,
out excepInfo,
out argErr
);
if (hresult == ComHresults.DISP_E_MEMBERNOTFOUND
&& (flags & ComTypes.INVOKEKIND.INVOKE_FUNC) != 0
&& (flags & (ComTypes.INVOKEKIND.INVOKE_PROPERTYPUT | ComTypes.INVOKEKIND.INVOKE_PROPERTYPUTREF)) == 0)
{
// Re-invoke with no result argument to accomodate Word
hresult = _IDispatchInvokeNoResult(
dispatchPointer,
memberDispId,
ComTypes.INVOKEKIND.INVOKE_FUNC,
ref dispParams,
out result,
out excepInfo,
out argErr);
}
return hresult;
}
[Obsolete("do not use this method", true)]
public static IntPtr GetIdsOfNamedParameters(IDispatch dispatch, string[] names, int methodDispId, out GCHandle pinningHandle)
{
pinningHandle = GCHandle.Alloc(null, GCHandleType.Pinned);
int[] dispIds = new int[names.Length];
Guid empty = Guid.Empty;
int hresult = dispatch.TryGetIDsOfNames(ref empty, names, (uint)names.Length, 0, dispIds);
if (hresult < 0)
{
Marshal.ThrowExceptionForHR(hresult);
}
if (methodDispId != dispIds[0])
{
throw Error.GetIDsOfNamesInvalid(names[0]);
}
int[] keywordArgDispIds = dispIds.RemoveFirst(); // Remove the dispId of the method name
pinningHandle.Target = keywordArgDispIds;
return Marshal.UnsafeAddrOfPinnedArrayElement(keywordArgDispIds, 0);
}
#endregion
#region non-public members
[SuppressMessage("Microsoft.Performance", "CA1810:InitializeReferenceTypeStaticFieldsInline")]
static UnsafeMethods()
{
}
private static void EmitLoadArg(ILGenerator il, int index)
{
switch (index)
{
case 0:
il.Emit(OpCodes.Ldarg_0);
break;
case 1:
il.Emit(OpCodes.Ldarg_1);
break;
case 2:
il.Emit(OpCodes.Ldarg_2);
break;
case 3:
il.Emit(OpCodes.Ldarg_3);
break;
default:
if (index <= Byte.MaxValue)
{
il.Emit(OpCodes.Ldarg_S, (byte)index);
}
else
{
il.Emit(OpCodes.Ldarg, index);
}
break;
}
}
///
/// Ensure that "value" is a local variable in some caller's frame. So converting
/// the byref to an IntPtr is a safe operation. Alternatively, we could also allow
/// allowed "value" to be a pinned object.
///
[Conditional("DEBUG")]
public static void AssertByrefPointsToStack(IntPtr ptr)
{
if (Marshal.ReadInt32(ptr) == _dummyMarker)
{
// Prevent recursion
return;
}
int dummy = _dummyMarker;
IntPtr ptrToLocal = ConvertInt32ByrefToPtr(ref dummy);
Debug.Assert(ptrToLocal.ToInt64() < ptr.ToInt64());
Debug.Assert((ptr.ToInt64() - ptrToLocal.ToInt64()) < (16 * 1024));
}
private static readonly object s_lock = new object();
private static ModuleBuilder s_dynamicModule;
internal static ModuleBuilder DynamicModule
{
get
{
if (s_dynamicModule != null)
{
return s_dynamicModule;
}
lock (s_lock)
{
if (s_dynamicModule == null)
{
var attributes = new[] {
new CustomAttributeBuilder(typeof(UnverifiableCodeAttribute).GetConstructor(Type.EmptyTypes), Array.Empty