{
internal static partial class Advapi32
{
-#if DLLIMPORTGENERATOR_ENABLED
[GeneratedDllImport(Libraries.Advapi32, EntryPoint = "LookupPrivilegeValueW", CharSet = CharSet.Unicode, SetLastError = true)]
internal static partial bool LookupPrivilegeValue(
-#else
- [DllImport(Libraries.Advapi32, EntryPoint = "LookupPrivilegeValueW", CharSet = CharSet.Unicode, SetLastError = true, BestFitMapping = false)]
- internal static extern bool LookupPrivilegeValue(
-#endif
[MarshalAs(UnmanagedType.LPTStr)] string? lpSystemName, [MarshalAs(UnmanagedType.LPTStr)] string lpName, out LUID lpLuid);
internal const string SeDebugPrivilege = "SeDebugPrivilege";
{
// Note: RegCreateKeyEx won't set the last error on failure - it returns
// an error code if it fails.
-#if DLLIMPORTGENERATOR_ENABLED
[GeneratedDllImport(Libraries.Advapi32, EntryPoint = "RegCreateKeyExW", CharSet = CharSet.Unicode, ExactSpelling = true)]
internal static partial int RegCreateKeyEx(
-#else
- [DllImport(Libraries.Advapi32, EntryPoint = "RegCreateKeyExW", BestFitMapping = false, CharSet = CharSet.Unicode, ExactSpelling = true)]
- internal static extern int RegCreateKeyEx(
-#endif
SafeRegistryHandle hKey,
string lpSubKey,
int Reserved,
{
internal static partial class Advapi32
{
-#if DLLIMPORTGENERATOR_ENABLED
[GeneratedDllImport(Libraries.Advapi32, EntryPoint = "RegDeleteKeyExW", CharSet = CharSet.Unicode, ExactSpelling = true)]
internal static partial int RegDeleteKeyEx(
-#else
- [DllImport(Libraries.Advapi32, EntryPoint = "RegDeleteKeyExW", BestFitMapping = false, CharSet = CharSet.Unicode, ExactSpelling = true)]
- internal static extern int RegDeleteKeyEx(
-#endif
SafeRegistryHandle hKey,
string lpSubKey,
int samDesired,
{
internal static partial class Advapi32
{
-#if DLLIMPORTGENERATOR_ENABLED
[GeneratedDllImport(Libraries.Advapi32, EntryPoint = "RegDeleteValueW", CharSet = CharSet.Unicode, ExactSpelling = true)]
internal static partial int RegDeleteValue(
-#else
- [DllImport(Libraries.Advapi32, EntryPoint = "RegDeleteValueW", BestFitMapping = false, CharSet = CharSet.Unicode, ExactSpelling = true)]
- internal static extern int RegDeleteValue(
-#endif
SafeRegistryHandle hKey,
string? lpValueName);
}
{
internal static partial class Advapi32
{
-#if DLLIMPORTGENERATOR_ENABLED
[GeneratedDllImport(Libraries.Advapi32)]
- internal static partial int RegFlushKey(
-#else
- [DllImport(Libraries.Advapi32)]
- internal static extern int RegFlushKey(
-#endif
- SafeRegistryHandle hKey);
+ internal static partial int RegFlushKey(SafeRegistryHandle hKey);
}
}
{
internal static partial class Advapi32
{
-#if DLLIMPORTGENERATOR_ENABLED
[GeneratedDllImport(Libraries.Advapi32, EntryPoint = "RegOpenKeyExW", CharSet = CharSet.Unicode, ExactSpelling = true)]
internal static partial int RegOpenKeyEx(
-#else
- [DllImport(Libraries.Advapi32, EntryPoint = "RegOpenKeyExW", CharSet = CharSet.Unicode, ExactSpelling = true)]
- internal static extern int RegOpenKeyEx(
-#endif
SafeRegistryHandle hKey,
string? lpSubKey,
int ulOptions,
int samDesired,
out SafeRegistryHandle hkResult);
-
-#if DLLIMPORTGENERATOR_ENABLED
[GeneratedDllImport(Libraries.Advapi32, EntryPoint = "RegOpenKeyExW", CharSet = CharSet.Unicode, ExactSpelling = true)]
internal static partial int RegOpenKeyEx(
-#else
- [DllImport(Libraries.Advapi32, EntryPoint = "RegOpenKeyExW", BestFitMapping = false, CharSet = CharSet.Unicode, ExactSpelling = true)]
- internal static extern int RegOpenKeyEx(
-#endif
IntPtr hKey,
string? lpSubKey,
int ulOptions,
{
internal static partial class Advapi32
{
-#if DLLIMPORTGENERATOR_ENABLED
[GeneratedDllImport(Libraries.Advapi32, EntryPoint = "RegSetValueExW", CharSet = CharSet.Unicode, ExactSpelling = true)]
internal static partial int RegSetValueEx(
-#else
- [DllImport(Libraries.Advapi32, EntryPoint = "RegSetValueExW", BestFitMapping = false, CharSet = CharSet.Unicode, ExactSpelling = true)]
- internal static extern int RegSetValueEx(
-#endif
SafeRegistryHandle hKey,
string? lpValueName,
int Reserved,
byte[]? lpData,
int cbData);
-#if DLLIMPORTGENERATOR_ENABLED
[GeneratedDllImport(Libraries.Advapi32, EntryPoint = "RegSetValueExW", CharSet = CharSet.Unicode, ExactSpelling = true)]
internal static partial int RegSetValueEx(
-#else
- [DllImport(Libraries.Advapi32, EntryPoint = "RegSetValueExW", BestFitMapping = false, CharSet = CharSet.Unicode, ExactSpelling = true)]
- internal static extern int RegSetValueEx(
-#endif
SafeRegistryHandle hKey,
string? lpValueName,
int Reserved,
char[]? lpData,
int cbData);
-#if DLLIMPORTGENERATOR_ENABLED
[GeneratedDllImport(Libraries.Advapi32, EntryPoint = "RegSetValueExW", CharSet = CharSet.Unicode, ExactSpelling = true)]
internal static partial int RegSetValueEx(
-#else
- [DllImport(Libraries.Advapi32, EntryPoint = "RegSetValueExW", BestFitMapping = false, CharSet = CharSet.Unicode, ExactSpelling = true)]
- internal static extern int RegSetValueEx(
-#endif
SafeRegistryHandle hKey,
string? lpValueName,
int Reserved,
ref int lpData,
int cbData);
-#if DLLIMPORTGENERATOR_ENABLED
[GeneratedDllImport(Libraries.Advapi32, EntryPoint = "RegSetValueExW", CharSet = CharSet.Unicode, ExactSpelling = true)]
internal static partial int RegSetValueEx(
-#else
- [DllImport(Libraries.Advapi32, EntryPoint = "RegSetValueExW", BestFitMapping = false, CharSet = CharSet.Unicode, ExactSpelling = true)]
- internal static extern int RegSetValueEx(
-#endif
SafeRegistryHandle hKey,
string? lpValueName,
int Reserved,
ref long lpData,
int cbData);
-#if DLLIMPORTGENERATOR_ENABLED
[GeneratedDllImport(Libraries.Advapi32, EntryPoint = "RegSetValueExW", CharSet = CharSet.Unicode, ExactSpelling = true)]
internal static partial int RegSetValueEx(
-#else
- [DllImport(Libraries.Advapi32, EntryPoint = "RegSetValueExW", BestFitMapping = false, CharSet = CharSet.Unicode, ExactSpelling = true)]
- internal static extern int RegSetValueEx(
-#endif
SafeRegistryHandle hKey,
string? lpValueName,
int Reserved,
/// <summary>
/// WARNING: This method does not implicitly handle long paths. Use GetFullPathName or PathHelper.
/// </summary>
-#if DLLIMPORTGENERATOR_ENABLED
[GeneratedDllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
internal static partial uint GetFullPathNameW(
-#else
- [DllImport(Libraries.Kernel32, BestFitMapping = false, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
- internal static extern uint GetFullPathNameW(
-#endif
ref char lpFileName,
uint nBufferLength,
ref char lpBuffer,
/// <summary>
/// WARNING: This method does not implicitly handle long paths. Use GetFullPath/PathHelper.
/// </summary>
-#if DLLIMPORTGENERATOR_ENABLED
[GeneratedDllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
internal static partial uint GetLongPathNameW(
-#else
- [DllImport(Libraries.Kernel32, BestFitMapping = false, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
- internal static extern uint GetLongPathNameW(
-#endif
ref char lpszShortPath,
ref char lpszLongPath,
uint cchBuffer);
//
// Types in this file are used for generated p/invokes (docs/design/features/source-generator-pinvokes.md).
-// See the DllImportGenerator experiment in https://github.com/dotnet/runtimelab.
//
namespace System.Runtime.InteropServices
{
#endif
sealed class GeneratedDllImportAttribute : Attribute
{
- public bool BestFitMapping { get; set; }
- public CallingConvention CallingConvention { get; set; }
public CharSet CharSet { get; set; }
public string? EntryPoint { get; set; }
public bool ExactSpelling { get; set; }
public bool PreserveSig { get; set; }
public bool SetLastError { get; set; }
- public bool ThrowOnUnmappableChar { get; set; }
public GeneratedDllImportAttribute(string dllName)
{
<Reference Include="System.Memory" />
<Reference Include="System.Resources.ResourceManager" />
<Reference Include="System.Runtime" />
+ <Reference Include="System.Runtime.CompilerServices.Unsafe" />
<Reference Include="System.Runtime.Extensions" />
<Reference Include="System.Runtime.InteropServices" />
</ItemGroup>
<PropertyGroup>
<DefineConstants>$(DefineConstants);REGISTRY_ASSEMBLY</DefineConstants>
<TargetFrameworks>$(NetCoreAppCurrent)-windows</TargetFrameworks>
+ <EnableDllImportGenerator>true</EnableDllImportGenerator>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(CommonPath)Interop\Windows\Interop.Libraries.cs"
// documented semanatics of DllImportAttribute:
// - https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.dllimportattribute
DllImportMember userDefinedValues = DllImportMember.None;
- bool bestFitMapping = false;
- CallingConvention callingConvention = CallingConvention.Winapi;
CharSet charSet = CharSet.Ansi;
string? entryPoint = null;
bool exactSpelling = false; // VB has different and unusual default behavior here.
bool preserveSig = true;
bool setLastError = false;
- bool throwOnUnmappableChar = false;
// All other data on attribute is defined as NamedArguments.
foreach (KeyValuePair<string, TypedConstant> namedArg in attrData.NamedArguments)
default:
Debug.Fail($"An unknown member was found on {GeneratedDllImport}");
continue;
- case nameof(GeneratedDllImportData.BestFitMapping):
- userDefinedValues |= DllImportMember.BestFitMapping;
- bestFitMapping = (bool)namedArg.Value.Value!;
- break;
- case nameof(GeneratedDllImportData.CallingConvention):
- userDefinedValues |= DllImportMember.CallingConvention;
- callingConvention = (CallingConvention)namedArg.Value.Value!;
- break;
case nameof(GeneratedDllImportData.CharSet):
userDefinedValues |= DllImportMember.CharSet;
charSet = (CharSet)namedArg.Value.Value!;
userDefinedValues |= DllImportMember.SetLastError;
setLastError = (bool)namedArg.Value.Value!;
break;
- case nameof(GeneratedDllImportData.ThrowOnUnmappableChar):
- userDefinedValues |= DllImportMember.ThrowOnUnmappableChar;
- throwOnUnmappableChar = (bool)namedArg.Value.Value!;
- break;
}
}
return new GeneratedDllImportData(attrData.ConstructorArguments[0].Value!.ToString())
{
IsUserDefined = userDefinedValues,
- BestFitMapping = bestFitMapping,
- CallingConvention = callingConvention,
CharSet = charSet,
EntryPoint = entryPoint,
ExactSpelling = exactSpelling,
PreserveSig = preserveSig,
SetLastError = setLastError,
- ThrowOnUnmappableChar = throwOnUnmappableChar
};
}
// Process the GeneratedDllImport attribute
GeneratedDllImportData stubDllImportData = ProcessGeneratedDllImportAttribute(generatedDllImportAttr!);
- if (stubDllImportData.IsUserDefined.HasFlag(DllImportMember.BestFitMapping))
- {
- generatorDiagnostics.ReportConfigurationNotSupported(generatedDllImportAttr!, nameof(GeneratedDllImportData.BestFitMapping));
- }
-
- if (stubDllImportData.IsUserDefined.HasFlag(DllImportMember.ThrowOnUnmappableChar))
- {
- generatorDiagnostics.ReportConfigurationNotSupported(generatedDllImportAttr!, nameof(GeneratedDllImportData.ThrowOnUnmappableChar));
- }
-
- if (stubDllImportData.IsUserDefined.HasFlag(DllImportMember.CallingConvention))
- {
- generatorDiagnostics.ReportConfigurationNotSupported(generatedDllImportAttr!, nameof(GeneratedDllImportData.CallingConvention));
- }
-
if (lcidConversionAttr != null)
{
// Using LCIDConversion with GeneratedDllImport is not supported
generatorDiagnostics.ReportConfigurationNotSupported(lcidConversionAttr, nameof(TypeNames.LCIDConversionAttribute));
}
- List<AttributeSyntax> additionalAttributes = GenerateSyntaxForForwardedAttributes(suppressGCTransitionAttribute, unmanagedCallConvAttribute);
// Create the stub.
var dllImportStub = DllImportStubContext.Create(symbol, stubDllImportData, environment, generatorDiagnostics, ct);
+ List<AttributeSyntax> additionalAttributes = GenerateSyntaxForForwardedAttributes(suppressGCTransitionAttribute, unmanagedCallConvAttribute);
return new IncrementalStubGenerationContext(environment, dllImportStub, additionalAttributes.ToImmutableArray(), stubDllImportData, generatorDiagnostics.Diagnostics.ToImmutableArray());
}
CreateStringExpressionSyntax(targetDllImportData.EntryPoint!))
};
- if (targetDllImportData.IsUserDefined.HasFlag(DllImportMember.BestFitMapping))
- {
- NameEqualsSyntax name = NameEquals(nameof(DllImportAttribute.BestFitMapping));
- ExpressionSyntax value = CreateBoolExpressionSyntax(targetDllImportData.BestFitMapping);
- newAttributeArgs.Add(AttributeArgument(name, null, value));
- }
- if (targetDllImportData.IsUserDefined.HasFlag(DllImportMember.CallingConvention))
- {
- NameEqualsSyntax name = NameEquals(nameof(DllImportAttribute.CallingConvention));
- ExpressionSyntax value = CreateEnumExpressionSyntax(targetDllImportData.CallingConvention);
- newAttributeArgs.Add(AttributeArgument(name, null, value));
- }
if (targetDllImportData.IsUserDefined.HasFlag(DllImportMember.CharSet))
{
NameEqualsSyntax name = NameEquals(nameof(DllImportAttribute.CharSet));
ExpressionSyntax value = CreateBoolExpressionSyntax(targetDllImportData.SetLastError);
newAttributeArgs.Add(AttributeArgument(name, null, value));
}
- if (targetDllImportData.IsUserDefined.HasFlag(DllImportMember.ThrowOnUnmappableChar))
- {
- NameEqualsSyntax name = NameEquals(nameof(DllImportAttribute.ThrowOnUnmappableChar));
- ExpressionSyntax value = CreateBoolExpressionSyntax(targetDllImportData.ThrowOnUnmappableChar);
- newAttributeArgs.Add(AttributeArgument(name, null, value));
- }
// Create new attribute
return Attribute(
var targetDllImportData = new GeneratedDllImportData(dllImportData.ModuleName)
{
CharSet = dllImportData.CharSet,
- BestFitMapping = dllImportData.BestFitMapping,
- CallingConvention = dllImportData.CallingConvention,
EntryPoint = dllImportData.EntryPoint,
ExactSpelling = dllImportData.ExactSpelling,
SetLastError = dllImportData.SetLastError,
PreserveSig = dllImportData.PreserveSig,
- ThrowOnUnmappableChar = dllImportData.ThrowOnUnmappableChar,
IsUserDefined = dllImportData.IsUserDefined & membersToForward
};
public enum DllImportMember
{
None = 0,
- BestFitMapping = 1 << 0,
- CallingConvention = 1 << 1,
- CharSet = 1 << 2,
- EntryPoint = 1 << 3,
- ExactSpelling = 1 << 4,
- PreserveSig = 1 << 5,
- SetLastError = 1 << 6,
- ThrowOnUnmappableChar = 1 << 7,
+ CharSet = 1 << 0,
+ EntryPoint = 1 << 1,
+ ExactSpelling = 1 << 2,
+ PreserveSig = 1 << 3,
+ SetLastError = 1 << 4,
All = ~None
}
/// Value set by the user on the original declaration.
/// </summary>
public DllImportMember IsUserDefined { get; init; }
- public bool BestFitMapping { get; init; }
- public CallingConvention CallingConvention { get; init; }
public CharSet CharSet { get; init; }
public string? EntryPoint { get; init; }
public bool ExactSpelling { get; init; }
public bool PreserveSig { get; init; }
public bool SetLastError { get; init; }
- public bool ThrowOnUnmappableChar { get; init; }
}
}
";
/// <summary>
- /// Declaration with all DllImport named arguments.
+ /// Declaration with all GeneratedDllImport named arguments.
/// </summary>
- 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();
-}
-";
-
- /// <summary>
- /// Declaration with all supported DllImport named arguments.
- /// </summary>
- public static readonly string AllSupportedDllImportNamedArguments = @"
+ public static readonly string AllGeneratedDllImportNamedArguments = @"
using System.Runtime.InteropServices;
partial class Test
{
yield return new object[] { CodeSnippets.ByValueParameterWithModifier<byte>("Out"), 1, 0 };
yield return new object[] { CodeSnippets.ByValueParameterWithModifier<byte>("In, Out"), 1, 0 };
- // Unsupported named arguments
- // * BestFitMapping, ThrowOnUnmappableChar, CallingConvention
- yield return new object[] { CodeSnippets.AllDllImportNamedArguments, 3, 0 };
-
// LCIDConversion
yield return new object[] { CodeSnippets.LCIDConversionAttribute, 1, 0 };
yield return new[] { CodeSnippets.NestedTypes };
yield return new[] { CodeSnippets.UnsafeContext };
yield return new[] { CodeSnippets.UserDefinedEntryPoint };
- yield return new[] { CodeSnippets.AllSupportedDllImportNamedArguments };
+ yield return new[] { CodeSnippets.AllGeneratedDllImportNamedArguments };
yield return new[] { CodeSnippets.DefaultParameters };
yield return new[] { CodeSnippets.UseCSharpFeaturesForConstants };
public static IEnumerable<object[]> SnippetsWithBlittableTypesButNonBlittableDataToCompile()
{
- yield return new[] { CodeSnippets.AllSupportedDllImportNamedArguments };
+ yield return new[] { CodeSnippets.AllGeneratedDllImportNamedArguments };
yield return new[] { CodeSnippets.BasicParametersAndModifiers<int>() };
yield return new[] { CodeSnippets.PreserveSigFalse<int>() };
}