ENCODE_CHECK_FIELD_OFFSET,
ENCODE_DELEGATE_CTOR,
+ ENCODE_METHOD_NATIVE_ENTRY, /* NativeCallable method token */
ENCODE_MODULE_HANDLE = 0x50, /* Module token */
ENCODE_STATIC_FIELD_ADDRESS, /* For accessing a static field */
// to 1 on the clone. The buffer has to be large enough to hold the stub object and the code
virtual HRESULT GetStubClone(void *pStub, BYTE *pBuffer, DWORD dwBufferSize) = 0;
+ // true if the method has [NativeCallableAttribute]
+ virtual BOOL IsNativeCallableMethod(CORINFO_METHOD_HANDLE handle) = 0;
+
#ifdef CLR_STANDALONE_BINDER
virtual HRESULT GetMetadataRvaInfo(
OUT DWORD *pFirstMethodRvaOffset,
<Member MemberType="Field" Name="Sequential" />
<Member MemberType="Field" Name="value__" />
</Type>
+ <Type Name="System.Runtime.InteropServices.NativeCallableAttribute">
+ <Member Name="#ctor" />
+ <Member MemberType="Field" Name="CallingConvention" /> <!-- EE -->
+ <Member MemberType="Field" Name="EntryPoint" /> <!-- EE -->
+ </Type>
<Type Name="System.Runtime.InteropServices.Marshal">
<Member MemberType="Field" Name="SystemDefaultCharSize" />
<Member Name="AddRef(System.IntPtr)" />
<InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\InvalidComObjectException.cs" />
<InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\SafeArrayRankMismatchException.cs" />
<InteropSources Include="$(BclSourcesRoot)\System\Runtime\InteropServices\SafeArrayTypeMismatchException.cs" />
+ <InteropSources Condition="'$(FeatureCoreClr)'=='true'" Include="$(BclSourcesRoot)\System\Runtime\InteropServices\NativeCallableAttribute.cs" />
<InteropSources Condition="'$(FeatureCominterop)' != 'true'" Include="$(BclSourcesRoot)\System\Runtime\InteropServices\NonPortable.cs" />
<InteropSources Condition="'$(FeatureCominterop)' == 'true'" Include="$(BclSourcesRoot)\System\Runtime\InteropServices\DispatchWrapper.cs" />
<InteropSources Condition="'$(FeatureCominterop)' == 'true'" Include="$(BclSourcesRoot)\System\Runtime\InteropServices\ExtensibleClassFactory.cs" />
--- /dev/null
+// Copyright (c) Microsoft. All rights reserved.
+// Licensed under the MIT license. See LICENSE file in the project root for full license information.
+
+/*=============================================================================
+** Any method marked with NativeCallableAttribute can be directly called from
+** native code.The function token can be loaded to a local variable using LDFTN and
+** passed as a callback to native method.
+=============================================================================*/
+
+using System;
+using System.Runtime.CompilerServices;
+
+namespace System.Runtime.InteropServices
+{
+
+ [AttributeUsage(AttributeTargets.Method)]
+ public sealed class NativeCallableAttribute : Attribute
+ {
+ public NativeCallableAttribute()
+ {
+ }
+ // Optional. If omitted , compiler will choose one for you.
+ public CallingConvention CallingConvention;
+ // Optional. If omitted, then the method is native callable, but no EAT is emitted.
+ public string EntryPoint;
+ }
+}
\ No newline at end of file
NotSupported_CollectibleAssemblyResolve = Resolving to a collectible assembly is not supported.
NotSupported_CollectibleBoundNonCollectible = A non-collectible assembly may not reference a collectible assembly.
NotSupported_CollectibleDelegateMarshal = Delegate marshaling for types within collectible assemblies is not supported.
+NotSupported_NonStaticMethod = Non-static methods with NativeCallableAttribute are not supported.
+NotSupported_NativeCallableTarget = Methods with NativeCallableAttribute cannot be used as delegate target.
+NotSupported_GenericMethod = Generic methods with NativeCallableAttribute are not supported.
+NotSupported_NonBlittableTypes = Non-blittable parameter types are not supported for NativeCallable methods.
+
#if FEATURE_WINDOWSPHONE
NotSupported_UserDllImport = DllImport cannot be used on user-defined methods.
NotSupported_UserCOM = COM Interop is not supported for user-defined types.
extern NDirect__IsHostHookEnabled:proc
endif
extern UMThunkStubRareDisableWorker:proc
-
+extern ReversePInvokeBadTransition:proc
;
; METHODDESC_REGISTER: UMEntryThunk*
mov r12, rax ; r12 <- Thread*
+ ;FailFast if a native callable method invoked via ldftn and calli.
+ cmp dword ptr [r12 + OFFSETOF__Thread__m_fPreemptiveGCDisabled], 1
+ jz InvalidTransition
+
;
; disable preemptive GC
;
jmp HaveThread
+InvalidTransition:
+ ; ReversePInvokeBadTransition will failfast
+ call ReversePInvokeBadTransition
+
DoTrapReturningThreadsTHROW:
mov [rbp + UMThunkStubAMD64_ARGUMENTS_STACK_HOME_OFFSET + 0h], rcx
mov r12, rax // r12 <- Thread*
+ //FailFast if a native callable method invoked via ldftn and calli.
+ cmp dword ptr [r12 + OFFSETOF__Thread__m_fPreemptiveGCDisabled], 1
+ jz LOCAL_LABEL(InvalidTransition)
+
//
// disable preemptive GC
//
call C_FUNC(CreateThreadBlockThrow)
jmp LOCAL_LABEL(HaveThread)
+LOCAL_LABEL(InvalidTransition):
+ //No arguments to setup , ReversePInvokeBadTransition will failfast
+ call C_FUNC(ReversePInvokeBadTransition)
+
LOCAL_LABEL(DoTrapReturningThreadsTHROW):
mov rdi, r12 // Thread* pThread
mov rsi, [rbp - UMThunkStubAMD64_RBP_OFFSET + UMThunkStubAMD64_METHODDESC_OFFSET] // UMEntryThunk* pUMEntry
#define g_CompilerServicesUnsafeValueTypeAttribute "System.Runtime.CompilerServices.UnsafeValueTypeAttribute"
#define g_UnmanagedFunctionPointerAttribute "System.Runtime.InteropServices.UnmanagedFunctionPointerAttribute"
#define g_DefaultDllImportSearchPathsAttribute "System.Runtime.InteropServices.DefaultDllImportSearchPathsAttribute"
+#define g_NativeCallableAttribute "System.Runtime.InteropServices.NativeCallableAttribute"
#define g_CompilerServicesTypeDependencyAttribute "System.Runtime.CompilerServices.TypeDependencyAttribute"
#include "security.h"
#include "virtualcallstub.h"
#include "callingconvention.h"
+#include "customattribute.h"
+#include "../md/compiler/custattr.h"
#ifdef FEATURE_COMINTEROP
#include "comcallablewrapper.h"
#endif // FEATURE_COMINTEROP
}
#endif // FEATURE_CORECLR
+// Marshals a managed method to an unmanaged callback provided the
+// managed method is static and it's parameters require no marshalling.
+PCODE COMDelegate::ConvertToCallback(MethodDesc* pMD)
+{
+ CONTRACTL
+ {
+ THROWS;
+ GC_TRIGGERS;
+ INJECT_FAULT(COMPlusThrowOM());
+ }
+ CONTRACTL_END;
+
+ PCODE pCode = NULL;
+
+ // only static methods are allowed
+ if (!pMD->IsStatic())
+ COMPlusThrow(kNotSupportedException, W("NotSupported_NonStaticMethod"));
+
+ // no generic methods
+ if (pMD->IsGenericMethodDefinition())
+ COMPlusThrow(kNotSupportedException, W("NotSupported_GenericMethod"));
+
+ // Arguments
+ if (NDirect::MarshalingRequired(pMD, pMD->GetSig(), pMD->GetModule()))
+ COMPlusThrow(kNotSupportedException, W("NotSupported_NonBlittableTypes"));
+
+ // Get UMEntryThunk from appdomain thunkcache cache.
+ UMEntryThunk *pUMEntryThunk = GetAppDomain()->GetUMEntryThunkCache()->GetUMEntryThunk(pMD);
+
+#ifdef _TARGET_X86_
+
+ // System.Runtime.InteropServices.NativeCallableAttribute
+ BYTE* pData = NULL;
+ LONG cData = 0;
+ CorPinvokeMap callConv = (CorPinvokeMap)0;
+
+ HRESULT hr = pMD->GetMDImport()->GetCustomAttributeByName(pMD->GetMemberDef(), g_NativeCallableAttribute, (const VOID **)(&pData), (ULONG *)&cData);
+ IfFailThrow(hr);
+
+ if (cData > 0)
+ {
+ CustomAttributeParser ca(pData, cData);
+ // NativeCallable has two optional named arguments CallingConvention and EntryPoint.
+ CaNamedArg namedArgs[2];
+ CaTypeCtor caType(SERIALIZATION_TYPE_STRING);
+ // First, the void constructor.
+ IfFailThrow(ParseKnownCaArgs(ca, NULL, 0));
+
+ // Now the optional named properties
+ namedArgs[0].InitI4FieldEnum("CallingConvention", "System.Runtime.InteropServices.CallingConvention", (ULONG)callConv);
+ namedArgs[1].Init("EntryPoint", SERIALIZATION_TYPE_STRING, caType);
+ IfFailThrow(ParseKnownCaNamedArgs(ca, namedArgs, lengthof(namedArgs)));
+
+ callConv = (CorPinvokeMap)(namedArgs[0].val.u4 << 8);
+ // Let UMThunkMarshalInfo choose the default if calling convension not definied.
+ if (namedArgs[0].val.type.tag != SERIALIZATION_TYPE_UNDEFINED)
+ {
+ UMThunkMarshInfo* pUMThunkMarshalInfo = pUMEntryThunk->GetUMThunkMarshInfo();
+ pUMThunkMarshalInfo->SetCallingConvention(callConv);
+ }
+}
+#endif //_TARGET_X86_
+
+ pCode = (PCODE)pUMEntryThunk->GetCode();
+ _ASSERTE(pCode != NULL);
+ return pCode;
+}
+
// Marshals a delegate to a unmanaged callback.
LPVOID COMDelegate::ConvertToCallback(OBJECTREF pDelegateObj)
{
// that has the _methodBase field filled in with the LoaderAllocator of the collectible assembly
// associated with the instantiation.
BOOL fMaybeCollectibleAndStatic = FALSE;
+
+ // Do not allow static methods with [NativeCallableAttribute] to be a delegate target.
+ // A native callable method is special and allowing it to be delegate target will destabilize the runtime.
+ if (pTargetMethod->HasNativeCallableAttribute())
+ {
+ COMPlusThrow(kNotSupportedException, W("NotSupported_NativeCallableTarget"));
+ }
if (isStatic)
{
// Marshals a delegate to a unmanaged callback.
static LPVOID ConvertToCallback(OBJECTREF pDelegate);
+
+ // Marshals a managed method to an unmanaged callback , provided the method is static and uses only
+ // blittable parameter types.
+ static PCODE ConvertToCallback(MethodDesc* pMD);
// Marshals an unmanaged callback to Delegate
static OBJECTREF ConvertToDelegate(LPVOID pCallback, MethodTable* pMT);
// Depends on what things are persisted by CEEPreloader
BOOL CEEPreloader::CanEmbedFunctionEntryPoint(
- CORINFO_METHOD_HANDLE methodHandle,
- CORINFO_METHOD_HANDLE contextHandle, /* = NULL */
- CORINFO_ACCESS_FLAGS accessFlags /*=CORINFO_ACCESS_ANY*/)
+ CORINFO_METHOD_HANDLE methodHandle,
+ CORINFO_METHOD_HANDLE contextHandle, /* = NULL */
+ CORINFO_ACCESS_FLAGS accessFlags /*=CORINFO_ACCESS_ANY*/)
{
STANDARD_VM_CONTRACT;
- MethodDesc * pMethod = GetMethod(methodHandle);
+ MethodDesc * pMethod = GetMethod(methodHandle);
MethodDesc * pContext = GetMethod(contextHandle);
// IsRemotingInterceptedViaVirtualDispatch is a rather special case.
// don't save these stubs. Unlike most other remoting stubs these ones
// are NOT inserted by DoPrestub.
//
- if (((accessFlags & CORINFO_ACCESS_THIS) == 0) &&
- (pMethod->IsRemotingInterceptedViaVirtualDispatch()) )
+ if (((accessFlags & CORINFO_ACCESS_THIS) == 0) &&
+ (pMethod->IsRemotingInterceptedViaVirtualDispatch()))
{
return FALSE;
}
+ // Methods with native callable attribute are special , since
+ // they are used as LDFTN targets.Native Callable methods
+ // uses the same code path as reverse pinvoke and embedding them
+ // in an ngen image require saving the reverse pinvoke stubs.
+ if (pMethod->HasNativeCallableAttribute())
+ return FALSE;
+
return TRUE;
}
return FALSE;
}
+BOOL CEECompileInfo::IsNativeCallableMethod(CORINFO_METHOD_HANDLE handle)
+{
+ MethodDesc * pMethod = GetMethod(handle);
+ return pMethod->HasNativeCallableAttribute();
+}
+
BOOL CEEPreloader::CanSkipDependencyActivation(CORINFO_METHOD_HANDLE context,
CORINFO_MODULE_HANDLE moduleFrom,
CORINFO_MODULE_HANDLE moduleTo)
BOOL IsEmptyString(mdString token,
CORINFO_MODULE_HANDLE module);
+ BOOL IsNativeCallableMethod(CORINFO_METHOD_HANDLE handle);
+
BOOL IsCachingOfInliningHintsEnabled()
{
return m_fCachingOfInliningHintsEnabled;
RETURN pThunk;
}
+// FailFast if a native callable method invoked directly from managed code.
+// UMThunkStub.asm check the mode and call this function to failfast.
+extern "C" VOID STDCALL ReversePInvokeBadTransition()
+{
+ STATIC_CONTRACT_THROWS;
+ STATIC_CONTRACT_GC_TRIGGERS;
+ // Fail
+ EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE(
+ COR_E_EXECUTIONENGINE,
+ W("Invalid Program: attempted to call a NativeCallable method from runtime-typesafe code.")
+ );
+}
+
// Disable from a place that is calling into managed code via a UMEntryThunk.
extern "C" VOID STDCALL UMThunkStubRareDisableWorker(Thread *pThread, UMEntryThunk *pUMEntryThunk)
{
return (CorPinvokeMap)m_callConv;
}
+
+ VOID SetCallingConvention(const CorPinvokeMap callConv)
+ {
+ m_callConv = (UINT16)callConv;
+ }
+
#else
PCODE GetExecStubEntryPoint();
#endif
MethodDesc * pMD = GetMethod(ftn);
pResult->accessType = IAT_VALUE;
- pResult->addr = (void *) pMD->GetMultiCallableAddrOfCode();
+
+#ifndef CROSSGEN_COMPILE
+ // If LDFTN target has [NativeCallable] attribute , then create a UMEntryThunk.
+ if (pMD->HasNativeCallableAttribute())
+ {
+ pResult->addr = (void*)COMDelegate::ConvertToCallback(pMD);
+ }
+ else
+#endif //CROSSGEN_COMPILE
+ {
+ pResult->addr = (void *)pMD->GetMultiCallableAddrOfCode();
+ }
EE_TO_JIT_TRANSITION();
}
}
break;
+ // ENCODE_METHOD_NATIVECALLABLE_HANDLE is same as ENCODE_METHOD_ENTRY_DEF_TOKEN
+ // except for AddrOfCode
+ case ENCODE_METHOD_NATIVE_ENTRY:
case ENCODE_METHOD_ENTRY_DEF_TOKEN:
{
mdToken MethodDef = TokenFromRid(CorSigUncompressData(pBlob), mdtMethodDef);
}
MethodEntry:
- result = pMD->GetMultiCallableAddrOfCode(CORINFO_ACCESS_ANY);
+ if (kind == ENCODE_METHOD_NATIVE_ENTRY)
+ {
+ result = COMDelegate::ConvertToCallback(pMD);
+ }
+ else
+ {
+ result = pMD->GetMultiCallableAddrOfCode(CORINFO_ACCESS_ANY);
+ }
#ifndef _TARGET_ARM_
if (CORCOMPILE_IS_PCODE_TAGGED(result))
}
//*******************************************************************************
+BOOL MethodDesc::HasNativeCallableAttribute()
+{
+
+ CONTRACTL
+ {
+ THROWS;
+ GC_NOTRIGGER;
+ FORBID_FAULT;
+ }
+ CONTRACTL_END;
+
+// enable only for amd64 now, other platforms are not tested.
+#if defined(_TARGET_AMD64_)
+
+#ifdef FEATURE_CORECLR
+ HRESULT hr = GetMDImport()->GetCustomAttributeByName(GetMemberDef(),
+ g_NativeCallableAttribute,
+ NULL,
+ NULL);
+ return (hr == S_OK);
+#endif //FEATURE_CORECLR
+
+#endif //_TARGET_AMD64_
+ return FALSE;
+}
+
+//*******************************************************************************
BOOL MethodDesc::HasSuppressUnmanagedCodeAccessAttr()
{
LIMITED_METHOD_CONTRACT;
void ComputeSuppressUnmanagedCodeAccessAttr(IMDInternalImport *pImport);
BOOL HasSuppressUnmanagedCodeAccessAttr();
+ BOOL HasNativeCallableAttribute();
#ifdef FEATURE_COMINTEROP
inline DWORD IsComPlusCall()
if (token != mdTokenNil)
{
_ASSERTE(TypeFromToken(token) == mdtMethodDef || TypeFromToken(token) == mdtMemberRef);
-
- pTable->EncodeModule(
- (TypeFromToken(token) == mdtMethodDef) ? ENCODE_METHOD_ENTRY_DEF_TOKEN : ENCODE_METHOD_ENTRY_REF_TOKEN,
- referencingModule, pSigBuilder);
+
+ // It's a NativeCallable method , then encode it as ENCODE_METHOD_NATIVE_ENTRY
+ if (pTable->GetCompileInfo()->IsNativeCallableMethod(handle))
+ {
+ pTable->EncodeModule(ENCODE_METHOD_NATIVE_ENTRY, referencingModule, pSigBuilder);
+ }
+ else
+ {
+ pTable->EncodeModule(
+ (TypeFromToken(token) == mdtMethodDef) ? ENCODE_METHOD_ENTRY_DEF_TOKEN : ENCODE_METHOD_ENTRY_REF_TOKEN,
+ referencingModule, pSigBuilder);
+ }
pSigBuilder->AppendData(RidFromToken(token));
}
--- /dev/null
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Runtime.CompilerServices;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Runtime.InteropServices;
+using System.Threading;
+
+public class Program
+{
+ public static class NativeMethods
+ {
+ [DllImport("user32.dll")]
+ public static extern int EnumWindows(IntPtr enumProc, IntPtr lParam);
+ }
+
+ private delegate void NativeMethodInvoker();
+ static EventWaitHandle waitHandle = new AutoResetEvent(false);
+
+ public static int Main()
+ {
+ //NegativeTest_NonBlittable();
+ TestNativeCallableValid();
+ //NegativeTest_ViaDelegate();
+ //NegativeTest_ViaLdftn();
+ return 100;
+ }
+
+ public static void TestNativeCallableValid()
+ {
+ /*
+ void TestNativeCallable()
+ {
+ .locals init ([0] native int ptr)
+ IL_0000: nop
+ IL_0002: ldftn int32 CallbackMethod(native int,native int)
+
+ IL_0012: stloc.0
+ IL_0013: ldloc.0
+ IL_0014: ldsfld native int [mscorlib]System.IntPtr::Zero
+ IL_0019: call bool NativeMethods::EnumWindows(native int,
+ native int)
+ IL_001e: pop
+ IL_001f: ret
+ }
+ */
+ DynamicMethod testNativeCallable = new DynamicMethod("TestNativeCallable", null, null, typeof(Program).Module);
+ ILGenerator il = testNativeCallable.GetILGenerator();
+ il.DeclareLocal(typeof(IntPtr));
+ il.Emit(OpCodes.Nop);
+ il.Emit(OpCodes.Ldftn, typeof(Program).GetMethod("CallbackMethod"));
+ il.Emit(OpCodes.Stloc_0);
+ il.Emit(OpCodes.Ldloc_0);
+ il.Emit(OpCodes.Ldsfld, typeof(IntPtr).GetField("Zero"));
+ il.Emit(OpCodes.Call, typeof(NativeMethods).GetMethod("EnumWindows"));
+ il.Emit(OpCodes.Pop);
+ il.Emit(OpCodes.Ret);
+ NativeMethodInvoker testNativeMethod = (NativeMethodInvoker)testNativeCallable.CreateDelegate(typeof(NativeMethodInvoker));
+ testNativeMethod();
+ }
+
+ public static void NegativeTest_ViaDelegate()
+ {
+ // Try invoking method directly
+ try
+ {
+ Func<IntPtr, IntPtr, int> invoker = CallbackMethod;
+ invoker(IntPtr.Zero, IntPtr.Zero);
+ }
+ catch (Exception)
+ {
+
+ }
+ }
+
+ public static void NegativeTest_NonBlittable()
+ {
+ // Try invoking method directly
+ try
+ {
+ Func<bool, int> invoker = CallbackMethodNonBlitabble;
+ invoker(true);
+ }
+ catch (Exception)
+ {
+ Console.WriteLine(":bla");
+ }
+ }
+
+
+ public static void NegativeTest_ViaLdftn()
+ {
+ /*
+ .locals init (native int V_0)
+ IL_0000: nop
+ IL_0001: ldftn void ConsoleApplication1.Program::callback(int32)
+ IL_0007: stloc.0
+ IL_0008: ldc.i4.s 12
+ IL_000a: ldloc.0
+ IL_000b: calli void(int32)
+ IL_0010: nop
+ IL_0011: ret
+ */
+ DynamicMethod testNativeCallable = new DynamicMethod("TestNativeCallableLdftn", null, null, typeof(Program).Module);
+ ILGenerator il = testNativeCallable.GetILGenerator();
+ il.DeclareLocal(typeof(IntPtr));
+ il.Emit(OpCodes.Nop);
+ il.Emit(OpCodes.Ldftn, typeof(Program).GetMethod("LdftnCallback"));
+ il.Emit(OpCodes.Stloc_0);
+ il.Emit(OpCodes.Ldc_I4,12);
+ il.Emit(OpCodes.Ldloc_0);
+
+ SignatureHelper sig = SignatureHelper.GetMethodSigHelper(typeof(Program).Module, null, new Type[] { typeof(int) });
+ sig.AddArgument(typeof(int));
+
+ // il.EmitCalli is not available and the below is not correct
+ il.Emit(OpCodes.Calli,sig);
+ il.Emit(OpCodes.Nop);
+ il.Emit(OpCodes.Ret);
+
+ NativeMethodInvoker testNativeMethod = (NativeMethodInvoker)testNativeCallable.CreateDelegate(typeof(NativeMethodInvoker));
+ testNativeMethod();
+
+ }
+
+ #region callbacks
+ [NativeCallable]
+ public static void LdftnCallback(int val)
+ {
+ }
+
+ [NativeCallable]
+ public static int CallbackMethod(IntPtr hWnd, IntPtr lParam)
+ {
+ waitHandle.Set();
+ return 1;
+ }
+
+ [NativeCallable]
+ public static int CallbackMethodGeneric<T>(IntPtr hWnd, IntPtr lParam)
+ {
+ return 1;
+ }
+
+ [NativeCallable]
+ public static int CallbackMethodNonBlitabble(bool x1)
+ {
+ return 1;
+ }
+ #endregion //callbacks
+
+}
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <AssemblyName>NativeCallableTest</AssemblyName>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <FileAlignment>512</FileAlignment>
+ <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages</ReferencePath>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+ <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp>
+ <DefineConstants>$(DefineConstants);STATIC</DefineConstants>
+ <ReferenceLocalMscorlib>true</ReferenceLocalMscorlib>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
+ </PropertyGroup>
+ <ItemGroup>
+ <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+ <Visible>False</Visible>
+ </CodeAnalysisDependentAssemblyPaths>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="project.json" />
+ <None Include="app.config" />
+ </ItemGroup>
+ <ItemGroup>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="NativeCallableTest.cs" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+ <runtime>
+ <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
+ </assemblyBinding>
+ </runtime>
+</configuration>
\ No newline at end of file
--- /dev/null
+{
+ "dependencies": {
+ },
+ "frameworks": {
+ "dnxcore50": {}
+ }
+}
--- /dev/null
+{
+ "locked": true,
+ "version": -9996,
+ "targets": {
+ "DNXCore,Version=v5.0": {}
+ },
+ "libraries": {},
+ "projectFileDependencyGroups": {
+ "": [],
+ "DNXCore,Version=v5.0": []
+ }
+}
\ No newline at end of file