public PInvokeTargetNativeMethod(TypeDesc owningType, MethodSignature signature, PInvokeMetadata methodMetadata) { _owningType = owningType; _signature = signature; _methodMetadata = methodMetadata; _sequenceNumber = System.Threading.Interlocked.Increment(ref s_nativeMethodCounter); }
private PInvokeMarshallingILEmitter(MethodDesc targetMethod) { Debug.Assert(targetMethod.IsPInvoke); Debug.Assert(RequiresMarshalling(targetMethod)); _targetMethod = targetMethod; _importMetadata = targetMethod.GetPInvokeMethodMetadata(); _emitter = null; _marshallingCodeStream = null; }
private PInvokeILEmitter(MethodDesc targetMethod) { Debug.Assert(targetMethod.IsPInvoke); _targetMethod = targetMethod; _context = _targetMethod.Context; _importMetadata = targetMethod.GetPInvokeMethodMetadata(); _emitter = null; _marshallingCodeStream = null; _returnValueMarshallingCodeStream = null; _unmarshallingCodestream = null; }
/// <summary> /// Gets an object representing the static data for RVA mapped fields from the PE image. /// </summary> public ObjectNode GetFieldRvaData(FieldDesc field) { if (field.GetType() == typeof(Internal.IL.Stubs.PInvokeLazyFixupField)) { var pInvokeFixup = (Internal.IL.Stubs.PInvokeLazyFixupField)field; PInvokeMetadata metadata = pInvokeFixup.PInvokeMetadata; return(_nodeFactory.PInvokeMethodFixup(metadata.Module, metadata.Name)); } else { return(_nodeFactory.ReadOnlyDataBlob(NameMangler.GetMangledFieldName(field), ((EcmaField)field).GetFieldRvaData(), _typeSystemContext.Target.PointerSize)); } }
/// <summary> /// Gets an object representing the static data for RVA mapped fields from the PE image. /// </summary> public ObjectNode GetFieldRvaData(FieldDesc field) { if (field.GetType() == typeof(PInvokeLazyFixupField)) { var pInvokeFixup = (PInvokeLazyFixupField)field; PInvokeMetadata metadata = pInvokeFixup.PInvokeMetadata; return(NodeFactory.PInvokeMethodFixup(metadata.Module, metadata.Name)); } else { // Use the typical field definition in case this is an instantiated generic type field = field.GetTypicalFieldDefinition(); return(NodeFactory.ReadOnlyDataBlob(NameMangler.GetMangledFieldName(field), ((EcmaField)field).GetFieldRvaData(), NodeFactory.Target.PointerSize)); } }
public PInvokeMethodData(PInvokeLazyFixupField pInvokeLazyFixupField) { PInvokeMetadata metadata = pInvokeLazyFixupField.PInvokeMetadata; ModuleDesc declaringModule = ((MetadataType)pInvokeLazyFixupField.TargetMethod.OwningType).Module; DllImportSearchPath?dllImportSearchPath = default; if (declaringModule.Assembly is EcmaAssembly asm) { // We look for [assembly:DefaultDllImportSearchPaths(...)] var attrHandle = asm.MetadataReader.GetCustomAttributeHandle(asm.AssemblyDefinition.GetCustomAttributes(), "System.Runtime.InteropServices", "DefaultDllImportSearchPathsAttribute"); if (!attrHandle.IsNil) { var attr = asm.MetadataReader.GetCustomAttribute(attrHandle); var decoded = attr.DecodeValue(new CustomAttributeTypeProvider(asm)); if (decoded.FixedArguments.Length == 1 && decoded.FixedArguments[0].Value is int searchPath) { dllImportSearchPath = (DllImportSearchPath)searchPath; } } } ModuleData = new PInvokeModuleData(metadata.Module, dllImportSearchPath, declaringModule); EntryPointName = metadata.Name; CharSet charSetMangling = default; if (declaringModule.Context.Target.IsWindows && !metadata.Flags.ExactSpelling) { // Mirror CharSet normalization from Marshaller.CreateMarshaller bool isAnsi = metadata.Flags.CharSet switch { CharSet.Ansi => true, CharSet.Unicode => false, CharSet.Auto => false, _ => true }; charSetMangling = isAnsi ? CharSet.Ansi : CharSet.Unicode; } CharSetMangling = charSetMangling; }
/// <summary> /// Gets an object representing the static data for RVA mapped fields from the PE image. /// </summary> public virtual ISymbolNode GetFieldRvaData(FieldDesc field) { if (field.GetType() == typeof(PInvokeLazyFixupField)) { var pInvokeFixup = (PInvokeLazyFixupField)field; PInvokeMetadata metadata = pInvokeFixup.PInvokeMetadata; ModuleDesc callingModule = ((MetadataType)pInvokeFixup.TargetMethod.OwningType).Module; DllImportSearchPath?dllImportSearchPath = default; if (callingModule.Assembly is EcmaAssembly asm) { // We look for [assembly:DefaultDllImportSearchPaths(...)] var attrHandle = asm.MetadataReader.GetCustomAttributeHandle(asm.AssemblyDefinition.GetCustomAttributes(), "System.Runtime.InteropServices", "DefaultDllImportSearchPathsAttribute"); if (!attrHandle.IsNil) { var attr = asm.MetadataReader.GetCustomAttribute(attrHandle); var decoded = attr.DecodeValue(new CustomAttributeTypeProvider(asm)); if (decoded.FixedArguments.Length == 1 && decoded.FixedArguments[0].Value is int searchPath) { dllImportSearchPath = (DllImportSearchPath)searchPath; } } } PInvokeModuleData moduleData = new PInvokeModuleData(metadata.Module, dllImportSearchPath, callingModule); return(NodeFactory.PInvokeMethodFixup(moduleData, metadata.Name, metadata.Flags)); } else if (field is ExternSymbolMappedField externField) { return(NodeFactory.ExternSymbol(externField.SymbolName)); } else { // Use the typical field definition in case this is an instantiated generic type field = field.GetTypicalFieldDefinition(); return(NodeFactory.ReadOnlyDataBlob(NameMangler.GetMangledFieldName(field), ((EcmaField)field).GetFieldRvaData(), NodeFactory.Target.PointerSize)); } }
public static bool IsMarshallingRequired(MethodDesc targetMethod) { Debug.Assert(targetMethod.IsPInvoke); if (targetMethod.IsUnmanagedCallersOnly) { return(true); } PInvokeMetadata metadata = targetMethod.GetPInvokeMethodMetadata(); PInvokeFlags flags = metadata.Flags; if (flags.SetLastError) { return(true); } if (!flags.PreserveSig) { return(true); } if (MarshalHelpers.ShouldCheckForPendingException(targetMethod.Context.Target, metadata)) { return(true); } var marshallers = GetMarshallersForMethod(targetMethod); for (int i = 0; i < marshallers.Length; i++) { if (marshallers[i].IsMarshallingRequired()) { return(true); } } return(false); }
private PInvokeILEmitter(MethodDesc targetMethod, PInvokeILEmitterConfiguration pinvokeILEmitterConfiguration, InteropStateManager interopStateManager) { Debug.Assert(targetMethod.IsPInvoke || targetMethod is DelegateMarshallingMethodThunk || targetMethod is CalliMarshallingMethodThunk); _targetMethod = targetMethod; _pInvokeILEmitterConfiguration = pinvokeILEmitterConfiguration; _pInvokeMetadata = targetMethod.GetPInvokeMethodMetadata(); _interopStateManager = interopStateManager; // // targetMethod could be either a PInvoke or a DelegateMarshallingMethodThunk // ForwardNativeFunctionWrapper method thunks are marked as PInvokes, so it is // important to check them first here so that we get the right flags. // if (_targetMethod is DelegateMarshallingMethodThunk delegateMethod) { _flags = ((EcmaType)delegateMethod.DelegateType.GetTypeDefinition()).GetDelegatePInvokeFlags(); } else { _flags = _pInvokeMetadata.Flags; } _marshallers = InitializeMarshallers(targetMethod, interopStateManager, _flags); }
public PInvokeTargetNativeMethod(TypeDesc owningType, MethodSignature signature, PInvokeMetadata methodMetadata) { _owningType = owningType; _signature = signature; _methodMetadata = methodMetadata; }
public PInvokeLazyFixupField(DefType owningType, PInvokeMetadata pInvokeMetadata) { _owningType = owningType; _pInvokeMetadata = pInvokeMetadata; }
public MethodIL EmitIL() { MethodSignature targetMethodSignature = _targetMethod.Signature; // We have 4 code streams: // - _marshallingCodeStream is used to convert each argument into a native type and // store that into the local // - callsiteSetupCodeStream is used to used to load each previously generated local // and call the actual target native method. // - _returnValueMarshallingCodeStream is used to convert the native return value // to managed one. // - _unmarshallingCodestream is used to propagate [out] native arguments values to // managed ones. _emitter = new ILEmitter(); ILCodeStream fnptrLoadStream = _emitter.NewCodeStream(); _marshallingCodeStream = _emitter.NewCodeStream(); ILCodeStream callsiteSetupCodeStream = _emitter.NewCodeStream(); _returnValueMarshallingCodeStream = _emitter.NewCodeStream(); _unmarshallingCodestream = _emitter.NewCodeStream(); TypeDesc[] nativeParameterTypes = new TypeDesc[targetMethodSignature.Length]; // // Parameter marshalling // // // Convert each argument to something we can pass to native and store it in a local. // Then load the local in the second code stream. // for (int i = 0; i < targetMethodSignature.Length; i++) { // TODO: throw if there's custom marshalling _marshallingCodeStream.EmitLdArg(i); TypeDesc nativeType = MarshalArgument(targetMethodSignature[i]); nativeParameterTypes[i] = nativeType; ILLocalVariable vMarshalledTypeTemp = _emitter.NewLocal(nativeType); _marshallingCodeStream.EmitStLoc(vMarshalledTypeTemp); callsiteSetupCodeStream.EmitLdLoc(vMarshalledTypeTemp); } // // Return value marshalling // // TODO: throw if SetLastError is true // TODO: throw if there's custom marshalling TypeDesc nativeReturnType = MarshalReturnValue(targetMethodSignature.ReturnType); if (UseLazyResolution(_targetMethod, _importMetadata.Module)) { MetadataType lazyHelperType = _targetMethod.Context.GetHelperType("InteropHelpers"); FieldDesc lazyDispatchCell = new PInvokeLazyFixupField((DefType)_targetMethod.OwningType, _importMetadata); fnptrLoadStream.Emit(ILOpcode.ldsflda, _emitter.NewToken(lazyDispatchCell)); fnptrLoadStream.Emit(ILOpcode.call, _emitter.NewToken(lazyHelperType.GetKnownMethod("ResolvePInvoke", null))); MethodSignatureFlags unmanagedCallConv = PInvokeMetadata.GetUnmanagedCallingConvention(_importMetadata.Attributes); MethodSignature nativeCalliSig = new MethodSignature( targetMethodSignature.Flags | unmanagedCallConv, 0, nativeReturnType, nativeParameterTypes); ILLocalVariable vNativeFunctionPointer = _emitter.NewLocal(_targetMethod.Context.GetWellKnownType(WellKnownType.IntPtr)); fnptrLoadStream.EmitStLoc(vNativeFunctionPointer); callsiteSetupCodeStream.EmitLdLoc(vNativeFunctionPointer); callsiteSetupCodeStream.Emit(ILOpcode.calli, _emitter.NewToken(nativeCalliSig)); } else { // Eager call PInvokeMetadata nativeImportMetadata = new PInvokeMetadata(_importMetadata.Module, _importMetadata.Name ?? _targetMethod.Name, _importMetadata.Attributes); MethodSignature nativeSig = new MethodSignature( targetMethodSignature.Flags, 0, nativeReturnType, nativeParameterTypes); MethodDesc nativeMethod = new PInvokeTargetNativeMethod(_targetMethod.OwningType, nativeSig, nativeImportMetadata); callsiteSetupCodeStream.Emit(ILOpcode.call, _emitter.NewToken(nativeMethod)); } _unmarshallingCodestream.Emit(ILOpcode.ret); return(_emitter.Link(_targetMethod)); }
private MethodIL EmitIL() { PInvokeILCodeStreams pInvokeILCodeStreams = new PInvokeILCodeStreams(); ILEmitter emitter = pInvokeILCodeStreams.Emitter; ILCodeStream fnptrLoadStream = pInvokeILCodeStreams.FunctionPointerLoadStream; ILCodeStream callsiteSetupCodeStream = pInvokeILCodeStreams.CallsiteSetupCodeStream; ILCodeStream unmarshallingCodestream = pInvokeILCodeStreams.UnmarshallingCodestream; // Marshal the arguments for (int i = 0; i < _marshallers.Length; i++) { _marshallers[i].EmitMarshallingIL(pInvokeILCodeStreams); } // make the call TypeDesc nativeReturnType = _marshallers[0].NativeParameterType; TypeDesc[] nativeParameterTypes = new TypeDesc[_marshallers.Length - 1]; for (int i = 1; i < _marshallers.Length; i++) { nativeParameterTypes[i - 1] = _marshallers[i].NativeParameterType; } MethodDesc targetMethod = _methodData.TargetMethod; PInvokeMetadata importMetadata = _methodData.ImportMetadata; PInvokeILEmitterConfiguration pinvokeILEmitterConfiguration = _methodData.PInvokeILEmitterConfiguration; MethodSignature nativeSig; // if the SetLastError flag is set in DllImport, clear the error code before doing P/Invoke if ((importMetadata.Attributes & PInvokeAttributes.SetLastError) == PInvokeAttributes.SetLastError) { callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken( _methodData.PInvokeMarshal.GetKnownMethod("ClearLastWin32Error", null))); } if (targetMethod is DelegateMarshallingMethodThunk) { nativeSig = new MethodSignature(MethodSignatureFlags.Static, 0, nativeReturnType, nativeParameterTypes); TypeDesc[] parameters = new TypeDesc[_marshallers.Length - 1]; for (int i = 1; i < _marshallers.Length; i++) { parameters[i - 1] = _marshallers[i].ManagedParameterType; } MethodSignature managedSignature = new MethodSignature(MethodSignatureFlags.Static, 0, _marshallers[0].ManagedParameterType, parameters); fnptrLoadStream.Emit(ILOpcode.call, emitter.NewToken(targetMethod.Context.GetHelperType("InteropHelpers").GetKnownMethod("GetDelegateFunctionPointer", null))); ILLocalVariable vDelegateStub = emitter.NewLocal(targetMethod.Context.GetWellKnownType(WellKnownType.IntPtr)); fnptrLoadStream.EmitStLoc(vDelegateStub); callsiteSetupCodeStream.EmitLdLoc(vDelegateStub); callsiteSetupCodeStream.Emit(ILOpcode.calli, emitter.NewToken(managedSignature)); } else if (MarshalHelpers.UseLazyResolution(targetMethod, importMetadata.Module, pinvokeILEmitterConfiguration)) { MetadataType lazyHelperType = targetMethod.Context.GetHelperType("InteropHelpers"); FieldDesc lazyDispatchCell = new PInvokeLazyFixupField((DefType)targetMethod.OwningType, importMetadata); fnptrLoadStream.Emit(ILOpcode.ldsflda, emitter.NewToken(lazyDispatchCell)); fnptrLoadStream.Emit(ILOpcode.call, emitter.NewToken(lazyHelperType.GetKnownMethod("ResolvePInvoke", null))); MethodSignatureFlags unmanagedCallConv = PInvokeMetadata.GetUnmanagedCallingConvention(importMetadata.Attributes); nativeSig = new MethodSignature( targetMethod.Signature.Flags | unmanagedCallConv, 0, nativeReturnType, nativeParameterTypes); ILLocalVariable vNativeFunctionPointer = emitter.NewLocal(targetMethod.Context.GetWellKnownType(WellKnownType.IntPtr)); fnptrLoadStream.EmitStLoc(vNativeFunctionPointer); callsiteSetupCodeStream.EmitLdLoc(vNativeFunctionPointer); callsiteSetupCodeStream.Emit(ILOpcode.calli, emitter.NewToken(nativeSig)); } else { // Eager call PInvokeMetadata nativeImportMetadata = new PInvokeMetadata(importMetadata.Module, importMetadata.Name ?? targetMethod.Name, importMetadata.Attributes); nativeSig = new MethodSignature( targetMethod.Signature.Flags, 0, nativeReturnType, nativeParameterTypes); MethodDesc nativeMethod = new PInvokeTargetNativeMethod(targetMethod.OwningType, nativeSig, nativeImportMetadata, pinvokeILEmitterConfiguration.GetNextNativeMethodId()); callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken(nativeMethod)); } // if the SetLastError flag is set in DllImport, call the PInvokeMarshal.SaveLastWin32Error so that last error can be used later // by calling PInvokeMarshal.GetLastWin32Error if ((importMetadata.Attributes & PInvokeAttributes.SetLastError) == PInvokeAttributes.SetLastError) { callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken( _methodData.PInvokeMarshal.GetKnownMethod("SaveLastWin32Error", null))); } unmarshallingCodestream.Emit(ILOpcode.ret); return(new PInvokeILStubMethodIL((ILStubMethodIL)emitter.Link(targetMethod), IsStubRequired(), nativeSig)); }
public PInvokeTargetNativeMethod(TypeDesc owningType, MethodSignature signature, PInvokeMetadata methodMetadata, int sequenceNumber) { _owningType = owningType; _signature = signature; _methodMetadata = methodMetadata; _sequenceNumber = sequenceNumber; }
private MethodIL EmitIL() { PInvokeILCodeStreams pInvokeILCodeStreams = new PInvokeILCodeStreams(); ILEmitter emitter = pInvokeILCodeStreams.Emitter; ILCodeStream fnptrLoadStream = pInvokeILCodeStreams.FunctionPointerLoadStream; ILCodeStream callsiteSetupCodeStream = pInvokeILCodeStreams.CallsiteSetupCodeStream; ILCodeStream unmarshallingCodestream = pInvokeILCodeStreams.UnmarshallingCodestream; TypeSystemContext context = _targetMethod.Context; // Marshal the arguments for (int i = 0; i < _marshallers.Length; i++) { _marshallers[i].EmitMarshallingIL(pInvokeILCodeStreams); } // make the call TypeDesc nativeReturnType = _marshallers[0].NativeParameterType; TypeDesc[] nativeParameterTypes = new TypeDesc[_marshallers.Length - 1]; for (int i = 1; i < _marshallers.Length; i++) { nativeParameterTypes[i - 1] = _marshallers[i].NativeParameterType; } MethodSignature nativeSig; // if the SetLastError flag is set in DllImport, clear the error code before doing P/Invoke if (_importMetadata.Flags.SetLastError) { callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken( InteropTypes.GetPInvokeMarshal(context).GetKnownMethod("ClearLastWin32Error", null))); } DelegateMarshallingMethodThunk delegateMethod = _targetMethod as DelegateMarshallingMethodThunk; if (delegateMethod != null) { if (delegateMethod.IsOpenStaticDelegate) { // // For Open static delegates call // InteropHelpers.GetCurrentCalleeOpenStaticDelegateFunctionPointer() // which returns a function pointer. Just call the function pointer and we are done. // TypeDesc[] parameters = new TypeDesc[_marshallers.Length - 1]; for (int i = 1; i < _marshallers.Length; i++) { parameters[i - 1] = _marshallers[i].ManagedParameterType; } MethodSignature managedSignature = new MethodSignature(MethodSignatureFlags.Static, 0, _marshallers[0].ManagedParameterType, parameters); fnptrLoadStream.Emit(ILOpcode.call, emitter.NewToken(delegateMethod.Context.GetHelperType("InteropHelpers").GetKnownMethod("GetCurrentCalleeOpenStaticDelegateFunctionPointer", null))); ILLocalVariable vDelegateStub = emitter.NewLocal(delegateMethod.Context.GetWellKnownType(WellKnownType.IntPtr)); fnptrLoadStream.EmitStLoc(vDelegateStub); callsiteSetupCodeStream.EmitLdLoc(vDelegateStub); callsiteSetupCodeStream.Emit(ILOpcode.calli, emitter.NewToken(managedSignature)); } else { // // For closed delegates call // InteropHelpers.GetCurrentCalleeDelegate<Delegate> // which returns the delegate. Do a CallVirt on the invoke method. // MethodDesc instantiatedHelper = delegateMethod.Context.GetInstantiatedMethod( delegateMethod.Context.GetHelperType("InteropHelpers").GetKnownMethod("GetCurrentCalleeDelegate", null), new Instantiation((delegateMethod.DelegateType))); fnptrLoadStream.Emit(ILOpcode.call, emitter.NewToken(instantiatedHelper)); ILLocalVariable vDelegateStub = emitter.NewLocal(delegateMethod.DelegateType); fnptrLoadStream.EmitStLoc(vDelegateStub); fnptrLoadStream.EmitLdLoc(vDelegateStub); MethodDesc invokeMethod = delegateMethod.DelegateType.GetKnownMethod("Invoke", null); callsiteSetupCodeStream.Emit(ILOpcode.callvirt, emitter.NewToken(invokeMethod)); } } else if (MarshalHelpers.UseLazyResolution(_targetMethod, _importMetadata.Module, _pInvokeILEmitterConfiguration)) { MetadataType lazyHelperType = _targetMethod.Context.GetHelperType("InteropHelpers"); FieldDesc lazyDispatchCell = new PInvokeLazyFixupField((DefType)_targetMethod.OwningType, _importMetadata); fnptrLoadStream.Emit(ILOpcode.ldsflda, emitter.NewToken(lazyDispatchCell)); fnptrLoadStream.Emit(ILOpcode.call, emitter.NewToken(lazyHelperType.GetKnownMethod("ResolvePInvoke", null))); MethodSignatureFlags unmanagedCallConv = _importMetadata.Flags.UnmanagedCallingConvention; nativeSig = new MethodSignature( _targetMethod.Signature.Flags | unmanagedCallConv, 0, nativeReturnType, nativeParameterTypes); ILLocalVariable vNativeFunctionPointer = emitter.NewLocal(_targetMethod.Context.GetWellKnownType(WellKnownType.IntPtr)); fnptrLoadStream.EmitStLoc(vNativeFunctionPointer); callsiteSetupCodeStream.EmitLdLoc(vNativeFunctionPointer); callsiteSetupCodeStream.Emit(ILOpcode.calli, emitter.NewToken(nativeSig)); } else { // Eager call PInvokeMetadata nativeImportMetadata = new PInvokeMetadata(_importMetadata.Module, _importMetadata.Name ?? _targetMethod.Name, _importMetadata.Flags); nativeSig = new MethodSignature( _targetMethod.Signature.Flags, 0, nativeReturnType, nativeParameterTypes); MethodDesc nativeMethod = new PInvokeTargetNativeMethod(_targetMethod.OwningType, nativeSig, nativeImportMetadata, _pInvokeILEmitterConfiguration.GetNextNativeMethodId()); callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken(nativeMethod)); } // if the SetLastError flag is set in DllImport, call the PInvokeMarshal.SaveLastWin32Error so that last error can be used later // by calling PInvokeMarshal.GetLastWin32Error if (_importMetadata.Flags.SetLastError) { callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken( InteropTypes.GetPInvokeMarshal(context).GetKnownMethod("SaveLastWin32Error", null))); } unmarshallingCodestream.Emit(ILOpcode.ret); return(new PInvokeILStubMethodIL((ILStubMethodIL)emitter.Link(_targetMethod), IsStubRequired())); }
private MethodIL EmitIL() { // We have 4 code streams: // - _marshallingCodeStream is used to convert each argument into a native type and // store that into the local // - callsiteSetupCodeStream is used to used to load each previously generated local // and call the actual target native method. // - _returnValueMarshallingCodeStream is used to convert the native return value // to managed one. // - _unmarshallingCodestream is used to propagate [out] native arguments values to // managed ones. ILEmitter emitter = new ILEmitter(); ILCodeStream fnptrLoadStream = emitter.NewCodeStream(); ILCodeStream marshallingCodeStream = emitter.NewCodeStream(); ILCodeStream callsiteSetupCodeStream = emitter.NewCodeStream(); ILCodeStream returnValueMarshallingCodeStream = emitter.NewCodeStream(); ILCodeStream unmarshallingCodestream = emitter.NewCodeStream(); // Marshal the arguments for (int i = 0; i < _marshallers.Length; i++) { Marshaller marshaller = _marshallers[i]; marshaller.EmitMarshallingIL(emitter, marshallingCodeStream, callsiteSetupCodeStream, unmarshallingCodestream, returnValueMarshallingCodeStream); } // make the call TypeDesc nativeReturnType = _marshallers[0].NativeType; TypeDesc[] nativeParameterTypes = new TypeDesc[_marshallers.Length - 1]; for (int i = 1; i < _marshallers.Length; i++) { nativeParameterTypes[i - 1] = _marshallers[i].NativeType; } MethodDesc targetMethod = _methodData.TargetMethod; PInvokeMetadata importMetadata = _methodData.ImportMetadata; PInvokeILEmitterConfiguration pinvokeILEmitterConfiguration = _methodData.PInvokeILEmitterConfiguration; // if the SetLastError flag is set in DllImport, clear the error code before doing P/Invoke if ((importMetadata.Attributes & PInvokeAttributes.SetLastError) == PInvokeAttributes.SetLastError) { callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken( _methodData.PInvokeMarshal.GetKnownMethod("ClearLastWin32Error", null))); } if (MarshalHelpers.UseLazyResolution(targetMethod, importMetadata.Module, pinvokeILEmitterConfiguration)) { MetadataType lazyHelperType = targetMethod.Context.GetHelperType("InteropHelpers"); FieldDesc lazyDispatchCell = new PInvokeLazyFixupField((DefType)targetMethod.OwningType, importMetadata); fnptrLoadStream.Emit(ILOpcode.ldsflda, emitter.NewToken(lazyDispatchCell)); fnptrLoadStream.Emit(ILOpcode.call, emitter.NewToken(lazyHelperType.GetKnownMethod("ResolvePInvoke", null))); MethodSignatureFlags unmanagedCallConv = PInvokeMetadata.GetUnmanagedCallingConvention(importMetadata.Attributes); MethodSignature nativeCalliSig = new MethodSignature( targetMethod.Signature.Flags | unmanagedCallConv, 0, nativeReturnType, nativeParameterTypes); ILLocalVariable vNativeFunctionPointer = emitter.NewLocal(targetMethod.Context.GetWellKnownType(WellKnownType.IntPtr)); fnptrLoadStream.EmitStLoc(vNativeFunctionPointer); callsiteSetupCodeStream.EmitLdLoc(vNativeFunctionPointer); callsiteSetupCodeStream.Emit(ILOpcode.calli, emitter.NewToken(nativeCalliSig)); } else { // Eager call PInvokeMetadata nativeImportMetadata = new PInvokeMetadata(importMetadata.Module, importMetadata.Name ?? targetMethod.Name, importMetadata.Attributes); MethodSignature nativeSig = new MethodSignature( targetMethod.Signature.Flags, 0, nativeReturnType, nativeParameterTypes); MethodDesc nativeMethod = new PInvokeTargetNativeMethod(targetMethod.OwningType, nativeSig, nativeImportMetadata, pinvokeILEmitterConfiguration.GetNextNativeMethodId()); callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken(nativeMethod)); } // if the SetLastError flag is set in DllImport, call the PInvokeMarshal.SaveLastWin32Error so that last error can be used later // by calling PInvokeMarshal.GetLastWin32Error if ((importMetadata.Attributes & PInvokeAttributes.SetLastError) == PInvokeAttributes.SetLastError) { callsiteSetupCodeStream.Emit(ILOpcode.call, emitter.NewToken( _methodData.PInvokeMarshal.GetKnownMethod("SaveLastWin32Error", null))); } unmarshallingCodestream.Emit(ILOpcode.ret); return(emitter.Link(targetMethod)); }