diff --git a/DllImportGenerator/Ancillary.Interop/Ancillary.Interop.csproj b/DllImportGenerator/Ancillary.Interop/Ancillary.Interop.csproj
new file mode 100644
index 000000000000..ad8edc594033
--- /dev/null
+++ b/DllImportGenerator/Ancillary.Interop/Ancillary.Interop.csproj
@@ -0,0 +1,8 @@
+
+
+
+ net5.0
+ 8.0
+
+
+
diff --git a/DllImportGenerator/Ancillary.Interop/GeneratedDllImportAttribute.cs b/DllImportGenerator/Ancillary.Interop/GeneratedDllImportAttribute.cs
new file mode 100644
index 000000000000..0f0d322da4dd
--- /dev/null
+++ b/DllImportGenerator/Ancillary.Interop/GeneratedDllImportAttribute.cs
@@ -0,0 +1,25 @@
+#nullable enable
+
+namespace System.Runtime.InteropServices
+{
+ // [TODO] Remove once the attribute has been added to the BCL
+ [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
+ public sealed class GeneratedDllImportAttribute : Attribute
+ {
+ public bool BestFitMapping;
+ public CallingConvention CallingConvention;
+ public CharSet CharSet;
+ public string? EntryPoint;
+ public bool ExactSpelling;
+ public bool PreserveSig;
+ public bool SetLastError;
+ public bool ThrowOnUnmappableChar;
+
+ public GeneratedDllImportAttribute(string dllName)
+ {
+ this.Value = dllName;
+ }
+
+ public string Value { get; private set; }
+ }
+}
diff --git a/DllImportGenerator/Demo/Demo.csproj b/DllImportGenerator/Demo/Demo.csproj
index f03d8a3f6c20..09299b00addb 100644
--- a/DllImportGenerator/Demo/Demo.csproj
+++ b/DllImportGenerator/Demo/Demo.csproj
@@ -8,6 +8,7 @@
+
diff --git a/DllImportGenerator/DllImportGenerator.Test/CodeSnippets.cs b/DllImportGenerator/DllImportGenerator.Test/CodeSnippets.cs
index 18888cf58795..b69856e49064 100644
--- a/DllImportGenerator/DllImportGenerator.Test/CodeSnippets.cs
+++ b/DllImportGenerator/DllImportGenerator.Test/CodeSnippets.cs
@@ -153,6 +153,50 @@ partial class Test
[GeneratedDllImport(""DoesNotExist"", EntryPoint=""UserDefinedEntryPoint"")]
public static partial void NotAnExport();
}
+";
+
+ ///
+ /// Declaration with all DllImport named arguments.
+ ///
+ public static readonly string AllDllImportNamedArguments = @"
+using System.Runtime.InteropServices;
+partial class Test
+{
+ [GeneratedDllImport(""DoesNotExist"",
+ BestFitMapping = false,
+ CallingConvention = CallingConvention.Cdecl,
+ CharSet = CharSet.Unicode,
+ EntryPoint = ""UserDefinedEntryPoint"",
+ ExactSpelling = true,
+ PreserveSig = false,
+ SetLastError = true,
+ ThrowOnUnmappableChar = true)]
+ public static partial void Method();
+}
+";
+
+ ///
+ /// Declaration using various methods to compute constants in C#.
+ ///
+ public static readonly string UseCSharpFeaturesForConstants = @"
+using System.Runtime.InteropServices;
+partial class Test
+{
+ private const bool IsTrue = true;
+ private const bool IsFalse = false;
+ private const string EntryPointName = nameof(Test) + nameof(IsFalse);
+
+ [GeneratedDllImport(nameof(Test),
+ BestFitMapping = 0 != 1,
+ CallingConvention = (CallingConvention)1,
+ CharSet = (CharSet)2,
+ EntryPoint = EntryPointName,
+ ExactSpelling = IsTrue,
+ PreserveSig = IsFalse,
+ SetLastError = !IsFalse,
+ ThrowOnUnmappableChar = !IsTrue)]
+ public static partial void Method();
+}
";
///
@@ -181,6 +225,52 @@ partial class Test
[GeneratedDllImport(""DoesNotExist"")]
public static partial void Method(int t = 0);
}
+";
+
+ ///
+ /// Apply MarshalAsAttribute to parameters and return types.
+ ///
+ public static readonly string MarshalAsAttributeOnTypes = @"
+using System;
+using System.Runtime.InteropServices;
+namespace NS
+{
+ class MyCustomMarshaler : ICustomMarshaler
+ {
+ static ICustomMarshaler GetInstance(string pstrCookie)
+ => new MyCustomMarshaler();
+
+ public void CleanUpManagedData(object ManagedObj)
+ => throw new NotImplementedException();
+
+ public void CleanUpNativeData(IntPtr pNativeData)
+ => throw new NotImplementedException();
+
+ public int GetNativeDataSize()
+ => throw new NotImplementedException();
+
+ public IntPtr MarshalManagedToNative(object ManagedObj)
+ => throw new NotImplementedException();
+
+ public object MarshalNativeToManaged(IntPtr pNativeData)
+ => throw new NotImplementedException();
+ }
+}
+
+partial class Test
+{
+ [GeneratedDllImport(""DoesNotExist"")]
+ [return: MarshalAs(UnmanagedType.LPWStr)]
+ public static partial string Method1([MarshalAs(UnmanagedType.LPStr)]string t);
+
+ [GeneratedDllImport(""DoesNotExist"")]
+ [return: MarshalAs(UnmanagedType.LPWStr)]
+ public static partial string Method2([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(NS.MyCustomMarshaler), MarshalCookie=""COOKIE1"")]string t);
+
+ [GeneratedDllImport(""DoesNotExist"")]
+ [return: MarshalAs(UnmanagedType.LPWStr)]
+ public static partial string Method3([MarshalAs(UnmanagedType.CustomMarshaler, MarshalType = ""NS.MyCustomMarshaler"", MarshalCookie=""COOKIE2"")]string t);
+}
";
///
diff --git a/DllImportGenerator/DllImportGenerator.Test/Compiles.cs b/DllImportGenerator/DllImportGenerator.Test/Compiles.cs
index 5375ab26a7e7..85cd5cad87a8 100644
--- a/DllImportGenerator/DllImportGenerator.Test/Compiles.cs
+++ b/DllImportGenerator/DllImportGenerator.Test/Compiles.cs
@@ -14,8 +14,11 @@ public static IEnumerable