diff --git a/Directory.Build.targets b/Directory.Build.targets index d0c6987977426..f59955242b29f 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -9,6 +9,7 @@ + @@ -17,14 +18,14 @@ unconditionally in Microsoft.NETCoreSdk.BundledVersions.props. --> $(MajorVersion).$(MinorVersion) - false + $(RunAnalyzers) Microsoft%AE .NET $(ProductVersion) $(ProductVersion)-$(VersionSuffix) - + > +<< Setup >> +try +{ + << Marshal >> + << Pin >> (fixed) + { + << Invoke >> + } + << Keep Alive >> + << Unmarshal >> +} +finally +{ + << GuaranteedUnmarshal >> + << Cleanup >> +} +``` + +### Stub conditional features + +Some marshalling optimizations are only available in specific scenarios. Generally, there are 4 basic marshalling contexts: + +- P/Invoke +- Reverse P/Invoke +- User-defined structure marshalling +- Non-blittable array marshalling + +This experiment generally is currently only focusing on two of the concepts: P/Invoke and non-blittable array marshalling (in the context of a P/Invoke). + +There are three features for specialized marshalling features that may only be available in some contexts: + +- Pinning to marshal data without copying (the `fixed` statement) +- Stack allocation across the native context (using the `stackalloc` keyword or https://github.com/dotnet/runtime/issues/25423) +- Storing additional temporary state in extra local variables + +Support for these features is indicated in code by the `abstract` `SingleFrameSpansNativeContext` and `AdditionalTemporaryStateLivesAcrossStages` properties on the `StubCodeContext` type. The `SingleFrameSpansNativeContext` property represents whether or not both pinning and stack-allocation are supported. These concepts are combined because we cannot safely support a conditional-stackalloc style API (such as https://github.com/dotnet/runtime/issues/52065) and safely get a pointer to data without also being able to pin. + +The various scenarios mentioned above have different levels of support for these specialized features: + +| Scenarios | Pinning and Stack allocation across the native context | Storing additional temporary state in locals | +|------|-----|-----| +| P/Invoke | supported | supported | +| Reverse P/Invoke | unsupported | supported | +| User-defined structure content marshalling | unsupported | unsupported | +| non-blittable array marshalling | unsupported | unuspported | + +To help enable developers to use the full model described in the [Struct Marshalling design](./StructMarshalling.md), we declare that in contexts where `AdditionalTemporaryStateLivesAcrossStages` is false, developers can still assume that state declared in the `Setup` phase is valid in any phase, but any side effects in code emitted in a phase other than `Setup` will not be guaranteed to be visible in other phases. This enables developers to still use the identifiers declared in the `Setup` phase in their other phases, but they'll need to take care to design their generators to handle these rules. + +### `SetLastError=true` + +The stub code generation also handles [`SetLastError=true`][SetLastError] behaviour. This configuration indicates that system error code ([`errno`](https://en.wikipedia.org/wiki/Errno.h) on Unix, [`GetLastError`](https://docs.microsoft.com/windows/win32/api/errhandlingapi/nf-errhandlingapi-getlasterror) on Windows) should be stored after the native invocation, such that it can be retrieved using [`Marshal.GetLastWin32Error`](https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.marshal.getlastwin32error). + +This means that, rather than simply invoke the native method, the generated stub will: + +1. Clear the system error by setting it to 0 +2. Invoke the native method +3. Get the system error +4. Set the stored error for the P/Invoke (accessible via `Marshal.GetLastWin32Error`) + +A core requirement of this functionality is that the P/Invoke called in (2) is blittable (the purpose of the P/Invoke source generator), such that there will be no additional operations (e.g unmarshalling) after the invocation that could change the system error that is retrieved in (3). Similarly, (3) must not involve any operations before getting the system error that could change the system error. This also relies on the runtime itself handling preserving the last error (see `BEGIN/END_PRESERVE_LAST_ERROR` macros) during JIT and P/Invoke resolution. + +Clearing the system error (1) is necessary because the native method may not set the error at all on success and the system error would retain its value from a previous operation. The developer should be able to check `Marshal.GetLastWin32Error` after a P/Inovke to determine success or failure, so the stub explicitly clears the error before the native invocation, such that the last error will indicate success if the native call does not change it. + +## P/Invoke + +The P/Invoke called by the stub is created based on the user's original declaration of the stub. The signature is generated using the syntax returned by `AsNativeType` and `AsParameter` of the marshalling generators for the return and parameters. Any marshalling attributes on the return and parameters of the managed method - [`MarshalAsAttribute`][MarshalAsAttribute], [`InAttribute`][InAttribute], [`OutAttribute`][OutAttribute] - are dropped. + +The fields of the [`DllImportAttribute`][DllImportAttribute] are set based on the fields of `GeneratedDllImportAttribute` as follows: + +| Field | Behaviour | +| ------------------------------------------------- | --------- | +| [`BestFitMapping`][BestFitMapping] | Not supported. See [Compatibility](Compatibility.md). +| [`CallingConvention`][CallingConvention] | Passed through to `DllImport`. +| [`CharSet`][CharSet] | Passed through to `DllImport`. +| [`EntryPoint`][EntryPoint] | If set, passed through to `DllImport`. If not set, explicitly set to method name. +| [`ExactSpelling`][ExactSpelling] | Passed through to `DllImport`. +| [`PreserveSig`][PreserveSig] | Handled by generated source. Not on generated `DllImport`. +| [`SetLastError`][SetLastError] | Handled by generated source. Not on generated `DllImport`. +| [`ThrowOnUnmappableChar`][ThrowOnUnmappableChar] | Not supported. See [Compatibility](Compatibility.md). + +### Examples + +Explicit `EntryPoint`: + +```C# +// Original declaration +[GeneratedDllImport("Lib")] +static partial void Method(out int i); + +// Generated P/Invoke +[DllImport("Lib", EntryPoint = "Method")] +static partial void Method__PInvoke__(int* i); +``` + +Passed through: + +```C# +// Original declaration +[GeneratedDllImport("Lib", EntryPoint = "EntryPoint", CharSet = CharSet.Unicode)] +static partial int Method(string s); + +// Generated P/Invoke +[DllImport("Lib", EntryPoint = "EntryPoint", CharSet = CharSet.Unicode)] +static partial int Method__PInvoke__(ushort* s); +``` + +Handled by generated source (dropped from `DllImport`): + +```C# +// Original declaration +[GeneratedDllImport("Lib", SetLastError = true)] +[return: [MarshalAs(UnmanagedType.U1)] +static partial bool Method([In][MarshasAs(UnmanagedType.LPWStr)] string s); + +// Generated P/Invoke +[DllImport("Lib", EntryPoint = "Method")] +static partial byte Method__PInvoke__(ushort* s); +``` + + +[src-MarshallingAttributeInfo]: ../DllImportGenerator/DllImportGenerator/MarshallingAttributeInfo.cs +[src-MarshallingGenerator]: ../DllImportGenerator/DllImportGenerator/Marshalling/MarshallingGenerator.cs +[src-StubCodeContext]: ../DllImportGenerator/DllImportGenerator/StubCodeContext.cs +[src-TypePositionInfo]: ../DllImportGenerator/DllImportGenerator/TypePositionInfo.cs + +[DllImportAttribute]: https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.dllimportattribute +[MarshalAsAttribute]: https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.marshalasattribute +[InAttribute]: https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.inattribute +[OutAttribute]: https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.outattribute + +[BestFitMapping]: https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.dllimportattribute.bestfitmapping +[CallingConvention]: https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.dllimportattribute.callingconvention +[CharSet]: https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.dllimportattribute.charset +[EntryPoint]: https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.dllimportattribute.entrypoint +[ExactSpelling]: https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.dllimportattribute.exactspelling +[PreserveSig]: https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.dllimportattribute.preservesig +[SetLastError]: https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.dllimportattribute.setlasterror +[ThrowOnUnmappableChar]: https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.dllimportattribute.throwonunmappablechar diff --git a/docs/design/libraries/DllImportGenerator/SpanMarshallers.md b/docs/design/libraries/DllImportGenerator/SpanMarshallers.md new file mode 100644 index 0000000000000..a1b3e74f672fe --- /dev/null +++ b/docs/design/libraries/DllImportGenerator/SpanMarshallers.md @@ -0,0 +1,317 @@ +# Support for Marshalling `(ReadOnly)Span` + +As part of the exit criteria for the DllImportGenerator experiment, we have decided to introduce support for marshalling `System.Span` and `System.ReadOnlySpan` into the DllImportGenerator-generated stubs. This document describes design decisions made during the implementation of these marshallers. + +## Design 1: "Intrinsic" support for `(ReadOnly)Span` + +In this design, the default support for `(ReadOnly)Span` is emitted into the marshalling stub directly and builds on the pattern we enabled for arrays. + +### Default behavior + +This section describes the behavior of the default emitted-in-stub marshallers. + +By default, we will marshal `Span` and `ReadOnlySpan` similarly to array types. When possible, we will pin the `(ReadOnly)Span`'s data and pass that down. When it is not possible to do so, we will try stack allocating scratch space for efficiency or allocate native memory with `Marshal.AllocCoTaskMem` for compatibility with arrays. + +To support marshalling from native to managed, we will support the same `MarshalAsAttribute` properties that arrays support today. + +When a `(ReadOnly)Span` is marshalled from native to managed, we will allocate a managed array and copy the data from the native memory into the array. + +### Empty spans + +We have decided to match the managed semantics of `(ReadOnly)Span` to provide the smoothest default experience for span users in interop. To assist developers who wish to transition from array parameters to span parameters, we will also provide an in-source marshaller that enables marshalling a span that wraps an empty array as a non-null pointer as an opt-in experience. + +### Additional proposed in-source marshallers + +As part of this design, we would also want to include some in-box marshallers that follow the design laid out in the [Struct Marshalling design doc](./StructMarshalling.md) to support some additional scenarios: + +- A marshaler that marshals an empty span as a non-null pointer. + - This marshaller would only support empty spans as it cannot correctly represent non-empty spans of non-blittable types. +- A marshaler that marshals out a pointer to the native memory as a Span instead of copying the data into a managed array. + - This marshaller would only support blittable spans by design. + - This marshaler will require the user to manually release the memory. Since this will be an opt-in marshaler, this scenario is already advanced and that additional requirement should be understandable to users who use this marshaler. + - Since there is no mechansim to provide a collection length, the question of how to provide the span's length in this case is still unresolved. One option would be to always provide a length 1 span and require the user to create a new span with the correct size, but that feels like a bad design. + +### Pros/Cons of Design 1 + +Pros: + +- This design builds on the array support that already exists, providing implementation experience and a slightly easier implementation. +- As we use the same MarshalAs attributes that already support arrays, developers can easily migrate their usage of array parameters in source-generated P/Invokes to use the span types with minimal hassle. + +Cons: + +- Defining custom marshalers for non-empty spans of non-blittable types generically is impossible since the marshalling rules of the element's type cannot be known. +- Custom non-default marshalling of the span element types is impossible for non-built-in types. +- Inlining the span marshalling fully into the stub increases on-disk IL size. +- This design does not enable developers to easily define custom marshalling support for their own collection types, which may be desireable. +- The MarshalAs attributes will continue to fail to work on spans used in non-source-generated DllImports, so this would be the first instance of enabling the "old" MarshalAs model on a new type in the generated DllImports, which may or may not be undesirable. + - The existing "native type marshalling" support cannot support marshalling collections of an unknown (at marshaller authoring time) non-blittable element type and cannot specify an element count for collections during unmarshalling. + +## Design 2: "Out-line" default support with extensions to Native Type Marshalling for Contiguous Collections + +An alternative option to fully inlining the stub would be to extend the model described in the [Struct Marshalling design doc](./StructMarshalling.md) to have custom support for collection-like types. By extending the model to be built with generic collection types in mind, many of the cons of the first approach would be resolved. + +Span marshalling would still be implemented with similar semantics as mentioned above in the Empty Spans section. Additional marshallers would still be provided as mentioned in the Additional proposed in-source marshallers section, but the non-`null` span marshaller and the no-alloc span marshaller would be able to be used in all cases, not just for empty spans. + +### Proposed extension to the custom type marshalling design + +Introduce a new attribute named `GenericContiguousCollectionMarshallerAttribute`. This attribute would have the following shape: + +```csharp +namespace System.Runtime.InteropServices +{ + [AttributeUsage(AttributeTargets.Struct | AttributeTargets.Class)] + public sealed class GenericContiguousCollectionMarshallerAttribute : Attribute + { + public GenericContiguousCollectionMarshallerAttribute(); + } +} +``` + +The attribute would be used with a collection type like `Span` as follows: + +```csharp +[NativeTypeMarshalling(typeof(DefaultSpanMarshaler<>))] +public ref struct Span +{ + ... +} + +[GenericContiguousCollectionMarshaller] +public ref struct DefaultSpanMarshaler +{ + ... +} +``` + +The `GenericContiguousCollectionMarshallerAttribute` attribute is applied to a generic marshaler type with the "collection marshaller" shape described below. Since generic parameters cannot be used in attributes, open generic types will be permitted in the `NativeTypeMarshallingAttribute` constructor as long as they have the same arity as the type the attribute is applied to and generic parameters provided to the applied-to type can also be used to construct the type passed as a parameter. + +#### Generic collection marshaller shape + +A generic collection marshaller would be required to have the following shape, in addition to the requirements for marshaler types used with the `NativeTypeMarshallingAttribute`, excluding the constructors. + +```csharp +[GenericContiguousCollectionMarshaller] +public struct GenericContiguousCollectionMarshallerImpl +{ + // this constructor is required if marshalling from native to managed is supported. + public GenericContiguousCollectionMarshallerImpl(int nativeSizeOfElement); + // these constructors are required if marshalling from managed to native is supported. + public GenericContiguousCollectionMarshallerImpl(GenericCollection collection, int nativeSizeOfElement); + public GenericContiguousCollectionMarshallerImpl(GenericCollection collection, Span stackSpace, int nativeSizeOfElement); // optional + + public const int StackBufferSize = /* */; // required if the span-based constructor is supplied. + + /// + /// A span that points to the memory where the managed values of the collection are stored (in the marshalling case) or should be stored (in the unmarshalling case). + /// + public Span ManagedValues { get; } + + /// + /// Set the expected length of the managed collection based on the parameter/return value/field marshalling information. + /// Required only when unmarshalling is supported. + /// + public void SetUnmarshalledCollectionLength(int length); + + public IntPtr Value { get; set; } + + /// + /// A span that points to the memory where the native values of the collection should be stored. + /// + public unsafe Span NativeValueStorage { get; } + + // The requirements on the Value property are the same as when used with `NativeTypeMarshallingAttribute`. + // The property is required with the generic collection marshalling. + public TNative Value { get; set; } +} +``` + +The constructors now require an additional `int` parameter specifying the native size of a collection element. The collection element type is represented as `TCollectionElement` above, and can be any type the marshaller defines. As the elements may be marshalled to types with different native sizes than managed, this enables the author of the generic collection marshaller to not need to know how to marshal the elements of the collection, just the collection structure itself. + +When the elements of the collection are blittable, the marshaller will emit a block copy of the span `ManagedValues` to the destination `NativeValueStorage`. When the elements are not blittable, the marshaller will emit a loop that will marshal the elements of the managed span one at a time and store them in the `NativeValueStorage` span. + +This would enable similar performance metrics as the current support for arrays as well as Design 1's support for the span types when the element type is blittable. + +#### Providing additional data for collection marshalling + +As part of collection marshalling, there needs to be a mechanism for the user to tell the stub code generator how many elements are in the native collection when unmarshalling. For parity with the previous system, there also needs to be a mechanism to describe how to marshal the elements of the collection. This proposal adds the following members to the `MarshalUsingAttribute` attribute to enable this and other features: + +```diff + +- [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.Field)] ++ [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.Field, AllowMultiple=true)] +public class MarshalUsingAttribute : Attribute +{ ++ public MarshalUsingAttribute() {} + public MarshalUsingAttribute(Type nativeType) {} ++ public string CountElementName { get; set; } ++ public int ConstantElementCount { get; set; } ++ public int ElementIndirectionLevel { get; set; } ++ public const string ReturnsCountValue = "return-value"; +} +``` + +The `MarshalUsingAttribute` will now provide a `CountElementName` property that will point to a parameter (or a field in a struct-marshalling context) whose value will hold the number of native collection elements, or to the return value if the value of `CountElementName` is `ReturnsCountValue`. The `ConstantElementCount` property allows users to provide a constant collection length. + +> Open Question: +> Should combining `CountElementName` and `ConstantElementCount` in the same attribute be allowed? +> With the `MarshalAs` marshalling, `SizeParamIndex` and `SizeConst` can be combined and the resulting size will be `paramValue(SizeParamIndex) + SizeConst`. + +To support supplying information about collection element counts, a parameterless constructor is added to the `MarshalUsingAttribute` type. The default constructor specifies that the code generator should use the information in the attribute but use the default marshalling rules for the type. + +The `ElementIndirectionLevel` property is added to support supplying marshalling info for element types in a collection. For example, if the user is passing a `List>` from managed to native code, they could provide the following attributes to specify marshalling rules for the outer and inner lists and `Foo` separately: + +```csharp +private static partial void Bar([MarshalUsing(typeof(ListAsArrayMarshaller>), CountElementName = nameof(count)), MarshalUsing(ConstantElementCount = 10, ElementIndirectionLevel = 1), MarshalUsing(typeof(FooMarshaler), ElementIndirectionLevel = 2)] List> foos, int count); +``` + +Multiple `MarshalUsing` attributes can only be supplied on the same parameter or return value if the `ElementIndirectionLevel` property is set to distinct values. One `MarshalUsing` attribute per parameter or return value can leave the `ElementIndirectionLevel` property unset. This attribute controls the marshalling of the collection object passed in as the parameter. The sequence of managed types for `ElementIndirectionLevel` is based on the elements of the `ManagedValues` span on the collection marshaller of the previous indirection level. For example, for the marshalling info for `ElementIndirectionLevel = 1` above, the managed type is the type of the following C# expression: `ListAsArrayMarshaller>.ManagedValues[0]`. + +Alternatively, the `MarshalUsingAttribute` could provide a `Type ElementNativeType { get; set; }` property instead of an `ElementIndirectionLevel` property and support specifying the native type of the element of the collection this way. However, this design would block support for marshalling collections of collections. + +#### Example: Using generic collection marshalling for spans + +This design could be used to provide a default marshaller for spans and arrays. Below is an example simple marshaller for `Span`. This design does not include all possible optimizations, such as stack allocation, for simpilicity of the example. + +```csharp +[GenericContiguousCollectionMarshaller] +public ref struct SpanMarshaler +{ + private Span managedCollection; + + private int nativeElementSize; + + public SpanMarshaler(Span collection, int nativeSizeOfElement) + { + managedCollection = collection; + Value = Marshal.AllocCoTaskMem(collection.Length * nativeSizeOfElement); + nativeElementSize = nativeSizeOfElement; + nativeElementSize = nativeSizeOfElement; + } + + public Span ManagedValues => managedCollection; + + public void SetUnmarshalledCollectionLength(int length) + { + managedCollection = new T[value]; + } + + public IntPtr Value { get; set; } + + public unsafe Span NativeValueStorage => MemoryMarshal.CreateSpan(ref *(byte*)(Value), Length); + + public Span ToManaged() => managedCollection; + + public void FreeNative() + { + if (Value != IntPtr.Zero) + { + Marshal.FreeCoTaskMem(Value); + } + } +} +``` + +The following example would show the expected stub for the provided signature (assuming that `Span` has a `[NativeMarshalling(typeof(SpanMarshaller<>))]` attribute): + +```csharp +struct WrappedInt +{ + private int value; + + public WrappedInt(int w) + { + value = w.i; + } + + public int ToManaged() => value; +} + +[GeneratedDllImport("Native")] +[return:MarshalUsing(CountElementName = nameof(length))] +public static partial Span DuplicateValues([MarshalUsing(typeof(WrappedInt), ElementIndirectionLevel = 1)] Span values, int length); + +// Generated stub: +public static partial unsafe Span DuplicateValues(Span values, int length) +{ + SpanMarshaller __values_marshaller = new SpanMarshaller(values, sizeof(WrappedInt)); + for (int i = 0; i < __values_marshaller.ManagedValues.Length; ++i) + { + WrappedInt native = new WrappedInt(__values_marshaller.ManagedValues[i]); + MemoryMarshal.Write(__values_marshaller.NativeValueStorage.Slice(sizeof(WrappedInt) * i), ref native); + } + + IntPtr __retVal_native = __PInvoke__(__values_marshaller.Value, length); + SpanMarshaller __retVal_marshaller = new + { + Value = __retVal_native + }; + __retVal_marshaller.SetUnmarshalledCollectionLength(length); + MemoryMarshal.Cast(__retVal_marshaller.NativeValueStorage).CopyTo(__retVal_marshaller.ManagedValues); + return __retVal_marshaller.ToManaged(); + + [DllImport("Native", EntryPoint="DuplicateValues")] + static extern IntPtr __PInvoke__(IntPtr values, int length); +} +``` + +This design could also be applied to support the built-in array marshalling if it is desired to move that marshalling out of the stub and into shared code. + +#### Future extension to the above model: Non-contiguous collection support + +If a managed or native representation of a collection has a non-contiguous element layout, then developers currently will need to convert to or from array/span types at the interop boundary. This section proposes an API that would enable developers to convert directly between a managed and native non-contiguous collection layout as part of marshalling. + +A new attribute named `GenericCollectionMarshaller` attribute could be added that would specify that the collection is noncontiguous in either managed or native representations. Then additional methods should be added to the generic collection model, and some methods would be removed: + +```diff +- [GenericContiguousCollectionMarshaller] ++ [GenericCollectionMarshaller] +public struct GenericContiguousCollectionMarshallerImpl +{ + // these constructors are required if marshalling from managed to native is supported. + public GenericContiguousCollectionMarshallerImpl(GenericCollection collection, int nativeSizeOfElements); + public GenericContiguousCollectionMarshallerImpl(GenericCollection collection, Span stackSpace, int nativeSizeOfElements); // optional + + public const int StackBufferSize = /* */; // required if the span-based constructor is supplied. + +- public Span ManagedValues { get; } + +- public void SetUnmarshalledCollectionLength(int length); + + public IntPtr Value { get; set; } + +- public unsafe Span NativeValueStorage { get; } + + // The requirements on the Value property are the same as when used with `NativeTypeMarshallingAttribute`. + // The property is required with the generic collection marshalling. + public TNative Value { get; set; } + ++ public ref byte GetOffsetForNativeValueAtIndex(int index); ++ public TCollectionElement GetManagedValueAtIndex(int index); ++ public TCollectionElement SetManagedValueAtIndex(int index); ++ public int Count { get; set; } +} +``` + +The `GetManagedValueAtIndex` method and `Count` getter are used in the process of marshalling from managed to native. The generated code will iterate through `Count` elements (retrieved through `GetManagedValueAtIndex`) and assign their marshalled result to the address represented by `GetOffsetForNativeValueAtIndex` called with the same index. Then either the `Value` property getter will be called or the marshaller's `GetPinnableReference` method will be called, depending on if pinning is supported in the current scenario. + +The `SetManagedValueAtIndex` method and the `Count` setter are used in the process of marshalling from native to managed. The `Count` property will be set to the number of elements that the native collection contains, and the `Value` property will be assigned the result value from native code. Then the stub will iterate through the native collection `Count` times, calling `GetOffsetForNativeValueAtIndex` to get the offset of the native value and calling `SetManagedValueAtIndex` to set the unmarshalled managed value at that index. + +### Pros/Cons of Design 2 + +Pros: + +- Collection type owners do not need to know how to marshal the elements of the collection. +- Custom non-default marshalling of collections of non-blittable types supported with the same code as blittable types. +- Sharing code for marshalling a given collection type reduces IL size on disk. +- Developers can easily enable marshalling their own collection types without needing to modify the source generator. +- Makes no assumptions about native collection layout, so collections like linked lists can be easily supported. + +Cons: + +- Introduces more attribute types into the BCL. +- Introduces more complexity in the marshalling type model. + - It may be worth describing the required members (other than constructors) in interfaces just to simplify the mental load of which members are required for which scenarios. + - A set of interfaces (one for managed-to-native members, one for native-to-managed members, and one for the sequential-specific members) could replace the `GenericContiguousCollectionMarshaller` attribute. +- The base proposal only supports contiguous collections. + - The feeling at time of writing is that we are okay asking developers to convert to/from arrays or spans at the interop boundary. diff --git a/docs/design/libraries/DllImportGenerator/StructMarshalling.md b/docs/design/libraries/DllImportGenerator/StructMarshalling.md new file mode 100644 index 0000000000000..2852880103c6c --- /dev/null +++ b/docs/design/libraries/DllImportGenerator/StructMarshalling.md @@ -0,0 +1,285 @@ +# Struct Marshalling + +As part of the new source-generated direction for .NET Interop, we are looking at various options for supporting marshaling user-defined struct types. + +These types pose an interesting problem for a number of reasons listed below. With a few constraints, I believe we can create a system that will enable users to use their own user-defined types and pass them by-value to native code. + +## Problems + +- Unmanaged vs Blittable + - The C# language (and Roslyn) do not have a concept of "blittable types". It only has the concept of "unmanaged types", which is similar to blittable, but differs for `bool`s and `char`s. `bool` and `char` types are "unmanaged", but are never (in the case of `bool`), or only sometimes (in the case of `char`) blittable. As a result, we cannot use the "is this type unmanaged" check in Roslyn for structures. +- Limited type information in ref assemblies. + - In the ref assemblies generated by dotnet/runtime, we save space and prevent users from relying on private implementation details of structures by emitting limited information about their fields. Structures that have at least one non-object field are given a private `int` field, and structures that have at least one field that transitively contains an object are given one private `object`-typed field. As a result, we do not have full type information at code-generation time for any structures defined in the BCL when compiling a library that uses the ref assemblies. +- Private reflection + - Even when we do have information about all of the fields, we can't emit code that references them if they are private, so we would have to emit unsafe code and calculate offsets manually to support marshaling them. + +## Opt-in Interop + +We've been working around another problem for a while in the runtime-integrated interop design: The user can use any type that is non-auto layout and has fields that can be marshaled in interop. This has lead to various issues where types that were not intended for interop usage became usable and then we couldn't update their behavior to be special-cased since users may have been relying on the generic behavior (`Span`, `Vector` come to mind). + +I propose an opt-in design where the owner of a struct has to explicitly opt-in to usage for interop. This enables our team to add special support as desired for various types such as `Span` while also avoiding the private reflection and limited type information issues mentioned above. + +This design would use these attributes: + +```csharp + +[AttributeUsage(AttributeTargets.Struct | AttributeTargets.Class)] +public class GeneratedMarshallingAttribute : Attribute {} + +[AttributeUsage(AttributeTargets.Struct | AttributeTargets.Class)] +public class BlittableTypeAttribute : Attribute {} + +[AttributeUsage(AttributeTargets.Struct | AttributeTargets.Class)] +public class NativeMarshallingAttribute : Attribute +{ + public NativeMarshallingAttribute(Type nativeType) {} +} + +[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.Field)] +public class MarshalUsingAttribute : Attribute +{ + public MarshalUsingAttribute(Type nativeType) {} +} +``` + +The `NativeMarshallingAttribute` and `MarshalUsingAttribute` attributes would require that the provided native type `TNative` is a blittable `struct` and has a subset of three methods with the following names and shapes (with the managed type named TManaged): + +```csharp +partial struct TNative +{ + public TNative(TManaged managed) {} + public TManaged ToManaged() {} + + public void FreeNative() {} +} +``` + +The analyzer will report an error if neither the construtor nor the ToManaged method is defined. When one of those two methods is missing, the direction of marshalling (managed to native/native to managed) that relies on the missing method is considered unsupported for the corresponding managed type. The FreeNative method is only required when there are resources that need to be released. + + +> :question: Does this API surface and shape work for all marshalling scenarios we plan on supporting? It may have issues with the current "layout class" by-value `[Out]` parameter marshalling where the runtime updates a `class` typed object in place. We already recommend against using classes for interop for performance reasons and a struct value passed via `ref` or `out` with the same members would cover this scenario. + +If the native type `TNative` also has a public `Value` property, then the value of the `Value` property will be passed to native code instead of the `TNative` value itself. As a result, the type `TNative` will be allowed to be non-blittable and the type of the `Value` property will be required to be blittable. If the `Value` property is settable, then when marshalling in the native-to-managed direction, a default value of `TNative` will have its `Value` property set to the native value. If `Value` does not have a setter, then marshalling from native to managed is not supported. + +A `ref` or `ref readonly` typed `Value` property is unsupported. If a ref-return is required, the type author can supply a `GetPinnableReference` method on the native type. If a `GetPinnableReference` method is supplied, then the `Value` property must have a pointer-sized primitive type. + +```csharp +[NativeMarshalling(typeof(TMarshaler))] +public struct TManaged +{ + // ... +} + +public struct TMarshaler +{ + public TNative(TManaged managed) {} + public TManaged ToManaged() {} + + public void FreeNative() {} + + public ref TNative GetPinnableReference() {} + + public TNative Value { get; set; } +} + +``` + +### Performance features + +#### Pinning + +Since C# 7.3 added a feature to enable custom pinning logic for user types, we should also add support for custom pinning logic. If the user provides a `GetPinnableReference` method that matches the requirements to be used in a `fixed` statement and the pointed-to type is blittable, then we will support using pinning to marshal the managed value when possible. The analyzer should issue a warning when the pointed-to type would not match the final native type, accounting for the `Value` property on the native type. Since `MarshalUsingAttribute` is applied at usage time instead of at type authoring time, we will not enable the pinning feature since the implementation of `GetPinnableReference` unless the pointed-to return type matches the native type. + +#### Caller-allocated memory + +Custom marshalers of collection-like types or custom string encodings (such as UTF-32) may want to use stack space for extra storage for additional performance when possible. If the `TNative` type provides additional members with the following signatures, then it will opt in to using a caller-allocated buffer: + +```csharp +partial struct TNative +{ + public TNative(TManaged managed, Span buffer) {} + + public const int BufferSize = /* */; + + public const bool RequiresStackBuffer = /* */; +} +``` + +When these members are present, the source generator will call the two-parameter constructor with a possibly stack-allocated buffer of `BufferSize` bytes when a stack-allocated buffer is usable. If a stack-allocated buffer is a requirement, the `RequiresStackBuffer` field should be set to `true` and the `buffer` will be guaranteed to be allocated on the stack. Setting the `RequiresStackBuffer` field to `false` is the same as omitting the field definition. Since a dynamically allocated buffer is not usable in all scenarios, for example Reverse P/Invoke and struct marshalling, a one-parameter constructor must also be provided for usage in those scenarios. This may also be provided by providing a two-parameter constructor with a default value for the second parameter. + +Type authors can pass down the `buffer` pointer to native code by defining a `GetPinnableReference()` method on the native type that returns a reference to the first element of the span. When the `RequiresStackBuffer` field is set to `true`, the type author is free to use APIs that would be dangerous in non-stack-allocated scenarios such as `MemoryMarshal.GetReference()` and `Unsafe.AsPointer()`. + +### Usage + +There are 2 usage mechanisms of these attributes. + +#### Usage 1, Source-generated interop + +The user can apply the `GeneratedMarshallingAttribute` to their structure `S`. The source generator will determine if the type is blittable. If it is blittable, the source generator will generate a partial definition and apply the `BlittableTypeAttribute` to the struct type `S`. Otherwise, it will generate a blittable representation of the struct with the aformentioned requried shape and apply the `NativeMarshallingAttribute` and point it to the blittable representation. The blittable representation can either be generated as a separate top-level type or as a nested type on `S`. + +#### Usage 2, Manual interop + +The user may want to manually mark their types as marshalable in this system due to specific restrictions in their code base around marshaling specific types that the source generator does not account for. We could also use this internally to support custom types in source instead of in the code generator. In this scenario, the user would apply either the `BlittableTypeAttribute` or the `NativeMarshallingAttribute` attribute to their struct type. An analyzer would validate that the struct is blittable if the `BlittableTypeAttribute` is applied or validate that the native struct type is blittable and has marshalling methods of the required shape when the `NativeMarshallingAttribute` is applied. + +The P/Invoke source generator (as well as the struct source generator when nested struct types are used) would use the `BlittableTypeAttribute` and `NativeMarshallingAttribute` to determine how to marshal a value type parameter or field instead of looking at the fields of the struct directly. + +If a structure type does not have either the `BlittableTypeAttribute` or the `NativeMarshallingAttribute` applied at the type definition, the user can supply a `MarshalUsingAttribute` at the marshalling location (field, parameter, or return value) with a native type matching the same requirements as `NativeMarshallingAttribute`'s native type. + +All generated stubs will be marked with [`SkipLocalsInitAttribute`](https://docs.microsoft.com/dotnet/api/system.runtime.compilerservices.skiplocalsinitattribute) on supported frameworks. This does require attention when performing custom marshalling as the state of stub allocated memory will be in an undefined state. + +### Why do we need `BlittableTypeAttribute`? + +Based on the design above, it seems that we wouldn't need `BlittableTypeAttribute`. However, due to the ref assembly issue above in combination with the desire to enable manual interop, we need to provide a way for users to signal that a given type should be blittable and that the source generator should not generate marshalling code. + +I'll give a specific example for where we need the `BlittableTypeAttribute` below. Let's take a scenario where we don't have `BlittableTypeAttribute`. + +In Foo.csproj, we have the following types: + +```csharp +public struct Foo +{ + private bool b; +} + +public struct Bar +{ + private short s; +} +``` + +We compile these types into an assembly Foo.dll and we want to publish a package. We decide to use infrastructure similar to dotnet/runtime and produce a ref assembly. The ref assembly will have the following types: + +```csharp +struct Foo +{ + private int dummy; +} +struct Bar +{ + private int dummy; +} +``` + +We package up the ref and impl assemblies and ship them in a NuGet package. + +Someone else pulls down this package and writes their own struct type Baz1 and Baz2: + +```csharp +struct Baz1 +{ + private Foo f; +} +struct Baz2 +{ + private Bar b; +} +``` + +Since the source generator only sees ref assemblies, it would think that both `Baz1` and `Baz2` are blittable, when in reality only `Baz2` is blittable. This is the ref assembly issue mentioned above. The source generator cannot trust the shape of structures in other assemblies since those types may have private implementation details hidden. + +Now let's take this scenario again with `BlittableTypeAttribute`: + +```csharp +[BlittableType] +public struct Foo +{ + private bool b; +} + +[BlittableType] +public struct Bar +{ + private short s; +} +``` + +This time, we produce an error since Foo is not blittable. We need to either apply the `GeneratedMarshalling` attribute (to generate marshalling code) or the `NativeMarshallingAttribute` attribute (so provide manually written marshalling code) to Foo. This is also why we require each type used in interop to have either a `[BlittableType]` attribute or a `[NativeMarshallingAttribute]` attribute; we can't validate the shape of a type not defined in the current assembly because its shape may be different between its reference assembly and the runtime type. + +Now there's another question: Why we can't just say that a type with `[GeneratedMarshalling]` and not `[NativeMarshallingAttribute]` has been considered blittable? + +We don't want to require usage of `[GeneratedMarshalling]` to mark that a type is blittable because then there is no way to enforce that the type is blittable. If we require usage of `[GeneratedMarshalling]`, then we will automatically generate marshalling code if the type is not blittable. By also having the `[BlittableType]` attribute, we enable users to mark types that they want to ensure are blittable and an analyzer will validate the blittability. + +Basically, the design of this feature is as follows: + +At build time, the user can apply either `[GeneratedMarshallling]`, `[BlittableType]`, or `[NativeMarshallingAttribute]`. If they apply `[GeneratedMarshalling]`, then the source generator will run and generate marshalling code as needed and apply either `[BlittableType]` or `[NativeMarshallingAttribute]`. If the user manually applies `[BlittableType]` or `[NativeMarshallingAttribute]` instead of `[GeneratedMarshalling]`, then an analyzer validates that the type is blittable (for `[BlitttableType]`) or that the marshalling methods and types have the required shapes (for `[NativeMarshallingAttribute]`). + +When the source generator (either Struct, P/Invoke, Reverse P/Invoke, etc.) encounters a struct type, it will look for either the `[BlittableType]` or the `[NativeMarshallingAttribute]` attributes to determine how to marshal the structure. If neither of these attributes are applied, then the struct cannot be passed by value. + + +If someone actively disables the analyzer or writes their types in IL, then they have stepped out of the supported scenarios and marshalling code generated for their types may be inaccurate. + +#### Exception: Generics + +Because the Roslyn compiler needs to be able to validate that there are not recursive struct definitions, reference assemblies have to contain a field of a type parameter type in the reference assembly if they do in the runtime assembly. As a result, we can inspect private generic fields reliably. + +To enable blittable generics support in this struct marshalling model, we extend `[BlittableType]` as follows: + +- In a generic type definition, we consider all type parameters that can be value types as blittable for the purposes of validating that `[BlittableType]` is only applied to blittable types. +- When the source generator discovers a generic type marked with `[BlittableType]` it will look through the fields on the type and validate that they are blittable. + +Since all fields typed with non-parameterized types are validated to be blittable at type definition time, we know that they are all blittable at type usage time. So, we only need to validate that the generic fields are instantiated with blittable types. + +### Special case: Transparent Structures + +There has been discussion about Transparent Structures, structure types that are treated as their underlying types when passed to native code. The support for a `Value` property on a generated marshalling type supports the transparent struct support. For example, we could support strongly typed `HRESULT` returns with this model as shown below: + +```csharp +[NativeMarshalling(typeof(HRESULT))] +struct HResult +{ + public HResult(int result) + { + Result = result; + } + public readonly int Result; +} + +struct HRESULT +{ + public HRESULT(HResult hr) + { + Value = hr; + } + + public HResult ToManaged() => new HResult(Value); + public int Value { get; set; } +} +``` + +In this case, the underlying native type would actually be an `int`, but the user could use the strongly-typed `HResult` type as the public surface area. + +> :question: Should we support transparent structures on manually annotated blittable types? If we do, we should do so in an opt-in manner to make it possible to have a `Value` property on the blittable type. + +#### Example: ComWrappers marshalling with Transparent Structures + +Building on this Transparent Structures support, we can also support ComWrappers marshalling with this proposal via the manually-decorated types approach: + +```csharp +[NativeMarshalling(typeof(ComWrappersMarshaler))] +class Foo +{} + +struct ComWrappersMarshaler + where TComWrappers : ComWrappers, new() +{ + private static readonly TComWrappers ComWrappers = new TComWrappers(); + + private IntPtr nativeObj; + + public ComWrappersMarshaler(TClass obj) + { + nativeObj = ComWrappers.GetOrCreateComInterfaceForObject(obj, CreateComInterfaceFlags.None); + } + + public IntPtr Value { get => nativeObj; set => nativeObj = value; } + + public TClass ToManaged() => (TClass)ComWrappers.GetOrCreateObjectForComInstance(nativeObj, CreateObjectFlags.None); + + public unsafe void FreeNative() + { + ((delegate* unmanaged[Stdcall])((*(void***)nativeObj)[2 /* Release */]))(nativeObj); + } +} +``` + +This ComWrappers-based marshaller works with all `ComWrappers`-derived types that have a parameterless constructor and correctly passes down a native integer (not a structure) to native code to match the expected ABI. diff --git a/eng/Versions.props b/eng/Versions.props index 09191a2974dff..24d48d1d8b372 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -48,6 +48,7 @@ + 3.3.2 4.0.0-4.final 4.0.0-4.final 7.0.0-preview1.21513.4 @@ -145,6 +146,7 @@ 1.0.0-beta-build0015 1.0.4-preview6.19326.1 0.2.61701 + 1.0.26 16.10.0 $(MicrosoftBuildVersion) 5.8.0 @@ -163,6 +165,7 @@ 4.12.0 2.14.3 6.0.100-rc.2.21474.31 + 1.1.1-beta1.21467.5 6.0.0-preview-20210916.1 diff --git a/eng/generators.targets b/eng/generators.targets new file mode 100644 index 0000000000000..e20fa992012aa --- /dev/null +++ b/eng/generators.targets @@ -0,0 +1,78 @@ + + + + true + false + true + + + + + + + + + + + + + + + + + + + + + true + + + + true + $(DefineConstants);DLLIMPORTGENERATOR_INTERNALUNSAFE + + + + + + + + + + + + $(DefineConstants);DLLIMPORTGENERATOR_ENABLED + + + + + diff --git a/eng/native/output-toolchain-info.cmake b/eng/native/output-toolchain-info.cmake new file mode 100644 index 0000000000000..8eed988e598ac --- /dev/null +++ b/eng/native/output-toolchain-info.cmake @@ -0,0 +1,21 @@ +# Output the toolchain information required to create a command line that builds with the right rootfs as XML + +set (ADDED_COMPILE_OPTIONS) +if (CMAKE_SCRIPT_MODE_FILE) + # add_compile_options and add_definitions can't be used in scripts, + # so override the implementations to append to a local property + macro(add_compile_options) + list(APPEND ADDED_COMPILE_OPTIONS ${ARGV}) + endmacro() + macro(add_definitions) + list(APPEND ADDED_COMPILE_OPTIONS ${ARGV}) + endmacro() +endif() + +include(${CMAKE_CURRENT_LIST_DIR}/../common/cross/toolchain.cmake) + +message("") +message("${TOOLCHAIN}") +message("${CMAKE_SHARED_LINKER_FLAGS_INIT}") +message("${ADDED_COMPILE_OPTIONS}") +message("") \ No newline at end of file diff --git a/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Evp.cs b/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Evp.cs index 66eaaa6f7ef0f..393f1bd7ba59d 100644 --- a/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Evp.cs +++ b/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Evp.cs @@ -32,7 +32,7 @@ internal static int EvpDigestUpdate(SafeEvpMdCtxHandle ctx, ReadOnlySpan d internal static extern int EvpDigestCurrent(SafeEvpMdCtxHandle ctx, ref byte md, ref uint s); [DllImport(Libraries.AndroidCryptoNative, EntryPoint = "CryptoNative_EvpDigestOneShot")] - internal static unsafe extern int EvpDigestOneShot(IntPtr type, byte* source, int sourceSize, byte* md, ref uint mdSize); + internal static unsafe extern int EvpDigestOneShot(IntPtr type, byte* source, int sourceSize, byte* md, uint* mdSize); [DllImport(Libraries.AndroidCryptoNative, EntryPoint = "CryptoNative_EvpMdSize")] internal static extern int EvpMdSize(IntPtr md); diff --git a/src/libraries/Common/src/Interop/BSD/System.Native/Interop.ProtocolStatistics.cs b/src/libraries/Common/src/Interop/BSD/System.Native/Interop.ProtocolStatistics.cs index ab7ac0fb962c6..476b7a653edb1 100644 --- a/src/libraries/Common/src/Interop/BSD/System.Native/Interop.ProtocolStatistics.cs +++ b/src/libraries/Common/src/Interop/BSD/System.Native/Interop.ProtocolStatistics.cs @@ -34,7 +34,7 @@ public readonly struct TcpGlobalStatistics } [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetTcpGlobalStatistics")] - public static extern int GetTcpGlobalStatistics(out TcpGlobalStatistics statistics); + public static unsafe extern int GetTcpGlobalStatistics(TcpGlobalStatistics* statistics); [StructLayoutAttribute(LayoutKind.Sequential)] public readonly struct IPv4GlobalStatistics @@ -56,7 +56,7 @@ public readonly struct IPv4GlobalStatistics } [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetIPv4GlobalStatistics")] - public static extern int GetIPv4GlobalStatistics(out IPv4GlobalStatistics statistics); + public static unsafe extern int GetIPv4GlobalStatistics(IPv4GlobalStatistics* statistics); [StructLayoutAttribute(LayoutKind.Sequential)] public readonly struct UdpGlobalStatistics @@ -69,7 +69,7 @@ public readonly struct UdpGlobalStatistics } [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetUdpGlobalStatistics")] - public static extern int GetUdpGlobalStatistics(out UdpGlobalStatistics statistics); + public static unsafe extern int GetUdpGlobalStatistics(UdpGlobalStatistics* statistics); [StructLayoutAttribute(LayoutKind.Sequential)] public readonly struct Icmpv4GlobalStatistics @@ -99,7 +99,7 @@ public readonly struct Icmpv4GlobalStatistics } [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetIcmpv4GlobalStatistics")] - public static extern int GetIcmpv4GlobalStatistics(out Icmpv4GlobalStatistics statistics); + public static unsafe extern int GetIcmpv4GlobalStatistics(Icmpv4GlobalStatistics* statistics); [StructLayoutAttribute(LayoutKind.Sequential)] public readonly struct Icmpv6GlobalStatistics @@ -135,7 +135,7 @@ public readonly struct Icmpv6GlobalStatistics } [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetIcmpv6GlobalStatistics")] - public static extern int GetIcmpv6GlobalStatistics(out Icmpv6GlobalStatistics statistics); + public static unsafe extern int GetIcmpv6GlobalStatistics(Icmpv6GlobalStatistics* statistics); public readonly struct NativeIPInterfaceStatistics { @@ -155,8 +155,8 @@ public readonly struct NativeIPInterfaceStatistics public readonly ulong Flags; } - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetNativeIPInterfaceStatistics")] - public static extern int GetNativeIPInterfaceStatistics(string name, out NativeIPInterfaceStatistics stats); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetNativeIPInterfaceStatistics", CharSet = CharSet.Ansi)] + public static partial int GetNativeIPInterfaceStatistics(string name, out NativeIPInterfaceStatistics stats); [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetNumRoutes")] public static extern int GetNumRoutes(); diff --git a/src/libraries/Common/src/Interop/BSD/System.Native/Interop.Sysctl.cs b/src/libraries/Common/src/Interop/BSD/System.Native/Interop.Sysctl.cs index de201f9e546e2..3c98d2d828d51 100644 --- a/src/libraries/Common/src/Interop/BSD/System.Native/Interop.Sysctl.cs +++ b/src/libraries/Common/src/Interop/BSD/System.Native/Interop.Sysctl.cs @@ -16,9 +16,8 @@ internal static partial class Interop { internal static partial class Sys { - - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Sysctl", SetLastError = true)] - private static extern unsafe int Sysctl(int* name, int namelen, void* value, size_t* len); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Sysctl", SetLastError = true)] + private static unsafe partial int Sysctl(int* name, int namelen, void* value, size_t* len); // This is 'raw' sysctl call, only wrapped to allocate memory if needed // caller always needs to free returned buffer using Marshal.FreeHGlobal() diff --git a/src/libraries/Common/src/Interop/Interop.Brotli.cs b/src/libraries/Common/src/Interop/Interop.Brotli.cs index a817bb971e263..b84bd9939e3db 100644 --- a/src/libraries/Common/src/Interop/Interop.Brotli.cs +++ b/src/libraries/Common/src/Interop/Interop.Brotli.cs @@ -8,13 +8,13 @@ internal static partial class Interop { - internal static class Brotli + internal static partial class Brotli { - [DllImport(Libraries.CompressionNative)] - internal static extern SafeBrotliDecoderHandle BrotliDecoderCreateInstance(IntPtr allocFunc, IntPtr freeFunc, IntPtr opaque); + [GeneratedDllImport(Libraries.CompressionNative)] + internal static partial SafeBrotliDecoderHandle BrotliDecoderCreateInstance(IntPtr allocFunc, IntPtr freeFunc, IntPtr opaque); - [DllImport(Libraries.CompressionNative)] - internal static extern unsafe int BrotliDecoderDecompressStream( + [GeneratedDllImport(Libraries.CompressionNative)] + internal static unsafe partial int BrotliDecoderDecompressStream( SafeBrotliDecoderHandle state, ref nuint availableIn, byte** nextIn, ref nuint availableOut, byte** nextOut, out nuint totalOut); @@ -24,22 +24,22 @@ internal static extern unsafe int BrotliDecoderDecompressStream( [DllImport(Libraries.CompressionNative)] internal static extern void BrotliDecoderDestroyInstance(IntPtr state); - [DllImport(Libraries.CompressionNative)] - internal static extern BOOL BrotliDecoderIsFinished(SafeBrotliDecoderHandle state); + [GeneratedDllImport(Libraries.CompressionNative)] + internal static partial BOOL BrotliDecoderIsFinished(SafeBrotliDecoderHandle state); - [DllImport(Libraries.CompressionNative)] - internal static extern SafeBrotliEncoderHandle BrotliEncoderCreateInstance(IntPtr allocFunc, IntPtr freeFunc, IntPtr opaque); + [GeneratedDllImport(Libraries.CompressionNative)] + internal static partial SafeBrotliEncoderHandle BrotliEncoderCreateInstance(IntPtr allocFunc, IntPtr freeFunc, IntPtr opaque); - [DllImport(Libraries.CompressionNative)] - internal static extern BOOL BrotliEncoderSetParameter(SafeBrotliEncoderHandle state, BrotliEncoderParameter parameter, uint value); + [GeneratedDllImport(Libraries.CompressionNative)] + internal static partial BOOL BrotliEncoderSetParameter(SafeBrotliEncoderHandle state, BrotliEncoderParameter parameter, uint value); - [DllImport(Libraries.CompressionNative)] - internal static extern unsafe BOOL BrotliEncoderCompressStream( + [GeneratedDllImport(Libraries.CompressionNative)] + internal static unsafe partial BOOL BrotliEncoderCompressStream( SafeBrotliEncoderHandle state, BrotliEncoderOperation op, ref nuint availableIn, byte** nextIn, ref nuint availableOut, byte** nextOut, out nuint totalOut); - [DllImport(Libraries.CompressionNative)] - internal static extern BOOL BrotliEncoderHasMoreOutput(SafeBrotliEncoderHandle state); + [GeneratedDllImport(Libraries.CompressionNative)] + internal static partial BOOL BrotliEncoderHasMoreOutput(SafeBrotliEncoderHandle state); [DllImport(Libraries.CompressionNative)] internal static extern void BrotliEncoderDestroyInstance(IntPtr state); diff --git a/src/libraries/Common/src/Interop/Linux/System.Native/Interop.INotify.cs b/src/libraries/Common/src/Interop/Linux/System.Native/Interop.INotify.cs index 6ff843ec89903..f93f542f7229f 100644 --- a/src/libraries/Common/src/Interop/Linux/System.Native/Interop.INotify.cs +++ b/src/libraries/Common/src/Interop/Linux/System.Native/Interop.INotify.cs @@ -10,14 +10,14 @@ internal static partial class Interop { internal static partial class Sys { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_INotifyInit", SetLastError = true)] - internal static extern SafeFileHandle INotifyInit(); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_INotifyInit", SetLastError = true)] + internal static partial SafeFileHandle INotifyInit(); - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_INotifyAddWatch", SetLastError = true)] - internal static extern int INotifyAddWatch(SafeFileHandle fd, string pathName, uint mask); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_INotifyAddWatch", CharSet = CharSet.Ansi, SetLastError = true)] + internal static partial int INotifyAddWatch(SafeFileHandle fd, string pathName, uint mask); - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_INotifyRemoveWatch", SetLastError = true)] - private static extern int INotifyRemoveWatch_private(SafeFileHandle fd, int wd); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_INotifyRemoveWatch", SetLastError = true)] + private static partial int INotifyRemoveWatch_private(SafeFileHandle fd, int wd); internal static int INotifyRemoveWatch(SafeFileHandle fd, int wd) { diff --git a/src/libraries/Common/src/Interop/OSX/Interop.CoreFoundation.CFArray.cs b/src/libraries/Common/src/Interop/OSX/Interop.CoreFoundation.CFArray.cs index 3c57e9f894291..aeba90d5bc546 100644 --- a/src/libraries/Common/src/Interop/OSX/Interop.CoreFoundation.CFArray.cs +++ b/src/libraries/Common/src/Interop/OSX/Interop.CoreFoundation.CFArray.cs @@ -13,13 +13,13 @@ internal static partial class Interop { internal static partial class CoreFoundation { - [DllImport(Libraries.CoreFoundationLibrary, EntryPoint = "CFArrayGetCount")] - private static extern CFIndex _CFArrayGetCount(SafeCFArrayHandle cfArray); + [GeneratedDllImport(Libraries.CoreFoundationLibrary, EntryPoint = "CFArrayGetCount")] + private static partial CFIndex _CFArrayGetCount(SafeCFArrayHandle cfArray); // Follows the "Get" version of the "Create" rule, so needs to return an IntPtr to // prevent CFRelease from being called on the SafeHandle close. - [DllImport(Libraries.CoreFoundationLibrary, EntryPoint = "CFArrayGetValueAtIndex")] - private static extern IntPtr CFArrayGetValueAtIndex(SafeCFArrayHandle cfArray, CFIndex index); + [GeneratedDllImport(Libraries.CoreFoundationLibrary, EntryPoint = "CFArrayGetValueAtIndex")] + private static partial IntPtr CFArrayGetValueAtIndex(SafeCFArrayHandle cfArray, CFIndex index); internal static long CFArrayGetCount(SafeCFArrayHandle cfArray) { diff --git a/src/libraries/Common/src/Interop/OSX/Interop.CoreFoundation.CFData.cs b/src/libraries/Common/src/Interop/OSX/Interop.CoreFoundation.CFData.cs index 68e8164a539f5..f0775d72cadf9 100644 --- a/src/libraries/Common/src/Interop/OSX/Interop.CoreFoundation.CFData.cs +++ b/src/libraries/Common/src/Interop/OSX/Interop.CoreFoundation.CFData.cs @@ -13,11 +13,11 @@ internal static partial class Interop { internal static partial class CoreFoundation { - [DllImport(Libraries.CoreFoundationLibrary)] - private static extern unsafe byte* CFDataGetBytePtr(SafeCFDataHandle cfData); + [GeneratedDllImport(Libraries.CoreFoundationLibrary)] + private static unsafe partial byte* CFDataGetBytePtr(SafeCFDataHandle cfData); - [DllImport(Libraries.CoreFoundationLibrary)] - private static extern CFIndex CFDataGetLength(SafeCFDataHandle cfData); + [GeneratedDllImport(Libraries.CoreFoundationLibrary)] + private static partial CFIndex CFDataGetLength(SafeCFDataHandle cfData); internal static unsafe Span CFDataDangerousGetSpan(SafeCFDataHandle cfData) { diff --git a/src/libraries/Common/src/Interop/OSX/Interop.CoreFoundation.CFDate.cs b/src/libraries/Common/src/Interop/OSX/Interop.CoreFoundation.CFDate.cs index 4393796ef6add..e43e20d83f679 100644 --- a/src/libraries/Common/src/Interop/OSX/Interop.CoreFoundation.CFDate.cs +++ b/src/libraries/Common/src/Interop/OSX/Interop.CoreFoundation.CFDate.cs @@ -17,8 +17,8 @@ internal static partial class CoreFoundation // https://developer.apple.com/reference/corefoundation/cfabsolutetime private static readonly DateTime s_cfDateEpoch = new DateTime(2001, 1, 1, 0, 0, 0, DateTimeKind.Utc); - [DllImport(Libraries.CoreFoundationLibrary)] - private static extern SafeCFDateHandle CFDateCreate(IntPtr zero, CFAbsoluteTime at); + [GeneratedDllImport(Libraries.CoreFoundationLibrary)] + private static partial SafeCFDateHandle CFDateCreate(IntPtr zero, CFAbsoluteTime at); internal static SafeCFDateHandle CFDateCreate(DateTime date) { diff --git a/src/libraries/Common/src/Interop/OSX/Interop.CoreFoundation.CFDictionary.cs b/src/libraries/Common/src/Interop/OSX/Interop.CoreFoundation.CFDictionary.cs index eeee71bd5a2a2..466bd584f46a6 100644 --- a/src/libraries/Common/src/Interop/OSX/Interop.CoreFoundation.CFDictionary.cs +++ b/src/libraries/Common/src/Interop/OSX/Interop.CoreFoundation.CFDictionary.cs @@ -11,8 +11,8 @@ internal static partial class Interop { internal static partial class CoreFoundation { - [DllImport(Libraries.CoreFoundationLibrary)] - internal static extern IntPtr CFDictionaryGetValue(SafeCFDictionaryHandle handle, IntPtr key); + [GeneratedDllImport(Libraries.CoreFoundationLibrary)] + internal static partial IntPtr CFDictionaryGetValue(SafeCFDictionaryHandle handle, IntPtr key); } } diff --git a/src/libraries/Common/src/Interop/OSX/Interop.CoreFoundation.CFError.cs b/src/libraries/Common/src/Interop/OSX/Interop.CoreFoundation.CFError.cs index 52c6507fb5438..056628a81e6ee 100644 --- a/src/libraries/Common/src/Interop/OSX/Interop.CoreFoundation.CFError.cs +++ b/src/libraries/Common/src/Interop/OSX/Interop.CoreFoundation.CFError.cs @@ -14,11 +14,11 @@ internal static partial class Interop { internal static partial class CoreFoundation { - [DllImport(Libraries.CoreFoundationLibrary)] - private static extern CFIndex CFErrorGetCode(SafeCFErrorHandle cfError); + [GeneratedDllImport(Libraries.CoreFoundationLibrary)] + private static partial CFIndex CFErrorGetCode(SafeCFErrorHandle cfError); - [DllImport(Libraries.CoreFoundationLibrary)] - private static extern SafeCFStringHandle CFErrorCopyDescription(SafeCFErrorHandle cfError); + [GeneratedDllImport(Libraries.CoreFoundationLibrary)] + private static partial SafeCFStringHandle CFErrorCopyDescription(SafeCFErrorHandle cfError); internal static int GetErrorCode(SafeCFErrorHandle cfError) { diff --git a/src/libraries/Common/src/Interop/OSX/Interop.CoreFoundation.CFNumber.cs b/src/libraries/Common/src/Interop/OSX/Interop.CoreFoundation.CFNumber.cs index 9addf8e12ca14..d01a5499a2ba0 100644 --- a/src/libraries/Common/src/Interop/OSX/Interop.CoreFoundation.CFNumber.cs +++ b/src/libraries/Common/src/Interop/OSX/Interop.CoreFoundation.CFNumber.cs @@ -17,6 +17,6 @@ internal enum CFNumberType } [DllImport(Libraries.CoreFoundationLibrary)] - private static extern int CFNumberGetValue(IntPtr handle, CFNumberType type, out int value); + private static unsafe extern int CFNumberGetValue(IntPtr handle, CFNumberType type, int* value); } } diff --git a/src/libraries/Common/src/Interop/OSX/Interop.CoreFoundation.CFProxy.cs b/src/libraries/Common/src/Interop/OSX/Interop.CoreFoundation.CFProxy.cs index c4d4a21fa455a..f31504146348f 100644 --- a/src/libraries/Common/src/Interop/OSX/Interop.CoreFoundation.CFProxy.cs +++ b/src/libraries/Common/src/Interop/OSX/Interop.CoreFoundation.CFProxy.cs @@ -13,23 +13,23 @@ internal static partial class Interop { internal static partial class CoreFoundation { - [DllImport(Libraries.CFNetworkLibrary)] - internal static extern SafeCFDictionaryHandle CFNetworkCopySystemProxySettings(); + [GeneratedDllImport(Libraries.CFNetworkLibrary)] + internal static partial SafeCFDictionaryHandle CFNetworkCopySystemProxySettings(); - [DllImport(Libraries.CFNetworkLibrary)] - internal static extern SafeCFArrayHandle CFNetworkCopyProxiesForURL(SafeCreateHandle url, SafeCFDictionaryHandle proxySettings); + [GeneratedDllImport(Libraries.CFNetworkLibrary)] + internal static partial SafeCFArrayHandle CFNetworkCopyProxiesForURL(SafeCreateHandle url, SafeCFDictionaryHandle proxySettings); internal delegate void CFProxyAutoConfigurationResultCallback(IntPtr client, IntPtr proxyList, IntPtr error); - [DllImport(Libraries.CFNetworkLibrary)] - internal static extern CFRunLoopSourceRef CFNetworkExecuteProxyAutoConfigurationURL( + [GeneratedDllImport(Libraries.CFNetworkLibrary)] + internal static partial CFRunLoopSourceRef CFNetworkExecuteProxyAutoConfigurationURL( IntPtr proxyAutoConfigURL, SafeCreateHandle targetURL, CFProxyAutoConfigurationResultCallback cb, ref CFStreamClientContext clientContext); - [DllImport(Libraries.CFNetworkLibrary)] - internal static extern CFRunLoopSourceRef CFNetworkExecuteProxyAutoConfigurationScript( + [GeneratedDllImport(Libraries.CFNetworkLibrary)] + internal static partial CFRunLoopSourceRef CFNetworkExecuteProxyAutoConfigurationScript( IntPtr proxyAutoConfigurationScript, SafeCreateHandle targetURL, CFProxyAutoConfigurationResultCallback cb, @@ -131,9 +131,13 @@ public int PortNumber get { IntPtr dictValue = CFDictionaryGetValue(_dictionary, kCFProxyPortNumberKey); - if (dictValue != IntPtr.Zero && CFNumberGetValue(dictValue, CFNumberType.kCFNumberIntType, out int value) > 0) + unsafe { - return value; + int value; + if (dictValue != IntPtr.Zero && CFNumberGetValue(dictValue, CFNumberType.kCFNumberIntType, &value) > 0) + { + return value; + } } return -1; } diff --git a/src/libraries/Common/src/Interop/OSX/Interop.CoreFoundation.CFString.cs b/src/libraries/Common/src/Interop/OSX/Interop.CoreFoundation.CFString.cs index 8c19957f55b7a..152741605e086 100644 --- a/src/libraries/Common/src/Interop/OSX/Interop.CoreFoundation.CFString.cs +++ b/src/libraries/Common/src/Interop/OSX/Interop.CoreFoundation.CFString.cs @@ -15,13 +15,13 @@ internal static partial class CoreFoundation /// Returns the interior pointer of the cfString if it has the specified encoding. /// If it has the wrong encoding, or if the interior pointer isn't being shared for some reason, returns NULL /// - [DllImport(Libraries.CoreFoundationLibrary)] - private static extern IntPtr CFStringGetCStringPtr( + [GeneratedDllImport(Libraries.CoreFoundationLibrary)] + private static partial IntPtr CFStringGetCStringPtr( SafeCFStringHandle cfString, CFStringBuiltInEncodings encoding); - [DllImport(Libraries.CoreFoundationLibrary)] - private static extern SafeCFDataHandle CFStringCreateExternalRepresentation( + [GeneratedDllImport(Libraries.CoreFoundationLibrary)] + private static partial SafeCFDataHandle CFStringCreateExternalRepresentation( IntPtr alloc, SafeCFStringHandle theString, CFStringBuiltInEncodings encoding, diff --git a/src/libraries/Common/src/Interop/OSX/Interop.CoreFoundation.CFUrl.cs b/src/libraries/Common/src/Interop/OSX/Interop.CoreFoundation.CFUrl.cs index 28e3d2d5b807b..96632448c113a 100644 --- a/src/libraries/Common/src/Interop/OSX/Interop.CoreFoundation.CFUrl.cs +++ b/src/libraries/Common/src/Interop/OSX/Interop.CoreFoundation.CFUrl.cs @@ -11,8 +11,8 @@ internal static partial class Interop { internal static partial class CoreFoundation { - [DllImport(Libraries.CoreFoundationLibrary)] - private static extern SafeCreateHandle CFURLCreateWithString( + [GeneratedDllImport(Libraries.CoreFoundationLibrary)] + private static partial SafeCreateHandle CFURLCreateWithString( IntPtr allocator, SafeCreateHandle str, IntPtr baseUrl); diff --git a/src/libraries/Common/src/Interop/OSX/Interop.CoreFoundation.cs b/src/libraries/Common/src/Interop/OSX/Interop.CoreFoundation.cs index 20fdcfd697313..11fe4891c4c99 100644 --- a/src/libraries/Common/src/Interop/OSX/Interop.CoreFoundation.cs +++ b/src/libraries/Common/src/Interop/OSX/Interop.CoreFoundation.cs @@ -47,8 +47,8 @@ private enum CFStringBuiltInEncodings : uint /// The encoding type. /// Whether or not a BOM is present. /// A CFStringRef on success, otherwise a SafeCreateHandle(IntPtr.Zero). - [DllImport(Interop.Libraries.CoreFoundationLibrary)] - private static extern SafeCreateHandle CFStringCreateWithBytes( + [GeneratedDllImport(Interop.Libraries.CoreFoundationLibrary)] + private static partial SafeCreateHandle CFStringCreateWithBytes( IntPtr alloc, IntPtr bytes, CFIndex numBytes, @@ -63,8 +63,8 @@ private static extern SafeCreateHandle CFStringCreateWithBytes( /// The encoding of the str variable. This should be UTF 8 for OS X /// Returns a pointer to a CFString on success; otherwise, returns IntPtr.Zero /// For *nix systems, the CLR maps ANSI to UTF-8, so be explicit about that - [DllImport(Interop.Libraries.CoreFoundationLibrary, CharSet = CharSet.Ansi)] - private static extern SafeCreateHandle CFStringCreateWithCString( + [GeneratedDllImport(Interop.Libraries.CoreFoundationLibrary, CharSet = CharSet.Ansi)] + private static partial SafeCreateHandle CFStringCreateWithCString( IntPtr allocator, string str, CFStringBuiltInEncodings encoding); @@ -77,8 +77,8 @@ private static extern SafeCreateHandle CFStringCreateWithCString( /// The encoding of the str variable. This should be UTF 8 for OS X /// Returns a pointer to a CFString on success; otherwise, returns IntPtr.Zero /// For *nix systems, the CLR maps ANSI to UTF-8, so be explicit about that - [DllImport(Interop.Libraries.CoreFoundationLibrary, CharSet = CharSet.Ansi)] - private static extern SafeCreateHandle CFStringCreateWithCString( + [GeneratedDllImport(Interop.Libraries.CoreFoundationLibrary, CharSet = CharSet.Ansi)] + private static partial SafeCreateHandle CFStringCreateWithCString( IntPtr allocator, IntPtr str, CFStringBuiltInEncodings encoding); @@ -130,8 +130,8 @@ internal static unsafe SafeCreateHandle CFStringCreateFromSpan(ReadOnlySpanThe number of values in the array /// Should be IntPtr.Zero /// Returns a pointer to a CFArray on success; otherwise, returns IntPtr.Zero - [DllImport(Interop.Libraries.CoreFoundationLibrary)] - private static extern SafeCreateHandle CFArrayCreate( + [GeneratedDllImport(Interop.Libraries.CoreFoundationLibrary)] + private static partial SafeCreateHandle CFArrayCreate( IntPtr allocator, [MarshalAs(UnmanagedType.LPArray)] IntPtr[] values, diff --git a/src/libraries/Common/src/Interop/OSX/Interop.EventStream.cs b/src/libraries/Common/src/Interop/OSX/Interop.EventStream.cs index 9f32269e1b8e4..b0d312ff824f4 100644 --- a/src/libraries/Common/src/Interop/OSX/Interop.EventStream.cs +++ b/src/libraries/Common/src/Interop/OSX/Interop.EventStream.cs @@ -99,8 +99,8 @@ internal struct FSEventStreamContext /// Flags to say what kind of events should be sent through this stream. /// On success, returns a pointer to an FSEventStream object; otherwise, returns IntPtr.Zero /// For *nix systems, the CLR maps ANSI to UTF-8, so be explicit about that - [DllImport(Interop.Libraries.CoreServicesLibrary, CharSet = CharSet.Ansi)] - internal static extern unsafe SafeEventStreamHandle FSEventStreamCreate( + [GeneratedDllImport(Interop.Libraries.CoreServicesLibrary, CharSet = CharSet.Ansi)] + internal static unsafe partial SafeEventStreamHandle FSEventStreamCreate( IntPtr allocator, delegate* unmanaged callback, FSEventStreamContext* context, @@ -115,8 +115,8 @@ internal static extern unsafe SafeEventStreamHandle FSEventStreamCreate( /// The stream to attach to the RunLoop /// The RunLoop to attach the stream to /// The mode of the RunLoop; this should usually be kCFRunLoopDefaultMode. See the documentation for RunLoops for more info. - [DllImport(Interop.Libraries.CoreServicesLibrary)] - internal static extern void FSEventStreamScheduleWithRunLoop( + [GeneratedDllImport(Interop.Libraries.CoreServicesLibrary)] + internal static partial void FSEventStreamScheduleWithRunLoop( SafeEventStreamHandle streamRef, CFRunLoopRef runLoop, SafeCreateHandle runLoopMode); @@ -126,15 +126,15 @@ internal static extern void FSEventStreamScheduleWithRunLoop( /// /// The stream to receive events on. /// Returns true if the stream was started; otherwise, returns false and no events will be received. - [DllImport(Interop.Libraries.CoreServicesLibrary)] - internal static extern bool FSEventStreamStart(SafeEventStreamHandle streamRef); + [GeneratedDllImport(Interop.Libraries.CoreServicesLibrary)] + internal static partial bool FSEventStreamStart(SafeEventStreamHandle streamRef); /// /// Stops receiving events on the specified stream. The stream can be restarted and not miss any events. /// /// The stream to stop receiving events on. - [DllImport(Interop.Libraries.CoreServicesLibrary)] - internal static extern void FSEventStreamStop(SafeEventStreamHandle streamRef); + [GeneratedDllImport(Interop.Libraries.CoreServicesLibrary)] + internal static partial void FSEventStreamStop(SafeEventStreamHandle streamRef); /// /// Stops receiving events on the specified stream. The stream can be restarted and not miss any events. @@ -157,8 +157,8 @@ internal static extern void FSEventStreamScheduleWithRunLoop( /// The stream to remove from the RunLoop /// The RunLoop to remove the stream from. /// The mode of the RunLoop; this should usually be kCFRunLoopDefaultMode. See the documentation for RunLoops for more info. - [DllImport(Interop.Libraries.CoreServicesLibrary)] - internal static extern void FSEventStreamUnscheduleFromRunLoop( + [GeneratedDllImport(Interop.Libraries.CoreServicesLibrary)] + internal static partial void FSEventStreamUnscheduleFromRunLoop( SafeEventStreamHandle streamRef, CFRunLoopRef runLoop, SafeCreateHandle runLoopMode); diff --git a/src/libraries/Common/src/Interop/OSX/Interop.RunLoop.cs b/src/libraries/Common/src/Interop/OSX/Interop.RunLoop.cs index 3d3a74cf9473c..6c662e6c3e68f 100644 --- a/src/libraries/Common/src/Interop/OSX/Interop.RunLoop.cs +++ b/src/libraries/Common/src/Interop/OSX/Interop.RunLoop.cs @@ -87,7 +87,7 @@ internal static partial class RunLoop /// waiting for a source or timer to become ready to fire; /// false if rl either is not running or is currently processing /// a source, timer, or observer. - [DllImport(Interop.Libraries.CoreFoundationLibrary)] - internal static extern bool CFRunLoopIsWaiting(CFRunLoopRef rl); + [GeneratedDllImport(Interop.Libraries.CoreFoundationLibrary)] + internal static partial bool CFRunLoopIsWaiting(CFRunLoopRef rl); } } diff --git a/src/libraries/Common/src/Interop/OSX/Interop.SystemConfiguration.cs b/src/libraries/Common/src/Interop/OSX/Interop.SystemConfiguration.cs index 5d9e896dd4024..f0e4e471667e9 100644 --- a/src/libraries/Common/src/Interop/OSX/Interop.SystemConfiguration.cs +++ b/src/libraries/Common/src/Interop/OSX/Interop.SystemConfiguration.cs @@ -34,8 +34,8 @@ internal struct SCDynamicStoreContext /// Pass null if no callouts are desired. /// The context associated with the callout. /// A reference to the new dynamic store session. - [DllImport(Libraries.SystemConfigurationLibrary)] - private static extern unsafe SafeCreateHandle SCDynamicStoreCreate( + [GeneratedDllImport(Libraries.SystemConfigurationLibrary)] + private static unsafe partial SafeCreateHandle SCDynamicStoreCreate( IntPtr allocator, CFStringRef name, delegate* unmanaged callout, @@ -67,8 +67,8 @@ internal static unsafe SafeCreateHandle SCDynamicStoreCreate( /// The service ID or a regular expression pattern. /// The specific global entity, such as IPv4 or DNS. /// A string containing the formatted key. - [DllImport(Libraries.SystemConfigurationLibrary)] - private static extern SafeCreateHandle SCDynamicStoreKeyCreateNetworkServiceEntity( + [GeneratedDllImport(Libraries.SystemConfigurationLibrary)] + private static partial SafeCreateHandle SCDynamicStoreKeyCreateNetworkServiceEntity( IntPtr allocator, CFStringRef domain, CFStringRef serviceID, @@ -99,8 +99,8 @@ internal static SafeCreateHandle SCDynamicStoreKeyCreateNetworkServiceEntity( /// The order in which the sources that are ready to be processed are handled, /// on platforms that support it and for source versions that support it. /// The new run loop source object. - [DllImport(Libraries.SystemConfigurationLibrary)] - private static extern SafeCreateHandle SCDynamicStoreCreateRunLoopSource( + [GeneratedDllImport(Libraries.SystemConfigurationLibrary)] + private static partial SafeCreateHandle SCDynamicStoreCreateRunLoopSource( IntPtr allocator, SCDynamicStoreRef store, CFIndex order); @@ -125,8 +125,8 @@ internal static SafeCreateHandle SCDynamicStoreCreateRunLoopSource(SCDynamicStor /// An array of keys to be monitored or IntPtr.Zero if no specific keys are to be monitored. /// An array of POSIX regex pattern strings used to match keys to be monitored, /// or IntPtr.Zero if no key patterns are to be monitored. - /// True if the set of notification keys and patterns was successfully updated; false otherwise. - [DllImport(Libraries.SystemConfigurationLibrary)] - internal static extern bool SCDynamicStoreSetNotificationKeys(SCDynamicStoreRef store, CFArrayRef keys, CFArrayRef patterns); + /// Non-zero if the set of notification keys and patterns was successfully updated; zero otherwise. + [GeneratedDllImport(Libraries.SystemConfigurationLibrary)] + internal static partial bool SCDynamicStoreSetNotificationKeys(SCDynamicStoreRef store, CFArrayRef keys, CFArrayRef patterns); } } diff --git a/src/libraries/Common/src/Interop/OSX/Interop.libproc.GetProcessInfoById.cs b/src/libraries/Common/src/Interop/OSX/Interop.libproc.GetProcessInfoById.cs index 7ac40a21e67f4..f667641d27c99 100644 --- a/src/libraries/Common/src/Interop/OSX/Interop.libproc.GetProcessInfoById.cs +++ b/src/libraries/Common/src/Interop/OSX/Interop.libproc.GetProcessInfoById.cs @@ -89,8 +89,8 @@ internal struct proc_taskallinfo /// the data is valid. If the sizes do not match then the data is invalid, most likely due /// to not having enough permissions to query for the data of that specific process /// - [DllImport(Interop.Libraries.libproc, SetLastError = true)] - private static extern unsafe int proc_pidinfo( + [GeneratedDllImport(Interop.Libraries.libproc, SetLastError = true)] + private static unsafe partial int proc_pidinfo( int pid, int flavor, ulong arg, diff --git a/src/libraries/Common/src/Interop/OSX/Interop.libproc.cs b/src/libraries/Common/src/Interop/OSX/Interop.libproc.cs index fd4b968c132ea..fefac9aac1fa8 100644 --- a/src/libraries/Common/src/Interop/OSX/Interop.libproc.cs +++ b/src/libraries/Common/src/Interop/OSX/Interop.libproc.cs @@ -107,8 +107,8 @@ internal struct proc_fdinfo /// A pointer to the memory block where the PID array will start /// The length of the block of memory allocated for the PID array /// Returns the number of elements (PIDs) in the buffer - [DllImport(Interop.Libraries.libproc, SetLastError = true)] - private static extern unsafe int proc_listallpids( + [GeneratedDllImport(Interop.Libraries.libproc, SetLastError = true)] + private static unsafe partial int proc_listallpids( int* pBuffer, int buffersize); @@ -166,8 +166,8 @@ internal static unsafe int[] proc_listallpids() /// the data is valid. If the sizes do not match then the data is invalid, most likely due /// to not having enough permissions to query for the data of that specific process /// - [DllImport(Interop.Libraries.libproc, SetLastError = true)] - private static extern unsafe int proc_pidinfo( + [GeneratedDllImport(Interop.Libraries.libproc, SetLastError = true)] + private static unsafe partial int proc_pidinfo( int pid, int flavor, ulong arg, @@ -187,8 +187,8 @@ private static extern unsafe int proc_pidinfo( /// the data is valid. If the sizes do not match then the data is invalid, most likely due /// to not having enough permissions to query for the data of that specific process /// - [DllImport(Interop.Libraries.libproc, SetLastError = true)] - private static extern unsafe int proc_pidinfo( + [GeneratedDllImport(Interop.Libraries.libproc, SetLastError = true)] + private static unsafe partial int proc_pidinfo( int pid, int flavor, ulong arg, @@ -208,8 +208,8 @@ private static extern unsafe int proc_pidinfo( /// the data is valid. If the sizes do not match then the data is invalid, most likely due /// to not having enough permissions to query for the data of that specific process /// - [DllImport(Interop.Libraries.libproc, SetLastError = true)] - private static extern unsafe int proc_pidinfo( + [GeneratedDllImport(Interop.Libraries.libproc, SetLastError = true)] + private static unsafe partial int proc_pidinfo( int pid, int flavor, ulong arg, @@ -307,8 +307,8 @@ private static extern unsafe int proc_pidinfo( /// A pointer to an allocated block of memory that will be filled with the process path /// The size of the buffer, should be PROC_PIDPATHINFO_MAXSIZE /// Returns the length of the path returned on success - [DllImport(Interop.Libraries.libproc, SetLastError = true)] - private static extern unsafe int proc_pidpath( + [GeneratedDllImport(Interop.Libraries.libproc, SetLastError = true)] + private static unsafe partial int proc_pidpath( int pid, byte* buffer, uint bufferSize); @@ -346,8 +346,8 @@ internal static unsafe string proc_pidpath(int pid) /// Specifies the type of struct that is passed in to buffer. Should be RUSAGE_INFO_V3 to specify a rusage_info_v3 struct. /// A buffer to be filled with rusage_info data /// Returns 0 on success; on fail, -1 and errno is set with the error code - [DllImport(Interop.Libraries.libproc, SetLastError = true)] - private static extern unsafe int proc_pid_rusage( + [GeneratedDllImport(Interop.Libraries.libproc, SetLastError = true)] + private static unsafe partial int proc_pid_rusage( int pid, int flavor, rusage_info_v3* buffer); diff --git a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Digest.cs b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Digest.cs index 144b66d2a1149..5a6939e0fb4b5 100644 --- a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Digest.cs +++ b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Digest.cs @@ -12,32 +12,32 @@ internal static partial class AppleCrypto [DllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_DigestFree")] internal static extern void DigestFree(IntPtr handle); - [DllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_DigestCreate")] - internal static extern SafeDigestCtxHandle DigestCreate(PAL_HashAlgorithm algorithm, out int cbDigest); + [GeneratedDllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_DigestCreate")] + internal static partial SafeDigestCtxHandle DigestCreate(PAL_HashAlgorithm algorithm, out int cbDigest); internal static int DigestUpdate(SafeDigestCtxHandle ctx, ReadOnlySpan data) => DigestUpdate(ctx, ref MemoryMarshal.GetReference(data), data.Length); - [DllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_DigestUpdate")] - private static extern int DigestUpdate(SafeDigestCtxHandle ctx, ref byte pbData, int cbData); + [GeneratedDllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_DigestUpdate")] + private static partial int DigestUpdate(SafeDigestCtxHandle ctx, ref byte pbData, int cbData); internal static int DigestFinal(SafeDigestCtxHandle ctx, Span output) => DigestFinal(ctx, ref MemoryMarshal.GetReference(output), output.Length); - [DllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_DigestFinal")] - private static extern int DigestFinal(SafeDigestCtxHandle ctx, ref byte pbOutput, int cbOutput); + [GeneratedDllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_DigestFinal")] + private static partial int DigestFinal(SafeDigestCtxHandle ctx, ref byte pbOutput, int cbOutput); internal static int DigestCurrent(SafeDigestCtxHandle ctx, Span output) => DigestCurrent(ctx, ref MemoryMarshal.GetReference(output), output.Length); - [DllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_DigestCurrent")] - private static extern int DigestCurrent(SafeDigestCtxHandle ctx, ref byte pbOutput, int cbOutput); + [GeneratedDllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_DigestCurrent")] + private static partial int DigestCurrent(SafeDigestCtxHandle ctx, ref byte pbOutput, int cbOutput); [DllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_DigestOneShot")] - internal static unsafe extern int DigestOneShot(PAL_HashAlgorithm algorithm, byte* pbData, int cbData, byte* pbOutput, int cbOutput, out int cbDigest); + internal static unsafe extern int DigestOneShot(PAL_HashAlgorithm algorithm, byte* pbData, int cbData, byte* pbOutput, int cbOutput, int* cbDigest); - [DllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_DigestReset")] - internal static extern int DigestReset(SafeDigestCtxHandle ctx); + [GeneratedDllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_DigestReset")] + internal static partial int DigestReset(SafeDigestCtxHandle ctx); } } diff --git a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Ecc.cs b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Ecc.cs index 18e6f62cc04e1..d1a27c769eb32 100644 --- a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Ecc.cs +++ b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Ecc.cs @@ -11,15 +11,15 @@ internal static partial class Interop { internal static partial class AppleCrypto { - [DllImport(Libraries.AppleCryptoNative)] - private static extern int AppleCryptoNative_EccGenerateKey( + [GeneratedDllImport(Libraries.AppleCryptoNative)] + private static partial int AppleCryptoNative_EccGenerateKey( int keySizeInBits, out SafeSecKeyRefHandle pPublicKey, out SafeSecKeyRefHandle pPrivateKey, out SafeCFErrorHandle pErrorOut); - [DllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_EccGetKeySizeInBits")] - internal static extern long EccGetKeySizeInBits(SafeSecKeyRefHandle publicKey); + [GeneratedDllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_EccGetKeySizeInBits")] + internal static partial long EccGetKeySizeInBits(SafeSecKeyRefHandle publicKey); internal static void EccGenerateKey( int keySizeInBits, diff --git a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Hmac.cs b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Hmac.cs index 7cedae49e5472..5b4e18c2e71a2 100644 --- a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Hmac.cs +++ b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Hmac.cs @@ -12,29 +12,29 @@ internal static partial class AppleCrypto [DllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_HmacFree")] internal static extern void HmacFree(IntPtr handle); - [DllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_HmacCreate")] - internal static extern SafeHmacHandle HmacCreate(PAL_HashAlgorithm algorithm, ref int cbDigest); + [GeneratedDllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_HmacCreate")] + internal static partial SafeHmacHandle HmacCreate(PAL_HashAlgorithm algorithm, ref int cbDigest); - [DllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_HmacInit")] - internal static extern int HmacInit(SafeHmacHandle ctx, [In] byte[] pbKey, int cbKey); + [GeneratedDllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_HmacInit")] + internal static partial int HmacInit(SafeHmacHandle ctx, byte[] pbKey, int cbKey); internal static int HmacUpdate(SafeHmacHandle ctx, ReadOnlySpan data) => HmacUpdate(ctx, ref MemoryMarshal.GetReference(data), data.Length); - [DllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_HmacUpdate")] - private static extern int HmacUpdate(SafeHmacHandle ctx, ref byte pbData, int cbData); + [GeneratedDllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_HmacUpdate")] + private static partial int HmacUpdate(SafeHmacHandle ctx, ref byte pbData, int cbData); internal static int HmacFinal(SafeHmacHandle ctx, ReadOnlySpan output) => HmacFinal(ctx, ref MemoryMarshal.GetReference(output), output.Length); - [DllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_HmacFinal")] - private static extern int HmacFinal(SafeHmacHandle ctx, ref byte pbOutput, int cbOutput); + [GeneratedDllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_HmacFinal")] + private static partial int HmacFinal(SafeHmacHandle ctx, ref byte pbOutput, int cbOutput); internal static int HmacCurrent(SafeHmacHandle ctx, ReadOnlySpan output) => HmacCurrent(ctx, ref MemoryMarshal.GetReference(output), output.Length); - [DllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_HmacCurrent")] - private static extern int HmacCurrent(SafeHmacHandle ctx, ref byte pbOutput, int cbOutput); + [GeneratedDllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_HmacCurrent")] + private static partial int HmacCurrent(SafeHmacHandle ctx, ref byte pbOutput, int cbOutput); [DllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_HmacOneShot")] internal static unsafe extern int HmacOneShot( @@ -45,7 +45,7 @@ internal static unsafe extern int HmacOneShot( int cbData, byte* pOutput, int cbOutput, - out int cbDigest); + int* cbDigest); } } diff --git a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.KeyAgree.cs b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.KeyAgree.cs index 379db2ee51264..703f72b7fafc2 100644 --- a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.KeyAgree.cs +++ b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.KeyAgree.cs @@ -12,8 +12,8 @@ internal static partial class Interop { internal static partial class AppleCrypto { - [DllImport(Libraries.AppleCryptoNative)] - private static extern int AppleCryptoNative_EcdhKeyAgree( + [GeneratedDllImport(Libraries.AppleCryptoNative)] + private static partial int AppleCryptoNative_EcdhKeyAgree( SafeSecKeyRefHandle privateKey, SafeSecKeyRefHandle publicKey, out SafeCFDataHandle cfDataOut, diff --git a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Keychain.macOS.cs b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Keychain.macOS.cs index c93319994bbd5..8898f400ada6b 100644 --- a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Keychain.macOS.cs +++ b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Keychain.macOS.cs @@ -15,20 +15,20 @@ internal static partial class Interop { internal static partial class AppleCrypto { - [DllImport(Libraries.AppleCryptoNative)] - private static extern int AppleCryptoNative_SecKeychainItemCopyKeychain( + [GeneratedDllImport(Libraries.AppleCryptoNative)] + private static partial int AppleCryptoNative_SecKeychainItemCopyKeychain( IntPtr item, out SafeKeychainHandle keychain); - [DllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_SecKeychainCreate")] - private static extern unsafe int AppleCryptoNative_SecKeychainCreateTemporary( + [GeneratedDllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_SecKeychainCreate", CharSet = CharSet.Ansi)] + private static unsafe partial int AppleCryptoNative_SecKeychainCreateTemporary( string path, int utf8PassphraseLength, byte* utf8Passphrase, out SafeTemporaryKeychainHandle keychain); - [DllImport(Libraries.AppleCryptoNative)] - private static extern int AppleCryptoNative_SecKeychainCreate( + [GeneratedDllImport(Libraries.AppleCryptoNative, CharSet = CharSet.Ansi)] + private static partial int AppleCryptoNative_SecKeychainCreate( string path, int utf8PassphraseLength, byte[] utf8Passphrase, @@ -37,43 +37,43 @@ private static extern int AppleCryptoNative_SecKeychainCreate( [DllImport(Libraries.AppleCryptoNative)] private static extern int AppleCryptoNative_SecKeychainDelete(IntPtr keychain); - [DllImport(Libraries.AppleCryptoNative)] - private static extern int AppleCryptoNative_SecKeychainCopyDefault(out SafeKeychainHandle keychain); + [GeneratedDllImport(Libraries.AppleCryptoNative)] + private static partial int AppleCryptoNative_SecKeychainCopyDefault(out SafeKeychainHandle keychain); - [DllImport(Libraries.AppleCryptoNative)] - private static extern int AppleCryptoNative_SecKeychainOpen( + [GeneratedDllImport(Libraries.AppleCryptoNative, CharSet = CharSet.Ansi)] + private static partial int AppleCryptoNative_SecKeychainOpen( string keychainPath, out SafeKeychainHandle keychain); - [DllImport(Libraries.AppleCryptoNative)] - private static extern int AppleCryptoNative_SecKeychainUnlock( + [GeneratedDllImport(Libraries.AppleCryptoNative)] + private static partial int AppleCryptoNative_SecKeychainUnlock( SafeKeychainHandle keychain, int utf8PassphraseLength, byte[] utf8Passphrase); - [DllImport(Libraries.AppleCryptoNative)] - private static extern int AppleCryptoNative_SetKeychainNeverLock(SafeKeychainHandle keychain); + [GeneratedDllImport(Libraries.AppleCryptoNative)] + private static partial int AppleCryptoNative_SetKeychainNeverLock(SafeKeychainHandle keychain); - [DllImport(Libraries.AppleCryptoNative)] - private static extern int AppleCryptoNative_SecKeychainEnumerateCerts( + [GeneratedDllImport(Libraries.AppleCryptoNative)] + private static partial int AppleCryptoNative_SecKeychainEnumerateCerts( SafeKeychainHandle keychain, out SafeCFArrayHandle matches, out int pOSStatus); - [DllImport(Libraries.AppleCryptoNative)] - private static extern int AppleCryptoNative_SecKeychainEnumerateIdentities( + [GeneratedDllImport(Libraries.AppleCryptoNative)] + private static partial int AppleCryptoNative_SecKeychainEnumerateIdentities( SafeKeychainHandle keychain, out SafeCFArrayHandle matches, out int pOSStatus); - [DllImport(Libraries.AppleCryptoNative)] - private static extern int AppleCryptoNative_X509StoreAddCertificate( + [GeneratedDllImport(Libraries.AppleCryptoNative)] + private static partial int AppleCryptoNative_X509StoreAddCertificate( SafeKeychainItemHandle cert, SafeKeychainHandle keychain, out int pOSStatus); - [DllImport(Libraries.AppleCryptoNative)] - private static extern int AppleCryptoNative_X509StoreRemoveCertificate( + [GeneratedDllImport(Libraries.AppleCryptoNative)] + private static partial int AppleCryptoNative_X509StoreRemoveCertificate( SafeKeychainItemHandle cert, SafeKeychainHandle keychain, bool isReadOnlyMode, diff --git a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Pbkdf2.cs b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Pbkdf2.cs index 4eb5bfd57edfa..04fc12ac935e3 100644 --- a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Pbkdf2.cs +++ b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Pbkdf2.cs @@ -21,6 +21,7 @@ internal static unsafe void Pbkdf2( fixed (byte* pSalt = salt) fixed (byte* pDestination = destination) { + int ccStatus; int ret = AppleCryptoNative_Pbkdf2( prfAlgorithm, pPassword, @@ -30,7 +31,7 @@ internal static unsafe void Pbkdf2( iterations, pDestination, destination.Length, - out int ccStatus); + &ccStatus); if (ret == 0) { @@ -57,6 +58,6 @@ private static extern unsafe int AppleCryptoNative_Pbkdf2( int iterations, byte* derivedKey, int derivedKeyLen, - out int errorCode); + int* errorCode); } } diff --git a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.RSA.cs b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.RSA.cs index f0ebcf94d95e5..e3c68bed82480 100644 --- a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.RSA.cs +++ b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.RSA.cs @@ -12,31 +12,31 @@ internal static partial class Interop { internal static partial class AppleCrypto { - [DllImport(Libraries.AppleCryptoNative)] - private static extern int AppleCryptoNative_RsaGenerateKey( + [GeneratedDllImport(Libraries.AppleCryptoNative)] + private static partial int AppleCryptoNative_RsaGenerateKey( int keySizeInBits, out SafeSecKeyRefHandle pPublicKey, out SafeSecKeyRefHandle pPrivateKey, out SafeCFErrorHandle pErrorOut); - [DllImport(Libraries.AppleCryptoNative)] - private static extern int AppleCryptoNative_RsaSignaturePrimitive( + [GeneratedDllImport(Libraries.AppleCryptoNative)] + private static partial int AppleCryptoNative_RsaSignaturePrimitive( SafeSecKeyRefHandle privateKey, ref byte pbData, int cbData, out SafeCFDataHandle pDataOut, out SafeCFErrorHandle pErrorOut); - [DllImport(Libraries.AppleCryptoNative)] - private static extern int AppleCryptoNative_RsaVerificationPrimitive( + [GeneratedDllImport(Libraries.AppleCryptoNative)] + private static partial int AppleCryptoNative_RsaVerificationPrimitive( SafeSecKeyRefHandle publicKey, ref byte pbData, int cbData, out SafeCFDataHandle pDataOut, out SafeCFErrorHandle pErrorOut); - [DllImport(Libraries.AppleCryptoNative)] - private static extern int AppleCryptoNative_RsaEncryptionPrimitive( + [GeneratedDllImport(Libraries.AppleCryptoNative)] + private static partial int AppleCryptoNative_RsaEncryptionPrimitive( SafeSecKeyRefHandle publicKey, ref byte pbData, int cbData, @@ -52,8 +52,8 @@ private static int RsaEncryptOaep( out SafeCFErrorHandle pErrorOut) => RsaEncryptOaep(publicKey, ref MemoryMarshal.GetReference(pbData), cbData, mgfAlgorithm, out pEncryptedOut, out pErrorOut); - [DllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_RsaEncryptOaep")] - private static extern int RsaEncryptOaep( + [GeneratedDllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_RsaEncryptOaep")] + private static partial int RsaEncryptOaep( SafeSecKeyRefHandle publicKey, ref byte pbData, int cbData, @@ -69,8 +69,8 @@ private static int RsaEncryptPkcs( out SafeCFErrorHandle pErrorOut) => RsaEncryptPkcs(publicKey, ref MemoryMarshal.GetReference(pbData), cbData, out pEncryptedOut, out pErrorOut); - [DllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_RsaEncryptPkcs")] - private static extern int RsaEncryptPkcs( + [GeneratedDllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_RsaEncryptPkcs")] + private static partial int RsaEncryptPkcs( SafeSecKeyRefHandle publicKey, ref byte pbData, int cbData, @@ -86,8 +86,8 @@ private static int RsaDecryptOaep( out SafeCFErrorHandle pErrorOut) => RsaDecryptOaep(publicKey, ref MemoryMarshal.GetReference(pbData), cbData, mgfAlgorithm, out pEncryptedOut, out pErrorOut); - [DllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_RsaDecryptOaep")] - private static extern int RsaDecryptOaep( + [GeneratedDllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_RsaDecryptOaep")] + private static partial int RsaDecryptOaep( SafeSecKeyRefHandle publicKey, ref byte pbData, int cbData, @@ -103,8 +103,8 @@ private static int RsaDecryptPkcs( out SafeCFErrorHandle pErrorOut) => RsaDecryptPkcs(publicKey, ref MemoryMarshal.GetReference(pbData), cbData, out pEncryptedOut, out pErrorOut); - [DllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_RsaDecryptPkcs")] - private static extern int RsaDecryptPkcs( + [GeneratedDllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_RsaDecryptPkcs")] + private static partial int RsaDecryptPkcs( SafeSecKeyRefHandle publicKey, ref byte pbData, int cbData, diff --git a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Random.cs b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Random.cs index adde4ad378243..aceadb978eae5 100644 --- a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Random.cs +++ b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Random.cs @@ -14,7 +14,7 @@ internal static unsafe void GetRandomBytes(byte* pbBuffer, int count) Debug.Assert(count >= 0); int errorCode; - int ret = AppleCryptoNative_GetRandomBytes(pbBuffer, count, out errorCode); + int ret = AppleCryptoNative_GetRandomBytes(pbBuffer, count, &errorCode); if (ret == 0) { @@ -28,6 +28,6 @@ internal static unsafe void GetRandomBytes(byte* pbBuffer, int count) } [DllImport(Libraries.AppleCryptoNative)] - private static extern unsafe int AppleCryptoNative_GetRandomBytes(byte* buf, int num, out int errorCode); + private static extern unsafe int AppleCryptoNative_GetRandomBytes(byte* buf, int num, int* errorCode); } } diff --git a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.SecErrMessage.cs b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.SecErrMessage.cs index cb94d972a361b..f353c503f8d34 100644 --- a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.SecErrMessage.cs +++ b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.SecErrMessage.cs @@ -8,8 +8,8 @@ internal static partial class Interop { internal static partial class AppleCrypto { - [DllImport(Libraries.AppleCryptoNative)] - private static extern SafeCFStringHandle AppleCryptoNative_SecCopyErrorMessageString(int osStatus); + [GeneratedDllImport(Libraries.AppleCryptoNative)] + private static partial SafeCFStringHandle AppleCryptoNative_SecCopyErrorMessageString(int osStatus); internal static string? GetSecErrorString(int osStatus) { diff --git a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.SecKeyRef.cs b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.SecKeyRef.cs index a479faf2be559..a37ecbf9634b2 100644 --- a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.SecKeyRef.cs +++ b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.SecKeyRef.cs @@ -23,8 +23,8 @@ internal enum PAL_KeyAlgorithm : uint RSA = 2, } - [DllImport(Libraries.AppleCryptoNative)] - private static extern ulong AppleCryptoNative_SecKeyGetSimpleKeySizeInBytes(SafeSecKeyRefHandle publicKey); + [GeneratedDllImport(Libraries.AppleCryptoNative)] + private static partial ulong AppleCryptoNative_SecKeyGetSimpleKeySizeInBytes(SafeSecKeyRefHandle publicKey); private delegate int SecKeyTransform(ReadOnlySpan source, out SafeCFDataHandle outputHandle, out SafeCFErrorHandle errorHandle); @@ -154,8 +154,8 @@ internal static bool TrySecKeyCopyExternalRepresentation( } } - [DllImport(Libraries.AppleCryptoNative)] - private static unsafe extern int AppleCryptoNative_SecKeyCreateWithData( + [GeneratedDllImport(Libraries.AppleCryptoNative)] + private static unsafe partial int AppleCryptoNative_SecKeyCreateWithData( byte* pKey, int cbKey, PAL_KeyAlgorithm keyAlgorithm, @@ -163,14 +163,14 @@ private static unsafe extern int AppleCryptoNative_SecKeyCreateWithData( out SafeSecKeyRefHandle pDataKey, out SafeCFErrorHandle pErrorOut); - [DllImport(Libraries.AppleCryptoNative)] - private static unsafe extern int AppleCryptoNative_SecKeyCopyExternalRepresentation( + [GeneratedDllImport(Libraries.AppleCryptoNative)] + private static unsafe partial int AppleCryptoNative_SecKeyCopyExternalRepresentation( SafeSecKeyRefHandle key, out SafeCFDataHandle pDataOut, out SafeCFErrorHandle pErrorOut); - [DllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_SecKeyCopyPublicKey")] - internal static unsafe extern SafeSecKeyRefHandle CopyPublicKey(SafeSecKeyRefHandle privateKey); + [GeneratedDllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_SecKeyCopyPublicKey")] + internal static unsafe partial SafeSecKeyRefHandle CopyPublicKey(SafeSecKeyRefHandle privateKey); } } diff --git a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.SecKeyRef.macOS.cs b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.SecKeyRef.macOS.cs index cb78aabd624e3..789415a0d5680 100644 --- a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.SecKeyRef.macOS.cs +++ b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.SecKeyRef.macOS.cs @@ -26,8 +26,8 @@ ref MemoryMarshal.GetReference(pbKeyBlob), out ppKeyOut, out pOSStatus); - [DllImport(Libraries.AppleCryptoNative)] - private static extern int AppleCryptoNative_SecKeyImportEphemeral( + [GeneratedDllImport(Libraries.AppleCryptoNative)] + private static partial int AppleCryptoNative_SecKeyImportEphemeral( ref byte pbKeyBlob, int cbKeyBlob, int isPrivateKey, @@ -61,8 +61,8 @@ internal static SafeSecKeyRefHandle ImportEphemeralKey(ReadOnlySpan keyBlo throw new CryptographicException(); } - [DllImport(Libraries.AppleCryptoNative)] - private static extern int AppleCryptoNative_SecKeyExport( + [GeneratedDllImport(Libraries.AppleCryptoNative)] + private static partial int AppleCryptoNative_SecKeyExport( SafeSecKeyRefHandle? key, int exportPrivate, SafeCreateHandle cfExportPassphrase, diff --git a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.SignVerify.cs b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.SignVerify.cs index 71ba802f4dae6..a612ce0f16c04 100644 --- a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.SignVerify.cs +++ b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.SignVerify.cs @@ -47,8 +47,8 @@ private static unsafe int AppleCryptoNative_SecKeyVerifySignature( } } - [DllImport(Libraries.AppleCryptoNative)] - private static unsafe extern int AppleCryptoNative_SecKeyVerifySignature( + [GeneratedDllImport(Libraries.AppleCryptoNative)] + private static unsafe partial int AppleCryptoNative_SecKeyVerifySignature( SafeSecKeyRefHandle publicKey, byte* pbDataHash, int cbDataHash, @@ -79,8 +79,8 @@ private static unsafe int AppleCryptoNative_SecKeyCreateSignature( } } - [DllImport(Libraries.AppleCryptoNative)] - private static unsafe extern int AppleCryptoNative_SecKeyCreateSignature( + [GeneratedDllImport(Libraries.AppleCryptoNative)] + private static unsafe partial int AppleCryptoNative_SecKeyCreateSignature( SafeSecKeyRefHandle privateKey, byte* pbDataHash, int cbDataHash, diff --git a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Ssl.cs b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Ssl.cs index f38e94761d658..2e6e72c9418b4 100644 --- a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Ssl.cs +++ b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Ssl.cs @@ -57,102 +57,102 @@ internal enum PAL_TlsIo Renegotiate, } - [DllImport(Interop.Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_SslCreateContext")] - internal static extern System.Net.SafeSslHandle SslCreateContext(int isServer); + [GeneratedDllImport(Interop.Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_SslCreateContext")] + internal static partial System.Net.SafeSslHandle SslCreateContext(int isServer); - [DllImport(Interop.Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_SslSetConnection")] - internal static extern int SslSetConnection( + [GeneratedDllImport(Interop.Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_SslSetConnection")] + internal static partial int SslSetConnection( SafeSslHandle sslHandle, IntPtr sslConnection); - [DllImport(Interop.Libraries.AppleCryptoNative)] - private static extern int AppleCryptoNative_SslSetMinProtocolVersion( + [GeneratedDllImport(Interop.Libraries.AppleCryptoNative)] + private static partial int AppleCryptoNative_SslSetMinProtocolVersion( SafeSslHandle sslHandle, SslProtocols minProtocolId); - [DllImport(Interop.Libraries.AppleCryptoNative)] - private static extern int AppleCryptoNative_SslSetMaxProtocolVersion( + [GeneratedDllImport(Interop.Libraries.AppleCryptoNative)] + private static partial int AppleCryptoNative_SslSetMaxProtocolVersion( SafeSslHandle sslHandle, SslProtocols maxProtocolId); - [DllImport(Interop.Libraries.AppleCryptoNative)] - private static extern int AppleCryptoNative_SslCopyCertChain( + [GeneratedDllImport(Interop.Libraries.AppleCryptoNative)] + private static partial int AppleCryptoNative_SslCopyCertChain( SafeSslHandle sslHandle, out SafeX509ChainHandle pTrustOut, out int pOSStatus); - [DllImport(Interop.Libraries.AppleCryptoNative)] - private static extern int AppleCryptoNative_SslCopyCADistinguishedNames( + [GeneratedDllImport(Interop.Libraries.AppleCryptoNative)] + private static partial int AppleCryptoNative_SslCopyCADistinguishedNames( SafeSslHandle sslHandle, out SafeCFArrayHandle pArrayOut, out int pOSStatus); - [DllImport(Interop.Libraries.AppleCryptoNative)] - private static extern int AppleCryptoNative_SslSetBreakOnServerAuth( + [GeneratedDllImport(Interop.Libraries.AppleCryptoNative)] + private static partial int AppleCryptoNative_SslSetBreakOnServerAuth( SafeSslHandle sslHandle, int setBreak, out int pOSStatus); - [DllImport(Interop.Libraries.AppleCryptoNative)] - private static extern int AppleCryptoNative_SslSetBreakOnClientAuth( + [GeneratedDllImport(Interop.Libraries.AppleCryptoNative)] + private static partial int AppleCryptoNative_SslSetBreakOnClientAuth( SafeSslHandle sslHandle, int setBreak, out int pOSStatus); - [DllImport(Interop.Libraries.AppleCryptoNative)] - private static extern int AppleCryptoNative_SslSetCertificate( + [GeneratedDllImport(Interop.Libraries.AppleCryptoNative)] + private static partial int AppleCryptoNative_SslSetCertificate( SafeSslHandle sslHandle, SafeCreateHandle cfCertRefs); - [DllImport(Interop.Libraries.AppleCryptoNative)] - private static extern int AppleCryptoNative_SslSetTargetName( + [GeneratedDllImport(Interop.Libraries.AppleCryptoNative, CharSet = CharSet.Ansi)] + private static partial int AppleCryptoNative_SslSetTargetName( SafeSslHandle sslHandle, string targetName, int cbTargetName, out int osStatus); - [DllImport(Interop.Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_SSLSetALPNProtocols")] - internal static extern int SSLSetALPNProtocols(SafeSslHandle ctx, SafeCreateHandle cfProtocolsRefs, out int osStatus); + [GeneratedDllImport(Interop.Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_SSLSetALPNProtocols")] + internal static partial int SSLSetALPNProtocols(SafeSslHandle ctx, SafeCreateHandle cfProtocolsRefs, out int osStatus); - [DllImport(Interop.Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_SslGetAlpnSelected")] - internal static extern int SslGetAlpnSelected(SafeSslHandle ssl, out SafeCFDataHandle protocol); + [GeneratedDllImport(Interop.Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_SslGetAlpnSelected")] + internal static partial int SslGetAlpnSelected(SafeSslHandle ssl, out SafeCFDataHandle protocol); - [DllImport(Interop.Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_SslHandshake")] - internal static extern PAL_TlsHandshakeState SslHandshake(SafeSslHandle sslHandle); + [GeneratedDllImport(Interop.Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_SslHandshake")] + internal static partial PAL_TlsHandshakeState SslHandshake(SafeSslHandle sslHandle); - [DllImport(Interop.Libraries.AppleCryptoNative)] - private static extern int AppleCryptoNative_SslSetAcceptClientCert(SafeSslHandle sslHandle); + [GeneratedDllImport(Interop.Libraries.AppleCryptoNative)] + private static partial int AppleCryptoNative_SslSetAcceptClientCert(SafeSslHandle sslHandle); - [DllImport(Interop.Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_SslSetIoCallbacks")] - internal static extern unsafe int SslSetIoCallbacks( + [GeneratedDllImport(Interop.Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_SslSetIoCallbacks")] + internal static unsafe partial int SslSetIoCallbacks( SafeSslHandle sslHandle, delegate* unmanaged readCallback, delegate* unmanaged writeCallback); - [DllImport(Interop.Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_SslWrite")] - internal static extern unsafe PAL_TlsIo SslWrite(SafeSslHandle sslHandle, byte* writeFrom, int count, out int bytesWritten); + [GeneratedDllImport(Interop.Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_SslWrite")] + internal static unsafe partial PAL_TlsIo SslWrite(SafeSslHandle sslHandle, byte* writeFrom, int count, out int bytesWritten); - [DllImport(Interop.Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_SslRead")] - internal static extern unsafe PAL_TlsIo SslRead(SafeSslHandle sslHandle, byte* writeFrom, int count, out int bytesWritten); + [GeneratedDllImport(Interop.Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_SslRead")] + internal static unsafe partial PAL_TlsIo SslRead(SafeSslHandle sslHandle, byte* writeFrom, int count, out int bytesWritten); - [DllImport(Interop.Libraries.AppleCryptoNative)] - private static extern int AppleCryptoNative_SslIsHostnameMatch( + [GeneratedDllImport(Interop.Libraries.AppleCryptoNative)] + private static partial int AppleCryptoNative_SslIsHostnameMatch( SafeSslHandle handle, SafeCreateHandle cfHostname, SafeCFDateHandle cfValidTime, out int pOSStatus); - [DllImport(Interop.Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_SslShutdown")] - internal static extern int SslShutdown(SafeSslHandle sslHandle); + [GeneratedDllImport(Interop.Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_SslShutdown")] + internal static partial int SslShutdown(SafeSslHandle sslHandle); - [DllImport(Interop.Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_SslGetCipherSuite")] - internal static extern int SslGetCipherSuite(SafeSslHandle sslHandle, out TlsCipherSuite cipherSuite); + [GeneratedDllImport(Interop.Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_SslGetCipherSuite")] + internal static partial int SslGetCipherSuite(SafeSslHandle sslHandle, out TlsCipherSuite cipherSuite); - [DllImport(Interop.Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_SslGetProtocolVersion")] - internal static extern int SslGetProtocolVersion(SafeSslHandle sslHandle, out SslProtocols protocol); + [GeneratedDllImport(Interop.Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_SslGetProtocolVersion")] + internal static partial int SslGetProtocolVersion(SafeSslHandle sslHandle, out SslProtocols protocol); - [DllImport(Interop.Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_SslSetEnabledCipherSuites")] - internal static extern unsafe int SslSetEnabledCipherSuites(SafeSslHandle sslHandle, uint* cipherSuites, int numCipherSuites); + [GeneratedDllImport(Interop.Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_SslSetEnabledCipherSuites")] + internal static unsafe partial int SslSetEnabledCipherSuites(SafeSslHandle sslHandle, uint* cipherSuites, int numCipherSuites); internal static void SslSetAcceptClientCert(SafeSslHandle sslHandle) { diff --git a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Symmetric.cs b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Symmetric.cs index 22f6e512109ed..bdd2a97f35abc 100644 --- a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Symmetric.cs +++ b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Symmetric.cs @@ -45,8 +45,8 @@ internal enum PAL_SymmetricOptions [DllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_CryptorFree")] internal static extern void CryptorFree(IntPtr handle); - [DllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_CryptorCreate")] - internal static extern unsafe int CryptorCreate( + [GeneratedDllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_CryptorCreate")] + internal static unsafe partial int CryptorCreate( PAL_SymmetricOperation operation, PAL_SymmetricAlgorithm algorithm, PAL_ChainingMode chainingMode, @@ -58,8 +58,8 @@ internal static extern unsafe int CryptorCreate( out SafeAppleCryptorHandle cryptor, out int ccStatus); - [DllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_CryptorUpdate")] - internal static extern unsafe int CryptorUpdate( + [GeneratedDllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_CryptorUpdate")] + internal static unsafe partial int CryptorUpdate( SafeAppleCryptorHandle cryptor, byte* pbData, int cbData, @@ -68,16 +68,16 @@ internal static extern unsafe int CryptorUpdate( out int cbWritten, out int ccStatus); - [DllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_CryptorFinal")] - internal static extern unsafe int CryptorFinal( + [GeneratedDllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_CryptorFinal")] + internal static unsafe partial int CryptorFinal( SafeAppleCryptorHandle cryptor, byte* pbOutput, int cbOutput, out int cbWritten, out int ccStatus); - [DllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_CryptorReset")] - internal static extern unsafe int CryptorReset(SafeAppleCryptorHandle cryptor, byte* pbIv, out int ccStatus); + [GeneratedDllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_CryptorReset")] + internal static unsafe partial int CryptorReset(SafeAppleCryptorHandle cryptor, byte* pbIv, out int ccStatus); } } diff --git a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Trust.cs b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Trust.cs index 1121a62553b0c..9a59dd089529b 100644 --- a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Trust.cs +++ b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.Trust.cs @@ -11,23 +11,23 @@ internal static partial class Interop { internal static partial class AppleCrypto { - [DllImport(Libraries.AppleCryptoNative)] - private static extern int AppleCryptoNative_StoreEnumerateUserRoot( + [GeneratedDllImport(Libraries.AppleCryptoNative)] + private static partial int AppleCryptoNative_StoreEnumerateUserRoot( out SafeCFArrayHandle pCertsOut, out int pOSStatusOut); - [DllImport(Libraries.AppleCryptoNative)] - private static extern int AppleCryptoNative_StoreEnumerateMachineRoot( + [GeneratedDllImport(Libraries.AppleCryptoNative)] + private static partial int AppleCryptoNative_StoreEnumerateMachineRoot( out SafeCFArrayHandle pCertsOut, out int pOSStatusOut); - [DllImport(Libraries.AppleCryptoNative)] - private static extern int AppleCryptoNative_StoreEnumerateUserDisallowed( + [GeneratedDllImport(Libraries.AppleCryptoNative)] + private static partial int AppleCryptoNative_StoreEnumerateUserDisallowed( out SafeCFArrayHandle pCertsOut, out int pOSStatusOut); - [DllImport(Libraries.AppleCryptoNative)] - private static extern int AppleCryptoNative_StoreEnumerateMachineDisallowed( + [GeneratedDllImport(Libraries.AppleCryptoNative)] + private static partial int AppleCryptoNative_StoreEnumerateMachineDisallowed( out SafeCFArrayHandle pCertsOut, out int pOSStatusOut); diff --git a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.X509.cs b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.X509.cs index b7a8be1ba8a7c..efb189b27662d 100644 --- a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.X509.cs +++ b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.X509.cs @@ -14,38 +14,38 @@ internal static partial class Interop { internal static partial class AppleCrypto { - [DllImport(Libraries.AppleCryptoNative)] - private static extern int AppleCryptoNative_X509GetRawData( + [GeneratedDllImport(Libraries.AppleCryptoNative)] + private static partial int AppleCryptoNative_X509GetRawData( SafeSecCertificateHandle cert, out SafeCFDataHandle cfDataOut, out int pOSStatus); - [DllImport(Libraries.AppleCryptoNative)] - private static extern int AppleCryptoNative_X509GetSubjectSummary( + [GeneratedDllImport(Libraries.AppleCryptoNative)] + private static partial int AppleCryptoNative_X509GetSubjectSummary( SafeSecCertificateHandle cert, out SafeCFStringHandle cfSubjectSummaryOut); - [DllImport(Libraries.AppleCryptoNative)] - private static extern int AppleCryptoNative_X509GetPublicKey(SafeSecCertificateHandle cert, out SafeSecKeyRefHandle publicKey, out int pOSStatus); + [GeneratedDllImport(Libraries.AppleCryptoNative)] + private static partial int AppleCryptoNative_X509GetPublicKey(SafeSecCertificateHandle cert, out SafeSecKeyRefHandle publicKey, out int pOSStatus); internal static X509ContentType X509GetContentType(ReadOnlySpan data) => X509GetContentType(ref MemoryMarshal.GetReference(data), data.Length); - [DllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_X509GetContentType")] - private static extern X509ContentType X509GetContentType(ref byte pbData, int cbData); + [GeneratedDllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_X509GetContentType")] + private static partial X509ContentType X509GetContentType(ref byte pbData, int cbData); - [DllImport(Libraries.AppleCryptoNative)] - private static extern int AppleCryptoNative_X509CopyCertFromIdentity( + [GeneratedDllImport(Libraries.AppleCryptoNative)] + private static partial int AppleCryptoNative_X509CopyCertFromIdentity( SafeSecIdentityHandle identity, out SafeSecCertificateHandle cert); - [DllImport(Libraries.AppleCryptoNative)] - private static extern int AppleCryptoNative_X509CopyPrivateKeyFromIdentity( + [GeneratedDllImport(Libraries.AppleCryptoNative)] + private static partial int AppleCryptoNative_X509CopyPrivateKeyFromIdentity( SafeSecIdentityHandle identity, out SafeSecKeyRefHandle key); - [DllImport(Libraries.AppleCryptoNative)] - private static extern int AppleCryptoNative_X509DemuxAndRetainHandle( + [GeneratedDllImport(Libraries.AppleCryptoNative)] + private static partial int AppleCryptoNative_X509DemuxAndRetainHandle( IntPtr handle, out SafeSecCertificateHandle certHandle, out SafeSecIdentityHandle identityHandle); diff --git a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.X509.macOS.cs b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.X509.macOS.cs index 3caca43d8ece6..785f9e6ad54ae 100644 --- a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.X509.macOS.cs +++ b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.X509.macOS.cs @@ -39,8 +39,8 @@ ref MemoryMarshal.GetReference(keyBlob), out pOSStatus); } - [DllImport(Libraries.AppleCryptoNative)] - private static extern int AppleCryptoNative_X509ImportCertificate( + [GeneratedDllImport(Libraries.AppleCryptoNative)] + private static partial int AppleCryptoNative_X509ImportCertificate( ref byte pbKeyBlob, int cbKeyBlob, X509ContentType contentType, @@ -51,8 +51,8 @@ private static extern int AppleCryptoNative_X509ImportCertificate( out SafeSecIdentityHandle pPrivateKeyOut, out int pOSStatus); - [DllImport(Libraries.AppleCryptoNative)] - private static extern int AppleCryptoNative_X509ImportCollection( + [GeneratedDllImport(Libraries.AppleCryptoNative)] + private static partial int AppleCryptoNative_X509ImportCollection( ref byte pbKeyBlob, int cbKeyBlob, X509ContentType contentType, @@ -62,24 +62,24 @@ private static extern int AppleCryptoNative_X509ImportCollection( out SafeCFArrayHandle pCollectionOut, out int pOSStatus); - [DllImport(Libraries.AppleCryptoNative)] - private static extern int AppleCryptoNative_X509ExportData( + [GeneratedDllImport(Libraries.AppleCryptoNative)] + private static partial int AppleCryptoNative_X509ExportData( SafeCreateHandle data, X509ContentType type, SafeCreateHandle cfExportPassphrase, out SafeCFDataHandle pExportOut, out int pOSStatus); - [DllImport(Libraries.AppleCryptoNative)] - private static extern int AppleCryptoNative_X509CopyWithPrivateKey( + [GeneratedDllImport(Libraries.AppleCryptoNative)] + private static partial int AppleCryptoNative_X509CopyWithPrivateKey( SafeSecCertificateHandle certHandle, SafeSecKeyRefHandle privateKeyHandle, SafeKeychainHandle targetKeychain, out SafeSecIdentityHandle pIdentityHandleOut, out int pOSStatus); - [DllImport(Libraries.AppleCryptoNative)] - private static extern int AppleCryptoNative_X509MoveToKeychain( + [GeneratedDllImport(Libraries.AppleCryptoNative)] + private static partial int AppleCryptoNative_X509MoveToKeychain( SafeSecCertificateHandle certHandle, SafeKeychainHandle targetKeychain, SafeSecKeyRefHandle privateKeyHandle, diff --git a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.X509Chain.cs b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.X509Chain.cs index 5e456410616c0..16525bfd370c8 100644 --- a/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.X509Chain.cs +++ b/src/libraries/Common/src/Interop/OSX/System.Security.Cryptography.Native.Apple/Interop.X509Chain.cs @@ -11,42 +11,42 @@ internal static partial class Interop { internal static partial class AppleCrypto { - [DllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_X509ChainCreateDefaultPolicy")] - internal static extern SafeCreateHandle X509ChainCreateDefaultPolicy(); + [GeneratedDllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_X509ChainCreateDefaultPolicy")] + internal static partial SafeCreateHandle X509ChainCreateDefaultPolicy(); - [DllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_X509ChainCreateRevocationPolicy")] - internal static extern SafeCreateHandle X509ChainCreateRevocationPolicy(); + [GeneratedDllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_X509ChainCreateRevocationPolicy")] + internal static partial SafeCreateHandle X509ChainCreateRevocationPolicy(); - [DllImport(Libraries.AppleCryptoNative)] - internal static extern int AppleCryptoNative_X509ChainCreate( + [GeneratedDllImport(Libraries.AppleCryptoNative)] + internal static partial int AppleCryptoNative_X509ChainCreate( SafeCreateHandle certs, SafeCreateHandle policies, out SafeX509ChainHandle pTrustOut, out int pOSStatus); - [DllImport(Libraries.AppleCryptoNative)] - internal static extern int AppleCryptoNative_X509ChainEvaluate( + [GeneratedDllImport(Libraries.AppleCryptoNative)] + internal static partial int AppleCryptoNative_X509ChainEvaluate( SafeX509ChainHandle chain, SafeCFDateHandle cfEvaluationTime, bool allowNetwork, out int pOSStatus); - [DllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_X509ChainGetChainSize")] - internal static extern long X509ChainGetChainSize(SafeX509ChainHandle chain); + [GeneratedDllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_X509ChainGetChainSize")] + internal static partial long X509ChainGetChainSize(SafeX509ChainHandle chain); - [DllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_X509ChainGetCertificateAtIndex")] - internal static extern IntPtr X509ChainGetCertificateAtIndex(SafeX509ChainHandle chain, long index); + [GeneratedDllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_X509ChainGetCertificateAtIndex")] + internal static partial IntPtr X509ChainGetCertificateAtIndex(SafeX509ChainHandle chain, long index); - [DllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_X509ChainGetTrustResults")] - internal static extern SafeCreateHandle X509ChainGetTrustResults(SafeX509ChainHandle chain); + [GeneratedDllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_X509ChainGetTrustResults")] + internal static partial SafeCreateHandle X509ChainGetTrustResults(SafeX509ChainHandle chain); - [DllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_X509ChainGetStatusAtIndex")] - internal static extern int X509ChainGetStatusAtIndex(SafeCreateHandle trustResults, long index, out int pdwStatus); + [GeneratedDllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_X509ChainGetStatusAtIndex")] + internal static partial int X509ChainGetStatusAtIndex(SafeCreateHandle trustResults, long index, out int pdwStatus); [DllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_GetOSStatusForChainStatus")] internal static extern int GetOSStatusForChainStatus(X509ChainStatusFlags flag); - [DllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_X509ChainSetTrustAnchorCertificates")] - internal static extern int X509ChainSetTrustAnchorCertificates(SafeX509ChainHandle chain, SafeCreateHandle anchorCertificates); + [GeneratedDllImport(Libraries.AppleCryptoNative, EntryPoint = "AppleCryptoNative_X509ChainSetTrustAnchorCertificates")] + internal static partial int X509ChainSetTrustAnchorCertificates(SafeX509ChainHandle chain, SafeCreateHandle anchorCertificates); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Accept.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Accept.cs index a36936b5db036..2385cf98bdbf2 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Accept.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Accept.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Sys { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Accept")] - internal static extern unsafe Error Accept(SafeHandle socket, byte* socketAddress, int* socketAddressLen, IntPtr* acceptedFd); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Accept")] + internal static unsafe partial Error Accept(SafeHandle socket, byte* socketAddress, int* socketAddressLen, IntPtr* acceptedFd); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Access.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Access.cs index bfeb1cf9e8a15..70728287b22ba 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Access.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Access.cs @@ -15,7 +15,7 @@ internal enum AccessMode : int R_OK = 4, /* Check for read */ } - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Access", SetLastError = true)] - internal static extern int Access(string path, AccessMode mode); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Access", CharSet = CharSet.Ansi, SetLastError = true)] + internal static partial int Access(string path, AccessMode mode); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Bind.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Bind.cs index b7e56d09d9d46..41dac6ff61cde 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Bind.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Bind.cs @@ -9,7 +9,7 @@ internal static partial class Interop { internal static partial class Sys { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Bind")] - internal static extern unsafe Error Bind(SafeHandle socket, ProtocolType socketProtocolType, byte* socketAddress, int socketAddressLen); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Bind")] + internal static unsafe partial Error Bind(SafeHandle socket, ProtocolType socketProtocolType, byte* socketAddress, int socketAddressLen); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.ChMod.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.ChMod.cs index c3a09ec513e2a..044f8cd414ac6 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.ChMod.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.ChMod.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Sys { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_ChMod", SetLastError = true)] - internal static extern int ChMod(string path, int mode); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_ChMod", CharSet = CharSet.Ansi, SetLastError = true)] + internal static partial int ChMod(string path, int mode); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Close.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Close.cs index 6dfec617396a9..dcf65c410fc33 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Close.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Close.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Sys { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Close", SetLastError = true)] - internal static extern int Close(IntPtr fd); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Close", SetLastError = true)] + internal static partial int Close(IntPtr fd); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.ConfigureTerminalForChildProcess.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.ConfigureTerminalForChildProcess.cs index 0801ed3b84e05..2c2318ea79710 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.ConfigureTerminalForChildProcess.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.ConfigureTerminalForChildProcess.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Sys { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_ConfigureTerminalForChildProcess")] - internal static extern void ConfigureTerminalForChildProcess(bool childUsesTerminal); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_ConfigureTerminalForChildProcess")] + internal static partial void ConfigureTerminalForChildProcess(bool childUsesTerminal); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Connect.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Connect.cs index 8e1fb3cc791d2..5149052c4ecd5 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Connect.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Connect.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Sys { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Connect")] - internal static extern unsafe Error Connect(SafeHandle socket, byte* socketAddress, int socketAddressLen); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Connect")] + internal static unsafe partial Error Connect(SafeHandle socket, byte* socketAddress, int socketAddressLen); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.CopyFile.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.CopyFile.cs index 8967e3fb2545f..89217982ea51b 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.CopyFile.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.CopyFile.cs @@ -9,7 +9,7 @@ internal static partial class Interop { internal static partial class Sys { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_CopyFile", SetLastError = true)] - internal static extern int CopyFile(SafeFileHandle source, SafeFileHandle destination); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_CopyFile", SetLastError = true)] + internal static partial int CopyFile(SafeFileHandle source, SafeFileHandle destination); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Dup.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Dup.cs index 37df5702161dd..d61ab47050fee 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Dup.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Dup.cs @@ -9,7 +9,7 @@ internal static partial class Interop { internal static partial class Sys { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Dup", SetLastError = true)] - internal static extern SafeFileHandle Dup(SafeFileHandle oldfd); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Dup", SetLastError = true)] + internal static partial SafeFileHandle Dup(SafeFileHandle oldfd); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.EnumerateInterfaceAddresses.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.EnumerateInterfaceAddresses.cs index 73e988eb7a52e..2ad68069e48c0 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.EnumerateInterfaceAddresses.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.EnumerateInterfaceAddresses.cs @@ -53,7 +53,7 @@ public static extern unsafe int EnumerateInterfaceAddresses( public static extern unsafe int EnumerateGatewayAddressesForInterface(void* context, uint interfaceIndex, delegate* unmanaged onGatewayFound); [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetNetworkInterfaces")] - public static unsafe extern int GetNetworkInterfaces(ref int count, ref NetworkInterfaceInfo* addrs, ref int addressCount, ref IpAddressInfo *aa); + public static unsafe extern int GetNetworkInterfaces(int* count, NetworkInterfaceInfo** addrs, int* addressCount, IpAddressInfo** aa); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.FChMod.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.FChMod.cs index 765ba23c3e6a5..57a278cd47a4d 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.FChMod.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.FChMod.cs @@ -9,7 +9,7 @@ internal static partial class Interop { internal static partial class Sys { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FChMod", SetLastError = true)] - internal static extern int FChMod(SafeFileHandle fd, int mode); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FChMod", SetLastError = true)] + internal static partial int FChMod(SafeFileHandle fd, int mode); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.FLock.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.FLock.cs index 4e6e36b8f94d7..a2a89fef02681 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.FLock.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.FLock.cs @@ -17,14 +17,14 @@ internal enum LockOperations : int LOCK_UN = 8, /* unlock */ } - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FLock", SetLastError = true)] - internal static extern int FLock(SafeFileHandle fd, LockOperations operation); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FLock", SetLastError = true)] + internal static partial int FLock(SafeFileHandle fd, LockOperations operation); /// /// Exposing this for SafeFileHandle.ReleaseHandle() to call. /// Normal callers should use FLock(SafeFileHandle fd). /// - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FLock", SetLastError = true)] - internal static extern int FLock(IntPtr fd, LockOperations operation); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FLock", SetLastError = true)] + internal static partial int FLock(IntPtr fd, LockOperations operation); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.FTruncate.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.FTruncate.cs index f7a726f904203..b8367261ffdc9 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.FTruncate.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.FTruncate.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Sys { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FTruncate", SetLastError = true)] - internal static extern int FTruncate(SafeFileHandle fd, long length); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FTruncate", SetLastError = true)] + internal static partial int FTruncate(SafeFileHandle fd, long length); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Fcntl.Pipe.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Fcntl.Pipe.cs index 9e86930ec2844..6361f87fc0ee4 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Fcntl.Pipe.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Fcntl.Pipe.cs @@ -13,11 +13,11 @@ internal static partial class Fcntl { internal static readonly bool CanGetSetPipeSz = (FcntlCanGetSetPipeSz() != 0); - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FcntlGetPipeSz", SetLastError=true)] - internal static extern int GetPipeSz(SafePipeHandle fd); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FcntlGetPipeSz", SetLastError=true)] + internal static partial int GetPipeSz(SafePipeHandle fd); - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FcntlSetPipeSz", SetLastError=true)] - internal static extern int SetPipeSz(SafePipeHandle fd, int size); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FcntlSetPipeSz", SetLastError=true)] + internal static partial int SetPipeSz(SafePipeHandle fd, int size); [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FcntlCanGetSetPipeSz")] [SuppressGCTransition] diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Fcntl.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Fcntl.cs index 231621f2fa307..e5fb22e44af2c 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Fcntl.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Fcntl.cs @@ -10,23 +10,23 @@ internal static partial class Sys { internal static partial class Fcntl { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FcntlSetIsNonBlocking", SetLastError = true)] - internal static extern int DangerousSetIsNonBlocking(IntPtr fd, int isNonBlocking); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FcntlSetIsNonBlocking", SetLastError = true)] + internal static partial int DangerousSetIsNonBlocking(IntPtr fd, int isNonBlocking); - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FcntlSetIsNonBlocking", SetLastError=true)] - internal static extern int SetIsNonBlocking(SafeHandle fd, int isNonBlocking); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FcntlSetIsNonBlocking", SetLastError=true)] + internal static partial int SetIsNonBlocking(SafeHandle fd, int isNonBlocking); - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FcntlGetIsNonBlocking", SetLastError = true)] - internal static extern int GetIsNonBlocking(SafeHandle fd, out bool isNonBlocking); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FcntlGetIsNonBlocking", SetLastError = true)] + internal static partial int GetIsNonBlocking(SafeHandle fd, out bool isNonBlocking); - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FcntlSetFD", SetLastError=true)] - internal static extern int SetFD(SafeHandle fd, int flags); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FcntlSetFD", SetLastError=true)] + internal static partial int SetFD(SafeHandle fd, int flags); - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FcntlGetFD", SetLastError=true)] - internal static extern int GetFD(SafeHandle fd); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FcntlGetFD", SetLastError=true)] + internal static partial int GetFD(SafeHandle fd); - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FcntlGetFD", SetLastError=true)] - internal static extern int GetFD(IntPtr fd); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FcntlGetFD", SetLastError=true)] + internal static partial int GetFD(IntPtr fd); } } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.ForkAndExecProcess.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.ForkAndExecProcess.cs index 585437706a1c4..295caba93c28d 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.ForkAndExecProcess.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.ForkAndExecProcess.cs @@ -40,8 +40,8 @@ internal static unsafe int ForkAndExecProcess( } } - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_ForkAndExecProcess", SetLastError = true)] - private static extern unsafe int ForkAndExecProcess( + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_ForkAndExecProcess", CharSet = CharSet.Ansi, SetLastError = true)] + private static unsafe partial int ForkAndExecProcess( string filename, byte** argv, byte** envp, string? cwd, int redirectStdin, int redirectStdout, int redirectStderr, int setUser, uint userId, uint groupId, uint* groups, int groupsLength, diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetBytesAvailable.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetBytesAvailable.cs index 741e132631eac..96b5791d13166 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetBytesAvailable.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetBytesAvailable.cs @@ -8,10 +8,10 @@ internal static partial class Interop { internal static partial class Sys { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetBytesAvailable")] - internal static extern unsafe Error GetBytesAvailable(SafeHandle socket, int* available); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetBytesAvailable")] + internal static unsafe partial Error GetBytesAvailable(SafeHandle socket, int* available); - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetAtOutOfBandMark")] - internal static extern unsafe Error GetAtOutOfBandMark(SafeHandle socket, int* atMark); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetAtOutOfBandMark")] + internal static unsafe partial Error GetAtOutOfBandMark(SafeHandle socket, int* atMark); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetControlCharacters.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetControlCharacters.cs index 7f8bb04babe3d..be1316a2b17a6 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetControlCharacters.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetControlCharacters.cs @@ -7,8 +7,8 @@ internal static partial class Interop { internal static partial class Sys { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetControlCharacters")] - internal static extern void GetControlCharacters( + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetControlCharacters")] + internal static partial void GetControlCharacters( ControlCharacterNames[] controlCharacterNames, byte[] controlCharacterValues, int controlCharacterLength, out byte posixDisableValue); diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetDomainName.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetDomainName.cs index 31f7c07c10c42..466afb7b0101d 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetDomainName.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetDomainName.cs @@ -10,7 +10,7 @@ internal static partial class Interop { internal static partial class Sys { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetDomainName", SetLastError = true)] + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetDomainName")] private static extern unsafe int GetDomainName(byte* name, int len); internal static unsafe string GetDomainName() diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetDomainSocketSizes.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetDomainSocketSizes.cs index 3748ebfe148f0..7daf1ba2aef34 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetDomainSocketSizes.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetDomainSocketSizes.cs @@ -10,6 +10,6 @@ internal static partial class Sys { [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetDomainSocketSizes")] [SuppressGCTransition] - internal static extern void GetDomainSocketSizes(out int pathOffset, out int pathSize, out int addressSize); + internal static unsafe extern void GetDomainSocketSizes(int* pathOffset, int* pathSize, int* addressSize); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetGroupList.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetGroupList.cs index 55960b5dbf06c..1b00355f570f0 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetGroupList.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetGroupList.cs @@ -43,7 +43,7 @@ internal static partial class Sys } while (true); } - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetGroupList", SetLastError = true)] - private static extern unsafe int GetGroupList(string name, uint group, uint* groups, int* ngroups); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetGroupList", CharSet = CharSet.Ansi, SetLastError = true)] + private static unsafe partial int GetGroupList(string name, uint group, uint* groups, int* ngroups); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetHostName.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetHostName.cs index 985edb4cadc22..72710dcf7e1f8 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetHostName.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetHostName.cs @@ -9,8 +9,8 @@ internal static partial class Interop { internal static partial class Sys { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetHostName", SetLastError = true)] - private static extern unsafe int GetHostName(byte* name, int nameLength); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetHostName", SetLastError = true)] + private static unsafe partial int GetHostName(byte* name, int nameLength); internal static unsafe string GetHostName() { diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetPeerID.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetPeerID.cs index 2e9e6f139c3bb..23a338a30a754 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetPeerID.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetPeerID.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Sys { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetPeerID", SetLastError = true)] - internal static extern int GetPeerID(SafeHandle socket, out uint euid); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetPeerID", SetLastError = true)] + internal static partial int GetPeerID(SafeHandle socket, out uint euid); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetPeerName.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetPeerName.cs index e400ae9a6f927..a66bcfe353609 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetPeerName.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetPeerName.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Sys { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetPeerName")] - internal static extern unsafe Error GetPeerName(SafeHandle socket, byte* socketAddress, int* socketAddressLen); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetPeerName")] + internal static unsafe partial Error GetPeerName(SafeHandle socket, byte* socketAddress, int* socketAddressLen); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetPeerUserName.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetPeerUserName.cs index ccc7d9c88e5a3..9dea586f1d6a0 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetPeerUserName.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetPeerUserName.cs @@ -9,7 +9,7 @@ internal static partial class Interop { internal static partial class Sys { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetPeerUserName", SetLastError = true)] - internal static extern string GetPeerUserName(SafeHandle socket); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetPeerUserName", CharSet = CharSet.Ansi, SetLastError = true)] + internal static partial string GetPeerUserName(SafeHandle socket); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetPwUid.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetPwUid.cs index 08cb7a4085983..06b431cbffd0e 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetPwUid.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetPwUid.cs @@ -20,10 +20,10 @@ internal unsafe struct Passwd internal byte* Shell; } - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetPwUidR", SetLastError = false)] - internal static extern unsafe int GetPwUidR(uint uid, out Passwd pwd, byte* buf, int bufLen); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetPwUidR", SetLastError = false)] + internal static unsafe partial int GetPwUidR(uint uid, out Passwd pwd, byte* buf, int bufLen); - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetPwNamR", SetLastError = false)] - internal static extern unsafe int GetPwNamR(string name, out Passwd pwd, byte* buf, int bufLen); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetPwNamR", CharSet = CharSet.Ansi, SetLastError = false)] + internal static unsafe partial int GetPwNamR(string name, out Passwd pwd, byte* buf, int bufLen); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetSetPriority.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetSetPriority.cs index 87eb5d0ac7a2d..4677fd8f63266 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetSetPriority.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetSetPriority.cs @@ -16,11 +16,11 @@ internal enum PriorityWhich : int PRIO_USER = 2, } - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetPriority", SetLastError = true)] - private static extern int GetPriority(PriorityWhich which, int who); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetPriority", SetLastError = true)] + private static partial int GetPriority(PriorityWhich which, int who); - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_SetPriority", SetLastError = true)] - internal static extern int SetPriority(PriorityWhich which, int who, int nice); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_SetPriority", SetLastError = true)] + internal static partial int SetPriority(PriorityWhich which, int who, int nice); /// /// Wrapper around getpriority since getpriority can return from -20 to 20; therefore, diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetSockName.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetSockName.cs index fb1aa6b735bb2..a0a44f2a1792e 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetSockName.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetSockName.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Sys { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetSockName")] - internal static extern unsafe Error GetSockName(SafeHandle socket, byte* socketAddress, int* socketAddressLen); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetSockName")] + internal static unsafe partial Error GetSockName(SafeHandle socket, byte* socketAddress, int* socketAddressLen); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetSockOpt.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetSockOpt.cs index 71f69d69ab76b..0a0dbae00073f 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetSockOpt.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetSockOpt.cs @@ -9,13 +9,13 @@ internal static partial class Interop { internal static partial class Sys { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetSockOpt")] - internal static extern unsafe Error GetSockOpt(SafeHandle socket, SocketOptionLevel optionLevel, SocketOptionName optionName, byte* optionValue, int* optionLen); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetSockOpt")] + internal static unsafe partial Error GetSockOpt(SafeHandle socket, SocketOptionLevel optionLevel, SocketOptionName optionName, byte* optionValue, int* optionLen); [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetSockOpt")] internal static extern unsafe Error GetSockOpt(IntPtr socket, SocketOptionLevel optionLevel, SocketOptionName optionName, byte* optionValue, int* optionLen); - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetRawSockOpt")] - internal static extern unsafe Error GetRawSockOpt(SafeHandle socket, int optionLevel, int optionName, byte* optionValue, int* optionLen); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetRawSockOpt")] + internal static unsafe partial Error GetRawSockOpt(SafeHandle socket, int optionLevel, int optionName, byte* optionValue, int* optionLen); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetSocketErrorOption.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetSocketErrorOption.cs index 1fb0dcecc207c..a77fb31b77a3a 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetSocketErrorOption.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetSocketErrorOption.cs @@ -9,7 +9,7 @@ internal static partial class Interop { internal static partial class Sys { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetSocketErrorOption")] - internal static extern unsafe Error GetSocketErrorOption(SafeHandle socket, Error* socketError); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetSocketErrorOption")] + internal static unsafe partial Error GetSocketErrorOption(SafeHandle socket, Error* socketError); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetSocketType.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetSocketType.cs index a97336d2cc8fc..387b02646f114 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetSocketType.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetSocketType.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Sys { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetSocketType")] - internal static extern Error GetSocketType(SafeSocketHandle socket, out AddressFamily addressFamily, out SocketType socketType, out ProtocolType protocolType, out bool isListening); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetSocketType")] + internal static partial Error GetSocketType(SafeSocketHandle socket, out AddressFamily addressFamily, out SocketType socketType, out ProtocolType protocolType, out bool isListening); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetUnixVersion.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetUnixVersion.cs index 75854552fa3d5..3c130da95f54d 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetUnixVersion.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetUnixVersion.cs @@ -10,8 +10,8 @@ internal static partial class Interop { internal static partial class Sys { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetUnixVersion", CharSet = CharSet.Ansi, SetLastError = true)] - private static extern int GetUnixVersion(byte[] version, ref int capacity); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetUnixVersion", CharSet = CharSet.Ansi, SetLastError = true)] + private static partial int GetUnixVersion(byte[] version, ref int capacity); internal static string GetUnixVersion() { diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetWindowWidth.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetWindowWidth.cs index 151b6a65ed524..83410484f60a7 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetWindowWidth.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.GetWindowWidth.cs @@ -17,7 +17,7 @@ internal struct WinSize internal ushort YPixel; }; - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetWindowSize", SetLastError = true)] - internal static extern int GetWindowSize(out WinSize winSize); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetWindowSize", SetLastError = true)] + internal static partial int GetWindowSize(out WinSize winSize); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.HostEntry.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.HostEntry.cs index d197637043e8a..98372054ec046 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.HostEntry.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.HostEntry.cs @@ -32,8 +32,8 @@ internal unsafe struct HostEntry internal int IPAddressCount; // Number of IP addresses in the list } - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetHostEntryForName")] - internal static extern unsafe int GetHostEntryForName(string address, AddressFamily family, HostEntry* entry); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetHostEntryForName", CharSet = CharSet.Ansi)] + internal static unsafe partial int GetHostEntryForName(string address, AddressFamily family, HostEntry* entry); [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FreeHostEntry")] internal static extern unsafe void FreeHostEntry(HostEntry* entry); diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.IPPacketInformation.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.IPPacketInformation.cs index 76c992748b626..37dab53c69365 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.IPPacketInformation.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.IPPacketInformation.cs @@ -20,7 +20,7 @@ internal struct IPPacketInformation [SuppressGCTransition] internal static extern int GetControlMessageBufferSize(int isIPv4, int isIPv6); - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_TryGetIPPacketInformation")] - internal static extern unsafe bool TryGetIPPacketInformation(MessageHeader* messageHeader, bool isIPv4, IPPacketInformation* packetInfo); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_TryGetIPPacketInformation")] + internal static unsafe partial bool TryGetIPPacketInformation(MessageHeader* messageHeader, bool isIPv4, IPPacketInformation* packetInfo); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.InitializeTerminalAndSignalHandling.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.InitializeTerminalAndSignalHandling.cs index 66e18a03def05..a9d4b29d23517 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.InitializeTerminalAndSignalHandling.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.InitializeTerminalAndSignalHandling.cs @@ -7,10 +7,10 @@ internal static partial class Interop { internal static partial class Sys { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_InitializeTerminalAndSignalHandling", SetLastError = true)] - internal static extern bool InitializeTerminalAndSignalHandling(); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_InitializeTerminalAndSignalHandling", SetLastError = true)] + internal static partial bool InitializeTerminalAndSignalHandling(); - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_SetKeypadXmit")] - internal static extern void SetKeypadXmit(string terminfoString); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_SetKeypadXmit", CharSet = CharSet.Ansi)] + internal static partial void SetKeypadXmit(string terminfoString); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.IsATty.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.IsATty.cs index a7e144519d002..94fccc8c6052d 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.IsATty.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.IsATty.cs @@ -9,7 +9,7 @@ internal static partial class Interop { internal static partial class Sys { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_IsATty", SetLastError = true)] - internal static extern bool IsATty(SafeFileHandle fd); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_IsATty", SetLastError = true)] + internal static partial bool IsATty(SafeFileHandle fd); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Kill.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Kill.cs index 80cfb59e173d8..1fb42efc27ec2 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Kill.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Kill.cs @@ -15,7 +15,7 @@ internal enum Signals : int SIGSTOP = 19 } - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Kill", SetLastError = true)] - internal static extern int Kill(int pid, Signals signal); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Kill", SetLastError = true)] + internal static partial int Kill(int pid, Signals signal); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.LChflags.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.LChflags.cs index 03afef646f086..17ba8e3233223 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.LChflags.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.LChflags.cs @@ -14,8 +14,8 @@ internal enum UserFlags : uint UF_HIDDEN = 0x8000 } - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_LChflags", SetLastError = true)] - internal static extern int LChflags(string path, uint flags); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_LChflags", CharSet = CharSet.Ansi, SetLastError = true)] + internal static partial int LChflags(string path, uint flags); internal static readonly bool CanSetHiddenFlag = (LChflagsCanSetHiddenFlag() != 0); diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.LSeek.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.LSeek.cs index 95574358639f4..c76231bb193b0 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.LSeek.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.LSeek.cs @@ -15,7 +15,7 @@ internal enum SeekWhence SEEK_END = 2 } - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_LSeek", SetLastError = true)] - internal static extern long LSeek(SafeFileHandle fd, long offset, SeekWhence whence); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_LSeek", SetLastError = true)] + internal static partial long LSeek(SafeFileHandle fd, long offset, SeekWhence whence); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.LingerOption.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.LingerOption.cs index 312222f042d5e..5092a15151dbb 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.LingerOption.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.LingerOption.cs @@ -15,11 +15,11 @@ internal struct LingerOption public int Seconds; // Number of seconds to linger for } - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetLingerOption")] - internal static extern unsafe Error GetLingerOption(SafeHandle socket, LingerOption* option); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetLingerOption")] + internal static unsafe partial Error GetLingerOption(SafeHandle socket, LingerOption* option); - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_SetLingerOption")] - internal static extern unsafe Error SetLingerOption(SafeHandle socket, LingerOption* option); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_SetLingerOption")] + internal static unsafe partial Error SetLingerOption(SafeHandle socket, LingerOption* option); [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_SetLingerOption")] internal static extern unsafe Error SetLingerOption(IntPtr socket, LingerOption* option); diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Link.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Link.cs index 64d1a32d27ba5..6fca0a14d003f 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Link.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Link.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Sys { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Link", SetLastError = true)] - internal static extern int Link(string source, string link); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Link", CharSet = CharSet.Ansi, SetLastError = true)] + internal static partial int Link(string source, string link); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Listen.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Listen.cs index b6196a3de5646..f630563bd1283 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Listen.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Listen.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Sys { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Listen")] - internal static extern Error Listen(SafeHandle socket, int backlog); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Listen")] + internal static partial Error Listen(SafeHandle socket, int backlog); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.MAdvise.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.MAdvise.cs index 539e27a04e3c1..5ac7aa1fc4d6a 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.MAdvise.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.MAdvise.cs @@ -8,8 +8,8 @@ internal static partial class Interop { internal static partial class Sys { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_MAdvise", SetLastError = true)] - internal static extern int MAdvise(IntPtr addr, ulong length, MemoryAdvice advice); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_MAdvise", SetLastError = true)] + internal static partial int MAdvise(IntPtr addr, ulong length, MemoryAdvice advice); internal enum MemoryAdvice { diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.MMap.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.MMap.cs index f75065210307a..5789ee734d45e 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.MMap.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.MMap.cs @@ -28,8 +28,8 @@ internal enum MemoryMappedFlags } // NOTE: Shim returns null pointer on failure, not non-null MAP_FAILED sentinel. - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_MMap", SetLastError = true)] - internal static extern IntPtr MMap( + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_MMap", SetLastError = true)] + internal static partial IntPtr MMap( IntPtr addr, ulong len, MemoryMappedProtections prot, MemoryMappedFlags flags, SafeFileHandle fd, long offset); diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.MSync.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.MSync.cs index d486c36811c61..78263cbdd6af6 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.MSync.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.MSync.cs @@ -16,7 +16,7 @@ internal enum MemoryMappedSyncFlags MS_INVALIDATE = 0x10, } - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_MSync", SetLastError = true)] - internal static extern int MSync(IntPtr addr, ulong len, MemoryMappedSyncFlags flags); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_MSync", SetLastError = true)] + internal static partial int MSync(IntPtr addr, ulong len, MemoryMappedSyncFlags flags); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.MUnmap.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.MUnmap.cs index fffd3fb941fdc..a0ed69251cc00 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.MUnmap.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.MUnmap.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Sys { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_MUnmap", SetLastError = true)] - internal static extern int MUnmap(IntPtr addr, ulong len); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_MUnmap", SetLastError = true)] + internal static partial int MUnmap(IntPtr addr, ulong len); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.MkDir.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.MkDir.cs index 8779967fd5d62..499b1e74597e9 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.MkDir.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.MkDir.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Sys { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_MkDir", SetLastError = true)] - internal static extern int MkDir(string path, int mode); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_MkDir", CharSet = CharSet.Ansi, SetLastError = true)] + internal static partial int MkDir(string path, int mode); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.MountPoints.FormatInfo.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.MountPoints.FormatInfo.cs index fbd95d485e841..3a38edcc82ecd 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.MountPoints.FormatInfo.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.MountPoints.FormatInfo.cs @@ -30,11 +30,11 @@ internal struct MountPointInformation internal ulong TotalSize; } - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetSpaceInfoForMountPoint", SetLastError = true)] - internal static extern int GetSpaceInfoForMountPoint([MarshalAs(UnmanagedType.LPStr)]string name, out MountPointInformation mpi); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetSpaceInfoForMountPoint", SetLastError = true)] + internal static partial int GetSpaceInfoForMountPoint([MarshalAs(UnmanagedType.LPStr)]string name, out MountPointInformation mpi); - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetFormatInfoForMountPoint", SetLastError = true)] - private static extern unsafe int GetFormatInfoForMountPoint( + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetFormatInfoForMountPoint", SetLastError = true)] + private static unsafe partial int GetFormatInfoForMountPoint( [MarshalAs(UnmanagedType.LPStr)]string name, byte* formatNameBuffer, int bufferLength, diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.MountPoints.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.MountPoints.cs index 716725a3b1944..1f547971e010f 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.MountPoints.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.MountPoints.cs @@ -11,8 +11,8 @@ internal static partial class Sys [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private unsafe delegate void MountPointFound(byte* name); - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetAllMountPoints", SetLastError = true)] - private static extern int GetAllMountPoints(MountPointFound mpf); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetAllMountPoints", SetLastError = true)] + private static partial int GetAllMountPoints(MountPointFound mpf); internal static string[] GetAllMountPoints() { diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.MulticastOption.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.MulticastOption.cs index aa4445573a4b2..f874683371108 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.MulticastOption.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.MulticastOption.cs @@ -31,16 +31,16 @@ internal struct IPv6MulticastOption private int _padding; } - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetIPv4MulticastOption")] - internal static extern unsafe Error GetIPv4MulticastOption(SafeHandle socket, MulticastOption multicastOption, IPv4MulticastOption* option); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetIPv4MulticastOption")] + internal static unsafe partial Error GetIPv4MulticastOption(SafeHandle socket, MulticastOption multicastOption, IPv4MulticastOption* option); - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_SetIPv4MulticastOption")] - internal static extern unsafe Error SetIPv4MulticastOption(SafeHandle socket, MulticastOption multicastOption, IPv4MulticastOption* option); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_SetIPv4MulticastOption")] + internal static unsafe partial Error SetIPv4MulticastOption(SafeHandle socket, MulticastOption multicastOption, IPv4MulticastOption* option); - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetIPv6MulticastOption")] - internal static extern unsafe Error GetIPv6MulticastOption(SafeHandle socket, MulticastOption multicastOption, IPv6MulticastOption* option); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetIPv6MulticastOption")] + internal static unsafe partial Error GetIPv6MulticastOption(SafeHandle socket, MulticastOption multicastOption, IPv6MulticastOption* option); - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_SetIPv6MulticastOption")] - internal static extern unsafe Error SetIPv6MulticastOption(SafeHandle socket, MulticastOption multicastOption, IPv6MulticastOption* option); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_SetIPv6MulticastOption")] + internal static unsafe partial Error SetIPv6MulticastOption(SafeHandle socket, MulticastOption multicastOption, IPv6MulticastOption* option); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.NetworkChange.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.NetworkChange.cs index 37de2ebb38807..152588f507885 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.NetworkChange.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.NetworkChange.cs @@ -17,7 +17,7 @@ public enum NetworkChangeKind } [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_CreateNetworkChangeListenerSocket")] - public static extern Error CreateNetworkChangeListenerSocket(out int socket); + public static unsafe extern Error CreateNetworkChangeListenerSocket(int* socket); [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_CloseNetworkChangeListenerSocket")] public static extern Error CloseNetworkChangeListenerSocket(int socket); diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Open.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Open.cs index a4ec5f57b1207..2024ee616943f 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Open.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Open.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Sys { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Open", SetLastError = true)] - internal static extern SafeFileHandle Open(string filename, OpenFlags flags, int mode); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Open", CharSet = CharSet.Ansi, SetLastError = true)] + internal static partial SafeFileHandle Open(string filename, OpenFlags flags, int mode); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.PathConf.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.PathConf.cs index 5a9f27b7db06c..4ed5bbb552d92 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.PathConf.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.PathConf.cs @@ -20,7 +20,7 @@ internal enum PathConfName : int PC_VDISABLE = 9, } - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_PathConf", SetLastError = true)] - private static extern int PathConf(string path, PathConfName name); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_PathConf", CharSet = CharSet.Ansi, SetLastError = true)] + private static partial int PathConf(string path, PathConfName name); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Pipe.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Pipe.cs index ca4fc28b2c612..92587f258f6af 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Pipe.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Pipe.cs @@ -24,7 +24,7 @@ internal enum PipeFlags /// internal const int WriteEndOfPipe = 1; - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Pipe", SetLastError = true)] - internal static extern unsafe int Pipe(int* pipefd, PipeFlags flags = 0); // pipefd is an array of two ints + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Pipe", SetLastError = true)] + internal static unsafe partial int Pipe(int* pipefd, PipeFlags flags = 0); // pipefd is an array of two ints } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Read.Pipe.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Read.Pipe.cs index 09d21bc9aa96d..c2ecd36478b58 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Read.Pipe.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Read.Pipe.cs @@ -18,7 +18,7 @@ internal static partial class Sys /// Returns the number of bytes read on success; otherwise, -1 is returned /// Note - on fail. the position of the stream may change depending on the platform; consult man 2 read for more info /// - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Read", SetLastError = true)] - internal static extern unsafe int Read(SafePipeHandle fd, byte* buffer, int count); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Read", SetLastError = true)] + internal static unsafe partial int Read(SafePipeHandle fd, byte* buffer, int count); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Read.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Read.cs index 51038fc099d97..7d9988d057eeb 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Read.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Read.cs @@ -17,7 +17,7 @@ internal static partial class Sys /// Returns the number of bytes read on success; otherwise, -1 is returned /// Note - on fail. the position of the stream may change depending on the platform; consult man 2 read for more info /// - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Read", SetLastError = true)] - internal static extern unsafe int Read(SafeHandle fd, byte* buffer, int count); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Read", SetLastError = true)] + internal static unsafe partial int Read(SafeHandle fd, byte* buffer, int count); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.ReadDir.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.ReadDir.cs index 67a8a6bfc9bd3..4801498489d61 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.ReadDir.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.ReadDir.cs @@ -53,17 +53,17 @@ internal ReadOnlySpan GetName(Span buffer) } } - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_OpenDir", SetLastError = true)] - internal static extern IntPtr OpenDir(string path); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_OpenDir", CharSet = CharSet.Ansi, SetLastError = true)] + internal static partial IntPtr OpenDir(string path); [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetReadDirRBufferSize", SetLastError = false)] [SuppressGCTransition] internal static extern int GetReadDirRBufferSize(); - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_ReadDirR", SetLastError = false)] - internal static extern unsafe int ReadDirR(IntPtr dir, byte* buffer, int bufferSize, out DirectoryEntry outputEntry); + [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_ReadDirR")] + internal static unsafe extern int ReadDirR(IntPtr dir, byte* buffer, int bufferSize, DirectoryEntry* outputEntry); - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_CloseDir", SetLastError = true)] - internal static extern int CloseDir(IntPtr dir); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_CloseDir", SetLastError = true)] + internal static partial int CloseDir(IntPtr dir); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.ReadLink.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.ReadLink.cs index 94f37d4ccc3f8..ce3b064881371 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.ReadLink.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.ReadLink.cs @@ -20,8 +20,8 @@ internal static partial class Sys /// /// Returns the number of bytes placed into the buffer on success; bufferSize if the buffer is too small; and -1 on error. /// - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_ReadLink", SetLastError = true)] - private static extern int ReadLink(ref byte path, byte[] buffer, int bufferSize); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_ReadLink", SetLastError = true)] + private static partial int ReadLink(ref byte path, byte[] buffer, int bufferSize); /// /// Takes a path to a symbolic link and returns the link target path. diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.ReadStdinUnbuffered.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.ReadStdinUnbuffered.cs index 2ac19f1d9d1bb..03565b1dd1747 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.ReadStdinUnbuffered.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.ReadStdinUnbuffered.cs @@ -8,8 +8,8 @@ internal static partial class Interop { internal static partial class Sys { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_ReadStdin", SetLastError = true)] - internal static extern unsafe int ReadStdin(byte* buffer, int bufferSize); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_ReadStdin", SetLastError = true)] + internal static unsafe partial int ReadStdin(byte* buffer, int bufferSize); [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_InitializeConsoleBeforeRead")] internal static extern void InitializeConsoleBeforeRead(byte minChars = 1, byte decisecondsTimeout = 0); diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.RealPath.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.RealPath.cs index 8daa79cd3e692..8ff4105dae6bf 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.RealPath.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.RealPath.cs @@ -13,7 +13,7 @@ internal static partial class Sys /// /// The path to the file system object /// Returns the result string on success and null on failure - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_RealPath", SetLastError = true)] - internal static extern string RealPath(string path); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_RealPath", CharSet = CharSet.Ansi, SetLastError = true)] + internal static partial string RealPath(string path); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Receive.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Receive.cs index a30f4c5e43a4f..a23bdad54aec7 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Receive.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Receive.cs @@ -9,7 +9,7 @@ internal static partial class Interop { internal static partial class Sys { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Receive")] - internal static extern unsafe Error Receive(SafeHandle socket, byte* buffer, int bufferLen, SocketFlags flags, int* received); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Receive")] + internal static unsafe partial Error Receive(SafeHandle socket, byte* buffer, int bufferLen, SocketFlags flags, int* received); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.ReceiveMessage.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.ReceiveMessage.cs index 643e2acc39dce..5757d46f6cc52 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.ReceiveMessage.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.ReceiveMessage.cs @@ -9,7 +9,7 @@ internal static partial class Interop { internal static partial class Sys { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_ReceiveMessage")] - internal static extern unsafe Error ReceiveMessage(SafeHandle socket, MessageHeader* messageHeader, SocketFlags flags, long* received); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_ReceiveMessage")] + internal static unsafe partial Error ReceiveMessage(SafeHandle socket, MessageHeader* messageHeader, SocketFlags flags, long* received); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Rename.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Rename.cs index be81942392d6d..8670f15a7ba40 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Rename.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Rename.cs @@ -16,7 +16,7 @@ internal static partial class Sys /// /// Returns 0 on success; otherwise, returns -1 /// - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Rename", SetLastError = true)] - internal static extern int Rename(string oldPath, string newPath); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Rename", CharSet = CharSet.Ansi, SetLastError = true)] + internal static partial int Rename(string oldPath, string newPath); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.ResourceLimits.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.ResourceLimits.cs index e3a10b7d13681..1d25b5c82ade9 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.ResourceLimits.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.ResourceLimits.cs @@ -30,10 +30,10 @@ internal struct RLimit internal ulong MaximumLimit; } - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetRLimit", SetLastError = true)] - internal static extern int GetRLimit(RlimitResources resourceType, out RLimit limits); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_GetRLimit", SetLastError = true)] + internal static partial int GetRLimit(RlimitResources resourceType, out RLimit limits); - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_SetRLimit", SetLastError = true)] - internal static extern int SetRLimit(RlimitResources resourceType, ref RLimit limits); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_SetRLimit", SetLastError = true)] + internal static partial int SetRLimit(RlimitResources resourceType, ref RLimit limits); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.RmDir.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.RmDir.cs index 5f178a33f7e4c..24b04035262c2 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.RmDir.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.RmDir.cs @@ -15,7 +15,7 @@ internal static partial class Sys /// /// Returns 0 on success; otherwise, returns -1 /// - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_RmDir", SetLastError = true)] - internal static extern int RmDir(string path); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_RmDir", CharSet = CharSet.Ansi, SetLastError = true)] + internal static partial int RmDir(string path); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.SNPrintF.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.SNPrintF.cs index 8755c7e0a6987..47a20fd435727 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.SNPrintF.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.SNPrintF.cs @@ -26,8 +26,8 @@ internal static partial class Sys /// success; if the return value is equal to the size then the result may have been truncated. /// On failure, returns a negative value. /// - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_SNPrintF", SetLastError = true)] - internal static extern unsafe int SNPrintF(byte* str, int size, string format, string arg1); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_SNPrintF", CharSet = CharSet.Ansi, SetLastError = true)] + internal static unsafe partial int SNPrintF(byte* str, int size, string format, string arg1); /// /// Takes a string and applies a formatting to it to transform @@ -47,7 +47,7 @@ internal static partial class Sys /// success; if the return value is equal to the size then the result may have been truncated. /// On failure, returns a negative value. /// - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_SNPrintF", SetLastError = true)] - internal static extern unsafe int SNPrintF(byte* str, int size, string format, int arg1); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_SNPrintF", CharSet = CharSet.Ansi, SetLastError = true)] + internal static unsafe partial int SNPrintF(byte* str, int size, string format, int arg1); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.SchedGetSetAffinity.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.SchedGetSetAffinity.cs index 0a39741df9e55..e304cc29d2dc0 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.SchedGetSetAffinity.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.SchedGetSetAffinity.cs @@ -8,10 +8,10 @@ internal static partial class Interop { internal static partial class Sys { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_SchedSetAffinity", SetLastError = true)] - internal static extern int SchedSetAffinity(int pid, ref IntPtr mask); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_SchedSetAffinity", SetLastError = true)] + internal static partial int SchedSetAffinity(int pid, ref IntPtr mask); - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_SchedGetAffinity", SetLastError = true)] - internal static extern int SchedGetAffinity(int pid, out IntPtr mask); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_SchedGetAffinity", SetLastError = true)] + internal static partial int SchedGetAffinity(int pid, out IntPtr mask); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Send.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Send.cs index b22723d266c1b..c65b45291709e 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Send.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Send.cs @@ -9,7 +9,7 @@ internal static partial class Interop { internal static partial class Sys { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Send")] - internal static extern unsafe Error Send(SafeHandle socket, byte* buffer, int bufferLen, SocketFlags flags, int* sent); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Send")] + internal static unsafe partial Error Send(SafeHandle socket, byte* buffer, int bufferLen, SocketFlags flags, int* sent); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.SendFile.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.SendFile.cs index 3eb343895fafb..b7310100384f7 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.SendFile.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.SendFile.cs @@ -7,7 +7,7 @@ internal static partial class Interop { internal static partial class Sys { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_SendFile", SetLastError = true)] - internal static extern Error SendFile(SafeHandle out_fd, SafeHandle in_fd, long offset, long count, out long sent); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_SendFile", SetLastError = true)] + internal static partial Error SendFile(SafeHandle out_fd, SafeHandle in_fd, long offset, long count, out long sent); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.SendMessage.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.SendMessage.cs index 7d1474896f634..d091c9d29dd82 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.SendMessage.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.SendMessage.cs @@ -9,7 +9,7 @@ internal static partial class Interop { internal static partial class Sys { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_SendMessage")] - internal static extern unsafe Error SendMessage(SafeHandle socket, MessageHeader* messageHeader, SocketFlags flags, long* sent); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_SendMessage")] + internal static unsafe partial Error SendMessage(SafeHandle socket, MessageHeader* messageHeader, SocketFlags flags, long* sent); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.SetReceiveTimeout.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.SetReceiveTimeout.cs index daba80bbed250..5eae239583689 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.SetReceiveTimeout.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.SetReceiveTimeout.cs @@ -9,7 +9,7 @@ internal static partial class Interop { internal static partial class Sys { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_SetReceiveTimeout")] - internal static extern Error SetReceiveTimeout(SafeHandle socket, int millisecondsTimeout); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_SetReceiveTimeout")] + internal static partial Error SetReceiveTimeout(SafeHandle socket, int millisecondsTimeout); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.SetSendTimeout.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.SetSendTimeout.cs index ac7171fa48352..7e2fe7c131d20 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.SetSendTimeout.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.SetSendTimeout.cs @@ -9,7 +9,7 @@ internal static partial class Interop { internal static partial class Sys { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_SetSendTimeout")] - internal static extern Error SetSendTimeout(SafeHandle socket, int millisecondsTimeout); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_SetSendTimeout")] + internal static partial Error SetSendTimeout(SafeHandle socket, int millisecondsTimeout); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.SetSockOpt.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.SetSockOpt.cs index 6172c266a61e4..10760287e439e 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.SetSockOpt.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.SetSockOpt.cs @@ -9,13 +9,13 @@ internal static partial class Interop { internal static partial class Sys { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_SetSockOpt")] - internal static extern unsafe Error SetSockOpt(SafeHandle socket, SocketOptionLevel optionLevel, SocketOptionName optionName, byte* optionValue, int optionLen); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_SetSockOpt")] + internal static unsafe partial Error SetSockOpt(SafeHandle socket, SocketOptionLevel optionLevel, SocketOptionName optionName, byte* optionValue, int optionLen); [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_SetSockOpt")] internal static extern unsafe Error SetSockOpt(IntPtr socket, SocketOptionLevel optionLevel, SocketOptionName optionName, byte* optionValue, int optionLen); - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_SetRawSockOpt")] - internal static extern unsafe Error SetRawSockOpt(SafeHandle socket, int optionLevel, int optionName, byte* optionValue, int optionLen); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_SetRawSockOpt")] + internal static unsafe partial Error SetRawSockOpt(SafeHandle socket, int optionLevel, int optionName, byte* optionValue, int optionLen); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.ShmOpen.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.ShmOpen.cs index f4749b8a5f7be..7d559cb34f4a7 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.ShmOpen.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.ShmOpen.cs @@ -8,10 +8,10 @@ internal static partial class Interop { internal static partial class Sys { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_ShmOpen", SetLastError = true)] - internal static extern SafeFileHandle ShmOpen(string name, OpenFlags flags, int mode); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_ShmOpen", CharSet = CharSet.Ansi, SetLastError = true)] + internal static partial SafeFileHandle ShmOpen(string name, OpenFlags flags, int mode); - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_ShmUnlink", SetLastError = true)] - internal static extern int ShmUnlink(string name); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_ShmUnlink", CharSet = CharSet.Ansi, SetLastError = true)] + internal static partial int ShmUnlink(string name); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Shutdown.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Shutdown.cs index 6bbb8d70da67a..ee516a59c2e86 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Shutdown.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Shutdown.cs @@ -9,8 +9,8 @@ internal static partial class Interop { internal static partial class Sys { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Shutdown")] - internal static extern Error Shutdown(SafeHandle socket, SocketShutdown how); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Shutdown")] + internal static partial Error Shutdown(SafeHandle socket, SocketShutdown how); [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Shutdown")] internal static extern Error Shutdown(IntPtr socket, SocketShutdown how); diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.SocketEvent.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.SocketEvent.cs index 2a8246a7b9ab0..c3e6769ac6cdd 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.SocketEvent.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.SocketEvent.cs @@ -28,19 +28,19 @@ internal struct SocketEvent } [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_CreateSocketEventPort")] - internal static extern Error CreateSocketEventPort(out IntPtr port); + internal static unsafe extern Error CreateSocketEventPort(IntPtr* port); [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_CloseSocketEventPort")] internal static extern Error CloseSocketEventPort(IntPtr port); [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_CreateSocketEventBuffer")] - internal static extern unsafe Error CreateSocketEventBuffer(int count, out SocketEvent* buffer); + internal static unsafe extern Error CreateSocketEventBuffer(int count, SocketEvent** buffer); [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FreeSocketEventBuffer")] internal static extern unsafe Error FreeSocketEventBuffer(SocketEvent* buffer); - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_TryChangeSocketEventRegistration")] - internal static extern Error TryChangeSocketEventRegistration(IntPtr port, SafeHandle socket, SocketEvents currentEvents, SocketEvents newEvents, IntPtr data); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_TryChangeSocketEventRegistration")] + internal static partial Error TryChangeSocketEventRegistration(IntPtr port, SafeHandle socket, SocketEvents currentEvents, SocketEvents newEvents, IntPtr data); [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_TryChangeSocketEventRegistration")] internal static extern Error TryChangeSocketEventRegistration(IntPtr port, IntPtr socket, SocketEvents currentEvents, SocketEvents newEvents, IntPtr data); diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Stat.Pipe.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Stat.Pipe.cs index 1852f983470f9..ccf6a4197954b 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Stat.Pipe.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Stat.Pipe.cs @@ -9,7 +9,7 @@ internal static partial class Interop { internal static partial class Sys { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FStat", SetLastError = true)] - internal static extern int FStat(SafePipeHandle fd, out FileStatus output); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FStat", SetLastError = true)] + internal static partial int FStat(SafePipeHandle fd, out FileStatus output); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Stat.Span.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Stat.Span.cs index 85028fd0fd088..094fa66a0dfa5 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Stat.Span.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Stat.Span.cs @@ -9,8 +9,8 @@ internal static partial class Interop { internal static partial class Sys { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Stat", SetLastError = true)] - internal static extern int Stat(ref byte path, out FileStatus output); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Stat", SetLastError = true)] + internal static partial int Stat(ref byte path, out FileStatus output); internal static int Stat(ReadOnlySpan path, out FileStatus output) { @@ -20,8 +20,8 @@ internal static int Stat(ReadOnlySpan path, out FileStatus output) return result; } - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_LStat", SetLastError = true)] - internal static extern int LStat(ref byte path, out FileStatus output); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_LStat", SetLastError = true)] + internal static partial int LStat(ref byte path, out FileStatus output); internal static int LStat(ReadOnlySpan path, out FileStatus output) { diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Stat.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Stat.cs index c143ab1828b83..4f8193e859599 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Stat.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Stat.cs @@ -53,13 +53,13 @@ internal enum FileStatusFlags HasBirthTime = 1, } - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FStat", SetLastError = true)] - internal static extern int FStat(SafeHandle fd, out FileStatus output); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_FStat", SetLastError = true)] + internal static partial int FStat(SafeHandle fd, out FileStatus output); - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Stat", SetLastError = true)] - internal static extern int Stat(string path, out FileStatus output); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Stat", CharSet = CharSet.Ansi, SetLastError = true)] + internal static partial int Stat(string path, out FileStatus output); - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_LStat", SetLastError = true)] - internal static extern int LStat(string path, out FileStatus output); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_LStat", CharSet = CharSet.Ansi, SetLastError = true)] + internal static partial int LStat(string path, out FileStatus output); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.StdinReady.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.StdinReady.cs index 8ba426acc962d..52f97e37747e1 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.StdinReady.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.StdinReady.cs @@ -7,7 +7,7 @@ internal static partial class Interop { internal static partial class Sys { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_StdinReady")] - internal static extern bool StdinReady(); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_StdinReady")] + internal static partial bool StdinReady(); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.SysConf.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.SysConf.cs index 022584ab95f4c..5790ad50046de 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.SysConf.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.SysConf.cs @@ -13,7 +13,7 @@ internal enum SysConfName _SC_PAGESIZE = 2 } - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_SysConf", SetLastError = true)] - internal static extern long SysConf(SysConfName name); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_SysConf", SetLastError = true)] + internal static partial long SysConf(SysConfName name); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.UTimensat.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.UTimensat.cs index 3477c6ae6fc91..dd9ab9014508c 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.UTimensat.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.UTimensat.cs @@ -22,7 +22,7 @@ internal struct TimeSpec /// /// Returns 0 on success; otherwise, returns -1 /// - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_UTimensat", SetLastError = true)] - internal static extern unsafe int UTimensat(string path, TimeSpec* times); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_UTimensat", CharSet = CharSet.Ansi, SetLastError = true)] + internal static unsafe partial int UTimensat(string path, TimeSpec* times); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Unlink.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Unlink.cs index c71ffe645edd3..fed2f15688ab7 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Unlink.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Unlink.cs @@ -7,7 +7,7 @@ internal static partial class Interop { internal static partial class Sys { - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Unlink", SetLastError = true)] - internal static extern int Unlink(string pathname); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Unlink", CharSet = CharSet.Ansi, SetLastError = true)] + internal static partial int Unlink(string pathname); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.WaitId.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.WaitId.cs index ec9c19ad6776e..4701e4729c37e 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.WaitId.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.WaitId.cs @@ -16,7 +16,7 @@ internal static partial class Sys /// 2) if no children are terminated, 0 is returned /// 3) on error, -1 is returned /// - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_WaitIdAnyExitedNoHangNoWait", SetLastError = true)] - internal static extern int WaitIdAnyExitedNoHangNoWait(); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_WaitIdAnyExitedNoHangNoWait", SetLastError = true)] + internal static partial int WaitIdAnyExitedNoHangNoWait(); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.WaitPid.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.WaitPid.cs index 766d47faeb79b..129ea867cb620 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.WaitPid.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.WaitPid.cs @@ -17,7 +17,7 @@ internal static partial class Sys /// 3) if the child has not yet terminated, 0 is returned /// 4) on error, -1 is returned. /// - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_WaitPidExitedNoHang", SetLastError = true)] - internal static extern int WaitPidExitedNoHang(int pid, out int exitCode); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_WaitPidExitedNoHang", SetLastError = true)] + internal static partial int WaitPidExitedNoHang(int pid, out int exitCode); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Write.Pipe.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Write.Pipe.cs index 2543be83046ae..b71b9c5e3f734 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Write.Pipe.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Write.Pipe.cs @@ -17,7 +17,7 @@ internal static partial class Sys /// /// Returns the number of bytes written on success; otherwise, returns -1 and sets errno /// - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Write", SetLastError = true)] - internal static extern unsafe int Write(SafePipeHandle fd, byte* buffer, int bufferSize); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Write", SetLastError = true)] + internal static unsafe partial int Write(SafePipeHandle fd, byte* buffer, int bufferSize); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Write.cs b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Write.cs index 6b322ee72a882..278346759d3eb 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Write.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Native/Interop.Write.cs @@ -17,10 +17,10 @@ internal static partial class Sys /// /// Returns the number of bytes written on success; otherwise, returns -1 and sets errno /// - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Write", SetLastError = true)] - internal static extern unsafe int Write(SafeHandle fd, byte* buffer, int bufferSize); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Write", SetLastError = true)] + internal static unsafe partial int Write(SafeHandle fd, byte* buffer, int bufferSize); - [DllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Write", SetLastError = true)] - internal static extern unsafe int Write(IntPtr fd, byte* buffer, int bufferSize); + [GeneratedDllImport(Libraries.SystemNative, EntryPoint = "SystemNative_Write", SetLastError = true)] + internal static unsafe partial int Write(IntPtr fd, byte* buffer, int bufferSize); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Net.Security.Native/Interop.NetSecurityNative.IsNtlmInstalled.cs b/src/libraries/Common/src/Interop/Unix/System.Net.Security.Native/Interop.NetSecurityNative.IsNtlmInstalled.cs index 24b5b9ad5a78c..cae5d6ad0642c 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Net.Security.Native/Interop.NetSecurityNative.IsNtlmInstalled.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Net.Security.Native/Interop.NetSecurityNative.IsNtlmInstalled.cs @@ -8,8 +8,8 @@ internal static partial class Interop { internal static partial class NetSecurityNative { - [DllImport(Interop.Libraries.NetSecurityNative, EntryPoint="NetSecurityNative_IsNtlmInstalled")] - internal static extern bool IsNtlmInstalled(); + [GeneratedDllImport(Interop.Libraries.NetSecurityNative, EntryPoint="NetSecurityNative_IsNtlmInstalled")] + internal static partial bool IsNtlmInstalled(); [DllImport(Interop.Libraries.NetSecurityNative, EntryPoint = "NetSecurityNative_EnsureGssInitialized")] private static extern int EnsureGssInitialized(); diff --git a/src/libraries/Common/src/Interop/Unix/System.Net.Security.Native/Interop.NetSecurityNative.cs b/src/libraries/Common/src/Interop/Unix/System.Net.Security.Native/Interop.NetSecurityNative.cs index 083b6ce18b77d..fc950025174c0 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Net.Security.Native/Interop.NetSecurityNative.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Net.Security.Native/Interop.NetSecurityNative.cs @@ -16,50 +16,50 @@ internal static extern void ReleaseGssBuffer( IntPtr bufferPtr, ulong length); - [DllImport(Interop.Libraries.NetSecurityNative, EntryPoint="NetSecurityNative_DisplayMinorStatus")] - internal static extern Status DisplayMinorStatus( + [GeneratedDllImport(Interop.Libraries.NetSecurityNative, EntryPoint="NetSecurityNative_DisplayMinorStatus")] + internal static partial Status DisplayMinorStatus( out Status minorStatus, Status statusValue, ref GssBuffer buffer); - [DllImport(Interop.Libraries.NetSecurityNative, EntryPoint="NetSecurityNative_DisplayMajorStatus")] - internal static extern Status DisplayMajorStatus( + [GeneratedDllImport(Interop.Libraries.NetSecurityNative, EntryPoint="NetSecurityNative_DisplayMajorStatus")] + internal static partial Status DisplayMajorStatus( out Status minorStatus, Status statusValue, ref GssBuffer buffer); - [DllImport(Interop.Libraries.NetSecurityNative, EntryPoint="NetSecurityNative_ImportUserName")] - internal static extern Status ImportUserName( + [GeneratedDllImport(Interop.Libraries.NetSecurityNative, EntryPoint="NetSecurityNative_ImportUserName")] + internal static partial Status ImportUserName( out Status minorStatus, - string inputName, + [MarshalAs(UnmanagedType.LPUTF8Str)] string inputName, int inputNameByteCount, out SafeGssNameHandle outputName); - [DllImport(Interop.Libraries.NetSecurityNative, EntryPoint="NetSecurityNative_ImportPrincipalName")] - internal static extern Status ImportPrincipalName( + [GeneratedDllImport(Interop.Libraries.NetSecurityNative, EntryPoint="NetSecurityNative_ImportPrincipalName")] + internal static partial Status ImportPrincipalName( out Status minorStatus, - string inputName, + [MarshalAs(UnmanagedType.LPUTF8Str)] string inputName, int inputNameByteCount, out SafeGssNameHandle outputName); [DllImport(Interop.Libraries.NetSecurityNative, EntryPoint="NetSecurityNative_ReleaseName")] - internal static extern Status ReleaseName( - out Status minorStatus, - ref IntPtr inputName); + internal static unsafe extern Status ReleaseName( + Status* minorStatus, + IntPtr* inputName); - [DllImport(Interop.Libraries.NetSecurityNative, EntryPoint="NetSecurityNative_AcquireAcceptorCred")] - internal static extern Status AcquireAcceptorCred( + [GeneratedDllImport(Interop.Libraries.NetSecurityNative, EntryPoint="NetSecurityNative_AcquireAcceptorCred")] + internal static partial Status AcquireAcceptorCred( out Status minorStatus, out SafeGssCredHandle outputCredHandle); - [DllImport(Interop.Libraries.NetSecurityNative, EntryPoint="NetSecurityNative_InitiateCredSpNego")] - internal static extern Status InitiateCredSpNego( + [GeneratedDllImport(Interop.Libraries.NetSecurityNative, EntryPoint="NetSecurityNative_InitiateCredSpNego")] + internal static partial Status InitiateCredSpNego( out Status minorStatus, SafeGssNameHandle desiredName, out SafeGssCredHandle outputCredHandle); - [DllImport(Interop.Libraries.NetSecurityNative, EntryPoint="NetSecurityNative_InitiateCredWithPassword")] - internal static extern Status InitiateCredWithPassword( + [GeneratedDllImport(Interop.Libraries.NetSecurityNative, EntryPoint="NetSecurityNative_InitiateCredWithPassword", CharSet = CharSet.Ansi)] + internal static partial Status InitiateCredWithPassword( out Status minorStatus, bool isNtlm, SafeGssNameHandle desiredName, @@ -68,12 +68,12 @@ internal static extern Status InitiateCredWithPassword( out SafeGssCredHandle outputCredHandle); [DllImport(Interop.Libraries.NetSecurityNative, EntryPoint="NetSecurityNative_ReleaseCred")] - internal static extern Status ReleaseCred( - out Status minorStatus, - ref IntPtr credHandle); + internal static unsafe extern Status ReleaseCred( + Status* minorStatus, + IntPtr* credHandle); - [DllImport(Interop.Libraries.NetSecurityNative, EntryPoint="NetSecurityNative_InitSecContext")] - internal static extern Status InitSecContext( + [GeneratedDllImport(Interop.Libraries.NetSecurityNative, EntryPoint="NetSecurityNative_InitSecContext")] + internal static partial Status InitSecContext( out Status minorStatus, SafeGssCredHandle initiatorCredHandle, ref SafeGssContextHandle contextHandle, @@ -86,8 +86,8 @@ internal static extern Status InitSecContext( out uint retFlags, out bool isNtlmUsed); - [DllImport(Interop.Libraries.NetSecurityNative, EntryPoint="NetSecurityNative_InitSecContextEx")] - internal static extern Status InitSecContext( + [GeneratedDllImport(Interop.Libraries.NetSecurityNative, EntryPoint="NetSecurityNative_InitSecContextEx")] + internal static partial Status InitSecContext( out Status minorStatus, SafeGssCredHandle initiatorCredHandle, ref SafeGssContextHandle contextHandle, @@ -102,8 +102,8 @@ internal static extern Status InitSecContext( out uint retFlags, out bool isNtlmUsed); - [DllImport(Interop.Libraries.NetSecurityNative, EntryPoint="NetSecurityNative_AcceptSecContext")] - internal static extern Status AcceptSecContext( + [GeneratedDllImport(Interop.Libraries.NetSecurityNative, EntryPoint="NetSecurityNative_AcceptSecContext")] + internal static partial Status AcceptSecContext( out Status minorStatus, SafeGssCredHandle acceptorCredHandle, ref SafeGssContextHandle acceptContextHandle, @@ -114,18 +114,18 @@ internal static extern Status AcceptSecContext( out bool isNtlmUsed); [DllImport(Interop.Libraries.NetSecurityNative, EntryPoint="NetSecurityNative_DeleteSecContext")] - internal static extern Status DeleteSecContext( - out Status minorStatus, - ref IntPtr contextHandle); + internal static unsafe extern Status DeleteSecContext( + Status* minorStatus, + IntPtr* contextHandle); - [DllImport(Interop.Libraries.NetSecurityNative, EntryPoint="NetSecurityNative_GetUser")] - internal static extern Status GetUser( + [GeneratedDllImport(Interop.Libraries.NetSecurityNative, EntryPoint="NetSecurityNative_GetUser")] + internal static partial Status GetUser( out Status minorStatus, SafeGssContextHandle? acceptContextHandle, ref GssBuffer token); - [DllImport(Interop.Libraries.NetSecurityNative, EntryPoint="NetSecurityNative_Wrap")] - private static extern unsafe Status Wrap( + [GeneratedDllImport(Interop.Libraries.NetSecurityNative, EntryPoint="NetSecurityNative_Wrap")] + private static unsafe partial Status Wrap( out Status minorStatus, SafeGssContextHandle? contextHandle, bool isEncrypt, @@ -133,8 +133,8 @@ private static extern unsafe Status Wrap( int count, ref GssBuffer outBuffer); - [DllImport(Interop.Libraries.NetSecurityNative, EntryPoint="NetSecurityNative_Unwrap")] - private static extern Status Unwrap( + [GeneratedDllImport(Interop.Libraries.NetSecurityNative, EntryPoint="NetSecurityNative_Unwrap")] + private static partial Status Unwrap( out Status minorStatus, SafeGssContextHandle? contextHandle, byte[] inputBytes, diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.ASN1.GetIntegerBytes.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.ASN1.GetIntegerBytes.cs index c5b94de3d20a9..e9a78844fd28a 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.ASN1.GetIntegerBytes.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.ASN1.GetIntegerBytes.cs @@ -11,11 +11,11 @@ internal static partial class Interop { internal static partial class Crypto { - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetAsn1IntegerDerSize")] - private static extern int GetAsn1IntegerDerSize(SafeSharedAsn1IntegerHandle i); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetAsn1IntegerDerSize")] + private static partial int GetAsn1IntegerDerSize(SafeSharedAsn1IntegerHandle i); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EncodeAsn1Integer")] - private static extern int EncodeAsn1Integer(SafeSharedAsn1IntegerHandle i, byte[] buf); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EncodeAsn1Integer")] + private static partial int EncodeAsn1Integer(SafeSharedAsn1IntegerHandle i, byte[] buf); internal static byte[] GetAsn1IntegerBytes(SafeSharedAsn1IntegerHandle asn1Integer) { diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.ASN1.Nid.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.ASN1.Nid.cs index a0f7ef27de21d..3d5167912dcc6 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.ASN1.Nid.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.ASN1.Nid.cs @@ -15,11 +15,11 @@ internal static partial class Crypto internal const int NID_undef = 0; - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_ObjSn2Nid", CharSet = CharSet.Ansi)] - internal static extern int ObjSn2Nid(string sn); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_ObjSn2Nid", CharSet = CharSet.Ansi)] + internal static partial int ObjSn2Nid(string sn); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_ObjTxt2Nid", CharSet = CharSet.Ansi)] - private static extern int ObjTxt2Nid(string oid); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_ObjTxt2Nid", CharSet = CharSet.Ansi)] + private static partial int ObjTxt2Nid(string oid); internal static int ResolveRequiredNid(string oid) { diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.ASN1.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.ASN1.cs index a4bfc8d962154..1f5c911383873 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.ASN1.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.ASN1.cs @@ -12,14 +12,14 @@ internal static partial class Interop { internal static partial class Crypto { - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_ObjTxt2Obj", CharSet = CharSet.Ansi)] - internal static extern SafeAsn1ObjectHandle ObjTxt2Obj(string s); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_ObjTxt2Obj", CharSet = CharSet.Ansi)] + internal static partial SafeAsn1ObjectHandle ObjTxt2Obj(string s); [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_ObjObj2Txt")] private static extern unsafe int ObjObj2Txt(byte* buf, int buf_len, IntPtr a); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetObjectDefinitionByName", CharSet = CharSet.Ansi)] - private static extern IntPtr CryptoNative_GetObjectDefinitionByName(string friendlyName); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetObjectDefinitionByName", CharSet = CharSet.Ansi)] + private static partial IntPtr CryptoNative_GetObjectDefinitionByName(string friendlyName); internal static IntPtr GetObjectDefinitionByName(string friendlyName) { IntPtr ret = CryptoNative_GetObjectDefinitionByName(friendlyName); @@ -38,18 +38,18 @@ internal static IntPtr GetObjectDefinitionByName(string friendlyName) [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_Asn1ObjectFree")] internal static extern void Asn1ObjectFree(IntPtr o); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_DecodeAsn1BitString")] - internal static extern SafeAsn1BitStringHandle DecodeAsn1BitString(byte[] buf, int len); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_DecodeAsn1BitString")] + internal static partial SafeAsn1BitStringHandle DecodeAsn1BitString(byte[] buf, int len); [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_Asn1BitStringFree")] internal static extern void Asn1BitStringFree(IntPtr o); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_Asn1OctetStringNew")] - internal static extern SafeAsn1OctetStringHandle Asn1OctetStringNew(); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_Asn1OctetStringNew")] + internal static partial SafeAsn1OctetStringHandle Asn1OctetStringNew(); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_Asn1OctetStringSet")] + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_Asn1OctetStringSet")] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool Asn1OctetStringSet(SafeAsn1OctetStringHandle o, byte[] d, int len); + internal static partial bool Asn1OctetStringSet(SafeAsn1OctetStringHandle o, byte[] d, int len); [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_Asn1OctetStringFree")] internal static extern void Asn1OctetStringFree(IntPtr o); diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.BIO.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.BIO.cs index bc5349745a845..64c1be633986f 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.BIO.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.BIO.cs @@ -9,35 +9,35 @@ internal static partial class Interop { internal static partial class Crypto { - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_CreateMemoryBio")] - internal static extern SafeBioHandle CreateMemoryBio(); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_CreateMemoryBio")] + internal static partial SafeBioHandle CreateMemoryBio(); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_BioNewFile")] - internal static extern SafeBioHandle BioNewFile(string filename, string mode); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_BioNewFile", CharSet = CharSet.Ansi)] + internal static partial SafeBioHandle BioNewFile(string filename, string mode); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_BioDestroy")] + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_BioDestroy")] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool BioDestroy(IntPtr a); + internal static partial bool BioDestroy(IntPtr a); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_BioGets")] - internal static extern int BioGets(SafeBioHandle b, byte[] buf, int size); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_BioGets")] + internal static partial int BioGets(SafeBioHandle b, byte[] buf, int size); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_BioRead")] - internal static extern int BioRead(SafeBioHandle b, byte[] data, int len); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_BioRead")] + internal static partial int BioRead(SafeBioHandle b, byte[] data, int len); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_BioWrite")] - internal static extern int BioWrite(SafeBioHandle b, byte[] data, int len); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_BioWrite")] + internal static partial int BioWrite(SafeBioHandle b, byte[] data, int len); internal static int BioWrite(SafeBioHandle b, ReadOnlySpan data) => BioWrite(b, ref MemoryMarshal.GetReference(data), data.Length); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_BioWrite")] - private static extern int BioWrite(SafeBioHandle b, ref byte data, int len); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_BioWrite")] + private static partial int BioWrite(SafeBioHandle b, ref byte data, int len); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetMemoryBioSize")] - internal static extern int GetMemoryBioSize(SafeBioHandle bio); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetMemoryBioSize")] + internal static partial int GetMemoryBioSize(SafeBioHandle bio); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_BioCtrlPending")] - internal static extern int BioCtrlPending(SafeBioHandle bio); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_BioCtrlPending")] + internal static partial int BioCtrlPending(SafeBioHandle bio); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Bignum.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Bignum.cs index 6d09f2d9810b8..b6eb67c99f023 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Bignum.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Bignum.cs @@ -16,11 +16,11 @@ internal static partial class Crypto [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_BigNumFromBinary")] private static extern unsafe IntPtr BigNumFromBinary(byte* s, int len); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_BigNumToBinary")] - private static extern unsafe int BigNumToBinary(SafeBignumHandle a, byte* to); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_BigNumToBinary")] + private static unsafe partial int BigNumToBinary(SafeBignumHandle a, byte* to); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetBigNumBytes")] - private static extern int GetBigNumBytes(SafeBignumHandle a); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetBigNumBytes")] + private static partial int GetBigNumBytes(SafeBignumHandle a); private static unsafe IntPtr CreateBignumPtr(ReadOnlySpan bigEndianValue) { diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Crypto.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Crypto.cs index c1d0d991a0e52..444101fb933c5 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Crypto.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Crypto.cs @@ -13,8 +13,8 @@ internal static partial class Crypto { internal delegate int NegativeSizeReadMethod(THandle handle, byte[]? buf, int cBuf); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_BioTell")] - internal static extern int CryptoNative_BioTell(SafeBioHandle bio); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_BioTell")] + internal static partial int CryptoNative_BioTell(SafeBioHandle bio); internal static int BioTell(SafeBioHandle bio) { @@ -27,46 +27,46 @@ internal static int BioTell(SafeBioHandle bio) return ret; } - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_BioSeek")] - internal static extern int BioSeek(SafeBioHandle bio, int pos); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_BioSeek")] + internal static partial int BioSeek(SafeBioHandle bio, int pos); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509Thumbprint")] - private static extern int GetX509Thumbprint(SafeX509Handle x509, byte[]? buf, int cBuf); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509Thumbprint")] + private static partial int GetX509Thumbprint(SafeX509Handle x509, byte[]? buf, int cBuf); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509NameRawBytes")] - private static extern int GetX509NameRawBytes(IntPtr x509Name, byte[]? buf, int cBuf); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509NameRawBytes")] + private static partial int GetX509NameRawBytes(IntPtr x509Name, byte[]? buf, int cBuf); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_ReadX509AsDerFromBio")] - internal static extern SafeX509Handle ReadX509AsDerFromBio(SafeBioHandle bio); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_ReadX509AsDerFromBio")] + internal static partial SafeX509Handle ReadX509AsDerFromBio(SafeBioHandle bio); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509CrlNextUpdate")] - internal static extern IntPtr GetX509CrlNextUpdate(SafeX509CrlHandle crl); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509CrlNextUpdate")] + internal static partial IntPtr GetX509CrlNextUpdate(SafeX509CrlHandle crl); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509Version")] - internal static extern int GetX509Version(SafeX509Handle x509); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509Version")] + internal static partial int GetX509Version(SafeX509Handle x509); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509PublicKeyParameterBytes")] - private static extern int GetX509PublicKeyParameterBytes(SafeX509Handle x509, byte[]? buf, int cBuf); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509PublicKeyParameterBytes")] + private static partial int GetX509PublicKeyParameterBytes(SafeX509Handle x509, byte[]? buf, int cBuf); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509EkuFieldCount")] - internal static extern int GetX509EkuFieldCount(SafeEkuExtensionHandle eku); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509EkuFieldCount")] + internal static partial int GetX509EkuFieldCount(SafeEkuExtensionHandle eku); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509EkuField")] - internal static extern IntPtr GetX509EkuField(SafeEkuExtensionHandle eku, int loc); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509EkuField")] + internal static partial IntPtr GetX509EkuField(SafeEkuExtensionHandle eku, int loc); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509NameInfo")] - internal static extern SafeBioHandle GetX509NameInfo(SafeX509Handle x509, int nameType, [MarshalAs(UnmanagedType.Bool)] bool forIssuer); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509NameInfo")] + internal static partial SafeBioHandle GetX509NameInfo(SafeX509Handle x509, int nameType, [MarshalAs(UnmanagedType.Bool)] bool forIssuer); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetAsn1StringBytes")] - private static extern int GetAsn1StringBytes(IntPtr asn1, byte[]? buf, int cBuf); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetAsn1StringBytes")] + private static partial int GetAsn1StringBytes(IntPtr asn1, byte[]? buf, int cBuf); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_PushX509StackField")] + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_PushX509StackField")] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool PushX509StackField(SafeX509StackHandle stack, SafeX509Handle x509); + internal static partial bool PushX509StackField(SafeX509StackHandle stack, SafeX509Handle x509); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_PushX509StackField")] + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_PushX509StackField")] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool PushX509StackField(SafeSharedX509StackHandle stack, SafeX509Handle x509); + internal static partial bool PushX509StackField(SafeSharedX509StackHandle stack, SafeX509Handle x509); internal static unsafe string? GetX509RootStorePath(out bool defaultPath) { @@ -88,8 +88,8 @@ internal static int BioTell(SafeBioHandle bio) [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509RootStoreFile")] private static unsafe extern IntPtr GetX509RootStoreFile_private(byte* defaultPath); - [DllImport(Libraries.CryptoNative)] - private static extern int CryptoNative_X509StoreSetVerifyTime( + [GeneratedDllImport(Libraries.CryptoNative)] + private static partial int CryptoNative_X509StoreSetVerifyTime( SafeX509StoreHandle ctx, int year, int month, @@ -99,11 +99,11 @@ private static extern int CryptoNative_X509StoreSetVerifyTime( int second, [MarshalAs(UnmanagedType.Bool)] bool isDst); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_CheckX509IpAddress")] - internal static extern int CheckX509IpAddress(SafeX509Handle x509, [In]byte[] addressBytes, int addressLen, string hostname, int cchHostname); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_CheckX509IpAddress", CharSet = CharSet.Ansi)] + internal static partial int CheckX509IpAddress(SafeX509Handle x509, byte[] addressBytes, int addressLen, string hostname, int cchHostname); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_CheckX509Hostname")] - internal static extern int CheckX509Hostname(SafeX509Handle x509, string hostname, int cchHostname); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_CheckX509Hostname", CharSet = CharSet.Ansi)] + internal static partial int CheckX509Hostname(SafeX509Handle x509, string hostname, int cchHostname); internal static byte[] GetAsn1StringBytes(IntPtr asn1) { diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Dsa.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Dsa.cs index ff9140632d3fb..54d868ecc185c 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Dsa.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Dsa.cs @@ -11,19 +11,19 @@ internal static partial class Interop { internal static partial class Crypto { - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_DsaUpRef")] + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_DsaUpRef")] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool DsaUpRef(IntPtr dsa); + internal static partial bool DsaUpRef(IntPtr dsa); [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_DsaDestroy")] internal static extern void DsaDestroy(IntPtr dsa); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_DsaGenerateKey")] + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_DsaGenerateKey")] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool DsaGenerateKey(out SafeDsaHandle dsa, int bits); + internal static partial bool DsaGenerateKey(out SafeDsaHandle dsa, int bits); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_DsaSizeSignature")] - private static extern int DsaSizeSignature(SafeDsaHandle dsa); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_DsaSizeSignature")] + private static partial int DsaSizeSignature(SafeDsaHandle dsa); /// /// Return the maximum size of the DER-encoded key in bytes. @@ -34,8 +34,8 @@ internal static int DsaEncodedSignatureSize(SafeDsaHandle dsa) return size; } - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_DsaSizeQ")] - private static extern int DsaSizeQ(SafeDsaHandle dsa); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_DsaSizeQ")] + private static partial int DsaSizeQ(SafeDsaHandle dsa); /// /// Return the size of the 'r' or 's' signature fields in bytes. @@ -47,8 +47,8 @@ internal static int DsaSignatureFieldSize(SafeDsaHandle dsa) return size; } - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_DsaSizeP")] - private static extern int DsaSizeP(SafeDsaHandle dsa); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_DsaSizeP")] + private static partial int DsaSizeP(SafeDsaHandle dsa); /// /// Return the size of the key in bytes. @@ -65,9 +65,9 @@ internal static int DsaKeySize(SafeDsaHandle dsa) internal static bool DsaSign(SafeDsaHandle dsa, ReadOnlySpan hash, Span refSignature, out int outSignatureLength) => DsaSign(dsa, ref MemoryMarshal.GetReference(hash), hash.Length, ref MemoryMarshal.GetReference(refSignature), out outSignatureLength); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_DsaSign")] + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_DsaSign")] [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool DsaSign(SafeDsaHandle dsa, ref byte hash, int hashLength, ref byte refSignature, out int outSignatureLength); + private static partial bool DsaSign(SafeDsaHandle dsa, ref byte hash, int hashLength, ref byte refSignature, out int outSignatureLength); internal static bool DsaVerify(SafeDsaHandle dsa, ReadOnlySpan hash, ReadOnlySpan signature) { @@ -83,9 +83,9 @@ ref MemoryMarshal.GetReference(signature), return ret; } - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_DsaVerify")] + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_DsaVerify")] [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool DsaVerify(SafeDsaHandle dsa, ref byte hash, int hashLength, ref byte signature, int signatureLength); + private static partial bool DsaVerify(SafeDsaHandle dsa, ref byte hash, int hashLength, ref byte signature, int signatureLength); internal static DSAParameters ExportDsaParameters(SafeDsaHandle key, bool includePrivateParameters) { @@ -144,9 +144,9 @@ internal static DSAParameters ExportDsaParameters(SafeDsaHandle key, bool includ } } - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetDsaParameters")] + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetDsaParameters")] [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool GetDsaParameters( + private static partial bool GetDsaParameters( SafeDsaHandle key, out IntPtr p, out int p_cb, out IntPtr q, out int q_cb, @@ -154,9 +154,9 @@ private static extern bool GetDsaParameters( out IntPtr y, out int y_cb, out IntPtr x, out int x_cb); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_DsaKeyCreateByExplicitParameters")] + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_DsaKeyCreateByExplicitParameters")] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool DsaKeyCreateByExplicitParameters( + internal static partial bool DsaKeyCreateByExplicitParameters( out SafeDsaHandle dsa, byte[] p, int pLength, diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.ERR.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.ERR.cs index 771a5ed4f88aa..c61707e71c3d8 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.ERR.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.ERR.cs @@ -13,8 +13,8 @@ internal static partial class Crypto [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_ErrClearError")] internal static extern ulong ErrClearError(); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_ErrGetErrorAlloc")] - private static extern ulong ErrGetErrorAlloc([MarshalAs(UnmanagedType.Bool)] out bool isAllocFailure); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_ErrGetErrorAlloc")] + private static partial ulong ErrGetErrorAlloc([MarshalAs(UnmanagedType.Bool)] out bool isAllocFailure); [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_ErrPeekError")] internal static extern ulong ErrPeekError(); diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EVP.Cipher.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EVP.Cipher.cs index 66bb14920a51b..ce77602722126 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EVP.Cipher.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EVP.Cipher.cs @@ -9,21 +9,21 @@ internal static partial class Interop { internal static partial class Crypto { - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpCipherCreate2")] - internal static extern SafeEvpCipherCtxHandle EvpCipherCreate( + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpCipherCreate2")] + internal static partial SafeEvpCipherCtxHandle EvpCipherCreate( IntPtr cipher, ref byte key, int keyLength, ref byte iv, int enc); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpCipherCreatePartial")] - internal static extern SafeEvpCipherCtxHandle EvpCipherCreatePartial( + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpCipherCreatePartial")] + internal static partial SafeEvpCipherCtxHandle EvpCipherCreatePartial( IntPtr cipher); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpCipherSetKeyAndIV")] + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpCipherSetKeyAndIV")] [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool EvpCipherSetKeyAndIV( + private static partial bool EvpCipherSetKeyAndIV( SafeEvpCipherCtxHandle ctx, ref byte key, ref byte iv, @@ -45,9 +45,9 @@ ref MemoryMarshal.GetReference(iv), } } - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpCipherSetGcmNonceLength")] + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpCipherSetGcmNonceLength")] [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool CryptoNative_EvpCipherSetGcmNonceLength( + private static partial bool CryptoNative_EvpCipherSetGcmNonceLength( SafeEvpCipherCtxHandle ctx, int nonceLength); internal static void EvpCipherSetGcmNonceLength(SafeEvpCipherCtxHandle ctx, int nonceLength) @@ -58,9 +58,9 @@ internal static void EvpCipherSetGcmNonceLength(SafeEvpCipherCtxHandle ctx, int } } - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpCipherSetCcmNonceLength")] + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpCipherSetCcmNonceLength")] [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool CryptoNative_EvpCipherSetCcmNonceLength( + private static partial bool CryptoNative_EvpCipherSetCcmNonceLength( SafeEvpCipherCtxHandle ctx, int nonceLength); internal static void EvpCipherSetCcmNonceLength(SafeEvpCipherCtxHandle ctx, int nonceLength) @@ -74,21 +74,21 @@ internal static void EvpCipherSetCcmNonceLength(SafeEvpCipherCtxHandle ctx, int [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpCipherDestroy")] internal static extern void EvpCipherDestroy(IntPtr ctx); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpCipherReset")] + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpCipherReset")] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool EvpCipherReset(SafeEvpCipherCtxHandle ctx); + internal static partial bool EvpCipherReset(SafeEvpCipherCtxHandle ctx); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpCipherCtxSetPadding")] + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpCipherCtxSetPadding")] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool EvpCipherCtxSetPadding(SafeEvpCipherCtxHandle x, int padding); + internal static partial bool EvpCipherCtxSetPadding(SafeEvpCipherCtxHandle x, int padding); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpCipherUpdate")] + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpCipherUpdate")] [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool EvpCipherUpdate( + private static partial bool EvpCipherUpdate( SafeEvpCipherCtxHandle ctx, - ref byte @out, + ref byte output, out int outl, - ref byte @in, + ref byte input, int inl); internal static bool EvpCipherUpdate( @@ -114,9 +114,9 @@ internal static void EvpCipherSetInputLength(SafeEvpCipherCtxHandle ctx, int inp } } - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpCipherFinalEx")] + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpCipherFinalEx")] [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool EvpCipherFinalEx( + private static partial bool EvpCipherFinalEx( SafeEvpCipherCtxHandle ctx, ref byte outm, out int outl); @@ -129,9 +129,9 @@ internal static bool EvpCipherFinalEx( return EvpCipherFinalEx(ctx, ref MemoryMarshal.GetReference(output), out bytesWritten); } - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpCipherGetGcmTag")] + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpCipherGetGcmTag")] [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool EvpCipherGetGcmTag( + private static partial bool EvpCipherGetGcmTag( SafeEvpCipherCtxHandle ctx, ref byte tag, int tagLength); @@ -144,9 +144,9 @@ internal static void EvpCipherGetGcmTag(SafeEvpCipherCtxHandle ctx, Span t } } - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpCipherGetAeadTag")] + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpCipherGetAeadTag")] [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool EvpCipherGetAeadTag( + private static partial bool EvpCipherGetAeadTag( SafeEvpCipherCtxHandle ctx, ref byte tag, int tagLength); @@ -159,9 +159,9 @@ internal static void EvpCipherGetAeadTag(SafeEvpCipherCtxHandle ctx, Span } } - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpCipherSetGcmTag")] + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpCipherSetGcmTag")] [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool EvpCipherSetGcmTag( + private static partial bool EvpCipherSetGcmTag( SafeEvpCipherCtxHandle ctx, ref byte tag, int tagLength); @@ -174,9 +174,9 @@ internal static void EvpCipherSetGcmTag(SafeEvpCipherCtxHandle ctx, ReadOnlySpan } } - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpCipherSetAeadTag")] + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpCipherSetAeadTag")] [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool EvpCipherSetAeadTag( + private static partial bool EvpCipherSetAeadTag( SafeEvpCipherCtxHandle ctx, ref byte tag, int tagLength); @@ -189,9 +189,9 @@ internal static void EvpCipherSetAeadTag(SafeEvpCipherCtxHandle ctx, ReadOnlySpa } } - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpCipherGetCcmTag")] + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpCipherGetCcmTag")] [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool EvpCipherGetCcmTag( + private static partial bool EvpCipherGetCcmTag( SafeEvpCipherCtxHandle ctx, ref byte tag, int tagLength); @@ -204,9 +204,9 @@ internal static void EvpCipherGetCcmTag(SafeEvpCipherCtxHandle ctx, Span t } } - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpCipherSetCcmTag")] + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpCipherSetCcmTag")] [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool EvpCipherSetCcmTag( + private static partial bool EvpCipherSetCcmTag( SafeEvpCipherCtxHandle ctx, ref byte tag, int tagLength); diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EVP.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EVP.cs index bd6cf8bfb5b61..1c853dfb47cc2 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EVP.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EVP.cs @@ -10,29 +10,29 @@ internal static partial class Interop { internal static partial class Crypto { - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpMdCtxCreate")] - internal static extern SafeEvpMdCtxHandle EvpMdCtxCreate(IntPtr type); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpMdCtxCreate")] + internal static partial SafeEvpMdCtxHandle EvpMdCtxCreate(IntPtr type); [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpMdCtxDestroy")] internal static extern void EvpMdCtxDestroy(IntPtr ctx); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpDigestReset")] - internal static extern int EvpDigestReset(SafeEvpMdCtxHandle ctx, IntPtr type); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpDigestReset")] + internal static partial int EvpDigestReset(SafeEvpMdCtxHandle ctx, IntPtr type); internal static int EvpDigestUpdate(SafeEvpMdCtxHandle ctx, ReadOnlySpan d, int cnt) => EvpDigestUpdate(ctx, ref MemoryMarshal.GetReference(d), cnt); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpDigestUpdate")] - private static extern int EvpDigestUpdate(SafeEvpMdCtxHandle ctx, ref byte d, int cnt); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpDigestUpdate")] + private static partial int EvpDigestUpdate(SafeEvpMdCtxHandle ctx, ref byte d, int cnt); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpDigestFinalEx")] - internal static extern int EvpDigestFinalEx(SafeEvpMdCtxHandle ctx, ref byte md, ref uint s); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpDigestFinalEx")] + internal static partial int EvpDigestFinalEx(SafeEvpMdCtxHandle ctx, ref byte md, ref uint s); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpDigestCurrent")] - internal static extern int EvpDigestCurrent(SafeEvpMdCtxHandle ctx, ref byte md, ref uint s); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpDigestCurrent")] + internal static partial int EvpDigestCurrent(SafeEvpMdCtxHandle ctx, ref byte md, ref uint s); [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpDigestOneShot")] - internal static unsafe extern int EvpDigestOneShot(IntPtr type, byte* source, int sourceSize, byte* md, ref uint mdSize); + internal static unsafe extern int EvpDigestOneShot(IntPtr type, byte* source, int sourceSize, byte* md, uint* mdSize); [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpMdSize")] internal static extern int EvpMdSize(IntPtr md); diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EcDsa.ImportExport.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EcDsa.ImportExport.cs index 9687abdafdc01..0b23fc788b997 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EcDsa.ImportExport.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EcDsa.ImportExport.cs @@ -11,8 +11,8 @@ internal static partial class Interop { internal static partial class Crypto { - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EcKeyCreateByKeyParameters", CharSet = CharSet.Ansi)] - private static extern int EcKeyCreateByKeyParameters( + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EcKeyCreateByKeyParameters", CharSet = CharSet.Ansi)] + private static partial int EcKeyCreateByKeyParameters( out SafeEcKeyHandle key, string oid, byte[]? qx, int qxLength, @@ -37,8 +37,8 @@ internal static SafeEcKeyHandle EcKeyCreateByKeyParameters( return key; } - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EcKeyCreateByExplicitParameters")] - internal static extern SafeEcKeyHandle EcKeyCreateByExplicitParameters( + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EcKeyCreateByExplicitParameters")] + internal static partial SafeEcKeyHandle EcKeyCreateByExplicitParameters( ECCurve.ECCurveType curveType, byte[]? qx, int qxLength, byte[]? qy, int qyLength, @@ -97,8 +97,8 @@ internal static SafeEcKeyHandle EcKeyCreateByExplicitCurve(ECCurve curve) } - [DllImport(Libraries.CryptoNative)] - private static extern int CryptoNative_GetECKeyParameters( + [GeneratedDllImport(Libraries.CryptoNative)] + private static partial int CryptoNative_GetECKeyParameters( SafeEcKeyHandle key, bool includePrivate, out SafeBignumHandle qx_bn, out int x_cb, @@ -166,8 +166,8 @@ internal static ECParameters GetECKeyParameters( return parameters; } - [DllImport(Libraries.CryptoNative)] - private static extern int CryptoNative_GetECCurveParameters( + [GeneratedDllImport(Libraries.CryptoNative)] + private static partial int CryptoNative_GetECCurveParameters( SafeEcKeyHandle key, bool includePrivate, out ECCurve.ECCurveType curveType, diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EcDsa.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EcDsa.cs index 9fa5f14055a38..77d7f78048927 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EcDsa.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EcDsa.cs @@ -12,9 +12,9 @@ internal static partial class Crypto internal static bool EcDsaSign(ReadOnlySpan dgst, Span sig, out int siglen, SafeEcKeyHandle ecKey) => EcDsaSign(ref MemoryMarshal.GetReference(dgst), dgst.Length, ref MemoryMarshal.GetReference(sig), out siglen, ecKey); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EcDsaSign")] + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EcDsaSign")] [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool EcDsaSign(ref byte dgst, int dlen, ref byte sig, out int siglen, SafeEcKeyHandle ecKey); + private static partial bool EcDsaSign(ref byte dgst, int dlen, ref byte sig, out int siglen, SafeEcKeyHandle ecKey); internal static int EcDsaVerify(ReadOnlySpan dgst, ReadOnlySpan sigbuf, SafeEcKeyHandle ecKey) { @@ -39,12 +39,12 @@ ref MemoryMarshal.GetReference(sigbuf), * 0: incorrect signature * -1: error */ - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EcDsaVerify")] - private static extern int EcDsaVerify(ref byte dgst, int dgst_len, ref byte sigbuf, int sig_len, SafeEcKeyHandle ecKey); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EcDsaVerify")] + private static partial int EcDsaVerify(ref byte dgst, int dgst_len, ref byte sigbuf, int sig_len, SafeEcKeyHandle ecKey); // returns the maximum length of a DER encoded ECDSA signature created with this key. - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EcDsaSize")] - private static extern int CryptoNative_EcDsaSize(SafeEcKeyHandle ecKey); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EcDsaSize")] + private static partial int CryptoNative_EcDsaSize(SafeEcKeyHandle ecKey); internal static int EcDsaSize(SafeEcKeyHandle ecKey) { diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EcKey.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EcKey.cs index ae841331f1e46..44cc49e07be94 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EcKey.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EcKey.cs @@ -10,8 +10,8 @@ internal static partial class Interop { internal static partial class Crypto { - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EcKeyCreateByOid")] - private static extern SafeEcKeyHandle CryptoNative_EcKeyCreateByOid(string oid); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EcKeyCreateByOid", CharSet = CharSet.Ansi)] + private static partial SafeEcKeyHandle CryptoNative_EcKeyCreateByOid(string oid); internal static SafeEcKeyHandle? EcKeyCreateByOid(string oid) { SafeEcKeyHandle handle = CryptoNative_EcKeyCreateByOid(oid); @@ -26,16 +26,16 @@ internal static partial class Crypto [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EcKeyDestroy")] internal static extern void EcKeyDestroy(IntPtr a); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EcKeyGenerateKey")] + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EcKeyGenerateKey")] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool EcKeyGenerateKey(SafeEcKeyHandle eckey); + internal static partial bool EcKeyGenerateKey(SafeEcKeyHandle eckey); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EcKeyUpRef")] + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EcKeyUpRef")] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool EcKeyUpRef(IntPtr r); + internal static partial bool EcKeyUpRef(IntPtr r); - [DllImport(Libraries.CryptoNative)] - private static extern int CryptoNative_EcKeyGetSize(SafeEcKeyHandle ecKey, out int keySize); + [GeneratedDllImport(Libraries.CryptoNative)] + private static partial int CryptoNative_EcKeyGetSize(SafeEcKeyHandle ecKey, out int keySize); internal static int EcKeyGetSize(SafeEcKeyHandle key) { int keySize; @@ -47,8 +47,8 @@ internal static int EcKeyGetSize(SafeEcKeyHandle key) throw Interop.Crypto.CreateOpenSslCryptographicException(); } - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EcKeyGetCurveName2")] - private static extern int CryptoNative_EcKeyGetCurveName(SafeEcKeyHandle ecKey, out int nid); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EcKeyGetCurveName2")] + private static partial int CryptoNative_EcKeyGetCurveName(SafeEcKeyHandle ecKey, out int nid); internal static string EcKeyGetCurveName(SafeEcKeyHandle key) { diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.Dsa.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.Dsa.cs index 820f300b0641e..cd25db971e2d4 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.Dsa.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.Dsa.cs @@ -9,11 +9,11 @@ internal static partial class Interop { internal static partial class Crypto { - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpPkeyGetDsa")] - internal static extern SafeDsaHandle EvpPkeyGetDsa(SafeEvpPKeyHandle pkey); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpPkeyGetDsa")] + internal static partial SafeDsaHandle EvpPkeyGetDsa(SafeEvpPKeyHandle pkey); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpPkeySetDsa")] + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpPkeySetDsa")] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool EvpPkeySetDsa(SafeEvpPKeyHandle pkey, SafeDsaHandle key); + internal static partial bool EvpPkeySetDsa(SafeEvpPKeyHandle pkey, SafeDsaHandle key); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.EcKey.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.EcKey.cs index 54790cbf1728d..2d61d8b1cad4c 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.EcKey.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.EcKey.cs @@ -9,11 +9,11 @@ internal static partial class Interop { internal static partial class Crypto { - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpPkeyGetEcKey")] - internal static extern SafeEcKeyHandle EvpPkeyGetEcKey(SafeEvpPKeyHandle pkey); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpPkeyGetEcKey")] + internal static partial SafeEcKeyHandle EvpPkeyGetEcKey(SafeEvpPKeyHandle pkey); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpPkeySetEcKey")] + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpPkeySetEcKey")] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool EvpPkeySetEcKey(SafeEvpPKeyHandle pkey, SafeEcKeyHandle key); + internal static partial bool EvpPkeySetEcKey(SafeEvpPKeyHandle pkey, SafeEcKeyHandle key); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.Ecdh.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.Ecdh.cs index 6e87f4e27e78e..a097a5bf31ad5 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.Ecdh.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.Ecdh.cs @@ -11,11 +11,11 @@ internal static partial class Interop { internal static partial class Crypto { - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpPKeyCtxCreate")] - internal static extern SafeEvpPKeyCtxHandle EvpPKeyCtxCreate(SafeEvpPKeyHandle pkey, SafeEvpPKeyHandle peerkey, out uint secretLength); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpPKeyCtxCreate")] + internal static partial SafeEvpPKeyCtxHandle EvpPKeyCtxCreate(SafeEvpPKeyHandle pkey, SafeEvpPKeyHandle peerkey, out uint secretLength); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpPKeyDeriveSecretAgreement")] - private static extern int EvpPKeyDeriveSecretAgreement( + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpPKeyDeriveSecretAgreement")] + private static partial int EvpPKeyDeriveSecretAgreement( ref byte secret, uint secretLength, SafeEvpPKeyCtxHandle ctx); diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.Rsa.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.Rsa.cs index 6437c1a7addc4..523d3f33882c4 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.Rsa.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.Rsa.cs @@ -11,8 +11,8 @@ internal static partial class Interop { internal static partial class Crypto { - [DllImport(Libraries.CryptoNative)] - private static extern SafeEvpPKeyHandle CryptoNative_EvpPKeyCreateRsa(IntPtr rsa); + [GeneratedDllImport(Libraries.CryptoNative)] + private static partial SafeEvpPKeyHandle CryptoNative_EvpPKeyCreateRsa(IntPtr rsa); internal static SafeEvpPKeyHandle EvpPKeyCreateRsa(IntPtr rsa) { @@ -29,8 +29,8 @@ internal static SafeEvpPKeyHandle EvpPKeyCreateRsa(IntPtr rsa) return pkey; } - [DllImport(Libraries.CryptoNative)] - private static extern SafeEvpPKeyHandle CryptoNative_RsaGenerateKey(int keySize); + [GeneratedDllImport(Libraries.CryptoNative)] + private static partial SafeEvpPKeyHandle CryptoNative_RsaGenerateKey(int keySize); internal static SafeEvpPKeyHandle RsaGenerateKey(int keySize) { @@ -45,8 +45,8 @@ internal static SafeEvpPKeyHandle RsaGenerateKey(int keySize) return pkey; } - [DllImport(Libraries.CryptoNative)] - private static extern int CryptoNative_RsaDecrypt( + [GeneratedDllImport(Libraries.CryptoNative)] + private static partial int CryptoNative_RsaDecrypt( SafeEvpPKeyHandle pkey, ref byte source, int sourceLength, @@ -80,8 +80,8 @@ ref MemoryMarshal.GetReference(destination), return written; } - [DllImport(Libraries.CryptoNative)] - private static extern int CryptoNative_RsaEncrypt( + [GeneratedDllImport(Libraries.CryptoNative)] + private static partial int CryptoNative_RsaEncrypt( SafeEvpPKeyHandle pkey, ref byte source, int sourceLength, @@ -115,8 +115,8 @@ ref MemoryMarshal.GetReference(destination), return written; } - [DllImport(Libraries.CryptoNative)] - private static extern int CryptoNative_RsaSignHash( + [GeneratedDllImport(Libraries.CryptoNative)] + private static partial int CryptoNative_RsaSignHash( SafeEvpPKeyHandle pkey, RSASignaturePaddingMode paddingMode, IntPtr digestAlgorithm, @@ -150,8 +150,8 @@ ref MemoryMarshal.GetReference(destination), return written; } - [DllImport(Libraries.CryptoNative)] - private static extern int CryptoNative_RsaVerifyHash( + [GeneratedDllImport(Libraries.CryptoNative)] + private static partial int CryptoNative_RsaVerifyHash( SafeEvpPKeyHandle pkey, RSASignaturePaddingMode paddingMode, IntPtr digestAlgorithm, diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.cs index 924c2da14d4b5..0cea642fcf90b 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.cs @@ -10,8 +10,8 @@ internal static partial class Interop { internal static partial class Crypto { - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpPkeyCreate")] - internal static extern SafeEvpPKeyHandle EvpPkeyCreate(); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpPkeyCreate")] + internal static partial SafeEvpPKeyHandle EvpPkeyCreate(); [DllImport(Libraries.CryptoNative)] private static extern SafeEvpPKeyHandle CryptoNative_EvpPKeyDuplicate( @@ -40,20 +40,20 @@ internal static SafeEvpPKeyHandle EvpPKeyDuplicate( [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpPkeyDestroy")] internal static extern void EvpPkeyDestroy(IntPtr pkey); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpPKeySize")] - internal static extern int EvpPKeySize(SafeEvpPKeyHandle pkey); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpPKeySize")] + internal static partial int EvpPKeySize(SafeEvpPKeyHandle pkey); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_UpRefEvpPkey")] - internal static extern int UpRefEvpPkey(SafeEvpPKeyHandle handle); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_UpRefEvpPkey")] + internal static partial int UpRefEvpPkey(SafeEvpPKeyHandle handle); - [DllImport(Libraries.CryptoNative)] - private static extern unsafe SafeEvpPKeyHandle CryptoNative_DecodeSubjectPublicKeyInfo( + [GeneratedDllImport(Libraries.CryptoNative)] + private static unsafe partial SafeEvpPKeyHandle CryptoNative_DecodeSubjectPublicKeyInfo( byte* buf, int len, int algId); - [DllImport(Libraries.CryptoNative)] - private static extern unsafe SafeEvpPKeyHandle CryptoNative_DecodePkcs8PrivateKey( + [GeneratedDllImport(Libraries.CryptoNative)] + private static unsafe partial SafeEvpPKeyHandle CryptoNative_DecodePkcs8PrivateKey( byte* buf, int len, int algId); diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Hmac.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Hmac.cs index 6074351cf383e..e689be5b60bcc 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Hmac.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Hmac.cs @@ -10,29 +10,29 @@ internal static partial class Interop { internal static partial class Crypto { - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_HmacCreate")] - internal static extern SafeHmacCtxHandle HmacCreate(ref byte key, int keyLen, IntPtr md); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_HmacCreate")] + internal static partial SafeHmacCtxHandle HmacCreate(ref byte key, int keyLen, IntPtr md); [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_HmacDestroy")] internal static extern void HmacDestroy(IntPtr ctx); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_HmacReset")] - internal static extern int HmacReset(SafeHmacCtxHandle ctx); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_HmacReset")] + internal static partial int HmacReset(SafeHmacCtxHandle ctx); internal static int HmacUpdate(SafeHmacCtxHandle ctx, ReadOnlySpan data, int len) => HmacUpdate(ctx, ref MemoryMarshal.GetReference(data), len); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_HmacUpdate")] - private static extern int HmacUpdate(SafeHmacCtxHandle ctx, ref byte data, int len); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_HmacUpdate")] + private static partial int HmacUpdate(SafeHmacCtxHandle ctx, ref byte data, int len); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_HmacFinal")] - internal static extern int HmacFinal(SafeHmacCtxHandle ctx, ref byte data, ref int len); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_HmacFinal")] + internal static partial int HmacFinal(SafeHmacCtxHandle ctx, ref byte data, ref int len); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_HmacCurrent")] - internal static extern int HmacCurrent(SafeHmacCtxHandle ctx, ref byte data, ref int len); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_HmacCurrent")] + internal static partial int HmacCurrent(SafeHmacCtxHandle ctx, ref byte data, ref int len); [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_HmacOneShot")] - private static unsafe extern int HmacOneShot(IntPtr type, byte* key, int keySize, byte* source, int sourceSize, byte* md, ref int mdSize); + private static unsafe extern int HmacOneShot(IntPtr type, byte* key, int keySize, byte* source, int sourceSize, byte* md, int* mdSize); internal static unsafe int HmacOneShot(IntPtr type, ReadOnlySpan key, ReadOnlySpan source, Span destination) { @@ -43,7 +43,7 @@ internal static unsafe int HmacOneShot(IntPtr type, ReadOnlySpan key, Read fixed (byte* pSource = source) fixed (byte* pDestination = destination) { - int result = HmacOneShot(type, pKey, key.Length, pSource, source.Length, pDestination, ref size); + int result = HmacOneShot(type, pKey, key.Length, pSource, source.Length, pDestination, &size); if (result != Success) { diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.LookupFriendlyNameByOid.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.LookupFriendlyNameByOid.cs index f4cdbae5401f9..db1b67c63bcdb 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.LookupFriendlyNameByOid.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.LookupFriendlyNameByOid.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Crypto { - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_LookupFriendlyNameByOid")] - internal static extern int LookupFriendlyNameByOid(string oidValue, ref IntPtr friendlyNamePtr); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_LookupFriendlyNameByOid", CharSet = CharSet.Ansi)] + internal static partial int LookupFriendlyNameByOid(string oidValue, ref IntPtr friendlyNamePtr); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OCSP.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OCSP.cs index edb731fc905d5..c052f5a4c5fe5 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OCSP.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OCSP.cs @@ -15,14 +15,14 @@ internal static partial class Crypto [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_OcspRequestDestroy")] internal static extern void OcspRequestDestroy(IntPtr ocspReq); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetOcspRequestDerSize")] - internal static extern int GetOcspRequestDerSize(SafeOcspRequestHandle req); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetOcspRequestDerSize")] + internal static partial int GetOcspRequestDerSize(SafeOcspRequestHandle req); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EncodeOcspRequest")] - internal static extern int EncodeOcspRequest(SafeOcspRequestHandle req, byte[] buf); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EncodeOcspRequest")] + internal static partial int EncodeOcspRequest(SafeOcspRequestHandle req, byte[] buf); - [DllImport(Libraries.CryptoNative)] - private static extern SafeOcspResponseHandle CryptoNative_DecodeOcspResponse(ref byte buf, int len); + [GeneratedDllImport(Libraries.CryptoNative)] + private static partial SafeOcspResponseHandle CryptoNative_DecodeOcspResponse(ref byte buf, int len); internal static SafeOcspResponseHandle DecodeOcspResponse(ReadOnlySpan buf) { @@ -34,8 +34,8 @@ ref MemoryMarshal.GetReference(buf), [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_OcspResponseDestroy")] internal static extern void OcspResponseDestroy(IntPtr ocspReq); - [DllImport(Libraries.CryptoNative)] - private static extern int CryptoNative_X509ChainGetCachedOcspStatus( + [GeneratedDllImport(Libraries.CryptoNative, CharSet = CharSet.Ansi)] + private static partial int CryptoNative_X509ChainGetCachedOcspStatus( SafeX509StoreCtxHandle ctx, string cachePath, int chainDepth); @@ -53,8 +53,8 @@ internal static X509VerifyStatusCode X509ChainGetCachedOcspStatus(SafeX509StoreC return response; } - [DllImport(Libraries.CryptoNative)] - private static extern int CryptoNative_X509ChainVerifyOcsp( + [GeneratedDllImport(Libraries.CryptoNative, CharSet = CharSet.Ansi)] + private static partial int CryptoNative_X509ChainVerifyOcsp( SafeX509StoreCtxHandle ctx, SafeOcspRequestHandle req, SafeOcspResponseHandle resp, @@ -79,8 +79,8 @@ internal static X509VerifyStatusCode X509ChainVerifyOcsp( return response; } - [DllImport(Libraries.CryptoNative)] - private static extern SafeOcspRequestHandle CryptoNative_X509ChainBuildOcspRequest( + [GeneratedDllImport(Libraries.CryptoNative)] + private static partial SafeOcspRequestHandle CryptoNative_X509ChainBuildOcspRequest( SafeX509StoreCtxHandle storeCtx, int chainDepth); diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Pkcs7.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Pkcs7.cs index 3f9dbf1f8e1fc..657e7cbcda4b9 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Pkcs7.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Pkcs7.cs @@ -9,32 +9,32 @@ internal static partial class Interop { internal static partial class Crypto { - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_PemReadBioPkcs7")] - internal static extern SafePkcs7Handle PemReadBioPkcs7(SafeBioHandle bp); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_PemReadBioPkcs7")] + internal static partial SafePkcs7Handle PemReadBioPkcs7(SafeBioHandle bp); internal static SafePkcs7Handle DecodePkcs7(ReadOnlySpan buf) => DecodePkcs7(ref MemoryMarshal.GetReference(buf), buf.Length); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_DecodePkcs7")] - private static extern SafePkcs7Handle DecodePkcs7(ref byte buf, int len); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_DecodePkcs7")] + private static partial SafePkcs7Handle DecodePkcs7(ref byte buf, int len); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_D2IPkcs7Bio")] - internal static extern SafePkcs7Handle D2IPkcs7Bio(SafeBioHandle bp); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_D2IPkcs7Bio")] + internal static partial SafePkcs7Handle D2IPkcs7Bio(SafeBioHandle bp); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_Pkcs7CreateCertificateCollection")] - internal static extern SafePkcs7Handle Pkcs7CreateCertificateCollection(SafeX509StackHandle certs); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_Pkcs7CreateCertificateCollection")] + internal static partial SafePkcs7Handle Pkcs7CreateCertificateCollection(SafeX509StackHandle certs); [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_Pkcs7Destroy")] internal static extern void Pkcs7Destroy(IntPtr p7); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetPkcs7Certificates")] - private static extern int GetPkcs7Certificates(SafePkcs7Handle p7, out SafeSharedX509StackHandle certs); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetPkcs7Certificates")] + private static partial int GetPkcs7Certificates(SafePkcs7Handle p7, out SafeSharedX509StackHandle certs); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetPkcs7DerSize")] - internal static extern int GetPkcs7DerSize(SafePkcs7Handle p7); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetPkcs7DerSize")] + internal static partial int GetPkcs7DerSize(SafePkcs7Handle p7); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EncodePkcs7")] - internal static extern int EncodePkcs7(SafePkcs7Handle p7, byte[] buf); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EncodePkcs7")] + internal static partial int EncodePkcs7(SafePkcs7Handle p7, byte[] buf); internal static SafeSharedX509StackHandle GetPkcs7Certificates(SafePkcs7Handle p7) { diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.RAND.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.RAND.cs index fc7f8956c4e4d..f01afda233ca6 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.RAND.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.RAND.cs @@ -12,11 +12,10 @@ internal static unsafe bool GetRandomBytes(byte* pbBuffer, int count) { Debug.Assert(count >= 0); - return CryptoNative_GetRandomBytes(pbBuffer, count); + return CryptoNative_GetRandomBytes(pbBuffer, count) != 0; } [DllImport(Libraries.CryptoNative)] - [return: MarshalAs(UnmanagedType.Bool)] - private static extern unsafe bool CryptoNative_GetRandomBytes(byte* buf, int num); + private static extern unsafe int CryptoNative_GetRandomBytes(byte* buf, int num); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Ssl.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Ssl.cs index a73de25354128..a2fdddd69979f 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Ssl.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Ssl.cs @@ -24,39 +24,39 @@ internal static partial class Ssl [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslV2_3Method")] internal static extern IntPtr SslV2_3Method(); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslCreate")] - internal static extern SafeSslHandle SslCreate(SafeSslContextHandle ctx); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslCreate")] + internal static partial SafeSslHandle SslCreate(SafeSslContextHandle ctx); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslGetError")] - internal static extern SslErrorCode SslGetError(SafeSslHandle ssl, int ret); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslGetError")] + internal static partial SslErrorCode SslGetError(SafeSslHandle ssl, int ret); [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslGetError")] internal static extern SslErrorCode SslGetError(IntPtr ssl, int ret); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslSetQuietShutdown")] - internal static extern void SslSetQuietShutdown(SafeSslHandle ssl, int mode); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslSetQuietShutdown")] + internal static partial void SslSetQuietShutdown(SafeSslHandle ssl, int mode); [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslDestroy")] internal static extern void SslDestroy(IntPtr ssl); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslSetConnectState")] - internal static extern void SslSetConnectState(SafeSslHandle ssl); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslSetConnectState")] + internal static partial void SslSetConnectState(SafeSslHandle ssl); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslSetAcceptState")] - internal static extern void SslSetAcceptState(SafeSslHandle ssl); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslSetAcceptState")] + internal static partial void SslSetAcceptState(SafeSslHandle ssl); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslSetAlpnProtos")] - internal static extern int SslSetAlpnProtos(SafeSslHandle ssl, IntPtr protos, int len); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslSetAlpnProtos")] + internal static partial int SslSetAlpnProtos(SafeSslHandle ssl, IntPtr protos, int len); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslGetVersion")] - internal static extern IntPtr SslGetVersion(SafeSslHandle ssl); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslGetVersion")] + internal static partial IntPtr SslGetVersion(SafeSslHandle ssl); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslSetTlsExtHostName")] + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslSetTlsExtHostName", CharSet = CharSet.Ansi)] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool SslSetTlsExtHostName(SafeSslHandle ssl, string host); + internal static partial bool SslSetTlsExtHostName(SafeSslHandle ssl, string host); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslGet0AlpnSelected")] - internal static extern void SslGetAlpnSelected(SafeSslHandle ssl, out IntPtr protocol, out int len); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslGet0AlpnSelected")] + internal static partial void SslGetAlpnSelected(SafeSslHandle ssl, out IntPtr protocol, out int len); internal static byte[]? SslGetAlpnSelected(SafeSslHandle ssl) { @@ -72,67 +72,67 @@ internal static partial class Ssl return result; } - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslWrite", SetLastError = true)] - internal static extern int SslWrite(SafeSslHandle ssl, ref byte buf, int num); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslWrite", SetLastError = true)] + internal static partial int SslWrite(SafeSslHandle ssl, ref byte buf, int num); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslRead", SetLastError = true)] - internal static extern int SslRead(SafeSslHandle ssl, ref byte buf, int num); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslRead", SetLastError = true)] + internal static partial int SslRead(SafeSslHandle ssl, ref byte buf, int num); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslRenegotiate")] - internal static extern int SslRenegotiate(SafeSslHandle ssl); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslRenegotiate")] + internal static partial int SslRenegotiate(SafeSslHandle ssl); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_IsSslRenegotiatePending")] + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_IsSslRenegotiatePending")] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool IsSslRenegotiatePending(SafeSslHandle ssl); + internal static partial bool IsSslRenegotiatePending(SafeSslHandle ssl); [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslShutdown")] internal static extern int SslShutdown(IntPtr ssl); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslShutdown")] - internal static extern int SslShutdown(SafeSslHandle ssl); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslShutdown")] + internal static partial int SslShutdown(SafeSslHandle ssl); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslSetBio")] - internal static extern void SslSetBio(SafeSslHandle ssl, SafeBioHandle rbio, SafeBioHandle wbio); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslSetBio")] + internal static partial void SslSetBio(SafeSslHandle ssl, SafeBioHandle rbio, SafeBioHandle wbio); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslDoHandshake", SetLastError = true)] - internal static extern int SslDoHandshake(SafeSslHandle ssl); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslDoHandshake", SetLastError = true)] + internal static partial int SslDoHandshake(SafeSslHandle ssl); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_IsSslStateOK")] + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_IsSslStateOK")] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool IsSslStateOK(SafeSslHandle ssl); + internal static partial bool IsSslStateOK(SafeSslHandle ssl); // NOTE: this is just an (unsafe) overload to the BioWrite method from Interop.Bio.cs. - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_BioWrite")] - internal static extern unsafe int BioWrite(SafeBioHandle b, byte* data, int len); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_BioWrite")] + internal static unsafe partial int BioWrite(SafeBioHandle b, byte* data, int len); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_BioWrite")] - internal static extern int BioWrite(SafeBioHandle b, ref byte data, int len); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_BioWrite")] + internal static partial int BioWrite(SafeBioHandle b, ref byte data, int len); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslGetPeerCertificate")] - internal static extern SafeX509Handle SslGetPeerCertificate(SafeSslHandle ssl); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslGetPeerCertificate")] + internal static partial SafeX509Handle SslGetPeerCertificate(SafeSslHandle ssl); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslGetPeerCertChain")] - internal static extern SafeSharedX509StackHandle SslGetPeerCertChain(SafeSslHandle ssl); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslGetPeerCertChain")] + internal static partial SafeSharedX509StackHandle SslGetPeerCertChain(SafeSslHandle ssl); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslGetPeerFinished")] - internal static extern int SslGetPeerFinished(SafeSslHandle ssl, IntPtr buf, int count); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslGetPeerFinished")] + internal static partial int SslGetPeerFinished(SafeSslHandle ssl, IntPtr buf, int count); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslGetFinished")] - internal static extern int SslGetFinished(SafeSslHandle ssl, IntPtr buf, int count); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslGetFinished")] + internal static partial int SslGetFinished(SafeSslHandle ssl, IntPtr buf, int count); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslSessionReused")] + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslSessionReused")] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool SslSessionReused(SafeSslHandle ssl); + internal static partial bool SslSessionReused(SafeSslHandle ssl); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslGetClientCAList")] - private static extern SafeSharedX509NameStackHandle SslGetClientCAList_private(SafeSslHandle ssl); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslGetClientCAList")] + private static partial SafeSharedX509NameStackHandle SslGetClientCAList_private(SafeSslHandle ssl); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslGetCurrentCipherId")] + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslGetCurrentCipherId")] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool SslGetCurrentCipherId(SafeSslHandle ssl, out int cipherId); + internal static partial bool SslGetCurrentCipherId(SafeSslHandle ssl, out int cipherId); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetOpenSslCipherSuiteName")] - private static extern IntPtr GetOpenSslCipherSuiteName(SafeSslHandle ssl, int cipherSuite, out int isTls12OrLower); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetOpenSslCipherSuiteName")] + private static partial IntPtr GetOpenSslCipherSuiteName(SafeSslHandle ssl, int cipherSuite, out int isTls12OrLower); [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SetCiphers")] internal static extern unsafe bool SslSetCiphers(SafeSslHandle ssl, byte* cipherList, byte* cipherSuites); @@ -191,9 +191,8 @@ internal static byte[] ConvertAlpnProtocolListToByteArray(List callback, IntPtr arg); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslCtxSetAlpnSelectCb")] + internal static unsafe partial void SslCtxSetAlpnSelectCb(SafeSslContextHandle ctx, delegate* unmanaged callback, IntPtr arg); internal static bool AddExtraChainCertificates(SafeSslContextHandle ctx, X509Certificate2[] chain) { diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.SslCtxOptions.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.SslCtxOptions.cs index 60c81072325c6..364ed6e933c7c 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.SslCtxOptions.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.SslCtxOptions.cs @@ -11,28 +11,28 @@ internal static partial class Interop { internal static partial class Ssl { - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslCtxAddExtraChainCert")] - internal static extern bool SslCtxAddExtraChainCert(SafeSslContextHandle ctx, SafeX509Handle x509); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslCtxAddExtraChainCert")] + internal static partial bool SslCtxAddExtraChainCert(SafeSslContextHandle ctx, SafeX509Handle x509); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslCtxUseCertificate")] - internal static extern int SslCtxUseCertificate(SafeSslContextHandle ctx, SafeX509Handle certPtr); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslCtxUseCertificate")] + internal static partial int SslCtxUseCertificate(SafeSslContextHandle ctx, SafeX509Handle certPtr); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslCtxUsePrivateKey")] - internal static extern int SslCtxUsePrivateKey(SafeSslContextHandle ctx, SafeEvpPKeyHandle keyPtr); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslCtxUsePrivateKey")] + internal static partial int SslCtxUsePrivateKey(SafeSslContextHandle ctx, SafeEvpPKeyHandle keyPtr); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslCtxCheckPrivateKey")] - internal static extern int SslCtxCheckPrivateKey(SafeSslContextHandle ctx); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslCtxCheckPrivateKey")] + internal static partial int SslCtxCheckPrivateKey(SafeSslContextHandle ctx); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslCtxSetQuietShutdown")] - internal static extern void SslCtxSetQuietShutdown(SafeSslContextHandle ctx); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslCtxSetQuietShutdown")] + internal static partial void SslCtxSetQuietShutdown(SafeSslContextHandle ctx); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslCtxSetVerify")] - internal static extern unsafe void SslCtxSetVerify(SafeSslContextHandle ctx, delegate* unmanaged callback); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslCtxSetVerify")] + internal static unsafe partial void SslCtxSetVerify(SafeSslContextHandle ctx, delegate* unmanaged callback); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslCtxSetCiphers")] - internal static extern unsafe bool SslCtxSetCiphers(SafeSslContextHandle ctx, byte* cipherList, byte* cipherSuites); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslCtxSetCiphers")] + internal static unsafe partial bool SslCtxSetCiphers(SafeSslContextHandle ctx, byte* cipherList, byte* cipherSuites); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslCtxSetEncryptionPolicy")] - internal static extern bool SetEncryptionPolicy(SafeSslContextHandle ctx, EncryptionPolicy policy); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SslCtxSetEncryptionPolicy")] + internal static partial bool SetEncryptionPolicy(SafeSslContextHandle ctx, EncryptionPolicy policy); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.X509.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.X509.cs index 00df24b9dae30..6e3775df4bf6a 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.X509.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.X509.cs @@ -14,38 +14,38 @@ internal static partial class Crypto { internal delegate int X509StoreVerifyCallback(int ok, IntPtr ctx); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509NotBefore")] - internal static extern IntPtr GetX509NotBefore(SafeX509Handle x509); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509NotBefore")] + internal static partial IntPtr GetX509NotBefore(SafeX509Handle x509); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509NotAfter")] - internal static extern IntPtr GetX509NotAfter(SafeX509Handle x509); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509NotAfter")] + internal static partial IntPtr GetX509NotAfter(SafeX509Handle x509); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509SignatureAlgorithm")] - internal static extern IntPtr GetX509SignatureAlgorithm(SafeX509Handle x509); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509SignatureAlgorithm")] + internal static partial IntPtr GetX509SignatureAlgorithm(SafeX509Handle x509); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509PublicKeyAlgorithm")] - internal static extern IntPtr GetX509PublicKeyAlgorithm(SafeX509Handle x509); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509PublicKeyAlgorithm")] + internal static partial IntPtr GetX509PublicKeyAlgorithm(SafeX509Handle x509); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509PublicKeyBytes")] - internal static extern IntPtr GetX509PublicKeyBytes(SafeX509Handle x509); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509PublicKeyBytes")] + internal static partial IntPtr GetX509PublicKeyBytes(SafeX509Handle x509); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509EvpPublicKey")] - internal static extern SafeEvpPKeyHandle GetX509EvpPublicKey(SafeX509Handle x509); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509EvpPublicKey")] + internal static partial SafeEvpPKeyHandle GetX509EvpPublicKey(SafeX509Handle x509); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_DecodeX509Crl")] - internal static extern SafeX509CrlHandle DecodeX509Crl(byte[] buf, int len); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_DecodeX509Crl")] + internal static partial SafeX509CrlHandle DecodeX509Crl(byte[] buf, int len); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_DecodeX509")] - internal static extern SafeX509Handle DecodeX509(ref byte buf, int len); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_DecodeX509")] + internal static partial SafeX509Handle DecodeX509(ref byte buf, int len); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_DecodeX509")] - internal static extern SafeX509Handle DecodeX509(IntPtr buf, int len); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_DecodeX509")] + internal static partial SafeX509Handle DecodeX509(IntPtr buf, int len); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509DerSize")] - internal static extern int GetX509DerSize(SafeX509Handle x); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509DerSize")] + internal static partial int GetX509DerSize(SafeX509Handle x); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EncodeX509")] - internal static extern int EncodeX509(SafeX509Handle x, byte[] buf); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EncodeX509")] + internal static partial int EncodeX509(SafeX509Handle x, byte[] buf); [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509Destroy")] internal static extern void X509Destroy(IntPtr a); @@ -53,37 +53,37 @@ internal static partial class Crypto /// /// Clone the input certificate into a new object. /// - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509Duplicate")] - internal static extern SafeX509Handle X509Duplicate(IntPtr handle); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509Duplicate")] + internal static partial SafeX509Handle X509Duplicate(IntPtr handle); /// /// Clone the input certificate into a new object. /// - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509Duplicate")] - internal static extern SafeX509Handle X509Duplicate(SafeX509Handle handle); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509Duplicate")] + internal static partial SafeX509Handle X509Duplicate(SafeX509Handle handle); /// /// Increment the native reference count of the certificate to protect against /// a free from another pointer-holder. /// - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509UpRef")] - internal static extern SafeX509Handle X509UpRef(IntPtr handle); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509UpRef")] + internal static partial SafeX509Handle X509UpRef(IntPtr handle); /// /// Increment the native reference count of the certificate to protect against /// a free from another pointer-holder. /// - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509UpRef")] - internal static extern SafeX509Handle X509UpRef(SafeX509Handle handle); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509UpRef")] + internal static partial SafeX509Handle X509UpRef(SafeX509Handle handle); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_PemReadX509FromBio")] - internal static extern SafeX509Handle PemReadX509FromBio(SafeBioHandle bio); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_PemReadX509FromBio")] + internal static partial SafeX509Handle PemReadX509FromBio(SafeBioHandle bio); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_PemReadX509FromBioAux")] - internal static extern SafeX509Handle PemReadX509FromBioAux(SafeBioHandle bio); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_PemReadX509FromBioAux")] + internal static partial SafeX509Handle PemReadX509FromBioAux(SafeBioHandle bio); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509GetSerialNumber")] - private static extern SafeSharedAsn1IntegerHandle X509GetSerialNumber_private(SafeX509Handle x); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509GetSerialNumber")] + private static partial SafeSharedAsn1IntegerHandle X509GetSerialNumber_private(SafeX509Handle x); internal static SafeSharedAsn1IntegerHandle X509GetSerialNumber(SafeX509Handle x) { @@ -94,21 +94,21 @@ internal static SafeSharedAsn1IntegerHandle X509GetSerialNumber(SafeX509Handle x x); } - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509GetIssuerName")] - internal static extern IntPtr X509GetIssuerName(SafeX509Handle x); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509GetIssuerName")] + internal static partial IntPtr X509GetIssuerName(SafeX509Handle x); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509GetSubjectName")] - internal static extern IntPtr X509GetSubjectName(SafeX509Handle x); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509GetSubjectName")] + internal static partial IntPtr X509GetSubjectName(SafeX509Handle x); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509CheckPurpose")] + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509CheckPurpose")] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool X509CheckPurpose(SafeX509Handle x, int id, int ca); + internal static partial bool X509CheckPurpose(SafeX509Handle x, int id, int ca); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509IssuerNameHash")] - internal static extern ulong X509IssuerNameHash(SafeX509Handle x); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509IssuerNameHash")] + internal static partial ulong X509IssuerNameHash(SafeX509Handle x); - [DllImport(Libraries.CryptoNative)] - private static extern SafeSharedAsn1OctetStringHandle CryptoNative_X509FindExtensionData( + [GeneratedDllImport(Libraries.CryptoNative)] + private static partial SafeSharedAsn1OctetStringHandle CryptoNative_X509FindExtensionData( SafeX509Handle x, int extensionNid); @@ -122,13 +122,13 @@ internal static SafeSharedAsn1OctetStringHandle X509FindExtensionData(SafeX509Ha extensionNid); } - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509GetExtCount")] - internal static extern int X509GetExtCount(SafeX509Handle x); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509GetExtCount")] + internal static partial int X509GetExtCount(SafeX509Handle x); // Returns a pointer already being tracked by the SafeX509Handle, shouldn't be SafeHandle tracked/freed. // Bounds checking is in place for "loc", IntPtr.Zero is returned on violations. - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509GetExt")] - internal static extern IntPtr X509GetExt(SafeX509Handle x, int loc); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509GetExt")] + internal static partial IntPtr X509GetExt(SafeX509Handle x, int loc); // Returns a pointer already being tracked by a SafeX509Handle, shouldn't be SafeHandle tracked/freed. [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509ExtensionGetOid")] @@ -138,12 +138,12 @@ internal static SafeSharedAsn1OctetStringHandle X509FindExtensionData(SafeX509Ha [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509ExtensionGetData")] internal static extern IntPtr X509ExtensionGetData(IntPtr ex); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509ExtensionGetCritical")] + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509ExtensionGetCritical")] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool X509ExtensionGetCritical(IntPtr ex); + internal static partial bool X509ExtensionGetCritical(IntPtr ex); - [DllImport(Libraries.CryptoNative)] - private static extern SafeX509StoreHandle CryptoNative_X509ChainNew(SafeX509StackHandle systemTrust, SafeX509StackHandle userTrust); + [GeneratedDllImport(Libraries.CryptoNative)] + private static partial SafeX509StoreHandle CryptoNative_X509ChainNew(SafeX509StackHandle systemTrust, SafeX509StackHandle userTrust); internal static SafeX509StoreHandle X509ChainNew(SafeX509StackHandle systemTrust, SafeX509StackHandle userTrust) { @@ -160,13 +160,13 @@ internal static SafeX509StoreHandle X509ChainNew(SafeX509StackHandle systemTrust [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509StoreDestory")] internal static extern void X509StoreDestory(IntPtr v); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509StoreAddCrl")] + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509StoreAddCrl")] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool X509StoreAddCrl(SafeX509StoreHandle ctx, SafeX509CrlHandle x); + internal static partial bool X509StoreAddCrl(SafeX509StoreHandle ctx, SafeX509CrlHandle x); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509StoreSetRevocationFlag")] + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509StoreSetRevocationFlag")] [return: MarshalAs(UnmanagedType.Bool)] - private static extern bool CryptoNative_X509StoreSetRevocationFlag(SafeX509StoreHandle ctx, X509RevocationFlag revocationFlag); + private static partial bool CryptoNative_X509StoreSetRevocationFlag(SafeX509StoreHandle ctx, X509RevocationFlag revocationFlag); internal static void X509StoreSetRevocationFlag(SafeX509StoreHandle ctx, X509RevocationFlag revocationFlag) { @@ -176,16 +176,16 @@ internal static void X509StoreSetRevocationFlag(SafeX509StoreHandle ctx, X509Rev } } - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509StoreCtxInit")] + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509StoreCtxInit")] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool X509StoreCtxInit( + internal static partial bool X509StoreCtxInit( SafeX509StoreCtxHandle ctx, SafeX509StoreHandle store, SafeX509Handle x509, SafeX509StackHandle extraCerts); - [DllImport(Libraries.CryptoNative)] - private static extern int CryptoNative_X509VerifyCert(SafeX509StoreCtxHandle ctx); + [GeneratedDllImport(Libraries.CryptoNative)] + private static partial int CryptoNative_X509VerifyCert(SafeX509StoreCtxHandle ctx); internal static bool X509VerifyCert(SafeX509StoreCtxHandle ctx) { @@ -199,16 +199,16 @@ internal static bool X509VerifyCert(SafeX509StoreCtxHandle ctx) return result != 0; } - [DllImport(Libraries.CryptoNative)] - internal static extern int CryptoNative_X509StoreCtxGetError(SafeX509StoreCtxHandle ctx); + [GeneratedDllImport(Libraries.CryptoNative)] + internal static partial int CryptoNative_X509StoreCtxGetError(SafeX509StoreCtxHandle ctx); internal static X509VerifyStatusCode X509StoreCtxGetError(SafeX509StoreCtxHandle ctx) { return (X509VerifyStatusCode)CryptoNative_X509StoreCtxGetError(ctx); } - [DllImport(Libraries.CryptoNative)] - private static extern int CryptoNative_X509StoreCtxReset(SafeX509StoreCtxHandle ctx); + [GeneratedDllImport(Libraries.CryptoNative)] + private static partial int CryptoNative_X509StoreCtxReset(SafeX509StoreCtxHandle ctx); internal static void X509StoreCtxReset(SafeX509StoreCtxHandle ctx) { @@ -218,8 +218,8 @@ internal static void X509StoreCtxReset(SafeX509StoreCtxHandle ctx) } } - [DllImport(Libraries.CryptoNative)] - private static extern int CryptoNative_X509StoreCtxRebuildChain(SafeX509StoreCtxHandle ctx); + [GeneratedDllImport(Libraries.CryptoNative)] + private static partial int CryptoNative_X509StoreCtxRebuildChain(SafeX509StoreCtxHandle ctx); internal static bool X509StoreCtxRebuildChain(SafeX509StoreCtxHandle ctx) { @@ -233,11 +233,11 @@ internal static bool X509StoreCtxRebuildChain(SafeX509StoreCtxHandle ctx) return result != 0; } - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509StoreCtxGetErrorDepth")] - internal static extern int X509StoreCtxGetErrorDepth(SafeX509StoreCtxHandle ctx); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509StoreCtxGetErrorDepth")] + internal static partial int X509StoreCtxGetErrorDepth(SafeX509StoreCtxHandle ctx); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509StoreCtxSetVerifyCallback")] - internal static extern void X509StoreCtxSetVerifyCallback(SafeX509StoreCtxHandle ctx, X509StoreVerifyCallback callback); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509StoreCtxSetVerifyCallback")] + internal static partial void X509StoreCtxSetVerifyCallback(SafeX509StoreCtxHandle ctx, X509StoreVerifyCallback callback); internal static string GetX509VerifyCertErrorString(int n) { @@ -250,17 +250,17 @@ internal static string GetX509VerifyCertErrorString(int n) [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509CrlDestroy")] internal static extern void X509CrlDestroy(IntPtr a); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_PemWriteBioX509Crl")] - internal static extern int PemWriteBioX509Crl(SafeBioHandle bio, SafeX509CrlHandle crl); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_PemWriteBioX509Crl")] + internal static partial int PemWriteBioX509Crl(SafeBioHandle bio, SafeX509CrlHandle crl); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_PemReadBioX509Crl")] - internal static extern SafeX509CrlHandle PemReadBioX509Crl(SafeBioHandle bio); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_PemReadBioX509Crl")] + internal static partial SafeX509CrlHandle PemReadBioX509Crl(SafeBioHandle bio); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509SubjectPublicKeyInfoDerSize")] - internal static extern int GetX509SubjectPublicKeyInfoDerSize(SafeX509Handle x509); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509SubjectPublicKeyInfoDerSize")] + internal static partial int GetX509SubjectPublicKeyInfoDerSize(SafeX509Handle x509); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EncodeX509SubjectPublicKeyInfo")] - internal static extern int EncodeX509SubjectPublicKeyInfo(SafeX509Handle x509, byte[] buf); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EncodeX509SubjectPublicKeyInfo")] + internal static partial int EncodeX509SubjectPublicKeyInfo(SafeX509Handle x509, byte[] buf); internal enum X509VerifyStatusCodeUniversal { diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.X509Ext.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.X509Ext.cs index b3374cdf934c8..f3d47ec4c293a 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.X509Ext.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.X509Ext.cs @@ -9,8 +9,8 @@ internal static partial class Interop { internal static partial class Crypto { - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509ExtensionCreateByObj")] - internal static extern SafeX509ExtensionHandle X509ExtensionCreateByObj( + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509ExtensionCreateByObj")] + internal static partial SafeX509ExtensionHandle X509ExtensionCreateByObj( SafeAsn1ObjectHandle oid, [MarshalAs(UnmanagedType.Bool)] bool isCritical, SafeAsn1OctetStringHandle data); @@ -18,21 +18,21 @@ internal static extern SafeX509ExtensionHandle X509ExtensionCreateByObj( [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509ExtensionDestroy")] internal static extern int X509ExtensionDestroy(IntPtr x); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509V3ExtPrint")] + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509V3ExtPrint")] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool X509V3ExtPrint(SafeBioHandle buf, SafeX509ExtensionHandle ext); + internal static partial bool X509V3ExtPrint(SafeBioHandle buf, SafeX509ExtensionHandle ext); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_DecodeX509BasicConstraints2Extension")] + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_DecodeX509BasicConstraints2Extension")] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool DecodeX509BasicConstraints2Extension( + internal static partial bool DecodeX509BasicConstraints2Extension( byte[] encoded, int encodedLength, [MarshalAs(UnmanagedType.Bool)] out bool certificateAuthority, [MarshalAs(UnmanagedType.Bool)] out bool hasPathLengthConstraint, out int pathLengthConstraint); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_DecodeExtendedKeyUsage")] - internal static extern SafeEkuExtensionHandle DecodeExtendedKeyUsage(byte[] buf, int len); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_DecodeExtendedKeyUsage")] + internal static partial SafeEkuExtensionHandle DecodeExtendedKeyUsage(byte[] buf, int len); [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_ExtendedKeyUsageDestory")] internal static extern void ExtendedKeyUsageDestory(IntPtr a); diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.X509Name.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.X509Name.cs index ad2b0fefc2404..17aeb1559a1a4 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.X509Name.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.X509Name.cs @@ -10,15 +10,15 @@ internal static partial class Interop { internal static partial class Crypto { - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509NameStackFieldCount")] - internal static extern int GetX509NameStackFieldCount(SafeSharedX509NameStackHandle sk); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509NameStackFieldCount")] + internal static partial int GetX509NameStackFieldCount(SafeSharedX509NameStackHandle sk); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509NameStackField")] - private static extern SafeSharedX509NameHandle GetX509NameStackField_private(SafeSharedX509NameStackHandle sk, + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509NameStackField")] + private static partial SafeSharedX509NameHandle GetX509NameStackField_private(SafeSharedX509NameStackHandle sk, int loc); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509NameRawBytes")] - private static extern int GetX509NameRawBytes(SafeSharedX509NameHandle x509Name, byte[]? buf, int cBuf); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509NameRawBytes")] + private static partial int GetX509NameRawBytes(SafeSharedX509NameHandle x509Name, byte[]? buf, int cBuf); internal static X500DistinguishedName LoadX500Name(SafeSharedX509NameHandle namePtr) { diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.X509Stack.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.X509Stack.cs index c3468042c0c69..2bf09b7eb9f50 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.X509Stack.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.X509Stack.cs @@ -9,34 +9,34 @@ internal static partial class Interop { internal static partial class Crypto { - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_NewX509Stack")] - internal static extern SafeX509StackHandle NewX509Stack(); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_NewX509Stack")] + internal static partial SafeX509StackHandle NewX509Stack(); [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_RecursiveFreeX509Stack")] internal static extern void RecursiveFreeX509Stack(IntPtr stack); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509StackFieldCount")] - internal static extern int GetX509StackFieldCount(SafeX509StackHandle stack); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509StackFieldCount")] + internal static partial int GetX509StackFieldCount(SafeX509StackHandle stack); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509StackFieldCount")] - internal static extern int GetX509StackFieldCount(SafeSharedX509StackHandle stack); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509StackFieldCount")] + internal static partial int GetX509StackFieldCount(SafeSharedX509StackHandle stack); /// /// Gets a pointer to a certificate within a STACK_OF(X509). This pointer will later /// be freed, so it should be cloned via new X509Certificate2(IntPtr) /// - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509StackField")] - internal static extern IntPtr GetX509StackField(SafeX509StackHandle stack, int loc); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509StackField")] + internal static partial IntPtr GetX509StackField(SafeX509StackHandle stack, int loc); /// /// Gets a pointer to a certificate within a STACK_OF(X509). This pointer will later /// be freed, so it should be cloned via new X509Certificate2(IntPtr) /// - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509StackField")] - internal static extern IntPtr GetX509StackField(SafeSharedX509StackHandle stack, int loc); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetX509StackField")] + internal static partial IntPtr GetX509StackField(SafeSharedX509StackHandle stack, int loc); - [DllImport(Libraries.CryptoNative)] - private static extern int CryptoNative_X509StackAddDirectoryStore(SafeX509StackHandle stack, string storePath); + [GeneratedDllImport(Libraries.CryptoNative, CharSet = CharSet.Ansi)] + private static partial int CryptoNative_X509StackAddDirectoryStore(SafeX509StackHandle stack, string storePath); internal static void X509StackAddDirectoryStore(SafeX509StackHandle stack, string storePath) { @@ -46,8 +46,8 @@ internal static void X509StackAddDirectoryStore(SafeX509StackHandle stack, strin } } - [DllImport(Libraries.CryptoNative)] - private static extern int CryptoNative_X509StackAddMultiple(SafeX509StackHandle dest, SafeX509StackHandle src); + [GeneratedDllImport(Libraries.CryptoNative)] + private static partial int CryptoNative_X509StackAddMultiple(SafeX509StackHandle dest, SafeX509StackHandle src); internal static void X509StackAddMultiple(SafeX509StackHandle dest, SafeX509StackHandle src) { diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.X509StoreCtx.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.X509StoreCtx.cs index 0b652965784e8..8325165c5cfa8 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.X509StoreCtx.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.X509StoreCtx.cs @@ -9,20 +9,20 @@ internal static partial class Interop { internal static partial class Crypto { - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509StoreCtxCreate")] - internal static extern SafeX509StoreCtxHandle X509StoreCtxCreate(); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509StoreCtxCreate")] + internal static partial SafeX509StoreCtxHandle X509StoreCtxCreate(); [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509StoreCtxDestroy")] internal static extern void X509StoreCtxDestroy(IntPtr v); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509StoreCtxGetChain")] - internal static extern SafeX509StackHandle X509StoreCtxGetChain(SafeX509StoreCtxHandle ctx); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509StoreCtxGetChain")] + internal static partial SafeX509StackHandle X509StoreCtxGetChain(SafeX509StoreCtxHandle ctx); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509StoreCtxGetCurrentCert")] - internal static extern SafeX509Handle X509StoreCtxGetCurrentCert(SafeX509StoreCtxHandle ctx); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509StoreCtxGetCurrentCert")] + internal static partial SafeX509Handle X509StoreCtxGetCurrentCert(SafeX509StoreCtxHandle ctx); - [DllImport(Libraries.CryptoNative)] - private static extern int CryptoNative_X509StoreCtxCommitToChain(SafeX509StoreCtxHandle ctx); + [GeneratedDllImport(Libraries.CryptoNative)] + private static partial int CryptoNative_X509StoreCtxCommitToChain(SafeX509StoreCtxHandle ctx); internal static void X509StoreCtxCommitToChain(SafeX509StoreCtxHandle ctx) { @@ -32,8 +32,8 @@ internal static void X509StoreCtxCommitToChain(SafeX509StoreCtxHandle ctx) } } - [DllImport(Libraries.CryptoNative)] - private static extern int CryptoNative_X509StoreCtxResetForSignatureError( + [GeneratedDllImport(Libraries.CryptoNative)] + private static partial int CryptoNative_X509StoreCtxResetForSignatureError( SafeX509StoreCtxHandle ctx, out SafeX509StoreHandle newStore); @@ -55,11 +55,11 @@ internal static void X509StoreCtxResetForSignatureError( } } - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509StoreCtxGetSharedUntrusted")] - private static extern SafeSharedX509StackHandle X509StoreCtxGetSharedUntrusted_private(SafeX509StoreCtxHandle ctx); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509StoreCtxGetSharedUntrusted")] + private static partial SafeSharedX509StackHandle X509StoreCtxGetSharedUntrusted_private(SafeX509StoreCtxHandle ctx); - [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509StoreCtxGetTargetCert")] - internal static extern IntPtr X509StoreCtxGetTargetCert(SafeX509StoreCtxHandle ctx); + [GeneratedDllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_X509StoreCtxGetTargetCert")] + internal static partial IntPtr X509StoreCtxGetTargetCert(SafeX509StoreCtxHandle ctx); internal static SafeSharedX509StackHandle X509StoreCtxGetSharedUntrusted(SafeX509StoreCtxHandle ctx) { diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.AdjustTokenPrivileges.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.AdjustTokenPrivileges.cs index b93d0660e61ab..5a3faa36313b3 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.AdjustTokenPrivileges.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.AdjustTokenPrivileges.cs @@ -9,8 +9,13 @@ internal static partial class Interop { internal static partial class Advapi32 { +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Advapi32, SetLastError = true)] + internal static unsafe partial bool AdjustTokenPrivileges( +#else [DllImport(Libraries.Advapi32, SetLastError = true)] internal static extern unsafe bool AdjustTokenPrivileges( +#endif SafeTokenHandle TokenHandle, bool DisableAllPrivileges, TOKEN_PRIVILEGE* NewState, diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.AllocateLocallyUniqueId.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.AllocateLocallyUniqueId.cs index 689f8328d5207..e587b759d45fd 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.AllocateLocallyUniqueId.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.AllocateLocallyUniqueId.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Advapi32 { - [DllImport(Libraries.Advapi32)] - internal static extern bool AllocateLocallyUniqueId(out LUID Luid); + [GeneratedDllImport(Libraries.Advapi32)] + internal static unsafe partial bool AllocateLocallyUniqueId(LUID* Luid); } } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CheckTokenMembership.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CheckTokenMembership.cs index 1af4dba20107b..44cd007990090 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CheckTokenMembership.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CheckTokenMembership.cs @@ -9,7 +9,15 @@ internal static partial class Interop { internal static partial class Advapi32 { +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.Advapi32, SetLastError = true)] + internal static partial bool CheckTokenMembership( +#else [DllImport(Interop.Libraries.Advapi32, SetLastError = true)] - internal static extern bool CheckTokenMembership(SafeAccessTokenHandle TokenHandle, byte[] SidToCheck, ref bool IsMember); + internal static extern bool CheckTokenMembership( +#endif + SafeAccessTokenHandle TokenHandle, + byte[] SidToCheck, + ref bool IsMember); } } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.ConvertSdToStringSd.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.ConvertSdToStringSd.cs index 6240d410105e5..a675aed0aefb9 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.ConvertSdToStringSd.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.ConvertSdToStringSd.cs @@ -8,9 +8,15 @@ internal static partial class Interop { internal static partial class Advapi32 { +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.Advapi32, EntryPoint = "ConvertSecurityDescriptorToStringSecurityDescriptorW", + CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] + internal static partial bool ConvertSdToStringSd( +#else [DllImport(Interop.Libraries.Advapi32, EntryPoint = "ConvertSecurityDescriptorToStringSecurityDescriptorW", - CallingConvention = CallingConvention.Winapi, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)] + CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] internal static extern bool ConvertSdToStringSd( +#endif byte[] securityDescriptor, /* DWORD */ uint requestedRevision, uint securityInformation, diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.ConvertStringSdToSd.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.ConvertStringSdToSd.cs index 5eb7023aad824..7e0aa27470b8b 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.ConvertStringSdToSd.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.ConvertStringSdToSd.cs @@ -8,9 +8,15 @@ internal static partial class Interop { internal static partial class Advapi32 { +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.Advapi32, EntryPoint = "ConvertStringSecurityDescriptorToSecurityDescriptorW", + CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] + internal static partial bool ConvertStringSdToSd( +#else [DllImport(Interop.Libraries.Advapi32, EntryPoint = "ConvertStringSecurityDescriptorToSecurityDescriptorW", - CallingConvention = CallingConvention.Winapi, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)] + CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] internal static extern bool ConvertStringSdToSd( +#endif string stringSd, /* DWORD */ uint stringSdRevision, out IntPtr resultSd, diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.ConvertStringSidToSid.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.ConvertStringSidToSid.cs index 39a9559f4f4a0..63f5b0a0d44c5 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.ConvertStringSidToSid.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.ConvertStringSidToSid.cs @@ -8,7 +8,14 @@ internal static partial class Interop { internal static partial class Advapi32 { - [DllImport(Interop.Libraries.Advapi32, EntryPoint = "ConvertStringSidToSidW", SetLastError = true, CharSet = CharSet.Unicode)] - internal static extern int ConvertStringSidToSid(string stringSid, out IntPtr ByteArray); +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.Advapi32, EntryPoint = "ConvertStringSidToSidW", CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial int ConvertStringSidToSid( +#else + [DllImport(Interop.Libraries.Advapi32, EntryPoint = "ConvertStringSidToSidW", CharSet = CharSet.Unicode, SetLastError = true)] + internal static extern int ConvertStringSidToSid( +#endif + string stringSid, + out IntPtr ByteArray); } } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CreateProcessWithLogon.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CreateProcessWithLogon.cs index 60f2745df3d6c..a8bf04dae447b 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CreateProcessWithLogon.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CreateProcessWithLogon.cs @@ -9,8 +9,8 @@ internal static partial class Interop { internal static partial class Advapi32 { - [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true, BestFitMapping = false, EntryPoint = "CreateProcessWithLogonW")] - internal static extern unsafe bool CreateProcessWithLogonW( + [GeneratedDllImport(Libraries.Advapi32, EntryPoint = "CreateProcessWithLogonW", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] + internal static unsafe partial bool CreateProcessWithLogonW( string userName, string domain, IntPtr password, diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CreateWellKnownSid.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CreateWellKnownSid.cs index 132f4a3e5846f..69c014a936236 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CreateWellKnownSid.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CreateWellKnownSid.cs @@ -8,7 +8,16 @@ internal static partial class Interop { internal static partial class Advapi32 { - [DllImport(Interop.Libraries.Advapi32, EntryPoint = "CreateWellKnownSid", SetLastError = true, CharSet = CharSet.Unicode)] - internal static extern int CreateWellKnownSid(int sidType, byte[]? domainSid, byte[] resultSid, ref uint resultSidLength); +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.Advapi32, EntryPoint = "CreateWellKnownSid", CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial int CreateWellKnownSid( +#else + [DllImport(Interop.Libraries.Advapi32, EntryPoint = "CreateWellKnownSid", CharSet = CharSet.Unicode, SetLastError = true)] + internal static extern int CreateWellKnownSid( +#endif + int sidType, + byte[]? domainSid, + byte[] resultSid, + ref uint resultSidLength); } } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptAcquireContext.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptAcquireContext.cs index 903733feee10d..d45b7e14e9200 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptAcquireContext.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptAcquireContext.cs @@ -20,8 +20,13 @@ internal enum CryptAcquireContextFlags : uint CRYPT_VERIFYCONTEXT = 0xF0000000 // CRYPT_VERIFYCONTEXT } - [DllImport(Libraries.Advapi32, SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "CryptAcquireContextW")] +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Advapi32, EntryPoint = "CryptAcquireContextW", CharSet = CharSet.Unicode, SetLastError = true)] + public static partial bool CryptAcquireContext( +#else + [DllImport(Libraries.Advapi32, EntryPoint = "CryptAcquireContextW", CharSet = CharSet.Unicode, SetLastError = true)] public static extern bool CryptAcquireContext( +#endif out SafeProvHandle phProv, string? szContainer, string? szProvider, diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptCreateHash.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptCreateHash.cs index 679b82aee2a5e..0a60ee7918ac3 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptCreateHash.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptCreateHash.cs @@ -15,8 +15,8 @@ internal enum CryptCreateHashFlags : int None = 0, } - [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern bool CryptCreateHash( + [GeneratedDllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial bool CryptCreateHash( SafeProvHandle hProv, int Algid, SafeKeyHandle hKey, diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptDecrypt.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptDecrypt.cs index 0761afdf79d77..7865c1180ff8f 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptDecrypt.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptDecrypt.cs @@ -14,8 +14,8 @@ internal enum CryptDecryptFlags : int CRYPT_DECRYPT_RSA_NO_PADDING_CHECK = 0x00000020 } - [DllImport(Libraries.Advapi32, SetLastError = true)] - public static extern bool CryptDecrypt( + [GeneratedDllImport(Libraries.Advapi32, SetLastError = true)] + public static partial bool CryptDecrypt( SafeKeyHandle hKey, SafeHashHandle hHash, bool Final, diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptDeriveKey.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptDeriveKey.cs index 5afc729706e37..2bc7d4ed8d8ba 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptDeriveKey.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptDeriveKey.cs @@ -8,8 +8,8 @@ internal static partial class Interop { internal static partial class Advapi32 { - [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern bool CryptDeriveKey( + [GeneratedDllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial bool CryptDeriveKey( SafeProvHandle hProv, int Algid, SafeHashHandle hBaseData, diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptDestroyHash.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptDestroyHash.cs index f0e94194bef77..8635ce377299c 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptDestroyHash.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptDestroyHash.cs @@ -8,7 +8,12 @@ internal static partial class Interop { internal static partial class Advapi32 { +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] + public static partial bool CryptDestroyHash(IntPtr hHash); +#else [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] public static extern bool CryptDestroyHash(IntPtr hHash); +#endif } } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptDestroyKey.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptDestroyKey.cs index 948165d336783..5bc36fbfd6c15 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptDestroyKey.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptDestroyKey.cs @@ -8,7 +8,12 @@ internal static partial class Interop { internal static partial class Advapi32 { +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] + public static partial bool CryptDestroyKey(IntPtr hKey); +#else [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] public static extern bool CryptDestroyKey(IntPtr hKey); +#endif } } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptEncrypt.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptEncrypt.cs index 15f4683bf379b..fa883e5eef421 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptEncrypt.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptEncrypt.cs @@ -8,8 +8,8 @@ internal static partial class Interop { internal static partial class Advapi32 { - [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] - public static extern bool CryptEncrypt( + [GeneratedDllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] + public static partial bool CryptEncrypt( SafeKeyHandle hKey, SafeHashHandle hHash, bool Final, diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptExportKey.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptExportKey.cs index 1e878fc9ae53d..9eb16f4019035 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptExportKey.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptExportKey.cs @@ -8,13 +8,13 @@ internal static partial class Interop { internal static partial class Advapi32 { - [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] - public static extern bool CryptExportKey( + [GeneratedDllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] + public static partial bool CryptExportKey( SafeKeyHandle hKey, SafeKeyHandle hExpKey, int dwBlobType, int dwFlags, - [In, Out] byte[]? pbData, + byte[]? pbData, ref int dwDataLen); } } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptGenKey.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptGenKey.cs index 6518252da2847..d19c090d84d60 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptGenKey.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptGenKey.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Advapi32 { - [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern bool CryptGenKey(SafeProvHandle hProv, int Algid, int dwFlags, out SafeKeyHandle phKey); + [GeneratedDllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial bool CryptGenKey(SafeProvHandle hProv, int Algid, int dwFlags, out SafeKeyHandle phKey); } } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptGetHashParam.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptGetHashParam.cs index 3b45b4f885f40..65ba7716ab645 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptGetHashParam.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptGetHashParam.cs @@ -18,15 +18,15 @@ internal enum CryptHashProperty : int HP_TLS1PRF_SEED = 0x0007, // seed for TLS1 PRF } - [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] - public static extern bool CryptGetHashParam( + [GeneratedDllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] + public static partial bool CryptGetHashParam( SafeHashHandle hHash, CryptHashProperty dwParam, out int pbData, - [In, Out] ref int pdwDataLen, + ref int pdwDataLen, int dwFlags); - [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] - public static extern bool CryptSetHashParam(SafeHashHandle hHash, CryptHashProperty dwParam, byte[] buffer, int dwFlags); + [GeneratedDllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] + public static partial bool CryptSetHashParam(SafeHashHandle hHash, CryptHashProperty dwParam, byte[] buffer, int dwFlags); } } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptGetKeyParam.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptGetKeyParam.cs index 880e2aa3ac8db..9737c2b066388 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptGetKeyParam.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptGetKeyParam.cs @@ -17,8 +17,8 @@ internal enum CryptGetKeyParamFlags : int KP_KEYLEN = 9 } - [DllImport(Libraries.Advapi32, SetLastError = true)] - public static extern bool CryptGetKeyParam( + [GeneratedDllImport(Libraries.Advapi32, SetLastError = true)] + public static partial bool CryptGetKeyParam( SafeKeyHandle hKey, CryptGetKeyParamFlags dwParam, byte[]? pbData, diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptGetProvParam.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptGetProvParam.cs index 63553bcee99ab..d5a6b6dcb5f8c 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptGetProvParam.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptGetProvParam.cs @@ -22,22 +22,37 @@ internal enum CryptProvParam : int PP_UNIQUE_CONTAINER = 36 } +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Advapi32, SetLastError = true)] + public static partial bool CryptSetProvParam( +#else [DllImport(Libraries.Advapi32, SetLastError = true)] public static extern bool CryptSetProvParam( +#endif SafeHandle safeProvHandle, CryptProvParam dwParam, IntPtr pbData, int dwFlags); +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Advapi32, SetLastError = true)] + public static partial bool CryptSetProvParam( +#else [DllImport(Libraries.Advapi32, SetLastError = true)] public static extern bool CryptSetProvParam( +#endif SafeProvHandle hProv, CryptProvParam dwParam, ref IntPtr pbData, int dwFlags); +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Advapi32, SetLastError = true)] + public static partial bool CryptGetProvParam( +#else [DllImport(Libraries.Advapi32, SetLastError = true)] public static extern bool CryptGetProvParam( +#endif SafeHandle safeProvHandle, CryptProvParam dwParam, IntPtr pbData, diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptGetUserKey.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptGetUserKey.cs index d1078c88ff705..c5080a0078470 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptGetUserKey.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptGetUserKey.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Advapi32 { - [DllImport(Libraries.Advapi32, SetLastError = true)] - internal static extern bool CryptGetUserKey(SafeProvHandle hProv, int dwKeySpec, out SafeKeyHandle phUserKey); + [GeneratedDllImport(Libraries.Advapi32, SetLastError = true)] + internal static partial bool CryptGetUserKey(SafeProvHandle hProv, int dwKeySpec, out SafeKeyHandle phUserKey); } } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptHashData.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptHashData.cs index c655276a9b2cd..38f4a57d0dc23 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptHashData.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptHashData.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Advapi32 { - [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] - public static extern bool CryptHashData(SafeHashHandle hHash, byte[] pbData, int dwDataLen, int dwFlags); + [GeneratedDllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] + public static partial bool CryptHashData(SafeHashHandle hHash, byte[] pbData, int dwDataLen, int dwFlags); } } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptImportKey.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptImportKey.cs index f1266457cbe01..f5e73879d99ca 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptImportKey.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptImportKey.cs @@ -8,8 +8,8 @@ internal static partial class Interop { internal static partial class Advapi32 { - [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern unsafe bool CryptImportKey( + [GeneratedDllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] + internal static unsafe partial bool CryptImportKey( SafeProvHandle hProv, byte* pbData, int dwDataLen, diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptReleaseContext.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptReleaseContext.cs index dd5922d21f64f..f36800f515057 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptReleaseContext.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptReleaseContext.cs @@ -8,7 +8,14 @@ internal static partial class Interop { internal static partial class Advapi32 { +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Advapi32, SetLastError = true)] + public static partial bool CryptReleaseContext( +#else [DllImport(Libraries.Advapi32, SetLastError = true)] - public static extern bool CryptReleaseContext(IntPtr hProv, int dwFlags); + public static extern bool CryptReleaseContext( +#endif + IntPtr hProv, + int dwFlags); } } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptSetKeyParam.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptSetKeyParam.cs index 568d6bce51416..5fb1c83ff37e5 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptSetKeyParam.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptSetKeyParam.cs @@ -8,10 +8,10 @@ internal static partial class Interop { internal static partial class Advapi32 { - [DllImport(Libraries.Advapi32, SetLastError = true)] - public static extern bool CryptSetKeyParam(SafeKeyHandle hKey, int dwParam, byte[] pbData, int dwFlags); + [GeneratedDllImport(Libraries.Advapi32, SetLastError = true)] + public static partial bool CryptSetKeyParam(SafeKeyHandle hKey, int dwParam, byte[] pbData, int dwFlags); - [DllImport(Libraries.Advapi32, SetLastError = true)] - public static extern bool CryptSetKeyParam(SafeKeyHandle safeKeyHandle, int dwParam, ref int pdw, int dwFlags); + [GeneratedDllImport(Libraries.Advapi32, SetLastError = true)] + public static partial bool CryptSetKeyParam(SafeKeyHandle safeKeyHandle, int dwParam, ref int pdw, int dwFlags); } } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptSignHash.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptSignHash.cs index ce8c93da4a574..0d9f3a1703141 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptSignHash.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.CryptSignHash.cs @@ -24,17 +24,17 @@ internal enum CryptSignAndVerifyHashFlags : int CRYPT_X931_FORMAT = 0x00000004, // Not supported } - [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, SetLastError = true, EntryPoint = "CryptSignHashW")] - public static extern bool CryptSignHash( + [GeneratedDllImport(Libraries.Advapi32, EntryPoint = "CryptSignHashW", CharSet = CharSet.Unicode, SetLastError = true)] + public static partial bool CryptSignHash( SafeHashHandle hHash, KeySpec dwKeySpec, string? szDescription, CryptSignAndVerifyHashFlags dwFlags, - [Out] byte[]? pbSignature, - [In, Out] ref int pdwSigLen); + byte[]? pbSignature, + ref int pdwSigLen); - [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, SetLastError = true, EntryPoint = "CryptVerifySignatureW")] - public static extern bool CryptVerifySignature( + [GeneratedDllImport(Libraries.Advapi32, EntryPoint = "CryptVerifySignatureW", CharSet = CharSet.Unicode, SetLastError = true)] + public static partial bool CryptVerifySignature( SafeHashHandle hHash, byte[] pbSignature, int dwSigLen, diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.DuplicateTokenEx.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.DuplicateTokenEx.cs index e0fd150bce014..9f4fd71dc6249 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.DuplicateTokenEx.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.DuplicateTokenEx.cs @@ -9,8 +9,13 @@ internal static partial class Interop { internal static partial class Advapi32 { +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.Advapi32, SetLastError = true)] + internal static partial bool DuplicateTokenEx( +#else [DllImport(Interop.Libraries.Advapi32, SetLastError = true)] internal static extern bool DuplicateTokenEx( +#endif SafeAccessTokenHandle hExistingToken, uint dwDesiredAccess, IntPtr lpTokenAttributes, // LPSECURITY_ATTRIBUTES diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.DuplicateTokenEx_SafeTokenHandle.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.DuplicateTokenEx_SafeTokenHandle.cs index 7f3af0e0c08a7..9e45c078e6ad6 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.DuplicateTokenEx_SafeTokenHandle.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.DuplicateTokenEx_SafeTokenHandle.cs @@ -10,8 +10,14 @@ internal static partial class Interop { internal static partial class Advapi32 { +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.Advapi32, SetLastError = true)] + internal static partial bool DuplicateTokenEx( +#else [DllImport(Interop.Libraries.Advapi32, SetLastError = true)] - internal static extern bool DuplicateTokenEx(SafeTokenHandle ExistingTokenHandle, + internal static extern bool DuplicateTokenEx( +#endif + SafeTokenHandle ExistingTokenHandle, TokenAccessLevels DesiredAccess, IntPtr TokenAttributes, SECURITY_IMPERSONATION_LEVEL ImpersonationLevel, diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.EncryptDecrypt.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.EncryptDecrypt.cs index 14cf346be531f..659fbe352c687 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.EncryptDecrypt.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.EncryptDecrypt.cs @@ -11,8 +11,13 @@ internal static partial class Advapi32 /// /// WARNING: This method does not implicitly handle long paths. Use EncryptFile. /// - [DllImport(Libraries.Advapi32, EntryPoint = "EncryptFileW", SetLastError = true, CharSet = CharSet.Unicode)] +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Advapi32, EntryPoint = "EncryptFileW", CharSet = CharSet.Unicode, SetLastError = true)] + private static partial bool EncryptFilePrivate(string lpFileName); +#else + [DllImport(Libraries.Advapi32, EntryPoint = "EncryptFileW", CharSet = CharSet.Unicode, SetLastError = true)] private static extern bool EncryptFilePrivate(string lpFileName); +#endif internal static bool EncryptFile(string path) { @@ -23,8 +28,15 @@ internal static bool EncryptFile(string path) /// /// WARNING: This method does not implicitly handle long paths. Use DecryptFile. /// - [DllImport(Libraries.Advapi32, EntryPoint = "DecryptFileW", SetLastError = true, CharSet = CharSet.Unicode)] - private static extern bool DecryptFileFilePrivate(string lpFileName, int dwReserved); +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Advapi32, EntryPoint = "DecryptFileW", CharSet = CharSet.Unicode, SetLastError = true)] + private static partial bool DecryptFileFilePrivate( +#else + [DllImport(Libraries.Advapi32, EntryPoint = "DecryptFileW", CharSet = CharSet.Unicode, SetLastError = true)] + private static extern bool DecryptFileFilePrivate( +#endif + string lpFileName, + int dwReserved); internal static bool DecryptFile(string path) { diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.GetSecurityDescriptorLength.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.GetSecurityDescriptorLength.cs index 8b89d14a13c8e..e94bd4b0f18c2 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.GetSecurityDescriptorLength.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.GetSecurityDescriptorLength.cs @@ -9,7 +9,7 @@ internal static partial class Interop internal static partial class Advapi32 { [DllImport(Interop.Libraries.Advapi32, EntryPoint = "GetSecurityDescriptorLength", CallingConvention = CallingConvention.Winapi, - SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)] + CharSet = CharSet.Unicode, ExactSpelling = true)] internal static extern /*DWORD*/ uint GetSecurityDescriptorLength(IntPtr byteArray); } } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.GetSecurityInfoByHandle.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.GetSecurityInfoByHandle.cs index 933d8079521ae..b331549c0cf49 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.GetSecurityInfoByHandle.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.GetSecurityInfoByHandle.cs @@ -8,8 +8,20 @@ internal static partial class Interop { internal static partial class Advapi32 { - [DllImport(Interop.Libraries.Advapi32, EntryPoint = "GetSecurityInfo", SetLastError = true, ExactSpelling = true)] - internal static extern /*DWORD*/ uint GetSecurityInfoByHandle(SafeHandle handle, /*DWORD*/ uint objectType, /*DWORD*/ uint securityInformation, - out IntPtr sidOwner, out IntPtr sidGroup, out IntPtr dacl, out IntPtr sacl, out IntPtr securityDescriptor); +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.Advapi32, EntryPoint = "GetSecurityInfo", ExactSpelling = true)] + internal static unsafe partial uint GetSecurityInfoByHandle( +#else + [DllImport(Interop.Libraries.Advapi32, EntryPoint = "GetSecurityInfo", ExactSpelling = true)] + internal static unsafe extern /*DWORD*/ uint GetSecurityInfoByHandle( +#endif + SafeHandle handle, + /*DWORD*/ uint objectType, + /*DWORD*/ uint securityInformation, + IntPtr* sidOwner, + IntPtr* sidGroup, + IntPtr* dacl, + IntPtr* sacl, + IntPtr* securityDescriptor); } } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.GetSecurityInfoByName.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.GetSecurityInfoByName.cs index 5146002941d2a..9b480db68b3fa 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.GetSecurityInfoByName.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.GetSecurityInfoByName.cs @@ -8,8 +8,20 @@ internal static partial class Interop { internal static partial class Advapi32 { - [DllImport(Interop.Libraries.Advapi32, EntryPoint = "GetNamedSecurityInfoW", SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)] - internal static extern /*DWORD*/ uint GetSecurityInfoByName(string name, /*DWORD*/ uint objectType, /*DWORD*/ uint securityInformation, - out IntPtr sidOwner, out IntPtr sidGroup, out IntPtr dacl, out IntPtr sacl, out IntPtr securityDescriptor); +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.Advapi32, EntryPoint = "GetNamedSecurityInfoW", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] + internal static partial uint GetSecurityInfoByName( +#else + [DllImport(Interop.Libraries.Advapi32, EntryPoint = "GetNamedSecurityInfoW", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] + internal static extern /*DWORD*/ uint GetSecurityInfoByName( +#endif + string name, + /*DWORD*/ uint objectType, + /*DWORD*/ uint securityInformation, + out IntPtr sidOwner, + out IntPtr sidGroup, + out IntPtr dacl, + out IntPtr sacl, + out IntPtr securityDescriptor); } } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.GetTokenInformation.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.GetTokenInformation.cs index 5423812f21ed1..d881a59ac0551 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.GetTokenInformation.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.GetTokenInformation.cs @@ -9,24 +9,39 @@ internal static partial class Interop { internal static partial class Advapi32 { +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.Advapi32, SetLastError = true)] + internal static partial bool GetTokenInformation( +#else [DllImport(Interop.Libraries.Advapi32, SetLastError = true)] internal static extern bool GetTokenInformation( +#endif SafeAccessTokenHandle TokenHandle, uint TokenInformationClass, SafeLocalAllocHandle TokenInformation, uint TokenInformationLength, out uint ReturnLength); +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.Advapi32, SetLastError = true)] + internal static partial bool GetTokenInformation( +#else [DllImport(Interop.Libraries.Advapi32, SetLastError = true)] internal static extern bool GetTokenInformation( +#endif IntPtr TokenHandle, uint TokenInformationClass, SafeLocalAllocHandle TokenInformation, uint TokenInformationLength, out uint ReturnLength); +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial bool GetTokenInformation( +#else [DllImport(Interop.Libraries.Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] internal static extern bool GetTokenInformation( +#endif IntPtr TokenHandle, uint TokenInformationClass, IntPtr TokenInformation, diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.GetWindowsAccountDomainSid.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.GetWindowsAccountDomainSid.cs index 9792f1f730c5d..6070b3e70c9e0 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.GetWindowsAccountDomainSid.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.GetWindowsAccountDomainSid.cs @@ -8,7 +8,15 @@ internal static partial class Interop { internal static partial class Advapi32 { - [DllImport(Interop.Libraries.Advapi32, EntryPoint = "GetWindowsAccountDomainSid", SetLastError = true, CharSet = CharSet.Unicode)] - internal static extern int GetWindowsAccountDomainSid(byte[] sid, byte[] resultSid, ref uint resultSidLength); +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.Advapi32, EntryPoint = "GetWindowsAccountDomainSid", CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial int GetWindowsAccountDomainSid( +#else + [DllImport(Interop.Libraries.Advapi32, EntryPoint = "GetWindowsAccountDomainSid", CharSet = CharSet.Unicode, SetLastError = true)] + internal static extern int GetWindowsAccountDomainSid( +#endif + byte[] sid, + byte[] resultSid, + ref uint resultSidLength); } } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.ImpersonateLoggedOnUser.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.ImpersonateLoggedOnUser.cs index cf9ff0bfe15f1..10ab8ec20a513 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.ImpersonateLoggedOnUser.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.ImpersonateLoggedOnUser.cs @@ -9,7 +9,12 @@ internal static partial class Interop { internal static partial class Advapi32 { +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial bool ImpersonateLoggedOnUser(SafeAccessTokenHandle userToken); +#else [DllImport(Interop.Libraries.Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] internal static extern bool ImpersonateLoggedOnUser(SafeAccessTokenHandle userToken); +#endif } } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.ImpersonateNamedPipeClient.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.ImpersonateNamedPipeClient.cs index 2b72ecd6572d5..2aef33a6589db 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.ImpersonateNamedPipeClient.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.ImpersonateNamedPipeClient.cs @@ -9,8 +9,8 @@ internal static partial class Interop { internal static partial class Advapi32 { - [DllImport(Interop.Libraries.Advapi32, SetLastError = true)] + [GeneratedDllImport(Interop.Libraries.Advapi32, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool ImpersonateNamedPipeClient(SafePipeHandle hNamedPipe); + internal static partial bool ImpersonateNamedPipeClient(SafePipeHandle hNamedPipe); } } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.IsEqualDomainSid.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.IsEqualDomainSid.cs index 501ab7a07e3da..80fa089f74e01 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.IsEqualDomainSid.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.IsEqualDomainSid.cs @@ -8,7 +8,15 @@ internal static partial class Interop { internal static partial class Advapi32 { - [DllImport(Interop.Libraries.Advapi32, EntryPoint = "EqualDomainSid", SetLastError = true, CharSet = CharSet.Unicode)] - internal static extern int IsEqualDomainSid(byte[] sid1, byte[] sid2, out bool result); +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.Advapi32, EntryPoint = "EqualDomainSid", CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial int IsEqualDomainSid( +#else + [DllImport(Interop.Libraries.Advapi32, EntryPoint = "EqualDomainSid", CharSet = CharSet.Unicode, SetLastError = true)] + internal static extern int IsEqualDomainSid( +#endif + byte[] sid1, + byte[] sid2, + out bool result); } } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.IsWellKnownSid.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.IsWellKnownSid.cs index db37418003075..fa63e7e406442 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.IsWellKnownSid.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.IsWellKnownSid.cs @@ -8,7 +8,14 @@ internal static partial class Interop { internal static partial class Advapi32 { - [DllImport(Interop.Libraries.Advapi32, EntryPoint = "IsWellKnownSid", SetLastError = true, CharSet = CharSet.Unicode)] - internal static extern int IsWellKnownSid(byte[] sid, int type); +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.Advapi32, EntryPoint = "IsWellKnownSid", CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial int IsWellKnownSid( +#else + [DllImport(Interop.Libraries.Advapi32, EntryPoint = "IsWellKnownSid", CharSet = CharSet.Unicode, SetLastError = true)] + internal static extern int IsWellKnownSid( +#endif + byte[] sid, + int type); } } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.LookupPrivilegeValue.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.LookupPrivilegeValue.cs index af16874c9bd7b..c4276f4af72ee 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.LookupPrivilegeValue.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.LookupPrivilegeValue.cs @@ -7,8 +7,14 @@ internal static partial class Interop { internal static partial class Advapi32 { - [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, SetLastError = true, BestFitMapping = false, EntryPoint = "LookupPrivilegeValueW")] - internal static extern bool LookupPrivilegeValue([MarshalAs(UnmanagedType.LPTStr)] string? lpSystemName, [MarshalAs(UnmanagedType.LPTStr)] string lpName, out LUID lpLuid); +#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"; } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.LsaClose.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.LsaClose.cs index bc29d83ab829b..e16ad2b7249f8 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.LsaClose.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.LsaClose.cs @@ -8,7 +8,12 @@ internal static partial class Interop { internal static partial class Advapi32 { +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.Advapi32, SetLastError = true)] + internal static partial int LsaClose(IntPtr handle); +#else [DllImport(Interop.Libraries.Advapi32, SetLastError = true)] internal static extern int LsaClose(IntPtr handle); +#endif } } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.LsaFreeMemory.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.LsaFreeMemory.cs index 5193363331ec2..9d4823cdd6f24 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.LsaFreeMemory.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.LsaFreeMemory.cs @@ -8,7 +8,12 @@ internal static partial class Interop { internal static partial class Advapi32 { +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.Advapi32, SetLastError = true)] + internal static partial int LsaFreeMemory(IntPtr handle); +#else [DllImport(Interop.Libraries.Advapi32, SetLastError = true)] internal static extern int LsaFreeMemory(IntPtr handle); +#endif } } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.LsaLookupSids.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.LsaLookupSids.cs index 9986e358ca186..f49432c0654ab 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.LsaLookupSids.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.LsaLookupSids.cs @@ -9,8 +9,13 @@ internal static partial class Interop { internal static partial class Advapi32 { - [DllImport(Interop.Libraries.Advapi32, EntryPoint = "LsaLookupSids", SetLastError = true, CharSet = CharSet.Unicode)] +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.Advapi32, EntryPoint = "LsaLookupSids", CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial uint LsaLookupSids( +#else + [DllImport(Interop.Libraries.Advapi32, EntryPoint = "LsaLookupSids", CharSet = CharSet.Unicode, SetLastError = true)] internal static extern uint LsaLookupSids( +#endif SafeLsaPolicyHandle handle, int count, IntPtr[] sids, diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.LsaOpenPolicy.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.LsaOpenPolicy.cs index 910e6ff0015e1..ca2278a70c55b 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.LsaOpenPolicy.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.LsaOpenPolicy.cs @@ -9,8 +9,13 @@ internal static partial class Interop { internal static partial class Advapi32 { - [DllImport(Interop.Libraries.Advapi32, EntryPoint = "LsaOpenPolicy", SetLastError = true, CharSet = CharSet.Unicode)] +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.Advapi32, EntryPoint = "LsaOpenPolicy", CharSet = CharSet.Unicode, SetLastError = true)] + private static partial uint LsaOpenPolicy( +#else + [DllImport(Interop.Libraries.Advapi32, EntryPoint = "LsaOpenPolicy", CharSet = CharSet.Unicode, SetLastError = true)] private static extern uint LsaOpenPolicy( +#endif ref UNICODE_STRING SystemName, ref OBJECT_ATTRIBUTES ObjectAttributes, int AccessMask, diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.OpenProcessToken.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.OpenProcessToken.cs index 3e992403871ce..d01c7725ea9d5 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.OpenProcessToken.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.OpenProcessToken.cs @@ -9,7 +9,7 @@ internal static partial class Interop { internal static partial class Advapi32 { - [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern bool OpenProcessToken(IntPtr ProcessHandle, int DesiredAccess, out SafeTokenHandle TokenHandle); + [GeneratedDllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial bool OpenProcessToken(IntPtr ProcessHandle, int DesiredAccess, out SafeTokenHandle TokenHandle); } } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.OpenProcessToken_IntPtr.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.OpenProcessToken_IntPtr.cs index e709f3263a9d3..480bc64264da5 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.OpenProcessToken_IntPtr.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.OpenProcessToken_IntPtr.cs @@ -10,10 +10,15 @@ internal static partial class Interop { internal static partial class Advapi32 { +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial bool OpenProcessToken( +#else [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, SetLastError = true)] internal static extern bool OpenProcessToken( - IntPtr ProcessToken, - TokenAccessLevels DesiredAccess, - out SafeTokenHandle TokenHandle); +#endif + IntPtr ProcessToken, + TokenAccessLevels DesiredAccess, + out SafeTokenHandle TokenHandle); } } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.OpenProcessToken_SafeAccessTokenHandle.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.OpenProcessToken_SafeAccessTokenHandle.cs index b0560ba54dd0c..bf48ccbd086b5 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.OpenProcessToken_SafeAccessTokenHandle.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.OpenProcessToken_SafeAccessTokenHandle.cs @@ -10,7 +10,15 @@ internal static partial class Interop { internal static partial class Advapi32 { +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.Advapi32, SetLastError = true)] + internal static partial bool OpenProcessToken( +#else [DllImport(Interop.Libraries.Advapi32, SetLastError = true)] - internal static extern bool OpenProcessToken(IntPtr ProcessToken, TokenAccessLevels DesiredAccess, out SafeAccessTokenHandle TokenHandle); + internal static extern bool OpenProcessToken( +#endif + IntPtr ProcessToken, + TokenAccessLevels DesiredAccess, + out SafeAccessTokenHandle TokenHandle); } } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.OpenThreadToken.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.OpenThreadToken.cs index 8bce8337b2154..1deda3432150e 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.OpenThreadToken.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.OpenThreadToken.cs @@ -10,8 +10,17 @@ internal static partial class Interop { internal static partial class Advapi32 { +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.Advapi32, SetLastError = true)] + private static partial bool OpenThreadToken( +#else [DllImport(Interop.Libraries.Advapi32, SetLastError = true)] - private static extern bool OpenThreadToken(IntPtr ThreadHandle, TokenAccessLevels dwDesiredAccess, bool bOpenAsSelf, out SafeAccessTokenHandle phThreadToken); + private static extern bool OpenThreadToken( +#endif + IntPtr ThreadHandle, + TokenAccessLevels dwDesiredAccess, + bool bOpenAsSelf, + out SafeAccessTokenHandle phThreadToken); internal static bool OpenThreadToken(TokenAccessLevels desiredAccess, WinSecurityContext openAs, out SafeAccessTokenHandle tokenHandle) { diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.OpenThreadToken_SafeTokenHandle.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.OpenThreadToken_SafeTokenHandle.cs index 7f038c1afdea8..d86bebeddf320 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.OpenThreadToken_SafeTokenHandle.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.OpenThreadToken_SafeTokenHandle.cs @@ -10,7 +10,16 @@ internal static partial class Interop { internal static partial class Advapi32 { +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.Advapi32, SetLastError = true)] + internal static partial bool OpenThreadToken( +#else [DllImport(Interop.Libraries.Advapi32, SetLastError = true)] - internal static extern bool OpenThreadToken(IntPtr ThreadHandle, TokenAccessLevels dwDesiredAccess, bool bOpenAsSelf, out SafeTokenHandle phThreadToken); + internal static extern bool OpenThreadToken( +#endif + IntPtr ThreadHandle, + TokenAccessLevels dwDesiredAccess, + bool bOpenAsSelf, + out SafeTokenHandle phThreadToken); } } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegConnectRegistry.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegConnectRegistry.cs index fe0dc958c36d4..83206d9f75ced 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegConnectRegistry.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegConnectRegistry.cs @@ -14,7 +14,15 @@ internal static partial class Interop { internal static partial class Advapi32 { - [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegConnectRegistryW")] - internal static extern int RegConnectRegistry(string machineName, SafeRegistryHandle key, out SafeRegistryHandle result); +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Advapi32, EntryPoint = "RegConnectRegistryW", CharSet = CharSet.Unicode)] + internal static partial int RegConnectRegistry( +#else + [DllImport(Libraries.Advapi32, EntryPoint = "RegConnectRegistryW", CharSet = CharSet.Unicode, BestFitMapping = false)] + internal static extern int RegConnectRegistry( +#endif + string machineName, + SafeRegistryHandle key, + out SafeRegistryHandle result); } } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegCreateKeyEx.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegCreateKeyEx.cs index a92f277d80bb1..44671dd679c0c 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegCreateKeyEx.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegCreateKeyEx.cs @@ -14,8 +14,13 @@ internal static partial class Advapi32 { // Note: RegCreateKeyEx won't set the last error on failure - it returns // an error code if it fails. - [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegCreateKeyExW", ExactSpelling = true)] +#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, diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegDeleteKeyEx.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegDeleteKeyEx.cs index 64b5cc4f27e86..d7a5752143430 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegDeleteKeyEx.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegDeleteKeyEx.cs @@ -12,7 +12,16 @@ internal static partial class Interop { internal static partial class Advapi32 { - [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegDeleteKeyExW", ExactSpelling = true)] - internal static extern int RegDeleteKeyEx(SafeRegistryHandle hKey, string lpSubKey, int samDesired, int Reserved); +#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, + int Reserved); } } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegDeleteValue.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegDeleteValue.cs index b8c040c021426..50824a4ede142 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegDeleteValue.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegDeleteValue.cs @@ -12,7 +12,14 @@ internal static partial class Interop { internal static partial class Advapi32 { - [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegDeleteValueW", ExactSpelling = true)] - internal static extern int RegDeleteValue(SafeRegistryHandle hKey, string? lpValueName); +#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); } } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegFlushKey.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegFlushKey.cs index 2f3d3ed1a7561..5bb1046bee338 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegFlushKey.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegFlushKey.cs @@ -12,7 +12,13 @@ internal static partial class Interop { 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(SafeRegistryHandle hKey); + internal static extern int RegFlushKey( +#endif + SafeRegistryHandle hKey); } } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegOpenKeyEx.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegOpenKeyEx.cs index 8e28c0a2be6ab..4ffba18c4a2c6 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegOpenKeyEx.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegOpenKeyEx.cs @@ -13,8 +13,13 @@ internal static partial class Interop { internal static partial class Advapi32 { - [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegOpenKeyExW", ExactSpelling = true)] +#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, @@ -22,8 +27,13 @@ internal static extern int RegOpenKeyEx( out SafeRegistryHandle hkResult); - [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegOpenKeyExW", ExactSpelling = true)] +#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, diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegSetValueEx.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegSetValueEx.cs index 41df9ba67e6f7..8bb444aa563f3 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegSetValueEx.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegSetValueEx.cs @@ -12,8 +12,13 @@ internal static partial class Interop { internal static partial class Advapi32 { - [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegSetValueExW", ExactSpelling = true)] +#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, @@ -21,8 +26,13 @@ internal static extern int RegSetValueEx( byte[]? lpData, int cbData); - [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegSetValueExW", ExactSpelling = true)] +#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, @@ -30,8 +40,13 @@ internal static extern int RegSetValueEx( char[]? lpData, int cbData); - [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegSetValueExW", ExactSpelling = true)] +#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, @@ -39,8 +54,13 @@ internal static extern int RegSetValueEx( ref int lpData, int cbData); - [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegSetValueExW", ExactSpelling = true)] +#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, @@ -48,8 +68,13 @@ internal static extern int RegSetValueEx( ref long lpData, int cbData); - [DllImport(Libraries.Advapi32, CharSet = CharSet.Unicode, BestFitMapping = false, EntryPoint = "RegSetValueExW", ExactSpelling = true)] +#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, diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RevertToSelf.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RevertToSelf.cs index e18e63f04b558..5b1eb051b00d4 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RevertToSelf.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RevertToSelf.cs @@ -8,7 +8,12 @@ internal static partial class Interop { internal static partial class Advapi32 { - [DllImport(Interop.Libraries.Advapi32, SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)] +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.Advapi32, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] + internal static partial bool RevertToSelf(); +#else + [DllImport(Interop.Libraries.Advapi32, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] internal static extern bool RevertToSelf(); +#endif } } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.SetSecurityInfoByHandle.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.SetSecurityInfoByHandle.cs index d39173b121300..1a4d74d887651 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.SetSecurityInfoByHandle.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.SetSecurityInfoByHandle.cs @@ -8,9 +8,21 @@ internal static partial class Interop { internal static partial class Advapi32 { +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.Advapi32, EntryPoint = "SetSecurityInfo", CallingConvention = CallingConvention.Winapi, + CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] + internal static partial uint SetSecurityInfoByHandle( +#else [DllImport(Interop.Libraries.Advapi32, EntryPoint = "SetSecurityInfo", CallingConvention = CallingConvention.Winapi, - SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)] - internal static extern /*DWORD*/ uint SetSecurityInfoByHandle(SafeHandle handle, /*DWORD*/ uint objectType, /*DWORD*/ uint securityInformation, - byte[]? owner, byte[]? group, byte[]? dacl, byte[]? sacl); + CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] + internal static extern /*DWORD*/ uint SetSecurityInfoByHandle( +#endif + SafeHandle handle, + /*DWORD*/ uint objectType, + /*DWORD*/ uint securityInformation, + byte[]? owner, + byte[]? group, + byte[]? dacl, + byte[]? sacl); } } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.SetSecurityInfoByName.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.SetSecurityInfoByName.cs index 1156e585cbcb4..ae52e9ed1a088 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.SetSecurityInfoByName.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.SetSecurityInfoByName.cs @@ -8,9 +8,21 @@ internal static partial class Interop { internal static partial class Advapi32 { +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.Advapi32, EntryPoint = "SetNamedSecurityInfoW", CallingConvention = CallingConvention.Winapi, + CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] + internal static partial uint SetSecurityInfoByName( +#else [DllImport(Interop.Libraries.Advapi32, EntryPoint = "SetNamedSecurityInfoW", CallingConvention = CallingConvention.Winapi, - SetLastError = true, ExactSpelling = true, CharSet = CharSet.Unicode)] - internal static extern /*DWORD*/ uint SetSecurityInfoByName(string name, /*DWORD*/ uint objectType, /*DWORD*/ uint securityInformation, - byte[]? owner, byte[]? group, byte[]? dacl, byte[]? sacl); + CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] + internal static extern /*DWORD*/ uint SetSecurityInfoByName( +#endif + string name, + /*DWORD*/ uint objectType, + /*DWORD*/ uint securityInformation, + byte[]? owner, + byte[]? group, + byte[]? dacl, + byte[]? sacl); } } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.SetThreadToken.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.SetThreadToken.cs index f3c64ca98d189..a0fb653df2948 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.SetThreadToken.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.SetThreadToken.cs @@ -9,7 +9,14 @@ internal static partial class Interop { internal static partial class Advapi32 { +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Advapi32, SetLastError = true)] + internal static partial bool SetThreadToken( +#else [DllImport(Libraries.Advapi32, SetLastError = true)] - internal static extern bool SetThreadToken(IntPtr ThreadHandle, SafeTokenHandle? hToken); + internal static extern bool SetThreadToken( +#endif + IntPtr ThreadHandle, + SafeTokenHandle? hToken); } } diff --git a/src/libraries/Common/src/Interop/Windows/BCrypt/Cng.cs b/src/libraries/Common/src/Interop/Windows/BCrypt/Cng.cs index 273a0a89863aa..eaafec4d7f807 100644 --- a/src/libraries/Common/src/Interop/Windows/BCrypt/Cng.cs +++ b/src/libraries/Common/src/Interop/Windows/BCrypt/Cng.cs @@ -119,16 +119,16 @@ private static Exception CreateCryptographicException(NTSTATUS ntStatus) internal static partial class Cng { - internal static class Interop + internal static partial class Interop { - [DllImport(Libraries.BCrypt, CharSet = CharSet.Unicode)] - public static extern NTSTATUS BCryptOpenAlgorithmProvider(out SafeAlgorithmHandle phAlgorithm, string pszAlgId, string? pszImplementation, int dwFlags); + [GeneratedDllImport(Libraries.BCrypt, CharSet = CharSet.Unicode)] + public static partial NTSTATUS BCryptOpenAlgorithmProvider(out SafeAlgorithmHandle phAlgorithm, string pszAlgId, string? pszImplementation, int dwFlags); - [DllImport(Libraries.BCrypt, CharSet = CharSet.Unicode)] - public static extern NTSTATUS BCryptSetProperty(SafeAlgorithmHandle hObject, string pszProperty, string pbInput, int cbInput, int dwFlags); + [GeneratedDllImport(Libraries.BCrypt, CharSet = CharSet.Unicode)] + public static partial NTSTATUS BCryptSetProperty(SafeAlgorithmHandle hObject, string pszProperty, string pbInput, int cbInput, int dwFlags); - [DllImport(Libraries.BCrypt, CharSet = CharSet.Unicode, EntryPoint = "BCryptSetProperty")] - private static extern NTSTATUS BCryptSetIntPropertyPrivate(SafeBCryptHandle hObject, string pszProperty, ref int pdwInput, int cbInput, int dwFlags); + [GeneratedDllImport(Libraries.BCrypt, EntryPoint = "BCryptSetProperty", CharSet = CharSet.Unicode)] + private static partial NTSTATUS BCryptSetIntPropertyPrivate(SafeBCryptHandle hObject, string pszProperty, ref int pdwInput, int cbInput, int dwFlags); public static unsafe NTSTATUS BCryptSetIntProperty(SafeBCryptHandle hObject, string pszProperty, ref int pdwInput, int dwFlags) { diff --git a/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptCreateHash.cs b/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptCreateHash.cs index bd3578a6a7b0d..619b9848fa13c 100644 --- a/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptCreateHash.cs +++ b/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptCreateHash.cs @@ -16,8 +16,8 @@ internal static NTSTATUS BCryptCreateHash(SafeBCryptAlgorithmHandle hAlgorithm, return BCryptCreateHash(hAlgorithm, out phHash, pbHashObject, cbHashObject, ref MemoryMarshal.GetReference(secret), cbSecret, dwFlags); } - [DllImport(Libraries.BCrypt, CharSet = CharSet.Unicode)] - private static extern NTSTATUS BCryptCreateHash(SafeBCryptAlgorithmHandle hAlgorithm, out SafeBCryptHashHandle phHash, IntPtr pbHashObject, int cbHashObject, ref byte pbSecret, int cbSecret, BCryptCreateHashFlags dwFlags); + [GeneratedDllImport(Libraries.BCrypt, CharSet = CharSet.Unicode)] + private static partial NTSTATUS BCryptCreateHash(SafeBCryptAlgorithmHandle hAlgorithm, out SafeBCryptHashHandle phHash, IntPtr pbHashObject, int cbHashObject, ref byte pbSecret, int cbSecret, BCryptCreateHashFlags dwFlags); [Flags] internal enum BCryptCreateHashFlags : int diff --git a/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptDeriveKeyPBKDF2.cs b/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptDeriveKeyPBKDF2.cs index 88ff68b7ae1c2..6a1eaaaed7c98 100644 --- a/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptDeriveKeyPBKDF2.cs +++ b/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptDeriveKeyPBKDF2.cs @@ -11,8 +11,8 @@ internal static partial class Interop { internal static partial class BCrypt { - [DllImport(Libraries.BCrypt, CharSet = CharSet.Unicode)] - internal static extern unsafe NTSTATUS BCryptDeriveKeyPBKDF2( + [GeneratedDllImport(Libraries.BCrypt, CharSet = CharSet.Unicode)] + internal static unsafe partial NTSTATUS BCryptDeriveKeyPBKDF2( SafeBCryptAlgorithmHandle hPrf, byte* pbPassword, int cbPassword, diff --git a/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptDuplicateHash.cs b/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptDuplicateHash.cs index 5635873ad17e5..fe03585bf9b41 100644 --- a/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptDuplicateHash.cs +++ b/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptDuplicateHash.cs @@ -23,8 +23,8 @@ internal static SafeBCryptHashHandle BCryptDuplicateHash(SafeBCryptHashHandle hH return newHash; } - [DllImport(Libraries.BCrypt, CharSet = CharSet.Unicode)] - private static extern NTSTATUS BCryptDuplicateHash( + [GeneratedDllImport(Libraries.BCrypt, CharSet = CharSet.Unicode)] + private static partial NTSTATUS BCryptDuplicateHash( SafeBCryptHashHandle hHash, out SafeBCryptHashHandle phNewHash, IntPtr pbHashObject, diff --git a/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptEncryptDecrypt.cs b/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptEncryptDecrypt.cs index 4cb1a123bc4e6..5ebad79983143 100644 --- a/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptEncryptDecrypt.cs +++ b/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptEncryptDecrypt.cs @@ -53,10 +53,10 @@ internal static int BCryptDecrypt(SafeKeyHandle hKey, ReadOnlySpan input, } } - [DllImport(Libraries.BCrypt, CharSet = CharSet.Unicode)] - public static extern unsafe NTSTATUS BCryptEncrypt(SafeKeyHandle hKey, byte* pbInput, int cbInput, IntPtr paddingInfo, [In, Out] byte[]? pbIV, int cbIV, byte* pbOutput, int cbOutput, out int cbResult, int dwFlags); + [GeneratedDllImport(Libraries.BCrypt, CharSet = CharSet.Unicode)] + public static unsafe partial NTSTATUS BCryptEncrypt(SafeKeyHandle hKey, byte* pbInput, int cbInput, IntPtr paddingInfo, byte[]? pbIV, int cbIV, byte* pbOutput, int cbOutput, out int cbResult, int dwFlags); - [DllImport(Libraries.BCrypt, CharSet = CharSet.Unicode)] - public static extern unsafe NTSTATUS BCryptDecrypt(SafeKeyHandle hKey, byte* pbInput, int cbInput, IntPtr paddingInfo, [In, Out] byte[]? pbIV, int cbIV, byte* pbOutput, int cbOutput, out int cbResult, int dwFlags); + [GeneratedDllImport(Libraries.BCrypt, CharSet = CharSet.Unicode)] + public static unsafe partial NTSTATUS BCryptDecrypt(SafeKeyHandle hKey, byte* pbInput, int cbInput, IntPtr paddingInfo, byte[]? pbIV, int cbIV, byte* pbOutput, int cbOutput, out int cbResult, int dwFlags); } } diff --git a/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptExportKey.cs b/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptExportKey.cs index 8f5936af4ce06..b9f585e3a245d 100644 --- a/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptExportKey.cs +++ b/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptExportKey.cs @@ -11,7 +11,7 @@ internal static partial class Interop { internal static partial class BCrypt { - [DllImport(Libraries.BCrypt, CharSet = CharSet.Unicode)] - internal static extern NTSTATUS BCryptExportKey(SafeBCryptKeyHandle hKey, IntPtr hExportKey, string pszBlobType, [Out] byte[]? pbOutput, int cbOutput, out int pcbResult, int dwFlags); + [GeneratedDllImport(Libraries.BCrypt, CharSet = CharSet.Unicode)] + internal static partial NTSTATUS BCryptExportKey(SafeBCryptKeyHandle hKey, IntPtr hExportKey, string pszBlobType, byte[]? pbOutput, int cbOutput, out int pcbResult, int dwFlags); } } diff --git a/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptFinishHash.cs b/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptFinishHash.cs index bf1b5a6571290..c91997b7af244 100644 --- a/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptFinishHash.cs +++ b/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptFinishHash.cs @@ -12,7 +12,7 @@ internal static partial class BCrypt internal static NTSTATUS BCryptFinishHash(SafeBCryptHashHandle hHash, Span pbOutput, int cbOutput, int dwFlags) => BCryptFinishHash(hHash, ref MemoryMarshal.GetReference(pbOutput), cbOutput, dwFlags); - [DllImport(Libraries.BCrypt, CharSet = CharSet.Unicode)] - private static extern NTSTATUS BCryptFinishHash(SafeBCryptHashHandle hHash, ref byte pbOutput, int cbOutput, int dwFlags); + [GeneratedDllImport(Libraries.BCrypt, CharSet = CharSet.Unicode)] + private static partial NTSTATUS BCryptFinishHash(SafeBCryptHashHandle hHash, ref byte pbOutput, int cbOutput, int dwFlags); } } diff --git a/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptGenerateSymmetricKey.cs b/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptGenerateSymmetricKey.cs index 2d3d2364b87ad..35cb2e8ea8b50 100644 --- a/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptGenerateSymmetricKey.cs +++ b/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptGenerateSymmetricKey.cs @@ -9,8 +9,8 @@ internal static partial class Interop { internal static partial class BCrypt { - [DllImport(Libraries.BCrypt, CharSet = CharSet.Unicode)] - internal static unsafe extern NTSTATUS BCryptGenerateSymmetricKey( + [GeneratedDllImport(Libraries.BCrypt, CharSet = CharSet.Unicode)] + internal static unsafe partial NTSTATUS BCryptGenerateSymmetricKey( SafeBCryptAlgorithmHandle hAlgorithm, out SafeBCryptKeyHandle phKey, IntPtr pbKeyObject, @@ -19,8 +19,8 @@ internal static unsafe extern NTSTATUS BCryptGenerateSymmetricKey( int cbSecret, uint dwFlags); - [DllImport(Libraries.BCrypt, CharSet = CharSet.Unicode)] - internal static unsafe extern NTSTATUS BCryptGenerateSymmetricKey( + [GeneratedDllImport(Libraries.BCrypt, CharSet = CharSet.Unicode)] + internal static unsafe partial NTSTATUS BCryptGenerateSymmetricKey( nuint hAlgorithm, out SafeBCryptKeyHandle phKey, IntPtr pbKeyObject, diff --git a/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptGetProperty.cs b/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptGetProperty.cs index b052cfead2db4..f5429ac535a12 100644 --- a/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptGetProperty.cs +++ b/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptGetProperty.cs @@ -11,7 +11,7 @@ internal static partial class Interop { internal static partial class BCrypt { - [DllImport(Libraries.BCrypt, CharSet = CharSet.Unicode)] - internal static extern unsafe NTSTATUS BCryptGetProperty(SafeBCryptHandle hObject, string pszProperty, void* pbOutput, int cbOutput, out int pcbResult, int dwFlags); + [GeneratedDllImport(Libraries.BCrypt, CharSet = CharSet.Unicode)] + internal static unsafe partial NTSTATUS BCryptGetProperty(SafeBCryptHandle hObject, string pszProperty, void* pbOutput, int cbOutput, out int pcbResult, int dwFlags); } } diff --git a/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptHashData.cs b/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptHashData.cs index 445a67b8f0f12..db9a126b48a99 100644 --- a/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptHashData.cs +++ b/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptHashData.cs @@ -13,7 +13,7 @@ internal static partial class BCrypt internal static NTSTATUS BCryptHashData(SafeBCryptHashHandle hHash, ReadOnlySpan pbInput, int cbInput, int dwFlags) => BCryptHashData(hHash, ref MemoryMarshal.GetReference(pbInput), cbInput, dwFlags); - [DllImport(Libraries.BCrypt, CharSet = CharSet.Unicode)] - private static extern NTSTATUS BCryptHashData(SafeBCryptHashHandle hHash, ref byte pbInput, int cbInput, int dwFlags); + [GeneratedDllImport(Libraries.BCrypt, CharSet = CharSet.Unicode)] + private static partial NTSTATUS BCryptHashData(SafeBCryptHashHandle hHash, ref byte pbInput, int cbInput, int dwFlags); } } diff --git a/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptImportKey.cs b/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptImportKey.cs index 5ee600d5283a9..13d709643a184 100644 --- a/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptImportKey.cs +++ b/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptImportKey.cs @@ -47,7 +47,7 @@ private struct BCRYPT_KEY_DATA_BLOB_HEADER public const uint BCRYPT_KEY_DATA_BLOB_VERSION1 = 0x1; } - [DllImport(Libraries.BCrypt, CharSet = CharSet.Unicode)] - private static extern NTSTATUS BCryptImportKey(SafeAlgorithmHandle hAlgorithm, IntPtr hImportKey, string pszBlobType, out SafeKeyHandle hKey, IntPtr pbKeyObject, int cbKeyObject, byte[] pbInput, int cbInput, int dwFlags); + [GeneratedDllImport(Libraries.BCrypt, CharSet = CharSet.Unicode)] + private static partial NTSTATUS BCryptImportKey(SafeAlgorithmHandle hAlgorithm, IntPtr hImportKey, string pszBlobType, out SafeKeyHandle hKey, IntPtr pbKeyObject, int cbKeyObject, byte[] pbInput, int cbInput, int dwFlags); } } diff --git a/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptKeyDerivation.cs b/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptKeyDerivation.cs index e9c93a367908d..9a0e6604f3bcb 100644 --- a/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptKeyDerivation.cs +++ b/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptKeyDerivation.cs @@ -11,8 +11,8 @@ internal static partial class Interop { internal static partial class BCrypt { - [DllImport(Libraries.BCrypt, CharSet = CharSet.Unicode)] - internal static unsafe extern NTSTATUS BCryptKeyDerivation( + [GeneratedDllImport(Libraries.BCrypt, CharSet = CharSet.Unicode)] + internal static unsafe partial NTSTATUS BCryptKeyDerivation( SafeBCryptKeyHandle hKey, BCryptBufferDesc* pParameterList, byte* pbDerivedKey, diff --git a/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptOpenAlgorithmProvider.cs b/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptOpenAlgorithmProvider.cs index 65b457f046ed0..a0bb0c9e35ee9 100644 --- a/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptOpenAlgorithmProvider.cs +++ b/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptOpenAlgorithmProvider.cs @@ -11,8 +11,8 @@ internal static partial class Interop { internal static partial class BCrypt { - [DllImport(Libraries.BCrypt, CharSet = CharSet.Unicode)] - internal static extern NTSTATUS BCryptOpenAlgorithmProvider(out SafeBCryptAlgorithmHandle phAlgorithm, string pszAlgId, string? pszImplementation, BCryptOpenAlgorithmProviderFlags dwFlags); + [GeneratedDllImport(Libraries.BCrypt, CharSet = CharSet.Unicode)] + internal static partial NTSTATUS BCryptOpenAlgorithmProvider(out SafeBCryptAlgorithmHandle phAlgorithm, string pszAlgId, string? pszImplementation, BCryptOpenAlgorithmProviderFlags dwFlags); [Flags] internal enum BCryptOpenAlgorithmProviderFlags : int diff --git a/src/libraries/Common/src/Interop/Windows/Crypt32/Interop.CertCloseStore.cs b/src/libraries/Common/src/Interop/Windows/Crypt32/Interop.CertCloseStore.cs index 8248d470d76c1..f26df2d4d8e5c 100644 --- a/src/libraries/Common/src/Interop/Windows/Crypt32/Interop.CertCloseStore.cs +++ b/src/libraries/Common/src/Interop/Windows/Crypt32/Interop.CertCloseStore.cs @@ -8,7 +8,12 @@ internal static partial class Interop { internal static partial class Crypt32 { +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial bool CertCloseStore(IntPtr hCertStore, uint dwFlags); +#else [DllImport(Interop.Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] internal static extern bool CertCloseStore(IntPtr hCertStore, uint dwFlags); +#endif } } diff --git a/src/libraries/Common/src/Interop/Windows/Crypt32/Interop.CertEnumCertificatesInStore.cs b/src/libraries/Common/src/Interop/Windows/Crypt32/Interop.CertEnumCertificatesInStore.cs index b6d12f6ca92ac..50cb6c5997be0 100644 --- a/src/libraries/Common/src/Interop/Windows/Crypt32/Interop.CertEnumCertificatesInStore.cs +++ b/src/libraries/Common/src/Interop/Windows/Crypt32/Interop.CertEnumCertificatesInStore.cs @@ -8,7 +8,14 @@ internal static partial class Interop { internal static partial class Crypt32 { +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] + public static unsafe partial CERT_CONTEXT* CertEnumCertificatesInStore( +#else [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] - public static extern unsafe CERT_CONTEXT* CertEnumCertificatesInStore(IntPtr hCertStore, CERT_CONTEXT* pPrevCertContext); + public static unsafe extern CERT_CONTEXT* CertEnumCertificatesInStore( +#endif + IntPtr hCertStore, + CERT_CONTEXT* pPrevCertContext); } } diff --git a/src/libraries/Common/src/Interop/Windows/Crypt32/Interop.CertFreeCertificateContext.cs b/src/libraries/Common/src/Interop/Windows/Crypt32/Interop.CertFreeCertificateContext.cs index 577283c94dca9..9158b597dbbb7 100644 --- a/src/libraries/Common/src/Interop/Windows/Crypt32/Interop.CertFreeCertificateContext.cs +++ b/src/libraries/Common/src/Interop/Windows/Crypt32/Interop.CertFreeCertificateContext.cs @@ -9,7 +9,12 @@ internal static partial class Interop internal static partial class Crypt32 { // Note: This api always return TRUE, regardless of success. +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial bool CertFreeCertificateContext(IntPtr pCertContext); +#else [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] internal static extern bool CertFreeCertificateContext(IntPtr pCertContext); +#endif } } diff --git a/src/libraries/Common/src/Interop/Windows/Crypt32/Interop.CertNameToStr.cs b/src/libraries/Common/src/Interop/Windows/Crypt32/Interop.CertNameToStr.cs index 30d5379eb6823..534dc6418c9c7 100644 --- a/src/libraries/Common/src/Interop/Windows/Crypt32/Interop.CertNameToStr.cs +++ b/src/libraries/Common/src/Interop/Windows/Crypt32/Interop.CertNameToStr.cs @@ -7,8 +7,13 @@ internal static partial class Interop { internal static partial class Crypt32 { - [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true, EntryPoint = "CertNameToStrW")] +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Crypt32, EntryPoint = "CertNameToStrW", CharSet = CharSet.Unicode, SetLastError = true)] + internal static unsafe partial int CertNameToStr( +#else + [DllImport(Libraries.Crypt32, EntryPoint = "CertNameToStrW", CharSet = CharSet.Unicode, SetLastError = true)] internal static extern unsafe int CertNameToStr( +#endif int dwCertEncodingType, void* pName, int dwStrType, diff --git a/src/libraries/Common/src/Interop/Windows/Crypt32/Interop.CryptFormatObject.cs b/src/libraries/Common/src/Interop/Windows/Crypt32/Interop.CryptFormatObject.cs index b9c3418823084..4f75276fcb2eb 100644 --- a/src/libraries/Common/src/Interop/Windows/Crypt32/Interop.CryptFormatObject.cs +++ b/src/libraries/Common/src/Interop/Windows/Crypt32/Interop.CryptFormatObject.cs @@ -12,16 +12,16 @@ internal static partial class Crypt32 internal const int CRYPT_FORMAT_STR_MULTI_LINE = 0x00000001; internal const int CRYPT_FORMAT_STR_NO_HEX = 0x00000010; - [DllImport(Libraries.Crypt32, SetLastError = true, BestFitMapping = false)] - internal static extern unsafe bool CryptFormatObject( - [In] int dwCertEncodingType, // only valid value is X509_ASN_ENCODING - [In] int dwFormatType, // unused - pass 0. - [In] int dwFormatStrType, // select multiline - [In] IntPtr pFormatStruct, // unused - pass IntPtr.Zero - [In] byte* lpszStructType, // OID value - [In] byte[] pbEncoded, // Data to be formatted - [In] int cbEncoded, // Length of data to be formatted - [Out] void* pbFormat, // Receives formatted string. - [In, Out] ref int pcbFormat); // Sends/receives length of formatted string in bytes + [GeneratedDllImport(Libraries.Crypt32, SetLastError = true)] + internal static unsafe partial bool CryptFormatObject( + int dwCertEncodingType, // only valid value is X509_ASN_ENCODING + int dwFormatType, // unused - pass 0. + int dwFormatStrType, // select multiline + IntPtr pFormatStruct, // unused - pass IntPtr.Zero + byte* lpszStructType, // OID value + byte[] pbEncoded, // Data to be formatted + int cbEncoded, // Length of data to be formatted + void* pbFormat, // Receives formatted string. + ref int pcbFormat); // Sends/receives length of formatted string in bytes } } diff --git a/src/libraries/Common/src/Interop/Windows/Crypt32/Interop.CryptMsgClose.cs b/src/libraries/Common/src/Interop/Windows/Crypt32/Interop.CryptMsgClose.cs index 08dd13648b85b..f4235e3d178bb 100644 --- a/src/libraries/Common/src/Interop/Windows/Crypt32/Interop.CryptMsgClose.cs +++ b/src/libraries/Common/src/Interop/Windows/Crypt32/Interop.CryptMsgClose.cs @@ -8,7 +8,12 @@ internal static partial class Interop { internal static partial class Crypt32 { +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial bool CryptMsgClose(IntPtr hCryptMsg); +#else [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] internal static extern bool CryptMsgClose(IntPtr hCryptMsg); +#endif } } diff --git a/src/libraries/Common/src/Interop/Windows/Crypt32/Interop.HashIdAlg.cs b/src/libraries/Common/src/Interop/Windows/Crypt32/Interop.HashIdAlg.cs index d9aac15e5d311..926d8f463024e 100644 --- a/src/libraries/Common/src/Interop/Windows/Crypt32/Interop.HashIdAlg.cs +++ b/src/libraries/Common/src/Interop/Windows/Crypt32/Interop.HashIdAlg.cs @@ -13,15 +13,19 @@ internal static partial class Crypt32 /// Version used for a buffer containing a scalar integer (not an IntPtr) /// [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode)] - private static extern IntPtr CryptFindOIDInfo(CryptOidInfoKeyType dwKeyType, ref int pvKey, OidGroup group); + private static unsafe extern IntPtr CryptFindOIDInfo(CryptOidInfoKeyType dwKeyType, int* pvKey, OidGroup group); public static CRYPT_OID_INFO FindAlgIdOidInfo(Interop.BCrypt.ECC_CURVE_ALG_ID_ENUM algId) { int intAlgId = (int)algId; - IntPtr fullOidInfo = CryptFindOIDInfo( - CryptOidInfoKeyType.CRYPT_OID_INFO_ALGID_KEY, - ref intAlgId, - OidGroup.HashAlgorithm); + IntPtr fullOidInfo; + unsafe + { + fullOidInfo = CryptFindOIDInfo( + CryptOidInfoKeyType.CRYPT_OID_INFO_ALGID_KEY, + &intAlgId, + OidGroup.HashAlgorithm); + } if (fullOidInfo != IntPtr.Zero) { diff --git a/src/libraries/Common/src/Interop/Windows/Crypt32/Interop.certificates.cs b/src/libraries/Common/src/Interop/Windows/Crypt32/Interop.certificates.cs index c177c76cfb2bb..e61361bfa8ae7 100644 --- a/src/libraries/Common/src/Interop/Windows/Crypt32/Interop.certificates.cs +++ b/src/libraries/Common/src/Interop/Windows/Crypt32/Interop.certificates.cs @@ -10,16 +10,28 @@ internal static partial class Interop { internal static partial class Crypt32 { +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static partial bool CertFreeCertificateContext(IntPtr pCertContext); +#else [DllImport(Interop.Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool CertFreeCertificateContext(IntPtr pCertContext); +#endif +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static partial bool CertVerifyCertificateChainPolicy( +#else [DllImport(Interop.Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool CertVerifyCertificateChainPolicy( +#endif IntPtr pszPolicyOID, SafeX509ChainHandle pChainContext, - [In] ref CERT_CHAIN_POLICY_PARA pPolicyPara, - [In, Out] ref CERT_CHAIN_POLICY_STATUS pPolicyStatus); + ref CERT_CHAIN_POLICY_PARA pPolicyPara, + ref CERT_CHAIN_POLICY_STATUS pPolicyStatus); } } diff --git a/src/libraries/Common/src/Interop/Windows/Crypt32/Interop.certificates_types.cs b/src/libraries/Common/src/Interop/Windows/Crypt32/Interop.certificates_types.cs index 2fa029d9d8f30..d51195c5b613d 100644 --- a/src/libraries/Common/src/Interop/Windows/Crypt32/Interop.certificates_types.cs +++ b/src/libraries/Common/src/Interop/Windows/Crypt32/Interop.certificates_types.cs @@ -92,7 +92,7 @@ internal unsafe struct SSL_EXTRA_CERT_CHAIN_POLICY_PARA internal uint cbSize; internal uint dwAuthType; internal uint fdwChecks; - internal char* pwszServerName; + internal ushort* pwszServerName; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] diff --git a/src/libraries/Common/src/Interop/Windows/HttpApi/Interop.HttpApi.cs b/src/libraries/Common/src/Interop/Windows/HttpApi/Interop.HttpApi.cs index 27c22800a42d5..ac41ba64035b0 100644 --- a/src/libraries/Common/src/Interop/Windows/HttpApi/Interop.HttpApi.cs +++ b/src/libraries/Common/src/Interop/Windows/HttpApi/Interop.HttpApi.cs @@ -455,54 +455,54 @@ internal struct HTTP_BINDING_INFO } - [DllImport(Libraries.HttpApi, SetLastError = true)] - internal static extern uint HttpInitialize(HTTPAPI_VERSION version, uint flags, IntPtr pReserved); + [GeneratedDllImport(Libraries.HttpApi, SetLastError = true)] + internal static partial uint HttpInitialize(HTTPAPI_VERSION version, uint flags, IntPtr pReserved); - [DllImport(Libraries.HttpApi, SetLastError = true)] - internal static extern uint HttpSetUrlGroupProperty(ulong urlGroupId, HTTP_SERVER_PROPERTY serverProperty, IntPtr pPropertyInfo, uint propertyInfoLength); + [GeneratedDllImport(Libraries.HttpApi, SetLastError = true)] + internal static partial uint HttpSetUrlGroupProperty(ulong urlGroupId, HTTP_SERVER_PROPERTY serverProperty, IntPtr pPropertyInfo, uint propertyInfoLength); - [DllImport(Libraries.HttpApi, SetLastError = true)] - internal static extern unsafe uint HttpCreateServerSession(HTTPAPI_VERSION version, ulong* serverSessionId, uint reserved); + [GeneratedDllImport(Libraries.HttpApi, SetLastError = true)] + internal static unsafe partial uint HttpCreateServerSession(HTTPAPI_VERSION version, ulong* serverSessionId, uint reserved); - [DllImport(Libraries.HttpApi, SetLastError = true)] - internal static extern unsafe uint HttpCreateUrlGroup(ulong serverSessionId, ulong* urlGroupId, uint reserved); + [GeneratedDllImport(Libraries.HttpApi, SetLastError = true)] + internal static unsafe partial uint HttpCreateUrlGroup(ulong serverSessionId, ulong* urlGroupId, uint reserved); - [DllImport(Libraries.HttpApi, SetLastError = true)] - internal static extern uint HttpCloseUrlGroup(ulong urlGroupId); + [GeneratedDllImport(Libraries.HttpApi, SetLastError = true)] + internal static partial uint HttpCloseUrlGroup(ulong urlGroupId); - [DllImport(Libraries.HttpApi, CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern unsafe uint HttpCreateRequestQueue(HTTPAPI_VERSION version, string pName, + [GeneratedDllImport(Libraries.HttpApi, CharSet = CharSet.Unicode, SetLastError = true)] + internal static unsafe partial uint HttpCreateRequestQueue(HTTPAPI_VERSION version, string pName, Interop.Kernel32.SECURITY_ATTRIBUTES* pSecurityAttributes, uint flags, out HttpRequestQueueV2Handle pReqQueueHandle); - [DllImport(Libraries.HttpApi, CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern uint HttpAddUrlToUrlGroup(ulong urlGroupId, string pFullyQualifiedUrl, ulong context, uint pReserved); + [GeneratedDllImport(Libraries.HttpApi, CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial uint HttpAddUrlToUrlGroup(ulong urlGroupId, string pFullyQualifiedUrl, ulong context, uint pReserved); - [DllImport(Libraries.HttpApi, CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern uint HttpRemoveUrlFromUrlGroup(ulong urlGroupId, string pFullyQualifiedUrl, uint flags); + [GeneratedDllImport(Libraries.HttpApi, CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial uint HttpRemoveUrlFromUrlGroup(ulong urlGroupId, string pFullyQualifiedUrl, uint flags); - [DllImport(Libraries.HttpApi, SetLastError = true)] - internal static extern unsafe uint HttpReceiveHttpRequest(SafeHandle requestQueueHandle, ulong requestId, uint flags, HTTP_REQUEST* pRequestBuffer, uint requestBufferLength, uint* pBytesReturned, NativeOverlapped* pOverlapped); + [GeneratedDllImport(Libraries.HttpApi, SetLastError = true)] + internal static unsafe partial uint HttpReceiveHttpRequest(SafeHandle requestQueueHandle, ulong requestId, uint flags, HTTP_REQUEST* pRequestBuffer, uint requestBufferLength, uint* pBytesReturned, NativeOverlapped* pOverlapped); - [DllImport(Libraries.HttpApi, SetLastError = true)] - internal static extern unsafe uint HttpSendHttpResponse(SafeHandle requestQueueHandle, ulong requestId, uint flags, HTTP_RESPONSE* pHttpResponse, void* pCachePolicy, uint* pBytesSent, SafeLocalAllocHandle pRequestBuffer, uint requestBufferLength, NativeOverlapped* pOverlapped, void* pLogData); + [GeneratedDllImport(Libraries.HttpApi, SetLastError = true)] + internal static unsafe partial uint HttpSendHttpResponse(SafeHandle requestQueueHandle, ulong requestId, uint flags, HTTP_RESPONSE* pHttpResponse, void* pCachePolicy, uint* pBytesSent, SafeLocalAllocHandle pRequestBuffer, uint requestBufferLength, NativeOverlapped* pOverlapped, void* pLogData); - [DllImport(Libraries.HttpApi, SetLastError = true)] - internal static extern unsafe uint HttpWaitForDisconnect(SafeHandle requestQueueHandle, ulong connectionId, NativeOverlapped* pOverlapped); + [GeneratedDllImport(Libraries.HttpApi, SetLastError = true)] + internal static unsafe partial uint HttpWaitForDisconnect(SafeHandle requestQueueHandle, ulong connectionId, NativeOverlapped* pOverlapped); - [DllImport(Libraries.HttpApi, SetLastError = true)] - internal static extern unsafe uint HttpReceiveRequestEntityBody(SafeHandle requestQueueHandle, ulong requestId, uint flags, void* pEntityBuffer, uint entityBufferLength, out uint bytesReturned, NativeOverlapped* pOverlapped); + [GeneratedDllImport(Libraries.HttpApi, SetLastError = true)] + internal static unsafe partial uint HttpReceiveRequestEntityBody(SafeHandle requestQueueHandle, ulong requestId, uint flags, void* pEntityBuffer, uint entityBufferLength, out uint bytesReturned, NativeOverlapped* pOverlapped); - [DllImport(Libraries.HttpApi, SetLastError = true)] - internal static extern unsafe uint HttpSendResponseEntityBody(SafeHandle requestQueueHandle, ulong requestId, uint flags, ushort entityChunkCount, HTTP_DATA_CHUNK* pEntityChunks, uint* pBytesSent, SafeLocalAllocHandle pRequestBuffer, uint requestBufferLength, NativeOverlapped* pOverlapped, void* pLogData); + [GeneratedDllImport(Libraries.HttpApi, SetLastError = true)] + internal static unsafe partial uint HttpSendResponseEntityBody(SafeHandle requestQueueHandle, ulong requestId, uint flags, ushort entityChunkCount, HTTP_DATA_CHUNK* pEntityChunks, uint* pBytesSent, SafeLocalAllocHandle pRequestBuffer, uint requestBufferLength, NativeOverlapped* pOverlapped, void* pLogData); - [DllImport(Libraries.HttpApi, SetLastError = true)] - internal static extern uint HttpCloseRequestQueue(IntPtr pReqQueueHandle); + [GeneratedDllImport(Libraries.HttpApi, SetLastError = true)] + internal static partial uint HttpCloseRequestQueue(IntPtr pReqQueueHandle); - [DllImport(Libraries.HttpApi, SetLastError = true)] - internal static extern uint HttpCancelHttpRequest(SafeHandle requestQueueHandle, ulong requestId, IntPtr pOverlapped); + [GeneratedDllImport(Libraries.HttpApi, SetLastError = true)] + internal static partial uint HttpCancelHttpRequest(SafeHandle requestQueueHandle, ulong requestId, IntPtr pOverlapped); - [DllImport(Libraries.HttpApi, SetLastError = true)] - internal static extern uint HttpCloseServerSession(ulong serverSessionId); + [GeneratedDllImport(Libraries.HttpApi, SetLastError = true)] + internal static partial uint HttpCloseServerSession(ulong serverSessionId); internal sealed class SafeLocalFreeChannelBinding : ChannelBinding { @@ -530,11 +530,11 @@ protected override bool ReleaseHandle() } } - [DllImport(Libraries.HttpApi, SetLastError = true)] - internal static extern unsafe uint HttpReceiveClientCertificate(SafeHandle requestQueueHandle, ulong connectionId, uint flags, HTTP_SSL_CLIENT_CERT_INFO* pSslClientCertInfo, uint sslClientCertInfoSize, uint* pBytesReceived, NativeOverlapped* pOverlapped); + [GeneratedDllImport(Libraries.HttpApi, SetLastError = true)] + internal static unsafe partial uint HttpReceiveClientCertificate(SafeHandle requestQueueHandle, ulong connectionId, uint flags, HTTP_SSL_CLIENT_CERT_INFO* pSslClientCertInfo, uint sslClientCertInfoSize, uint* pBytesReceived, NativeOverlapped* pOverlapped); - [DllImport(Libraries.HttpApi, SetLastError = true)] - internal static extern unsafe uint HttpReceiveClientCertificate(SafeHandle requestQueueHandle, ulong connectionId, uint flags, byte* pSslClientCertInfo, uint sslClientCertInfoSize, uint* pBytesReceived, NativeOverlapped* pOverlapped); + [GeneratedDllImport(Libraries.HttpApi, SetLastError = true)] + internal static unsafe partial uint HttpReceiveClientCertificate(SafeHandle requestQueueHandle, ulong connectionId, uint flags, byte* pSslClientCertInfo, uint sslClientCertInfoSize, uint* pBytesReceived, NativeOverlapped* pOverlapped); internal static readonly string?[] HttpVerbs = new string?[] { diff --git a/src/libraries/Common/src/Interop/Windows/IpHlpApi/Interop.GetNetworkParams.cs b/src/libraries/Common/src/Interop/Windows/IpHlpApi/Interop.GetNetworkParams.cs index d6760bfc17bab..f731ce50e7a38 100644 --- a/src/libraries/Common/src/Interop/Windows/IpHlpApi/Interop.GetNetworkParams.cs +++ b/src/libraries/Common/src/Interop/Windows/IpHlpApi/Interop.GetNetworkParams.cs @@ -9,6 +9,6 @@ internal static partial class Interop internal static partial class IpHlpApi { [DllImport(Interop.Libraries.IpHlpApi, ExactSpelling = true)] - internal static extern uint GetNetworkParams(IntPtr pFixedInfo, ref uint pOutBufLen); + internal static unsafe extern uint GetNetworkParams(IntPtr pFixedInfo, uint* pOutBufLen); } } diff --git a/src/libraries/Common/src/Interop/Windows/IpHlpApi/Interop.ICMP.cs b/src/libraries/Common/src/Interop/Windows/IpHlpApi/Interop.ICMP.cs index 3f7dba6e50551..71823ea3c74c3 100644 --- a/src/libraries/Common/src/Interop/Windows/IpHlpApi/Interop.ICMP.cs +++ b/src/libraries/Common/src/Interop/Windows/IpHlpApi/Interop.ICMP.cs @@ -89,21 +89,21 @@ protected override bool ReleaseHandle() } } - [DllImport(Interop.Libraries.IpHlpApi, SetLastError = true)] - internal static extern SafeCloseIcmpHandle IcmpCreateFile(); + [GeneratedDllImport(Interop.Libraries.IpHlpApi, SetLastError = true)] + internal static partial SafeCloseIcmpHandle IcmpCreateFile(); - [DllImport(Interop.Libraries.IpHlpApi, SetLastError = true)] - internal static extern SafeCloseIcmpHandle Icmp6CreateFile(); + [GeneratedDllImport(Interop.Libraries.IpHlpApi, SetLastError = true)] + internal static partial SafeCloseIcmpHandle Icmp6CreateFile(); - [DllImport(Interop.Libraries.IpHlpApi, SetLastError = true)] - internal static extern bool IcmpCloseHandle(IntPtr handle); + [GeneratedDllImport(Interop.Libraries.IpHlpApi, SetLastError = true)] + internal static partial bool IcmpCloseHandle(IntPtr handle); - [DllImport(Interop.Libraries.IpHlpApi, SetLastError = true)] - internal static extern uint IcmpSendEcho2(SafeCloseIcmpHandle icmpHandle, SafeWaitHandle Event, IntPtr apcRoutine, IntPtr apcContext, - uint ipAddress, [In] SafeLocalAllocHandle data, ushort dataSize, ref IPOptions options, SafeLocalAllocHandle replyBuffer, uint replySize, uint timeout); + [GeneratedDllImport(Interop.Libraries.IpHlpApi, SetLastError = true)] + internal static partial uint IcmpSendEcho2(SafeCloseIcmpHandle icmpHandle, SafeWaitHandle Event, IntPtr apcRoutine, IntPtr apcContext, + uint ipAddress, SafeLocalAllocHandle data, ushort dataSize, ref IPOptions options, SafeLocalAllocHandle replyBuffer, uint replySize, uint timeout); - [DllImport(Interop.Libraries.IpHlpApi, SetLastError = true)] - internal static extern uint Icmp6SendEcho2(SafeCloseIcmpHandle icmpHandle, SafeWaitHandle Event, IntPtr apcRoutine, IntPtr apcContext, - byte[] sourceSocketAddress, byte[] destSocketAddress, [In] SafeLocalAllocHandle data, ushort dataSize, ref IPOptions options, SafeLocalAllocHandle replyBuffer, uint replySize, uint timeout); + [GeneratedDllImport(Interop.Libraries.IpHlpApi, SetLastError = true)] + internal static partial uint Icmp6SendEcho2(SafeCloseIcmpHandle icmpHandle, SafeWaitHandle Event, IntPtr apcRoutine, IntPtr apcContext, + byte[] sourceSocketAddress, byte[] destSocketAddress, SafeLocalAllocHandle data, ushort dataSize, ref IPOptions options, SafeLocalAllocHandle replyBuffer, uint replySize, uint timeout); } } diff --git a/src/libraries/Common/src/Interop/Windows/IpHlpApi/Interop.NetworkInformation.cs b/src/libraries/Common/src/Interop/Windows/IpHlpApi/Interop.NetworkInformation.cs index 81faff1d9a04a..40d3df8e16079 100644 --- a/src/libraries/Common/src/Interop/Windows/IpHlpApi/Interop.NetworkInformation.cs +++ b/src/libraries/Common/src/Interop/Windows/IpHlpApi/Interop.NetworkInformation.cs @@ -324,7 +324,7 @@ internal struct MibTcpStats [StructLayout(LayoutKind.Sequential)] internal struct MibIpStats { - internal bool forwardingEnabled; + internal int forwardingEnabled; internal uint defaultTtl; internal uint packetsReceived; internal uint receivedPacketsWithHeaderErrors; @@ -509,50 +509,50 @@ internal unsafe struct MibUdp6RowOwnerPid } [DllImport(Interop.Libraries.IpHlpApi)] - internal static extern uint GetAdaptersAddresses( + internal static unsafe extern uint GetAdaptersAddresses( AddressFamily family, uint flags, IntPtr pReserved, IntPtr adapterAddresses, - ref uint outBufLen); + uint* outBufLen); [DllImport(Interop.Libraries.IpHlpApi)] - internal static extern uint GetBestInterfaceEx(byte[] ipAddress, out int index); + internal static unsafe extern uint GetBestInterfaceEx(byte* ipAddress, int* index); [DllImport(Interop.Libraries.IpHlpApi)] internal static extern uint GetIfEntry2(ref MibIfRow2 pIfRow); [DllImport(Interop.Libraries.IpHlpApi)] - internal static extern uint GetIpStatisticsEx(out MibIpStats statistics, AddressFamily family); + internal static unsafe extern uint GetIpStatisticsEx(MibIpStats* statistics, AddressFamily family); [DllImport(Interop.Libraries.IpHlpApi)] - internal static extern uint GetTcpStatisticsEx(out MibTcpStats statistics, AddressFamily family); + internal static unsafe extern uint GetTcpStatisticsEx(MibTcpStats* statistics, AddressFamily family); [DllImport(Interop.Libraries.IpHlpApi)] - internal static extern uint GetUdpStatisticsEx(out MibUdpStats statistics, AddressFamily family); + internal static unsafe extern uint GetUdpStatisticsEx(MibUdpStats* statistics, AddressFamily family); [DllImport(Interop.Libraries.IpHlpApi)] - internal static extern uint GetIcmpStatistics(out MibIcmpInfo statistics); + internal static unsafe extern uint GetIcmpStatistics(MibIcmpInfo* statistics); [DllImport(Interop.Libraries.IpHlpApi)] internal static extern uint GetIcmpStatisticsEx(out MibIcmpInfoEx statistics, AddressFamily family); - [DllImport(Interop.Libraries.IpHlpApi)] - internal static extern uint GetTcpTable(IntPtr pTcpTable, ref uint dwOutBufLen, bool order); + [GeneratedDllImport(Interop.Libraries.IpHlpApi)] + internal static unsafe partial uint GetTcpTable(IntPtr pTcpTable, uint* dwOutBufLen, bool order); - [DllImport(Interop.Libraries.IpHlpApi)] - internal static extern uint GetExtendedTcpTable(IntPtr pTcpTable, ref uint dwOutBufLen, bool order, + [GeneratedDllImport(Interop.Libraries.IpHlpApi)] + internal static unsafe partial uint GetExtendedTcpTable(IntPtr pTcpTable, uint* dwOutBufLen, bool order, uint IPVersion, TcpTableClass tableClass, uint reserved); - [DllImport(Interop.Libraries.IpHlpApi)] - internal static extern uint GetUdpTable(IntPtr pUdpTable, ref uint dwOutBufLen, bool order); + [GeneratedDllImport(Interop.Libraries.IpHlpApi)] + internal static unsafe partial uint GetUdpTable(IntPtr pUdpTable, uint* dwOutBufLen, bool order); - [DllImport(Interop.Libraries.IpHlpApi)] - internal static extern uint GetExtendedUdpTable(IntPtr pUdpTable, ref uint dwOutBufLen, bool order, + [GeneratedDllImport(Interop.Libraries.IpHlpApi)] + internal static unsafe partial uint GetExtendedUdpTable(IntPtr pUdpTable, uint* dwOutBufLen, bool order, uint IPVersion, UdpTableClass tableClass, uint reserved); [DllImport(Interop.Libraries.IpHlpApi)] - internal static extern uint GetPerAdapterInfo(uint IfIndex, IntPtr pPerAdapterInfo, ref uint pOutBufLen); + internal static unsafe extern uint GetPerAdapterInfo(uint IfIndex, IntPtr pPerAdapterInfo, uint* pOutBufLen); [DllImport(Interop.Libraries.IpHlpApi)] internal static extern void FreeMibTable(IntPtr handle); @@ -560,8 +560,8 @@ internal static extern uint GetExtendedUdpTable(IntPtr pUdpTable, ref uint dwOut [DllImport(Interop.Libraries.IpHlpApi)] internal static extern uint CancelMibChangeNotify2(IntPtr notificationHandle); - [DllImport(Interop.Libraries.IpHlpApi)] - internal static extern unsafe uint NotifyStableUnicastIpAddressTable( + [GeneratedDllImport(Interop.Libraries.IpHlpApi)] + internal static unsafe partial uint NotifyStableUnicastIpAddressTable( AddressFamily addressFamily, out SafeFreeMibTable table, delegate* unmanaged callback, diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.Beep.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.Beep.cs index 7c7c79e76899b..ed50f3346fce1 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.Beep.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.Beep.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, SetLastError = true)] - internal static extern bool Beep(int frequency, int duration); + [GeneratedDllImport(Libraries.Kernel32, SetLastError = true)] + internal static partial bool Beep(int frequency, int duration); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CancelIoEx.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CancelIoEx.cs index 124578deb49b6..45d5dcfcac14c 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CancelIoEx.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CancelIoEx.cs @@ -9,10 +9,10 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, SetLastError = true)] - internal static extern unsafe bool CancelIoEx(SafeHandle handle, NativeOverlapped* lpOverlapped); + [GeneratedDllImport(Libraries.Kernel32, SetLastError = true)] + internal static unsafe partial bool CancelIoEx(SafeHandle handle, NativeOverlapped* lpOverlapped); - [DllImport(Libraries.Kernel32, SetLastError = true)] - internal static extern unsafe bool CancelIoEx(IntPtr handle, NativeOverlapped* lpOverlapped); + [GeneratedDllImport(Libraries.Kernel32, SetLastError = true)] + internal static unsafe partial bool CancelIoEx(IntPtr handle, NativeOverlapped* lpOverlapped); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CloseHandle.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CloseHandle.cs index bf767ece3d2d1..0e4280b39dbf4 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CloseHandle.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CloseHandle.cs @@ -8,6 +8,8 @@ internal static partial class Interop { internal static partial class Kernel32 { +#pragma warning disable DLLIMPORTGENANALYZER015 // Use 'GeneratedDllImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time + // Disabled since CloseHandle is a QCall in some scenarios and DllImportGenerator doesn't support QCalls. [DllImport(Libraries.Kernel32, SetLastError = true)] internal static extern bool CloseHandle(IntPtr handle); } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ConnectNamedPipe.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ConnectNamedPipe.cs index 2805d3d1b7684..1838d726f86bf 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ConnectNamedPipe.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ConnectNamedPipe.cs @@ -10,12 +10,12 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, SetLastError = true)] + [GeneratedDllImport(Libraries.Kernel32, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern unsafe bool ConnectNamedPipe(SafePipeHandle handle, NativeOverlapped* overlapped); + internal static unsafe partial bool ConnectNamedPipe(SafePipeHandle handle, NativeOverlapped* overlapped); - [DllImport(Libraries.Kernel32, SetLastError = true)] + [GeneratedDllImport(Libraries.Kernel32, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool ConnectNamedPipe(SafePipeHandle handle, IntPtr overlapped); + internal static partial bool ConnectNamedPipe(SafePipeHandle handle, IntPtr overlapped); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ConsoleCursorInfo.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ConsoleCursorInfo.cs index 5b34e2210b965..38c4419699a3e 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ConsoleCursorInfo.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ConsoleCursorInfo.cs @@ -12,13 +12,13 @@ internal static partial class Kernel32 internal struct CONSOLE_CURSOR_INFO { internal int dwSize; - internal bool bVisible; + internal BOOL bVisible; } - [DllImport(Libraries.Kernel32, SetLastError = true)] - internal static extern bool GetConsoleCursorInfo(IntPtr hConsoleOutput, out CONSOLE_CURSOR_INFO cci); + [GeneratedDllImport(Libraries.Kernel32, SetLastError = true)] + internal static partial bool GetConsoleCursorInfo(IntPtr hConsoleOutput, out CONSOLE_CURSOR_INFO cci); - [DllImport(Libraries.Kernel32, SetLastError = true)] - internal static extern bool SetConsoleCursorInfo(IntPtr hConsoleOutput, ref CONSOLE_CURSOR_INFO cci); + [GeneratedDllImport(Libraries.Kernel32, SetLastError = true)] + internal static partial bool SetConsoleCursorInfo(IntPtr hConsoleOutput, ref CONSOLE_CURSOR_INFO cci); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CopyFileEx.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CopyFileEx.cs index f0766d2477b26..2dd22d45b3ae4 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CopyFileEx.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CopyFileEx.cs @@ -12,8 +12,13 @@ internal static partial class Kernel32 /// /// WARNING: This method does not implicitly handle long paths. Use CopyFileEx. /// - [DllImport(Libraries.Kernel32, EntryPoint = "CopyFileExW", SetLastError = true, CharSet = CharSet.Unicode, BestFitMapping = false)] +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Kernel32, EntryPoint = "CopyFileExW", CharSet = CharSet.Unicode, SetLastError = true)] + private static partial bool CopyFileExPrivate( +#else + [DllImport(Libraries.Kernel32, EntryPoint = "CopyFileExW", CharSet = CharSet.Unicode, SetLastError = true)] private static extern bool CopyFileExPrivate( +#endif string src, string dst, IntPtr progressRoutine, diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreateDirectory.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreateDirectory.cs index 5c4e754f86019..60c13362b8eda 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreateDirectory.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreateDirectory.cs @@ -12,8 +12,15 @@ internal static partial class Kernel32 /// /// WARNING: This method does not implicitly handle long paths. Use CreateDirectory. /// - [DllImport(Libraries.Kernel32, EntryPoint = "CreateDirectoryW", SetLastError = true, CharSet = CharSet.Unicode, BestFitMapping = false)] - private static extern bool CreateDirectoryPrivate(string path, ref SECURITY_ATTRIBUTES lpSecurityAttributes); +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Kernel32, EntryPoint = "CreateDirectoryW", CharSet = CharSet.Unicode, SetLastError = true)] + private static partial bool CreateDirectoryPrivate( +#else + [DllImport(Libraries.Kernel32, EntryPoint = "CreateDirectoryW", CharSet = CharSet.Unicode, SetLastError = true)] + private static extern bool CreateDirectoryPrivate( +#endif + string path, + ref SECURITY_ATTRIBUTES lpSecurityAttributes); internal static bool CreateDirectory(string path, ref SECURITY_ATTRIBUTES lpSecurityAttributes) { diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreateFile.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreateFile.cs index ce5bfd9fd5321..f26661c5e2635 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreateFile.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreateFile.cs @@ -13,8 +13,13 @@ internal static partial class Kernel32 /// /// WARNING: This method does not implicitly handle long paths. Use CreateFile. /// - [DllImport(Libraries.Kernel32, EntryPoint = "CreateFileW", SetLastError = true, CharSet = CharSet.Unicode, BestFitMapping = false, ExactSpelling = true)] - private static extern unsafe SafeFileHandle CreateFilePrivate( +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Kernel32, EntryPoint = "CreateFileW", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] + private static unsafe partial SafeFileHandle CreateFilePrivate( +#else + [DllImport(Libraries.Kernel32, EntryPoint = "CreateFileW", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] + private static unsafe extern SafeFileHandle CreateFilePrivate( +#endif string lpFileName, int dwDesiredAccess, FileShare dwShareMode, diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreateFileMapping.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreateFileMapping.cs index cc85cc91756ba..81ffec311fbc6 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreateFileMapping.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreateFileMapping.cs @@ -10,8 +10,13 @@ internal static partial class Interop { internal static partial class Kernel32 { +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Kernel32, EntryPoint = "CreateFileMappingW", CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial SafeMemoryMappedFileHandle CreateFileMapping( +#else [DllImport(Libraries.Kernel32, EntryPoint = "CreateFileMappingW", CharSet = CharSet.Unicode, SetLastError = true)] internal static extern SafeMemoryMappedFileHandle CreateFileMapping( +#endif SafeFileHandle hFile, ref SECURITY_ATTRIBUTES lpFileMappingAttributes, int flProtect, @@ -19,8 +24,13 @@ internal static extern SafeMemoryMappedFileHandle CreateFileMapping( int dwMaximumSizeLow, string? lpName); +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Kernel32, EntryPoint = "CreateFileMappingW", CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial SafeMemoryMappedFileHandle CreateFileMapping( +#else [DllImport(Libraries.Kernel32, EntryPoint = "CreateFileMappingW", CharSet = CharSet.Unicode, SetLastError = true)] internal static extern SafeMemoryMappedFileHandle CreateFileMapping( +#endif IntPtr hFile, ref SECURITY_ATTRIBUTES lpFileMappingAttributes, int flProtect, diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreateFile_IntPtr.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreateFile_IntPtr.cs index de8ec49722c54..41b2f88d22343 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreateFile_IntPtr.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreateFile_IntPtr.cs @@ -12,8 +12,13 @@ internal static partial class Kernel32 /// /// WARNING: This method does not implicitly handle long paths. Use CreateFile. /// - [DllImport(Libraries.Kernel32, EntryPoint = "CreateFileW", SetLastError = true, CharSet = CharSet.Unicode, BestFitMapping = false, ExactSpelling = true)] - private static extern unsafe IntPtr CreateFilePrivate_IntPtr( +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Kernel32, EntryPoint = "CreateFileW", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] + private static unsafe partial IntPtr CreateFilePrivate_IntPtr( +#else + [DllImport(Libraries.Kernel32, EntryPoint = "CreateFileW", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] + private static unsafe extern IntPtr CreateFilePrivate_IntPtr( +#endif string lpFileName, int dwDesiredAccess, FileShare dwShareMode, diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreateNamedPipe.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreateNamedPipe.cs index 3d88bf3c5ba94..cc190de6989c7 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreateNamedPipe.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreateNamedPipe.cs @@ -9,8 +9,8 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true, BestFitMapping = false, EntryPoint = "CreateNamedPipeW")] - internal static extern SafePipeHandle CreateNamedPipe( + [GeneratedDllImport(Libraries.Kernel32, EntryPoint = "CreateNamedPipeW", CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial SafePipeHandle CreateNamedPipe( string pipeName, int openMode, int pipeMode, diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreateNamedPipeClient.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreateNamedPipeClient.cs index 4c8b9cbc06bc2..f5cad97b7c477 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreateNamedPipeClient.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreateNamedPipeClient.cs @@ -10,8 +10,8 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, EntryPoint = "CreateFileW", CharSet = CharSet.Unicode, SetLastError = true, BestFitMapping = false)] - internal static extern SafePipeHandle CreateNamedPipeClient( + [GeneratedDllImport(Libraries.Kernel32, EntryPoint = "CreateFileW", CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial SafePipeHandle CreateNamedPipeClient( string? lpFileName, int dwDesiredAccess, System.IO.FileShare dwShareMode, diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreatePipe_SafeFileHandle.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreatePipe_SafeFileHandle.cs index ae4e43a73a386..46c64430603ec 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreatePipe_SafeFileHandle.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreatePipe_SafeFileHandle.cs @@ -9,7 +9,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, SetLastError = true)] - internal static extern bool CreatePipe(out SafeFileHandle hReadPipe, out SafeFileHandle hWritePipe, ref SECURITY_ATTRIBUTES lpPipeAttributes, int nSize); + [GeneratedDllImport(Libraries.Kernel32, SetLastError = true)] + internal static partial bool CreatePipe(out SafeFileHandle hReadPipe, out SafeFileHandle hWritePipe, ref SECURITY_ATTRIBUTES lpPipeAttributes, int nSize); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreatePipe_SafePipeHandle.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreatePipe_SafePipeHandle.cs index 92a3257d33d37..0b1e88acd5126 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreatePipe_SafePipeHandle.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreatePipe_SafePipeHandle.cs @@ -9,7 +9,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, SetLastError = true)] - internal static extern bool CreatePipe(out SafePipeHandle hReadPipe, out SafePipeHandle hWritePipe, ref SECURITY_ATTRIBUTES lpPipeAttributes, int nSize); + [GeneratedDllImport(Libraries.Kernel32, SetLastError = true)] + internal static partial bool CreatePipe(out SafePipeHandle hReadPipe, out SafePipeHandle hWritePipe, ref SECURITY_ATTRIBUTES lpPipeAttributes, int nSize); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreateProcess.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreateProcess.cs index ede776e82438f..c31f8a36755cb 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreateProcess.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CreateProcess.cs @@ -10,8 +10,8 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true, BestFitMapping = false, EntryPoint = "CreateProcessW")] - internal static extern unsafe bool CreateProcess( + [GeneratedDllImport(Libraries.Kernel32, EntryPoint = "CreateProcessW", CharSet = CharSet.Unicode, SetLastError = true)] + internal static unsafe partial bool CreateProcess( string? lpApplicationName, char* lpCommandLine, ref SECURITY_ATTRIBUTES procSecAttrs, diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.DeleteFile.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.DeleteFile.cs index 112538259e925..a811e31f4f49f 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.DeleteFile.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.DeleteFile.cs @@ -12,8 +12,13 @@ internal static partial class Kernel32 /// /// WARNING: This method does not implicitly handle long paths. Use DeleteFile. /// - [DllImport(Libraries.Kernel32, EntryPoint = "DeleteFileW", SetLastError = true, CharSet = CharSet.Unicode, BestFitMapping = false)] +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Kernel32, EntryPoint = "DeleteFileW", CharSet = CharSet.Unicode, SetLastError = true)] + private static partial bool DeleteFilePrivate(string path); +#else + [DllImport(Libraries.Kernel32, EntryPoint = "DeleteFileW", CharSet = CharSet.Unicode, SetLastError = true)] private static extern bool DeleteFilePrivate(string path); +#endif internal static bool DeleteFile(string path) { diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.DeleteVolumeMountPoint.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.DeleteVolumeMountPoint.cs index 66b39032eb90e..e898e36613477 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.DeleteVolumeMountPoint.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.DeleteVolumeMountPoint.cs @@ -12,9 +12,13 @@ internal static partial class Kernel32 /// /// WARNING: This method does not implicitly handle long paths. Use DeleteVolumeMountPoint. /// - [DllImport(Libraries.Kernel32, EntryPoint = "DeleteVolumeMountPointW", SetLastError = true, CharSet = CharSet.Unicode, BestFitMapping = false)] +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Kernel32, EntryPoint = "DeleteVolumeMountPointW", CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial bool DeleteVolumeMountPointPrivate(string mountPoint); +#else + [DllImport(Libraries.Kernel32, EntryPoint = "DeleteVolumeMountPointW", CharSet = CharSet.Unicode, SetLastError = true)] internal static extern bool DeleteVolumeMountPointPrivate(string mountPoint); - +#endif internal static bool DeleteVolumeMountPoint(string mountPoint) { diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.DisconnectNamedPipe.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.DisconnectNamedPipe.cs index ccef10e08a77a..c0d137618c1e7 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.DisconnectNamedPipe.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.DisconnectNamedPipe.cs @@ -9,8 +9,8 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, SetLastError = true)] + [GeneratedDllImport(Libraries.Kernel32, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool DisconnectNamedPipe(SafePipeHandle hNamedPipe); + internal static partial bool DisconnectNamedPipe(SafePipeHandle hNamedPipe); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.DuplicateHandle_SafeAccessTokenHandle.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.DuplicateHandle_SafeAccessTokenHandle.cs index fff392dedad44..ddfd30f11ff6d 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.DuplicateHandle_SafeAccessTokenHandle.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.DuplicateHandle_SafeAccessTokenHandle.cs @@ -9,8 +9,13 @@ internal static partial class Interop { internal static partial class Kernel32 { +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Kernel32, SetLastError = true)] + internal static partial bool DuplicateHandle( +#else [DllImport(Libraries.Kernel32, SetLastError = true)] internal static extern bool DuplicateHandle( +#endif IntPtr hSourceProcessHandle, IntPtr hSourceHandle, IntPtr hTargetProcessHandle, diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.DuplicateHandle_SafeFileHandle.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.DuplicateHandle_SafeFileHandle.cs index fb542316a2438..843b39780ac7a 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.DuplicateHandle_SafeFileHandle.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.DuplicateHandle_SafeFileHandle.cs @@ -9,8 +9,8 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, SetLastError = true)] - internal static extern bool DuplicateHandle( + [GeneratedDllImport(Libraries.Kernel32, SetLastError = true)] + internal static partial bool DuplicateHandle( IntPtr hSourceProcessHandle, SafeHandle hSourceHandle, IntPtr hTargetProcess, diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.DuplicateHandle_SafePipeHandle.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.DuplicateHandle_SafePipeHandle.cs index 96726abc91fd4..88f2b8c4568ef 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.DuplicateHandle_SafePipeHandle.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.DuplicateHandle_SafePipeHandle.cs @@ -9,8 +9,8 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, SetLastError = true)] - internal static extern bool DuplicateHandle( + [GeneratedDllImport(Libraries.Kernel32, SetLastError = true)] + internal static partial bool DuplicateHandle( IntPtr hSourceProcessHandle, SafeHandle hSourceHandle, IntPtr hTargetProcessHandle, diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.DuplicateHandle_SafeWaitHandle.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.DuplicateHandle_SafeWaitHandle.cs index 5749d82479f87..f68f28bc1eadc 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.DuplicateHandle_SafeWaitHandle.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.DuplicateHandle_SafeWaitHandle.cs @@ -9,8 +9,13 @@ internal static partial class Interop { internal static partial class Kernel32 { +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Kernel32, SetLastError = true)] + internal static partial bool DuplicateHandle( +#else [DllImport(Libraries.Kernel32, SetLastError = true)] internal static extern bool DuplicateHandle( +#endif IntPtr hSourceProcessHandle, SafeHandle hSourceHandle, IntPtr hTargetProcess, diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.EnumProcessModules.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.EnumProcessModules.cs index 5a5ae4ddca197..e88e5050b84cb 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.EnumProcessModules.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.EnumProcessModules.cs @@ -9,7 +9,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true, EntryPoint = "K32EnumProcessModules")] - internal static extern bool EnumProcessModules(SafeProcessHandle handle, IntPtr[]? modules, int size, out int needed); + [GeneratedDllImport(Libraries.Kernel32, EntryPoint = "K32EnumProcessModules", CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial bool EnumProcessModules(SafeProcessHandle handle, IntPtr[]? modules, int size, out int needed); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.EnumProcesses.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.EnumProcesses.cs index f5298dc2cc879..6ffb508d3f018 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.EnumProcesses.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.EnumProcesses.cs @@ -7,7 +7,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true, EntryPoint = "K32EnumProcesses")] - internal static extern bool EnumProcesses(int[] processIds, int size, out int needed); + [GeneratedDllImport(Libraries.Kernel32, EntryPoint = "K32EnumProcesses", CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial bool EnumProcesses(int[] processIds, int size, out int needed); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.FillConsoleOutputAttribute.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.FillConsoleOutputAttribute.cs index 4a1657f02119a..9d8542a8a3449 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.FillConsoleOutputAttribute.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.FillConsoleOutputAttribute.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, SetLastError = true, CharSet = CharSet.Unicode)] - internal static extern bool FillConsoleOutputAttribute(IntPtr hConsoleOutput, short wColorAttribute, int numCells, COORD startCoord, out int pNumBytesWritten); + [GeneratedDllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial bool FillConsoleOutputAttribute(IntPtr hConsoleOutput, short wColorAttribute, int numCells, COORD startCoord, out int pNumBytesWritten); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.FillConsoleOutputCharacter.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.FillConsoleOutputCharacter.cs index 5b5f6ac477246..4e9f464e4702a 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.FillConsoleOutputCharacter.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.FillConsoleOutputCharacter.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "FillConsoleOutputCharacterW")] - internal static extern bool FillConsoleOutputCharacter(IntPtr hConsoleOutput, char character, int nLength, COORD dwWriteCoord, out int pNumCharsWritten); + [GeneratedDllImport(Libraries.Kernel32, EntryPoint = "FillConsoleOutputCharacterW", CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial bool FillConsoleOutputCharacter(IntPtr hConsoleOutput, char character, int nLength, COORD dwWriteCoord, out int pNumCharsWritten); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.FindClose.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.FindClose.cs index 9999d8b94186e..c32ccf24f480b 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.FindClose.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.FindClose.cs @@ -8,7 +8,12 @@ internal static partial class Interop { internal static partial class Kernel32 { +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Kernel32, SetLastError = true)] + internal static partial bool FindClose(IntPtr hFindFile); +#else [DllImport(Libraries.Kernel32, SetLastError = true)] internal static extern bool FindClose(IntPtr hFindFile); +#endif } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.FlushFileBuffers.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.FlushFileBuffers.cs index 094ef6134db79..9b0e8571854e3 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.FlushFileBuffers.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.FlushFileBuffers.cs @@ -7,8 +7,14 @@ internal static partial class Interop { internal static partial class Kernel32 { +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Kernel32, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + internal static partial bool FlushFileBuffers(SafeHandle hHandle); +#else [DllImport(Libraries.Kernel32, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool FlushFileBuffers(SafeHandle hHandle); +#endif } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.FlushViewOfFile.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.FlushViewOfFile.cs index ce82cfa23c33d..72a0560fa1f79 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.FlushViewOfFile.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.FlushViewOfFile.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, SetLastError = true)] - internal static extern bool FlushViewOfFile(IntPtr lpBaseAddress, UIntPtr dwNumberOfBytesToFlush); + [GeneratedDllImport(Libraries.Kernel32, SetLastError = true)] + internal static partial bool FlushViewOfFile(IntPtr lpBaseAddress, UIntPtr dwNumberOfBytesToFlush); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.FormatMessage.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.FormatMessage.cs index 53b0ad25573dd..27eccfd454052 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.FormatMessage.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.FormatMessage.cs @@ -15,7 +15,9 @@ internal static partial class Kernel32 private const int FORMAT_MESSAGE_ALLOCATE_BUFFER = 0x00000100; private const int ERROR_INSUFFICIENT_BUFFER = 0x7A; - [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, EntryPoint = "FormatMessageW", SetLastError = true, BestFitMapping = true, ExactSpelling = true)] +#pragma warning disable DLLIMPORTGENANALYZER015 // Use 'GeneratedDllImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time + // Disabled since FormatMessage is a QCall in some scenarios and DllImportGenerator doesn't support QCalls. + [DllImport(Libraries.Kernel32, EntryPoint = "FormatMessageW", BestFitMapping = true, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] private static extern unsafe int FormatMessage( int dwFlags, IntPtr lpSource, @@ -24,6 +26,7 @@ private static extern unsafe int FormatMessage( void* lpBuffer, int nSize, IntPtr arguments); +#pragma warning restore DLLIMPORTGENANALYZER015 /// /// Returns a string message for the specified Win32 error code. diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetComputerName.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetComputerName.cs index 4d41070638856..e186ac2be5725 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetComputerName.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetComputerName.cs @@ -10,7 +10,7 @@ internal static partial class Interop internal static partial class Kernel32 { [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, EntryPoint = "GetComputerNameW", ExactSpelling = true)] - private static extern int GetComputerName(ref char lpBuffer, ref uint nSize); + private static unsafe extern int GetComputerName(char* lpBuffer, uint* nSize); // maximum length of the NETBIOS name (not including NULL) private const int MAX_COMPUTERNAME_LENGTH = 15; @@ -19,10 +19,15 @@ internal static partial class Kernel32 { Span buffer = stackalloc char[MAX_COMPUTERNAME_LENGTH + 1]; uint length = (uint)buffer.Length; - - return GetComputerName(ref MemoryMarshal.GetReference(buffer), ref length) != 0 ? - buffer.Slice(0, (int)length).ToString() : - null; + unsafe + { + fixed (char* lpBuffer = &MemoryMarshal.GetReference(buffer)) + { + return GetComputerName(lpBuffer, &length) != 0 ? + buffer.Slice(0, (int)length).ToString() : + null; + } + } } } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetConsoleMode.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetConsoleMode.cs index 99e725c885bfb..b03d88f475094 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetConsoleMode.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetConsoleMode.cs @@ -8,8 +8,13 @@ internal static partial class Interop { internal static partial class Kernel32 { +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Kernel32, SetLastError = true)] + internal static partial bool GetConsoleMode(IntPtr handle, out int mode); +#else [DllImport(Libraries.Kernel32, SetLastError = true)] internal static extern bool GetConsoleMode(IntPtr handle, out int mode); +#endif internal static bool IsGetConsoleModeCallSuccessful(IntPtr handle) { @@ -17,8 +22,13 @@ internal static bool IsGetConsoleModeCallSuccessful(IntPtr handle) return GetConsoleMode(handle, out mode); } +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Kernel32, SetLastError = true)] + internal static partial bool SetConsoleMode(IntPtr handle, int mode); +#else [DllImport(Libraries.Kernel32, SetLastError = true)] internal static extern bool SetConsoleMode(IntPtr handle, int mode); +#endif internal const int ENABLE_PROCESSED_INPUT = 0x0001; internal const uint ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004; diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetConsoleScreenBufferInfo.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetConsoleScreenBufferInfo.cs index b782fb94d391b..3ff5965ac77d3 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetConsoleScreenBufferInfo.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetConsoleScreenBufferInfo.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, SetLastError = true)] - internal static extern bool GetConsoleScreenBufferInfo(IntPtr hConsoleOutput, out CONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo); + [GeneratedDllImport(Libraries.Kernel32, SetLastError = true)] + internal static partial bool GetConsoleScreenBufferInfo(IntPtr hConsoleOutput, out CONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetConsoleTitle.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetConsoleTitle.cs index 39f7ef1e4678e..f757cfa892cd3 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetConsoleTitle.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetConsoleTitle.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)] - internal static extern unsafe uint GetConsoleTitleW(char* title, uint nSize); + [GeneratedDllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] + internal static unsafe partial uint GetConsoleTitleW(char* title, uint nSize); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetDiskFreeSpaceEx.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetDiskFreeSpaceEx.cs index d7dfb5d5c1d09..c9d6b8d878774 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetDiskFreeSpaceEx.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetDiskFreeSpaceEx.cs @@ -9,7 +9,7 @@ internal static partial class Kernel32 { // NOTE: The out parameters are PULARGE_INTEGERs and may require // some byte munging magic. - [DllImport(Libraries.Kernel32, EntryPoint = "GetDiskFreeSpaceExW", CharSet = CharSet.Unicode, SetLastError = true, BestFitMapping = false)] - internal static extern bool GetDiskFreeSpaceEx(string drive, out long freeBytesForUser, out long totalBytes, out long freeBytes); + [GeneratedDllImport(Libraries.Kernel32, EntryPoint = "GetDiskFreeSpaceExW", CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial bool GetDiskFreeSpaceEx(string drive, out long freeBytesForUser, out long totalBytes, out long freeBytes); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetDriveType.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetDriveType.cs index 4c45c528f9aa1..51321d6d6b0a0 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetDriveType.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetDriveType.cs @@ -7,8 +7,8 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, EntryPoint = "GetDriveTypeW", CharSet = CharSet.Unicode, SetLastError = true, BestFitMapping = false)] - internal static extern int GetDriveType(string drive); + [GeneratedDllImport(Libraries.Kernel32, EntryPoint = "GetDriveTypeW", CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial int GetDriveType(string drive); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetExitCodeProcess.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetExitCodeProcess.cs index 6184ad87a5bc5..05260a7d4882d 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetExitCodeProcess.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetExitCodeProcess.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, SetLastError = true)] - internal static extern bool GetExitCodeProcess(SafeProcessHandle processHandle, out int exitCode); + [GeneratedDllImport(Libraries.Kernel32, SetLastError = true)] + internal static partial bool GetExitCodeProcess(SafeProcessHandle processHandle, out int exitCode); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetFileAttributesEx.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetFileAttributesEx.cs index 0df1c75cd4c65..25ca04d5c2eb8 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetFileAttributesEx.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetFileAttributesEx.cs @@ -11,8 +11,16 @@ internal static partial class Kernel32 /// /// WARNING: This method does not implicitly handle long paths. Use GetFileAttributesEx. /// - [DllImport(Libraries.Kernel32, EntryPoint = "GetFileAttributesExW", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true)] - private static extern bool GetFileAttributesExPrivate(string? name, GET_FILEEX_INFO_LEVELS fileInfoLevel, ref WIN32_FILE_ATTRIBUTE_DATA lpFileInformation); +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Kernel32, EntryPoint = "GetFileAttributesExW", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] + private static partial bool GetFileAttributesExPrivate( +#else + [DllImport(Libraries.Kernel32, EntryPoint = "GetFileAttributesExW", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] + private static extern bool GetFileAttributesExPrivate( +#endif + string? name, + GET_FILEEX_INFO_LEVELS fileInfoLevel, + ref WIN32_FILE_ATTRIBUTE_DATA lpFileInformation); internal static bool GetFileAttributesEx(string? name, GET_FILEEX_INFO_LEVELS fileInfoLevel, ref WIN32_FILE_ATTRIBUTE_DATA lpFileInformation) { diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetFileType_IntPtr.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetFileType_IntPtr.cs index 313ca31e97dd5..1a2e5432e3a6a 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetFileType_IntPtr.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetFileType_IntPtr.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, SetLastError = true)] - internal static extern uint GetFileType(IntPtr hFile); + [GeneratedDllImport(Libraries.Kernel32, SetLastError = true)] + internal static partial uint GetFileType(IntPtr hFile); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetFileType_SafeHandle.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetFileType_SafeHandle.cs index 557866dbf55b8..d5d2062f05d13 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetFileType_SafeHandle.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetFileType_SafeHandle.cs @@ -7,7 +7,12 @@ internal static partial class Interop { internal static partial class Kernel32 { +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Kernel32, SetLastError = true)] + internal static partial int GetFileType(SafeHandle hFile); +#else [DllImport(Libraries.Kernel32, SetLastError = true)] internal static extern int GetFileType(SafeHandle hFile); +#endif } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetFullPathNameW.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetFullPathNameW.cs index 0c69a28cc79ea..191cfd64591d1 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetFullPathNameW.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetFullPathNameW.cs @@ -11,7 +11,16 @@ internal static partial class Kernel32 /// /// WARNING: This method does not implicitly handle long paths. Use GetFullPathName or PathHelper. /// - [DllImport(Libraries.Kernel32, SetLastError = true, CharSet = CharSet.Unicode, BestFitMapping = false, ExactSpelling = true)] - internal static extern uint GetFullPathNameW(ref char lpFileName, uint nBufferLength, ref char lpBuffer, IntPtr lpFilePart); +#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, + IntPtr lpFilePart); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetLargestConsoleWindowSize.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetLargestConsoleWindowSize.cs index d26a2d924f5c1..ca7bf2b5ef48a 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetLargestConsoleWindowSize.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetLargestConsoleWindowSize.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, SetLastError = true)] - internal static extern Interop.Kernel32.COORD GetLargestConsoleWindowSize(IntPtr hConsoleOutput); + [GeneratedDllImport(Libraries.Kernel32, SetLastError = true)] + internal static partial Interop.Kernel32.COORD GetLargestConsoleWindowSize(IntPtr hConsoleOutput); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetLogicalDrives.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetLogicalDrives.cs index 557c019e6a647..c756043141c59 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetLogicalDrives.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetLogicalDrives.cs @@ -7,7 +7,12 @@ internal static partial class Interop { internal static partial class Kernel32 { +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Kernel32, SetLastError = true)] + internal static partial int GetLogicalDrives(); +#else [DllImport(Libraries.Kernel32, SetLastError = true)] internal static extern int GetLogicalDrives(); +#endif } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetLongPathNameW.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetLongPathNameW.cs index 616edc72c61b7..10d536df0964e 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetLongPathNameW.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetLongPathNameW.cs @@ -10,7 +10,16 @@ internal static partial class Kernel32 /// /// WARNING: This method does not implicitly handle long paths. Use GetFullPath/PathHelper. /// - [DllImport(Libraries.Kernel32, SetLastError = true, CharSet = CharSet.Unicode, BestFitMapping = false, ExactSpelling = true)] - internal static extern uint GetLongPathNameW(ref char lpszShortPath, ref char lpszLongPath, uint cchBuffer); +#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); + } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetModuleBaseName.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetModuleBaseName.cs index 9cfb175b0a16c..930b96442f112 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetModuleBaseName.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetModuleBaseName.cs @@ -9,7 +9,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true, BestFitMapping = false, EntryPoint = "K32GetModuleBaseNameW")] - internal static extern int GetModuleBaseName(SafeProcessHandle processHandle, IntPtr moduleHandle, [Out] char[] baseName, int size); + [GeneratedDllImport(Libraries.Kernel32, EntryPoint = "K32GetModuleBaseNameW", CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial int GetModuleBaseName(SafeProcessHandle processHandle, IntPtr moduleHandle, [Out] char[] baseName, int size); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetModuleFileNameEx.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetModuleFileNameEx.cs index fc99fca9a0942..285ad50403d8f 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetModuleFileNameEx.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetModuleFileNameEx.cs @@ -9,7 +9,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true, BestFitMapping = false, EntryPoint = "K32GetModuleFileNameExW")] - internal static extern int GetModuleFileNameEx(SafeProcessHandle processHandle, IntPtr moduleHandle, [Out] char[] baseName, int size); + [GeneratedDllImport(Libraries.Kernel32, EntryPoint = "K32GetModuleFileNameExW", CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial int GetModuleFileNameEx(SafeProcessHandle processHandle, IntPtr moduleHandle, [Out] char[] baseName, int size); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetModuleInformation.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetModuleInformation.cs index 6ec386711ca4c..73470ceecb841 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetModuleInformation.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetModuleInformation.cs @@ -9,8 +9,8 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true, EntryPoint = "K32GetModuleInformation")] - private static extern bool GetModuleInformation(SafeProcessHandle processHandle, IntPtr moduleHandle, out NtModuleInfo ntModuleInfo, int size); + [GeneratedDllImport(Libraries.Kernel32, EntryPoint = "K32GetModuleInformation", CharSet = CharSet.Unicode, SetLastError = true)] + private static partial bool GetModuleInformation(SafeProcessHandle processHandle, IntPtr moduleHandle, out NtModuleInfo ntModuleInfo, int size); internal static unsafe bool GetModuleInformation(SafeProcessHandle processHandle, IntPtr moduleHandle, out NtModuleInfo ntModuleInfo) => GetModuleInformation(processHandle, moduleHandle, out ntModuleInfo, sizeof(NtModuleInfo)); diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetNamedPipeHandleState.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetNamedPipeHandleState.cs index f98c2c1c31b5c..a8c28bf9ca4ea 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetNamedPipeHandleState.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetNamedPipeHandleState.cs @@ -8,8 +8,8 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)] - internal static extern unsafe bool GetNamedPipeHandleStateW( + [GeneratedDllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] + internal static unsafe partial bool GetNamedPipeHandleStateW( SafePipeHandle hNamedPipe, uint* lpState, uint* lpCurInstances, diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetNamedPipeInfo.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetNamedPipeInfo.cs index 586f661857c2e..b370c8efb2b56 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetNamedPipeInfo.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetNamedPipeInfo.cs @@ -8,8 +8,8 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, SetLastError = true)] - internal static extern unsafe bool GetNamedPipeInfo( + [GeneratedDllImport(Libraries.Kernel32, SetLastError = true)] + internal static unsafe partial bool GetNamedPipeInfo( SafePipeHandle hNamedPipe, uint* lpFlags, uint* lpOutBufferSize, diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetNativeSystemInfo.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetNativeSystemInfo.cs index 60bbcca66c548..2322bdd4d7b14 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetNativeSystemInfo.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetNativeSystemInfo.cs @@ -9,6 +9,6 @@ internal static partial class Interop internal static partial class Kernel32 { [DllImport(Libraries.Kernel32)] - internal static extern void GetNativeSystemInfo(out SYSTEM_INFO lpSystemInfo); + internal static unsafe extern void GetNativeSystemInfo(SYSTEM_INFO* lpSystemInfo); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetPriorityClass.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetPriorityClass.cs index 385b534acb3f8..9ce76e68252ae 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetPriorityClass.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetPriorityClass.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern int GetPriorityClass(SafeProcessHandle handle); + [GeneratedDllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial int GetPriorityClass(SafeProcessHandle handle); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetProcessAffinityMask.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetProcessAffinityMask.cs index 0cd7484e25289..ced602109c306 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetProcessAffinityMask.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetProcessAffinityMask.cs @@ -9,7 +9,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern bool GetProcessAffinityMask(SafeProcessHandle handle, out IntPtr processMask, out IntPtr systemMask); + [GeneratedDllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial bool GetProcessAffinityMask(SafeProcessHandle handle, out IntPtr processMask, out IntPtr systemMask); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetProcessId.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetProcessId.cs index 9d9167df4a13c..5261c0d5a065d 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetProcessId.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetProcessId.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32)] - public static extern int GetProcessId(SafeProcessHandle nativeHandle); + [GeneratedDllImport(Libraries.Kernel32)] + public static partial int GetProcessId(SafeProcessHandle nativeHandle); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetProcessPriorityBoost.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetProcessPriorityBoost.cs index 93619bebe7f97..d5efb5e07cabd 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetProcessPriorityBoost.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetProcessPriorityBoost.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern bool GetProcessPriorityBoost(SafeProcessHandle handle, out bool disabled); + [GeneratedDllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial bool GetProcessPriorityBoost(SafeProcessHandle handle, out bool disabled); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetProcessTimes.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetProcessTimes.cs index 1c585d6e74a80..e76f80712ba4a 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetProcessTimes.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetProcessTimes.cs @@ -8,7 +8,13 @@ internal static partial class Interop { internal static partial class Kernel32 { +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial bool GetProcessTimes( +#else [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern bool GetProcessTimes(SafeProcessHandle handle, out long creation, out long exit, out long kernel, out long user); + internal static extern bool GetProcessTimes( +#endif + SafeProcessHandle handle, out long creation, out long exit, out long kernel, out long user); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetProcessWorkingSetSizeEx.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetProcessWorkingSetSizeEx.cs index 64284d546f7fa..74ce0e8a6a3a5 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetProcessWorkingSetSizeEx.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetProcessWorkingSetSizeEx.cs @@ -9,7 +9,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern bool GetProcessWorkingSetSizeEx(SafeProcessHandle handle, out IntPtr min, out IntPtr max, out int flags); + [GeneratedDllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial bool GetProcessWorkingSetSizeEx(SafeProcessHandle handle, out IntPtr min, out IntPtr max, out int flags); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetSystemInfo.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetSystemInfo.cs index 48e4b23dfcc3d..f3872f106180e 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetSystemInfo.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetSystemInfo.cs @@ -8,6 +8,6 @@ internal static partial class Interop internal static partial class Kernel32 { [DllImport(Libraries.Kernel32)] - internal static extern void GetSystemInfo(out SYSTEM_INFO lpSystemInfo); + internal static unsafe extern void GetSystemInfo(SYSTEM_INFO* lpSystemInfo); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetThreadPriority.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetThreadPriority.cs index b55390030f24b..5e30e6b5d085d 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetThreadPriority.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetThreadPriority.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern int GetThreadPriority(SafeThreadHandle handle); + [GeneratedDllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial int GetThreadPriority(SafeThreadHandle handle); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetThreadPriorityBoost.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetThreadPriorityBoost.cs index e9a9bc9924174..18cb3cb262384 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetThreadPriorityBoost.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetThreadPriorityBoost.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern bool GetThreadPriorityBoost(SafeThreadHandle handle, out bool disabled); + [GeneratedDllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial bool GetThreadPriorityBoost(SafeThreadHandle handle, out bool disabled); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetThreadTimes.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetThreadTimes.cs index 54e2e43458ccb..0d4d5b03988e0 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetThreadTimes.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetThreadTimes.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern bool GetThreadTimes(SafeThreadHandle handle, out long creation, out long exit, out long kernel, out long user); + [GeneratedDllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial bool GetThreadTimes(SafeThreadHandle handle, out long creation, out long exit, out long kernel, out long user); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetVolumeInformation.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetVolumeInformation.cs index 48775f06c5a9d..05a2b6357cc40 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetVolumeInformation.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetVolumeInformation.cs @@ -8,8 +8,21 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, EntryPoint = "GetVolumeInformationW", CharSet = CharSet.Unicode, SetLastError = true, BestFitMapping = false)] - internal static extern unsafe bool GetVolumeInformation(string drive, char* volumeName, int volumeNameBufLen, int* volSerialNumber, int* maxFileNameLen, out int fileSystemFlags, char* fileSystemName, int fileSystemNameBufLen); +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Kernel32, EntryPoint = "GetVolumeInformationW", CharSet = CharSet.Unicode, SetLastError = true)] + internal static unsafe partial bool GetVolumeInformation( +#else + [DllImport(Libraries.Kernel32, EntryPoint = "GetVolumeInformationW", CharSet = CharSet.Unicode, SetLastError = true)] + internal static unsafe extern bool GetVolumeInformation( +#endif + string drive, + char* volumeName, + int volumeNameBufLen, + int* volSerialNumber, + int* maxFileNameLen, + out int fileSystemFlags, + char* fileSystemName, + int fileSystemNameBufLen); internal const uint FILE_SUPPORTS_ENCRYPTION = 0x00020000; } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.HandleInformation.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.HandleInformation.cs index fdc12144d35ae..85c07d6c34a99 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.HandleInformation.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.HandleInformation.cs @@ -17,7 +17,7 @@ internal enum HandleFlags : uint HANDLE_FLAG_PROTECT_FROM_CLOSE = 2 } - [DllImport(Libraries.Kernel32, SetLastError = true)] - internal static extern bool SetHandleInformation(SafeHandle hObject, HandleFlags dwMask, HandleFlags dwFlags); + [GeneratedDllImport(Libraries.Kernel32, SetLastError = true)] + internal static partial bool SetHandleInformation(SafeHandle hObject, HandleFlags dwMask, HandleFlags dwFlags); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.IsWow64Process_IntPtr.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.IsWow64Process_IntPtr.cs index 60ddd4225b2a0..cfd93cc036b7f 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.IsWow64Process_IntPtr.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.IsWow64Process_IntPtr.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, SetLastError = true)] - internal static extern bool IsWow64Process(IntPtr hProcess, out bool Wow64Process); + [GeneratedDllImport(Libraries.Kernel32, SetLastError = true)] + internal static partial bool IsWow64Process(IntPtr hProcess, out bool Wow64Process); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.IsWow64Process_SafeProcessHandle.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.IsWow64Process_SafeProcessHandle.cs index eb365d7e18a54..764456f73e116 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.IsWow64Process_SafeProcessHandle.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.IsWow64Process_SafeProcessHandle.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, SetLastError = true)] - internal static extern bool IsWow64Process(SafeProcessHandle hProcess, out bool Wow64Process); + [GeneratedDllImport(Libraries.Kernel32, SetLastError = true)] + internal static partial bool IsWow64Process(SafeProcessHandle hProcess, out bool Wow64Process); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.LoadLibraryEx_IntPtr.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.LoadLibraryEx_IntPtr.cs index f5fdb6ca97fa6..78d1c184fb8a2 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.LoadLibraryEx_IntPtr.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.LoadLibraryEx_IntPtr.cs @@ -11,7 +11,7 @@ internal static partial class Kernel32 internal const int LOAD_LIBRARY_AS_DATAFILE = 0x00000002; internal const int LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800; - [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, EntryPoint = "LoadLibraryExW", SetLastError = true, ExactSpelling = true)] - internal static extern IntPtr LoadLibraryEx(string libFilename, IntPtr reserved, int flags); + [GeneratedDllImport(Libraries.Kernel32, EntryPoint = "LoadLibraryExW", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] + internal static partial IntPtr LoadLibraryEx(string libFilename, IntPtr reserved, int flags); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.MapViewOfFile.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.MapViewOfFile.cs index 73f714d64164c..764a6ad8080a9 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.MapViewOfFile.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.MapViewOfFile.cs @@ -9,8 +9,13 @@ internal static partial class Interop { internal static partial class Kernel32 { +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Kernel32, EntryPoint = "MapViewOfFile", CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial SafeMemoryMappedViewHandle MapViewOfFile( +#else [DllImport(Libraries.Kernel32, EntryPoint = "MapViewOfFile", CharSet = CharSet.Unicode, SetLastError = true)] internal static extern SafeMemoryMappedViewHandle MapViewOfFile( +#endif SafeMemoryMappedFileHandle hFileMappingObject, int dwDesiredAccess, int dwFileOffsetHigh, diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.MoveFileEx.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.MoveFileEx.cs index 507d325517443..b76e051ab114f 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.MoveFileEx.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.MoveFileEx.cs @@ -15,8 +15,14 @@ internal static partial class Kernel32 /// /// WARNING: This method does not implicitly handle long paths. Use MoveFile. /// - [DllImport(Libraries.Kernel32, EntryPoint = "MoveFileExW", SetLastError = true, CharSet = CharSet.Unicode, BestFitMapping = false)] - private static extern bool MoveFileExPrivate(string src, string dst, uint flags); +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Kernel32, EntryPoint = "MoveFileExW", CharSet = CharSet.Unicode, SetLastError = true)] + private static partial bool MoveFileExPrivate( +#else + [DllImport(Libraries.Kernel32, EntryPoint = "MoveFileExW", CharSet = CharSet.Unicode, SetLastError = true)] + private static extern bool MoveFileExPrivate( +#endif + string src, string dst, uint flags); /// /// Moves a file or directory, optionally overwriting existing destination file. NOTE: overwrite must be false for directories. diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.OpenFileMapping.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.OpenFileMapping.cs index 70e3075e816c4..6ac60a8fa558f 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.OpenFileMapping.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.OpenFileMapping.cs @@ -8,7 +8,15 @@ internal static partial class Interop { internal static partial class Kernel32 { +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Kernel32, EntryPoint = "OpenFileMappingW", CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial SafeMemoryMappedFileHandle OpenFileMapping( +#else [DllImport(Libraries.Kernel32, EntryPoint = "OpenFileMappingW", CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern SafeMemoryMappedFileHandle OpenFileMapping(int dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, string lpName); + internal static extern SafeMemoryMappedFileHandle OpenFileMapping( +#endif + int dwDesiredAccess, + [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, + string lpName); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.OpenProcess.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.OpenProcess.cs index 970193fe756ef..2eaa7a9e5f597 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.OpenProcess.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.OpenProcess.cs @@ -8,7 +8,13 @@ internal static partial class Interop { internal static partial class Kernel32 { +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial SafeProcessHandle OpenProcess( +#else [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern SafeProcessHandle OpenProcess(int access, bool inherit, int processId); + internal static extern SafeProcessHandle OpenProcess( +#endif + int access, bool inherit, int processId); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.OpenThread.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.OpenThread.cs index 0eebf8b61d96d..dab1c7c79d964 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.OpenThread.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.OpenThread.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern SafeThreadHandle OpenThread(int access, bool inherit, int threadId); + [GeneratedDllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial SafeThreadHandle OpenThread(int access, bool inherit, int threadId); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.PeekConsoleInput.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.PeekConsoleInput.cs index 98ef5c59c7898..179d0b29dbe6f 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.PeekConsoleInput.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.PeekConsoleInput.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "PeekConsoleInputW")] - internal static extern bool PeekConsoleInput(IntPtr hConsoleInput, out InputRecord buffer, int numInputRecords_UseOne, out int numEventsRead); + [GeneratedDllImport(Libraries.Kernel32, EntryPoint = "PeekConsoleInputW", CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial bool PeekConsoleInput(IntPtr hConsoleInput, out InputRecord buffer, int numInputRecords_UseOne, out int numEventsRead); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ReadConsole.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ReadConsole.cs index 1ef39b4465df2..022d0849b5e38 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ReadConsole.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ReadConsole.cs @@ -8,8 +8,8 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true, EntryPoint = "ReadConsoleW")] - internal static extern unsafe bool ReadConsole( + [GeneratedDllImport(Libraries.Kernel32, EntryPoint = "ReadConsoleW", CharSet = CharSet.Unicode, SetLastError = true)] + internal static unsafe partial bool ReadConsole( IntPtr hConsoleInput, byte* lpBuffer, int nNumberOfCharsToRead, diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ReadConsoleInput.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ReadConsoleInput.cs index 413ad3d88042f..c6ed13076daf5 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ReadConsoleInput.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ReadConsoleInput.cs @@ -16,7 +16,7 @@ internal struct KeyEventRecord internal short repeatCount; internal short virtualKeyCode; internal short virtualScanCode; - internal char uChar; // Union between WCHAR and ASCII char + internal ushort uChar; // Union between WCHAR and ASCII char internal int controlKeyState; } @@ -32,9 +32,7 @@ internal struct InputRecord internal static partial class Kernel32 { - - [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true, EntryPoint = "ReadConsoleInputW")] - internal static extern bool ReadConsoleInput(IntPtr hConsoleInput, out InputRecord buffer, int numInputRecords_UseOne, out int numEventsRead); - + [GeneratedDllImport(Libraries.Kernel32, EntryPoint = "ReadConsoleInputW", CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial bool ReadConsoleInput(IntPtr hConsoleInput, out InputRecord buffer, int numInputRecords_UseOne, out int numEventsRead); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ReadConsoleOutput.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ReadConsoleOutput.cs index 5a40457dc5f26..d5722aea5ecb9 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ReadConsoleOutput.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ReadConsoleOutput.cs @@ -15,7 +15,7 @@ internal struct CHAR_INFO private short attributes; } - [DllImport(Libraries.Kernel32, SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "ReadConsoleOutputW")] - internal static extern unsafe bool ReadConsoleOutput(IntPtr hConsoleOutput, CHAR_INFO* pBuffer, COORD bufferSize, COORD bufferCoord, ref SMALL_RECT readRegion); + [GeneratedDllImport(Libraries.Kernel32, EntryPoint = "ReadConsoleOutputW", CharSet = CharSet.Unicode, SetLastError = true)] + internal static unsafe partial bool ReadConsoleOutput(IntPtr hConsoleOutput, CHAR_INFO* pBuffer, COORD bufferSize, COORD bufferCoord, ref SMALL_RECT readRegion); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ReadDirectoryChangesW.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ReadDirectoryChangesW.cs index ccbffb6d14a82..aa94e95d556a5 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ReadDirectoryChangesW.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ReadDirectoryChangesW.cs @@ -10,8 +10,8 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, EntryPoint = "ReadDirectoryChangesW", CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern unsafe bool ReadDirectoryChangesW( + [GeneratedDllImport(Libraries.Kernel32, EntryPoint = "ReadDirectoryChangesW", CharSet = CharSet.Unicode, SetLastError = true)] + internal static unsafe partial bool ReadDirectoryChangesW( SafeFileHandle hDirectory, byte[] lpBuffer, uint nBufferLength, diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ReadFile_IntPtr.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ReadFile_IntPtr.cs index 2ccefd764674a..6e8aa47a7f9ad 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ReadFile_IntPtr.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ReadFile_IntPtr.cs @@ -8,8 +8,8 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, SetLastError = true)] - internal static extern unsafe int ReadFile( + [GeneratedDllImport(Libraries.Kernel32, SetLastError = true)] + internal static unsafe partial int ReadFile( IntPtr handle, byte* bytes, int numBytesToRead, diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ReadFile_SafeHandle_IntPtr.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ReadFile_SafeHandle_IntPtr.cs index d2ab765d448bc..9651a10fb64bd 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ReadFile_SafeHandle_IntPtr.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ReadFile_SafeHandle_IntPtr.cs @@ -8,8 +8,13 @@ internal static partial class Interop { internal static partial class Kernel32 { +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Kernel32, SetLastError = true)] + internal static unsafe partial int ReadFile( +#else [DllImport(Libraries.Kernel32, SetLastError = true)] internal static extern unsafe int ReadFile( +#endif SafeHandle handle, byte* bytes, int numBytesToRead, diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ReadFile_SafeHandle_NativeOverlapped.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ReadFile_SafeHandle_NativeOverlapped.cs index c6fb2c4311cf3..ba9b6a91c0eb6 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ReadFile_SafeHandle_NativeOverlapped.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ReadFile_SafeHandle_NativeOverlapped.cs @@ -9,16 +9,26 @@ internal static partial class Interop { internal static partial class Kernel32 { +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Kernel32, SetLastError = true)] + internal static unsafe partial int ReadFile( +#else [DllImport(Libraries.Kernel32, SetLastError = true)] internal static extern unsafe int ReadFile( +#endif SafeHandle handle, byte* bytes, int numBytesToRead, IntPtr numBytesRead_mustBeZero, NativeOverlapped* overlapped); +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Kernel32, SetLastError = true)] + internal static unsafe partial int ReadFile( +#else [DllImport(Libraries.Kernel32, SetLastError = true)] internal static extern unsafe int ReadFile( +#endif SafeHandle handle, byte* bytes, int numBytesToRead, diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.RemoveDirectory.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.RemoveDirectory.cs index 2d9d01ea06445..96754abc2f5a8 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.RemoveDirectory.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.RemoveDirectory.cs @@ -12,8 +12,13 @@ internal static partial class Kernel32 /// /// WARNING: This method does not implicitly handle long paths. Use RemoveDirectory. /// - [DllImport(Libraries.Kernel32, EntryPoint = "RemoveDirectoryW", SetLastError = true, CharSet = CharSet.Unicode, BestFitMapping = false)] +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Kernel32, EntryPoint = "RemoveDirectoryW", CharSet = CharSet.Unicode, SetLastError = true)] + private static partial bool RemoveDirectoryPrivate(string path); +#else + [DllImport(Libraries.Kernel32, EntryPoint = "RemoveDirectoryW", CharSet = CharSet.Unicode, SetLastError = true)] private static extern bool RemoveDirectoryPrivate(string path); +#endif internal static bool RemoveDirectory(string path) { diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ReplaceFile.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ReplaceFile.cs index e3a6eb5c2d805..cb1353628b3af 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ReplaceFile.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.ReplaceFile.cs @@ -9,8 +9,13 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, EntryPoint = "ReplaceFileW", SetLastError = true, CharSet = CharSet.Unicode, BestFitMapping = false)] +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Kernel32, EntryPoint = "ReplaceFileW", CharSet = CharSet.Unicode, SetLastError = true)] + private static partial bool ReplaceFilePrivate( +#else + [DllImport(Libraries.Kernel32, EntryPoint = "ReplaceFileW", CharSet = CharSet.Unicode, SetLastError = true)] private static extern bool ReplaceFilePrivate( +#endif string replacedFileName, string replacementFileName, string? backupFileName, int dwReplaceFlags, IntPtr lpExclude, IntPtr lpReserved); diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetConsoleCP.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetConsoleCP.cs index e7c2140d16beb..adf85070a1e3c 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetConsoleCP.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetConsoleCP.cs @@ -7,7 +7,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, SetLastError = true)] - internal static extern bool SetConsoleCP(int codePage); + [GeneratedDllImport(Libraries.Kernel32, SetLastError = true)] + internal static partial bool SetConsoleCP(int codePage); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetConsoleCtrlHandler.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetConsoleCtrlHandler.cs index 112d5b4d5a89b..8a64d27c19660 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetConsoleCtrlHandler.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetConsoleCtrlHandler.cs @@ -13,7 +13,12 @@ internal static partial class Kernel32 internal const int CTRL_LOGOFF_EVENT = 5; internal const int CTRL_SHUTDOWN_EVENT = 6; +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Kernel32, SetLastError = true)] + internal static unsafe partial bool SetConsoleCtrlHandler(delegate* unmanaged handler, bool Add); +#else [DllImport(Libraries.Kernel32, SetLastError = true)] internal static extern unsafe bool SetConsoleCtrlHandler(delegate* unmanaged HandlerRoutine, bool Add); +#endif } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetConsoleCursorPosition.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetConsoleCursorPosition.cs index 39a951b4399bb..78f6440e75ac2 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetConsoleCursorPosition.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetConsoleCursorPosition.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, SetLastError = true)] - internal static extern bool SetConsoleCursorPosition(IntPtr hConsoleOutput, COORD cursorPosition); + [GeneratedDllImport(Libraries.Kernel32, SetLastError = true)] + internal static partial bool SetConsoleCursorPosition(IntPtr hConsoleOutput, COORD cursorPosition); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetConsoleOutputCP.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetConsoleOutputCP.cs index 81441a4a66012..3a705e51c8f67 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetConsoleOutputCP.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetConsoleOutputCP.cs @@ -7,7 +7,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, SetLastError = true)] - internal static extern bool SetConsoleOutputCP(int codePage); + [GeneratedDllImport(Libraries.Kernel32, SetLastError = true)] + internal static partial bool SetConsoleOutputCP(int codePage); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetConsoleScreenBufferSize.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetConsoleScreenBufferSize.cs index 7c55bf6b3c614..049a9821b988e 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetConsoleScreenBufferSize.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetConsoleScreenBufferSize.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, SetLastError = true)] - internal static extern bool SetConsoleScreenBufferSize(IntPtr hConsoleOutput, Interop.Kernel32.COORD size); + [GeneratedDllImport(Libraries.Kernel32, SetLastError = true)] + internal static partial bool SetConsoleScreenBufferSize(IntPtr hConsoleOutput, Interop.Kernel32.COORD size); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetConsoleTextAttribute.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetConsoleTextAttribute.cs index a4cfcd65b49a9..23bd38e24bf2c 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetConsoleTextAttribute.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetConsoleTextAttribute.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, SetLastError = true)] - internal static extern int SetConsoleTextAttribute(IntPtr hConsoleOutput, short wAttributes); + [GeneratedDllImport(Libraries.Kernel32, SetLastError = true)] + internal static partial int SetConsoleTextAttribute(IntPtr hConsoleOutput, short wAttributes); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetConsoleTitle.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetConsoleTitle.cs index 34fb5bf40e436..246f395c9a024 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetConsoleTitle.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetConsoleTitle.cs @@ -7,7 +7,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true, EntryPoint = "SetConsoleTitleW")] - internal static extern bool SetConsoleTitle(string title); + [GeneratedDllImport(Libraries.Kernel32, EntryPoint = "SetConsoleTitleW", CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial bool SetConsoleTitle(string title); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetConsoleWindowInfo.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetConsoleWindowInfo.cs index ae87d60ffe9b2..af33386ca831c 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetConsoleWindowInfo.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetConsoleWindowInfo.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, SetLastError = true)] - internal static extern unsafe bool SetConsoleWindowInfo(IntPtr hConsoleOutput, bool absolute, SMALL_RECT* consoleWindow); + [GeneratedDllImport(Libraries.Kernel32, SetLastError = true)] + internal static unsafe partial bool SetConsoleWindowInfo(IntPtr hConsoleOutput, bool absolute, SMALL_RECT* consoleWindow); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetFileAttributes.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetFileAttributes.cs index 33ecdabc76f1a..4e436e0c49dc0 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetFileAttributes.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetFileAttributes.cs @@ -11,8 +11,15 @@ internal static partial class Kernel32 /// /// WARNING: This method does not implicitly handle long paths. Use SetFileAttributes. /// - [DllImport(Libraries.Kernel32, EntryPoint = "SetFileAttributesW", SetLastError = true, CharSet = CharSet.Unicode, BestFitMapping = false)] - private static extern bool SetFileAttributesPrivate(string name, int attr); +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Kernel32, EntryPoint = "SetFileAttributesW", CharSet = CharSet.Unicode, SetLastError = true)] + private static partial bool SetFileAttributesPrivate( +#else + [DllImport(Libraries.Kernel32, EntryPoint = "SetFileAttributesW", CharSet = CharSet.Unicode, SetLastError = true)] + private static extern bool SetFileAttributesPrivate( +#endif + string name, + int attr); internal static bool SetFileAttributes(string name, int attr) { diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetFileCompletionNotificationModes.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetFileCompletionNotificationModes.cs index 684fabc0cafd0..9a1bcadfbd953 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetFileCompletionNotificationModes.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetFileCompletionNotificationModes.cs @@ -16,7 +16,7 @@ internal enum FileCompletionNotificationModes : byte SkipSetEventOnHandle = 2 } - [DllImport(Libraries.Kernel32, SetLastError = true)] - internal static extern bool SetFileCompletionNotificationModes(SafeHandle handle, FileCompletionNotificationModes flags); + [GeneratedDllImport(Libraries.Kernel32, SetLastError = true)] + internal static partial bool SetFileCompletionNotificationModes(SafeHandle handle, FileCompletionNotificationModes flags); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetFileInformationByHandle.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetFileInformationByHandle.cs index 193fa9b988710..28361c06f9134 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetFileInformationByHandle.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetFileInformationByHandle.cs @@ -9,7 +9,16 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, SetLastError = true, ExactSpelling = true)] - internal static extern unsafe bool SetFileInformationByHandle(SafeFileHandle hFile, int FileInformationClass, void* lpFileInformation, uint dwBufferSize); +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Kernel32, ExactSpelling = true, SetLastError = true)] + internal static unsafe partial bool SetFileInformationByHandle( +#else + [DllImport(Libraries.Kernel32, ExactSpelling = true, SetLastError = true)] + internal static unsafe extern bool SetFileInformationByHandle( +#endif + SafeFileHandle hFile, + int FileInformationClass, + void* lpFileInformation, + uint dwBufferSize); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetNamedPipeHandleState.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetNamedPipeHandleState.cs index 70f0ab13483e7..2ee991183b760 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetNamedPipeHandleState.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetNamedPipeHandleState.cs @@ -9,9 +9,9 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, SetLastError = true)] + [GeneratedDllImport(Libraries.Kernel32, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern unsafe bool SetNamedPipeHandleState( + internal static unsafe partial bool SetNamedPipeHandleState( SafePipeHandle hNamedPipe, int* lpMode, IntPtr lpMaxCollectionCount, diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetPriorityClass.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetPriorityClass.cs index eaa743fd26c36..4793622b546a4 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetPriorityClass.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetPriorityClass.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern bool SetPriorityClass(SafeProcessHandle handle, int priorityClass); + [GeneratedDllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial bool SetPriorityClass(SafeProcessHandle handle, int priorityClass); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetProcessAffinityMask.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetProcessAffinityMask.cs index f4bf52550ae8b..d95af73e97151 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetProcessAffinityMask.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetProcessAffinityMask.cs @@ -9,7 +9,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern bool SetProcessAffinityMask(SafeProcessHandle handle, IntPtr mask); + [GeneratedDllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial bool SetProcessAffinityMask(SafeProcessHandle handle, IntPtr mask); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetProcessPriorityBoost.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetProcessPriorityBoost.cs index 73263e99458fc..069c1a6227871 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetProcessPriorityBoost.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetProcessPriorityBoost.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern bool SetProcessPriorityBoost(SafeProcessHandle handle, bool disabled); + [GeneratedDllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial bool SetProcessPriorityBoost(SafeProcessHandle handle, bool disabled); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetProcessWorkingSetSizeEx.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetProcessWorkingSetSizeEx.cs index 06b06a704675a..069e3099e4221 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetProcessWorkingSetSizeEx.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetProcessWorkingSetSizeEx.cs @@ -9,7 +9,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern bool SetProcessWorkingSetSizeEx(SafeProcessHandle handle, IntPtr min, IntPtr max, int flags); + [GeneratedDllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial bool SetProcessWorkingSetSizeEx(SafeProcessHandle handle, IntPtr min, IntPtr max, int flags); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetThreadAffinityMask.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetThreadAffinityMask.cs index 54120f20d8bcd..32270d39ec9c8 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetThreadAffinityMask.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetThreadAffinityMask.cs @@ -9,7 +9,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern IntPtr SetThreadAffinityMask(SafeThreadHandle handle, IntPtr mask); + [GeneratedDllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial IntPtr SetThreadAffinityMask(SafeThreadHandle handle, IntPtr mask); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetThreadErrorMode.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetThreadErrorMode.cs index ebf30875b1c6d..8028a1256e44a 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetThreadErrorMode.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetThreadErrorMode.cs @@ -7,9 +7,16 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, SetLastError = true, ExactSpelling = true)] [SuppressGCTransition] - internal static extern bool SetThreadErrorMode(uint dwNewMode, out uint lpOldMode); +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Kernel32, ExactSpelling = true, SetLastError = true)] + internal static partial bool SetThreadErrorMode( +#else + [DllImport(Libraries.Kernel32, ExactSpelling = true, SetLastError = true)] + internal static extern bool SetThreadErrorMode( +#endif + uint dwNewMode, + out uint lpOldMode); internal const uint SEM_FAILCRITICALERRORS = 1; } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetThreadIdealProcessor.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetThreadIdealProcessor.cs index 3d4f3e9d0b22f..3614ac2a34e5b 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetThreadIdealProcessor.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetThreadIdealProcessor.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern int SetThreadIdealProcessor(SafeThreadHandle handle, int processor); + [GeneratedDllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial int SetThreadIdealProcessor(SafeThreadHandle handle, int processor); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetThreadPriority.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetThreadPriority.cs index 4024214bc64dc..b7910e8283053 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetThreadPriority.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetThreadPriority.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern bool SetThreadPriority(SafeThreadHandle handle, int priority); + [GeneratedDllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial bool SetThreadPriority(SafeThreadHandle handle, int priority); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetThreadPriorityBoost.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetThreadPriorityBoost.cs index b285164670226..479acffcdfe75 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetThreadPriorityBoost.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetThreadPriorityBoost.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern bool SetThreadPriorityBoost(SafeThreadHandle handle, bool disabled); + [GeneratedDllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial bool SetThreadPriorityBoost(SafeThreadHandle handle, bool disabled); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetVolumeLabel.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetVolumeLabel.cs index 4b6c9344e262c..ca70a7fa2c52f 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetVolumeLabel.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SetVolumeLabel.cs @@ -7,7 +7,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, EntryPoint = "SetVolumeLabelW", CharSet = CharSet.Unicode, SetLastError = true, BestFitMapping = false)] - internal static extern bool SetVolumeLabel(string driveLetter, string? volumeName); + [GeneratedDllImport(Libraries.Kernel32, EntryPoint = "SetVolumeLabelW", CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial bool SetVolumeLabel(string driveLetter, string? volumeName); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.TerminateProcess.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.TerminateProcess.cs index 37dfec5d196f3..e835fce96eea5 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.TerminateProcess.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.TerminateProcess.cs @@ -9,7 +9,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern bool TerminateProcess(SafeProcessHandle processHandle, int exitCode); + [GeneratedDllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial bool TerminateProcess(SafeProcessHandle processHandle, int exitCode); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.UnmapViewOfFile.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.UnmapViewOfFile.cs index 55d3b8eeb49b5..dd519a7f1f87f 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.UnmapViewOfFile.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.UnmapViewOfFile.cs @@ -8,7 +8,12 @@ internal static partial class Interop { internal static partial class Kernel32 { +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Kernel32, SetLastError = true)] + internal static partial bool UnmapViewOfFile(IntPtr lpBaseAddress); +#else [DllImport(Libraries.Kernel32, SetLastError = true)] internal static extern bool UnmapViewOfFile(IntPtr lpBaseAddress); +#endif } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.VirtualAlloc.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.VirtualAlloc.cs index 19f93d2791dd0..1d5ec8ec56848 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.VirtualAlloc.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.VirtualAlloc.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, SetLastError = true, ExactSpelling = true)] - internal static extern IntPtr VirtualAlloc(SafeHandle lpAddress, UIntPtr dwSize, int flAllocationType, int flProtect); + [GeneratedDllImport(Libraries.Kernel32, ExactSpelling = true, SetLastError = true)] + internal static partial IntPtr VirtualAlloc(SafeHandle lpAddress, UIntPtr dwSize, int flAllocationType, int flProtect); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.VirtualQuery.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.VirtualQuery.cs index 25e3fd62b0dad..9ede606895a45 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.VirtualQuery.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.VirtualQuery.cs @@ -8,7 +8,15 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, SetLastError = true, ExactSpelling = true)] - internal static extern UIntPtr VirtualQuery(SafeHandle lpAddress, ref MEMORY_BASIC_INFORMATION lpBuffer, UIntPtr dwLength); +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Kernel32, ExactSpelling = true, SetLastError = true)] + internal static partial UIntPtr VirtualQuery( +#else + [DllImport(Libraries.Kernel32, ExactSpelling = true, SetLastError = true)] + internal static extern UIntPtr VirtualQuery( +#endif + SafeHandle lpAddress, + ref MEMORY_BASIC_INFORMATION lpBuffer, + UIntPtr dwLength); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.WaitNamedPipe.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.WaitNamedPipe.cs index cb95a8e120cd5..118464eac29fb 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.WaitNamedPipe.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.WaitNamedPipe.cs @@ -7,8 +7,8 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true, BestFitMapping = false, EntryPoint = "WaitNamedPipeW")] + [GeneratedDllImport(Libraries.Kernel32, EntryPoint = "WaitNamedPipeW", CharSet = CharSet.Unicode, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] - internal static extern bool WaitNamedPipe(string? name, int timeout); + internal static partial bool WaitNamedPipe(string? name, int timeout); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.WriteConsole.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.WriteConsole.cs index ed5cfee214666..95b6495d216db 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.WriteConsole.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.WriteConsole.cs @@ -8,8 +8,8 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, CharSet = CharSet.Unicode, SetLastError = true, EntryPoint = "WriteConsoleW")] - internal static extern unsafe bool WriteConsole( + [GeneratedDllImport(Libraries.Kernel32, EntryPoint = "WriteConsoleW", CharSet = CharSet.Unicode, SetLastError = true)] + internal static unsafe partial bool WriteConsole( IntPtr hConsoleOutput, byte* lpBuffer, int nNumberOfCharsToWrite, diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.WriteConsoleOutput.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.WriteConsoleOutput.cs index 47e03d8057633..d656cebed02c3 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.WriteConsoleOutput.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.WriteConsoleOutput.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "WriteConsoleOutputW")] - internal static extern unsafe bool WriteConsoleOutput(IntPtr hConsoleOutput, CHAR_INFO* buffer, COORD bufferSize, COORD bufferCoord, ref SMALL_RECT writeRegion); + [GeneratedDllImport(Libraries.Kernel32, EntryPoint = "WriteConsoleOutputW", CharSet = CharSet.Unicode, SetLastError = true)] + internal static unsafe partial bool WriteConsoleOutput(IntPtr hConsoleOutput, CHAR_INFO* buffer, COORD bufferSize, COORD bufferCoord, ref SMALL_RECT writeRegion); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.WriteFile_IntPtr.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.WriteFile_IntPtr.cs index 7ebff795dcfb4..2c4e963dbc59d 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.WriteFile_IntPtr.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.WriteFile_IntPtr.cs @@ -7,8 +7,8 @@ internal static partial class Interop { internal static partial class Kernel32 { - [DllImport(Libraries.Kernel32, SetLastError = true)] - internal static extern unsafe int WriteFile( + [GeneratedDllImport(Libraries.Kernel32, SetLastError = true)] + internal static unsafe partial int WriteFile( IntPtr handle, byte* bytes, int numBytesToWrite, diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.WriteFile_SafeHandle_IntPtr.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.WriteFile_SafeHandle_IntPtr.cs index 9101041ab4f04..6354c1a5926b4 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.WriteFile_SafeHandle_IntPtr.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.WriteFile_SafeHandle_IntPtr.cs @@ -15,7 +15,17 @@ internal static partial class Kernel32 // struct in a callback (or an EndWrite method called by that callback), // and pass in an address for the numBytesRead parameter. +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Kernel32, SetLastError = true)] + internal static unsafe partial int WriteFile( +#else [DllImport(Libraries.Kernel32, SetLastError = true)] - internal static extern unsafe int WriteFile(SafeHandle handle, byte* bytes, int numBytesToWrite, out int numBytesWritten, IntPtr mustBeZero); + internal static extern unsafe int WriteFile( +#endif + SafeHandle handle, + byte* bytes, + int numBytesToWrite, + out int numBytesWritten, + IntPtr mustBeZero); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.WriteFile_SafeHandle_NativeOverlapped.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.WriteFile_SafeHandle_NativeOverlapped.cs index 3eaff9ca07626..0f66079a24a9e 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.WriteFile_SafeHandle_NativeOverlapped.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.WriteFile_SafeHandle_NativeOverlapped.cs @@ -15,10 +15,30 @@ internal static partial class Kernel32 // simultaneously: overlapped IO, free the memory for the overlapped // struct in a callback (or an EndWrite method called by that callback), // and pass in an address for the numBytesRead parameter. +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Kernel32, SetLastError = true)] + internal static unsafe partial int WriteFile( +#else [DllImport(Libraries.Kernel32, SetLastError = true)] - internal static extern unsafe int WriteFile(SafeHandle handle, byte* bytes, int numBytesToWrite, IntPtr numBytesWritten_mustBeZero, NativeOverlapped* lpOverlapped); + internal static extern unsafe int WriteFile( +#endif + SafeHandle handle, + byte* bytes, + int numBytesToWrite, + IntPtr numBytesWritten_mustBeZero, + NativeOverlapped* lpOverlapped); +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.Kernel32, SetLastError = true)] + internal static unsafe partial int WriteFile( +#else [DllImport(Libraries.Kernel32, SetLastError = true)] - internal static extern unsafe int WriteFile(SafeHandle handle, byte* bytes, int numBytesToWrite, out int numBytesWritten, NativeOverlapped* lpOverlapped); + internal static extern unsafe int WriteFile( +#endif + SafeHandle handle, + byte* bytes, + int numBytesToWrite, + out int numBytesWritten, + NativeOverlapped* lpOverlapped); } } diff --git a/src/libraries/Common/src/Interop/Windows/NCrypt/Interop.EncryptDecrypt.cs b/src/libraries/Common/src/Interop/Windows/NCrypt/Interop.EncryptDecrypt.cs index 5382193fcd0c9..7013035c7e2fb 100644 --- a/src/libraries/Common/src/Interop/Windows/NCrypt/Interop.EncryptDecrypt.cs +++ b/src/libraries/Common/src/Interop/Windows/NCrypt/Interop.EncryptDecrypt.cs @@ -12,13 +12,13 @@ internal static partial class NCrypt internal static unsafe ErrorCode NCryptEncrypt(SafeNCryptKeyHandle hKey, ReadOnlySpan pbInput, int cbInput, void* pPaddingInfo, Span pbOutput, int cbOutput, out int pcbResult, AsymmetricPaddingMode dwFlags) => NCryptEncrypt(hKey, ref MemoryMarshal.GetReference(pbInput), cbInput, pPaddingInfo, ref MemoryMarshal.GetReference(pbOutput), cbOutput, out pcbResult, dwFlags); - [DllImport(Interop.Libraries.NCrypt, CharSet = CharSet.Unicode)] - private static extern unsafe ErrorCode NCryptEncrypt(SafeNCryptKeyHandle hKey, ref byte pbInput, int cbInput, void* pPaddingInfo, ref byte pbOutput, int cbOutput, out int pcbResult, AsymmetricPaddingMode dwFlags); + [GeneratedDllImport(Interop.Libraries.NCrypt, CharSet = CharSet.Unicode)] + private static unsafe partial ErrorCode NCryptEncrypt(SafeNCryptKeyHandle hKey, ref byte pbInput, int cbInput, void* pPaddingInfo, ref byte pbOutput, int cbOutput, out int pcbResult, AsymmetricPaddingMode dwFlags); internal static unsafe ErrorCode NCryptDecrypt(SafeNCryptKeyHandle hKey, ReadOnlySpan pbInput, int cbInput, void* pPaddingInfo, Span pbOutput, int cbOutput, out int pcbResult, AsymmetricPaddingMode dwFlags) => NCryptDecrypt(hKey, ref MemoryMarshal.GetReference(pbInput), cbInput, pPaddingInfo, ref MemoryMarshal.GetReference(pbOutput), cbOutput, out pcbResult, dwFlags); - [DllImport(Interop.Libraries.NCrypt, CharSet = CharSet.Unicode)] - private static extern unsafe ErrorCode NCryptDecrypt(SafeNCryptKeyHandle hKey, ref byte pbInput, int cbInput, void* pPaddingInfo, ref byte pbOutput, int cbOutput, out int pcbResult, AsymmetricPaddingMode dwFlags); + [GeneratedDllImport(Interop.Libraries.NCrypt, CharSet = CharSet.Unicode)] + private static unsafe partial ErrorCode NCryptDecrypt(SafeNCryptKeyHandle hKey, ref byte pbInput, int cbInput, void* pPaddingInfo, ref byte pbOutput, int cbOutput, out int pcbResult, AsymmetricPaddingMode dwFlags); } } diff --git a/src/libraries/Common/src/Interop/Windows/NCrypt/Interop.Keys.cs b/src/libraries/Common/src/Interop/Windows/NCrypt/Interop.Keys.cs index 08ff909431756..406e0177f8ecf 100644 --- a/src/libraries/Common/src/Interop/Windows/NCrypt/Interop.Keys.cs +++ b/src/libraries/Common/src/Interop/Windows/NCrypt/Interop.Keys.cs @@ -13,32 +13,32 @@ internal static partial class NCrypt { internal const string NCRYPT_PKCS8_PRIVATE_KEY_BLOB = "PKCS8_PRIVATEKEY"; - [DllImport(Interop.Libraries.NCrypt, CharSet = CharSet.Unicode)] - internal static extern ErrorCode NCryptOpenKey(SafeNCryptProviderHandle hProvider, out SafeNCryptKeyHandle phKey, string pszKeyName, int dwLegacyKeySpec, CngKeyOpenOptions dwFlags); + [GeneratedDllImport(Interop.Libraries.NCrypt, CharSet = CharSet.Unicode)] + internal static partial ErrorCode NCryptOpenKey(SafeNCryptProviderHandle hProvider, out SafeNCryptKeyHandle phKey, string pszKeyName, int dwLegacyKeySpec, CngKeyOpenOptions dwFlags); - [DllImport(Interop.Libraries.NCrypt, CharSet = CharSet.Unicode)] - internal static extern ErrorCode NCryptImportKey(SafeNCryptProviderHandle hProvider, IntPtr hImportKey, string pszBlobType, IntPtr pParameterList, [Out] out SafeNCryptKeyHandle phKey, ref byte pbData, int cbData, int dwFlags); + [GeneratedDllImport(Interop.Libraries.NCrypt, CharSet = CharSet.Unicode)] + internal static partial ErrorCode NCryptImportKey(SafeNCryptProviderHandle hProvider, IntPtr hImportKey, string pszBlobType, IntPtr pParameterList, out SafeNCryptKeyHandle phKey, ref byte pbData, int cbData, int dwFlags); - [DllImport(Interop.Libraries.NCrypt, CharSet = CharSet.Unicode)] - internal static extern ErrorCode NCryptImportKey(SafeNCryptProviderHandle hProvider, IntPtr hImportKey, string pszBlobType, ref NCryptBufferDesc pParameterList, [Out] out SafeNCryptKeyHandle phKey, ref byte pbData, int cbData, int dwFlags); + [GeneratedDllImport(Interop.Libraries.NCrypt, CharSet = CharSet.Unicode)] + internal static partial ErrorCode NCryptImportKey(SafeNCryptProviderHandle hProvider, IntPtr hImportKey, string pszBlobType, ref NCryptBufferDesc pParameterList, out SafeNCryptKeyHandle phKey, ref byte pbData, int cbData, int dwFlags); - [DllImport(Interop.Libraries.NCrypt, CharSet = CharSet.Unicode)] - internal static extern ErrorCode NCryptExportKey(SafeNCryptKeyHandle hKey, IntPtr hExportKey, string pszBlobType, IntPtr pParameterList, [Out] byte[]? pbOutput, int cbOutput, [Out] out int pcbResult, int dwFlags); + [GeneratedDllImport(Interop.Libraries.NCrypt, CharSet = CharSet.Unicode)] + internal static partial ErrorCode NCryptExportKey(SafeNCryptKeyHandle hKey, IntPtr hExportKey, string pszBlobType, IntPtr pParameterList, byte[]? pbOutput, int cbOutput, out int pcbResult, int dwFlags); - [DllImport(Interop.Libraries.NCrypt, CharSet = CharSet.Unicode)] - internal static extern ErrorCode NCryptExportKey(SafeNCryptKeyHandle hKey, IntPtr hExportKey, string pszBlobType, IntPtr pParameterList, ref byte pbOutput, int cbOutput, [Out] out int pcbResult, int dwFlags); + [GeneratedDllImport(Interop.Libraries.NCrypt, CharSet = CharSet.Unicode)] + internal static partial ErrorCode NCryptExportKey(SafeNCryptKeyHandle hKey, IntPtr hExportKey, string pszBlobType, IntPtr pParameterList, ref byte pbOutput, int cbOutput, out int pcbResult, int dwFlags); - [DllImport(Interop.Libraries.NCrypt, CharSet = CharSet.Unicode)] - internal static extern ErrorCode NCryptExportKey(SafeNCryptKeyHandle hKey, IntPtr hExportKey, string pszBlobType, ref NCryptBufferDesc pParameterList, ref byte pbOutput, int cbOutput, [Out] out int pcbResult, int dwFlags); + [GeneratedDllImport(Interop.Libraries.NCrypt, CharSet = CharSet.Unicode)] + internal static partial ErrorCode NCryptExportKey(SafeNCryptKeyHandle hKey, IntPtr hExportKey, string pszBlobType, ref NCryptBufferDesc pParameterList, ref byte pbOutput, int cbOutput, out int pcbResult, int dwFlags); - [DllImport(Interop.Libraries.NCrypt, CharSet = CharSet.Unicode)] - internal static extern ErrorCode NCryptDeleteKey(SafeNCryptKeyHandle hKey, int dwFlags); + [GeneratedDllImport(Interop.Libraries.NCrypt, CharSet = CharSet.Unicode)] + internal static partial ErrorCode NCryptDeleteKey(SafeNCryptKeyHandle hKey, int dwFlags); - [DllImport(Interop.Libraries.NCrypt, CharSet = CharSet.Unicode)] - internal static extern ErrorCode NCryptCreatePersistedKey(SafeNCryptProviderHandle hProvider, out SafeNCryptKeyHandle phKey, string pszAlgId, string? pszKeyName, int dwLegacyKeySpec, CngKeyCreationOptions dwFlags); + [GeneratedDllImport(Interop.Libraries.NCrypt, CharSet = CharSet.Unicode)] + internal static partial ErrorCode NCryptCreatePersistedKey(SafeNCryptProviderHandle hProvider, out SafeNCryptKeyHandle phKey, string pszAlgId, string? pszKeyName, int dwLegacyKeySpec, CngKeyCreationOptions dwFlags); - [DllImport(Interop.Libraries.NCrypt, CharSet = CharSet.Unicode)] - internal static extern ErrorCode NCryptFinalizeKey(SafeNCryptKeyHandle hKey, int dwFlags); + [GeneratedDllImport(Interop.Libraries.NCrypt, CharSet = CharSet.Unicode)] + internal static partial ErrorCode NCryptFinalizeKey(SafeNCryptKeyHandle hKey, int dwFlags); [StructLayout(LayoutKind.Sequential)] internal struct CRYPT_PKCS12_PBE_PARAMS diff --git a/src/libraries/Common/src/Interop/Windows/NCrypt/Interop.NCryptDeriveKeyMaterial.cs b/src/libraries/Common/src/Interop/Windows/NCrypt/Interop.NCryptDeriveKeyMaterial.cs index 2c7bfbd434d9a..f0fa8ff23249a 100644 --- a/src/libraries/Common/src/Interop/Windows/NCrypt/Interop.NCryptDeriveKeyMaterial.cs +++ b/src/libraries/Common/src/Interop/Windows/NCrypt/Interop.NCryptDeriveKeyMaterial.cs @@ -15,14 +15,14 @@ internal static partial class NCrypt /// /// Generate a key from a secret agreement /// - [DllImport(Interop.Libraries.NCrypt, CharSet = CharSet.Unicode)] - private static extern ErrorCode NCryptDeriveKey( + [GeneratedDllImport(Interop.Libraries.NCrypt, CharSet = CharSet.Unicode)] + private static partial ErrorCode NCryptDeriveKey( SafeNCryptSecretHandle hSharedSecret, string pwszKDF, - [In] ref NCryptBufferDesc pParameterList, - [Out, MarshalAs(UnmanagedType.LPArray)] byte[]? pbDerivedKey, + ref NCryptBufferDesc pParameterList, + [MarshalAs(UnmanagedType.LPArray)] byte[]? pbDerivedKey, int cbDerivedKey, - [Out] out int pcbResult, + out int pcbResult, SecretAgreementFlags dwFlags); /// diff --git a/src/libraries/Common/src/Interop/Windows/NCrypt/Interop.NCryptDeriveSecretAgreement.cs b/src/libraries/Common/src/Interop/Windows/NCrypt/Interop.NCryptDeriveSecretAgreement.cs index 422f9537ff36f..6c5b2a70cf2a4 100644 --- a/src/libraries/Common/src/Interop/Windows/NCrypt/Interop.NCryptDeriveSecretAgreement.cs +++ b/src/libraries/Common/src/Interop/Windows/NCrypt/Interop.NCryptDeriveSecretAgreement.cs @@ -20,11 +20,11 @@ internal enum SecretAgreementFlags /// /// Generate a secret agreement for generating shared key material /// - [DllImport(Interop.Libraries.NCrypt)] - private static extern ErrorCode NCryptSecretAgreement( + [GeneratedDllImport(Interop.Libraries.NCrypt)] + private static partial ErrorCode NCryptSecretAgreement( SafeNCryptKeyHandle hPrivKey, SafeNCryptKeyHandle hPubKey, - [Out] out SafeNCryptSecretHandle phSecret, + out SafeNCryptSecretHandle phSecret, int dwFlags); diff --git a/src/libraries/Common/src/Interop/Windows/NCrypt/Interop.NCryptOpenStorageProvider.cs b/src/libraries/Common/src/Interop/Windows/NCrypt/Interop.NCryptOpenStorageProvider.cs index 90e4a2e933380..97368d0550922 100644 --- a/src/libraries/Common/src/Interop/Windows/NCrypt/Interop.NCryptOpenStorageProvider.cs +++ b/src/libraries/Common/src/Interop/Windows/NCrypt/Interop.NCryptOpenStorageProvider.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class NCrypt { - [DllImport(Interop.Libraries.NCrypt, CharSet = CharSet.Unicode)] - internal static extern ErrorCode NCryptOpenStorageProvider(out SafeNCryptProviderHandle phProvider, string pszProviderName, int dwFlags); + [GeneratedDllImport(Interop.Libraries.NCrypt, CharSet = CharSet.Unicode)] + internal static partial ErrorCode NCryptOpenStorageProvider(out SafeNCryptProviderHandle phProvider, string pszProviderName, int dwFlags); } } diff --git a/src/libraries/Common/src/Interop/Windows/NCrypt/Interop.Properties.cs b/src/libraries/Common/src/Interop/Windows/NCrypt/Interop.Properties.cs index 9c6ce0359c00a..4304ccf9bbf4c 100644 --- a/src/libraries/Common/src/Interop/Windows/NCrypt/Interop.Properties.cs +++ b/src/libraries/Common/src/Interop/Windows/NCrypt/Interop.Properties.cs @@ -13,11 +13,32 @@ internal static partial class Interop { internal static partial class NCrypt { +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.NCrypt, CharSet = CharSet.Unicode)] + internal static unsafe partial ErrorCode NCryptGetProperty( +#else [DllImport(Interop.Libraries.NCrypt, CharSet = CharSet.Unicode)] - internal static extern unsafe ErrorCode NCryptGetProperty(SafeNCryptHandle hObject, string pszProperty, [Out] void* pbOutput, int cbOutput, out int pcbResult, CngPropertyOptions dwFlags); + internal static extern unsafe ErrorCode NCryptGetProperty( +#endif + SafeNCryptHandle hObject, + string pszProperty, + void* pbOutput, + int cbOutput, + out int pcbResult, + CngPropertyOptions dwFlags); +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.NCrypt, CharSet = CharSet.Unicode)] + internal static unsafe partial ErrorCode NCryptSetProperty( +#else [DllImport(Interop.Libraries.NCrypt, CharSet = CharSet.Unicode)] - internal static extern unsafe ErrorCode NCryptSetProperty(SafeNCryptHandle hObject, string pszProperty, [In] void* pbInput, int cbInput, CngPropertyOptions dwFlags); + internal static extern unsafe ErrorCode NCryptSetProperty( +#endif + SafeNCryptHandle hObject, + string pszProperty, + void* pbInput, + int cbInput, + CngPropertyOptions dwFlags); [SupportedOSPlatform("windows")] internal static unsafe ErrorCode NCryptGetByteProperty(SafeNCryptHandle hObject, string pszProperty, ref byte result, CngPropertyOptions options = CngPropertyOptions.None) diff --git a/src/libraries/Common/src/Interop/Windows/NCrypt/Interop.SignVerify.cs b/src/libraries/Common/src/Interop/Windows/NCrypt/Interop.SignVerify.cs index e6a23b5bac4d0..8e651c7277df8 100644 --- a/src/libraries/Common/src/Interop/Windows/NCrypt/Interop.SignVerify.cs +++ b/src/libraries/Common/src/Interop/Windows/NCrypt/Interop.SignVerify.cs @@ -12,13 +12,13 @@ internal static partial class NCrypt internal static unsafe ErrorCode NCryptSignHash(SafeNCryptKeyHandle hKey, void* pPaddingInfo, ReadOnlySpan pbHashValue, int cbHashValue, Span pbSignature, int cbSignature, out int pcbResult, AsymmetricPaddingMode dwFlags) => NCryptSignHash(hKey, pPaddingInfo, ref MemoryMarshal.GetReference(pbHashValue), cbHashValue, ref MemoryMarshal.GetReference(pbSignature), cbSignature, out pcbResult, dwFlags); - [DllImport(Libraries.NCrypt, CharSet = CharSet.Unicode)] - private static extern unsafe ErrorCode NCryptSignHash(SafeNCryptKeyHandle hKey, void* pPaddingInfo, ref byte pbHashValue, int cbHashValue, ref byte pbSignature, int cbSignature, out int pcbResult, AsymmetricPaddingMode dwFlags); + [GeneratedDllImport(Libraries.NCrypt, CharSet = CharSet.Unicode)] + private static unsafe partial ErrorCode NCryptSignHash(SafeNCryptKeyHandle hKey, void* pPaddingInfo, ref byte pbHashValue, int cbHashValue, ref byte pbSignature, int cbSignature, out int pcbResult, AsymmetricPaddingMode dwFlags); internal static unsafe ErrorCode NCryptVerifySignature(SafeNCryptKeyHandle hKey, void* pPaddingInfo, ReadOnlySpan pbHashValue, int cbHashValue, ReadOnlySpan pbSignature, int cbSignature, AsymmetricPaddingMode dwFlags) => NCryptVerifySignature(hKey, pPaddingInfo, ref MemoryMarshal.GetReference(pbHashValue), cbHashValue, ref MemoryMarshal.GetReference(pbSignature), cbSignature, dwFlags); - [DllImport(Libraries.NCrypt, CharSet = CharSet.Unicode)] - private static extern unsafe ErrorCode NCryptVerifySignature(SafeNCryptKeyHandle hKey, void* pPaddingInfo, ref byte pbHashValue, int cbHashValue, ref byte pbSignature, int cbSignature, AsymmetricPaddingMode dwFlags); + [GeneratedDllImport(Libraries.NCrypt, CharSet = CharSet.Unicode)] + private static unsafe partial ErrorCode NCryptVerifySignature(SafeNCryptKeyHandle hKey, void* pPaddingInfo, ref byte pbHashValue, int cbHashValue, ref byte pbSignature, int cbSignature, AsymmetricPaddingMode dwFlags); } } diff --git a/src/libraries/Common/src/Interop/Windows/NtDll/Interop.NtQueryDirectoryFile.cs b/src/libraries/Common/src/Interop/Windows/NtDll/Interop.NtQueryDirectoryFile.cs index 63b6bf9767c24..25d5f5f925bc4 100644 --- a/src/libraries/Common/src/Interop/Windows/NtDll/Interop.NtQueryDirectoryFile.cs +++ b/src/libraries/Common/src/Interop/Windows/NtDll/Interop.NtQueryDirectoryFile.cs @@ -11,7 +11,7 @@ internal static partial class NtDll // https://msdn.microsoft.com/en-us/library/windows/hardware/ff556633.aspx // https://msdn.microsoft.com/en-us/library/windows/hardware/ff567047.aspx [DllImport(Libraries.NtDll, CharSet = CharSet.Unicode, ExactSpelling = true)] - public static extern unsafe int NtQueryDirectoryFile( + public static unsafe extern int NtQueryDirectoryFile( IntPtr FileHandle, IntPtr Event, IntPtr ApcRoutine, diff --git a/src/libraries/Common/src/Interop/Windows/NtDll/Interop.NtQueryInformationProcess.cs b/src/libraries/Common/src/Interop/Windows/NtDll/Interop.NtQueryInformationProcess.cs index 24db7e74756d0..b591db05d1c0d 100644 --- a/src/libraries/Common/src/Interop/Windows/NtDll/Interop.NtQueryInformationProcess.cs +++ b/src/libraries/Common/src/Interop/Windows/NtDll/Interop.NtQueryInformationProcess.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class NtDll { - [DllImport(Libraries.NtDll, ExactSpelling = true)] - internal static extern unsafe uint NtQueryInformationProcess(SafeProcessHandle ProcessHandle, int ProcessInformationClass, void* ProcessInformation, uint ProcessInformationLength, out uint ReturnLength); + [GeneratedDllImport(Libraries.NtDll, ExactSpelling = true)] + internal static unsafe partial uint NtQueryInformationProcess(SafeProcessHandle ProcessHandle, int ProcessInformationClass, void* ProcessInformation, uint ProcessInformationLength, out uint ReturnLength); } } diff --git a/src/libraries/Common/src/Interop/Windows/Shell32/Interop.ShellExecuteExW.cs b/src/libraries/Common/src/Interop/Windows/Shell32/Interop.ShellExecuteExW.cs index 2d2213ae70b0b..b9af6b4b5df46 100644 --- a/src/libraries/Common/src/Interop/Windows/Shell32/Interop.ShellExecuteExW.cs +++ b/src/libraries/Common/src/Interop/Windows/Shell32/Interop.ShellExecuteExW.cs @@ -50,8 +50,8 @@ internal unsafe struct SHELLEXECUTEINFO internal const uint SEE_MASK_NOCLOSEPROCESS = 0x00000040; internal const uint SEE_MASK_FLAG_NO_UI = 0x00000400; - [DllImport(Libraries.Shell32, ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern unsafe bool ShellExecuteExW( + [GeneratedDllImport(Libraries.Shell32, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] + internal static unsafe partial bool ShellExecuteExW( SHELLEXECUTEINFO* pExecInfo); } } diff --git a/src/libraries/Common/src/Interop/Windows/SspiCli/Interop.LsaConnectUntrusted.cs b/src/libraries/Common/src/Interop/Windows/SspiCli/Interop.LsaConnectUntrusted.cs index 73b9e1aa80b52..1d956fe52a09a 100644 --- a/src/libraries/Common/src/Interop/Windows/SspiCli/Interop.LsaConnectUntrusted.cs +++ b/src/libraries/Common/src/Interop/Windows/SspiCli/Interop.LsaConnectUntrusted.cs @@ -10,7 +10,12 @@ internal static partial class Interop { internal static partial class SspiCli { +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.SspiCli)] + internal static partial int LsaConnectUntrusted(out SafeLsaHandle LsaHandle); +#else [DllImport(Interop.Libraries.SspiCli)] internal static extern int LsaConnectUntrusted(out SafeLsaHandle LsaHandle); +#endif } } diff --git a/src/libraries/Common/src/Interop/Windows/SspiCli/Interop.LsaFreeReturnBuffer.cs b/src/libraries/Common/src/Interop/Windows/SspiCli/Interop.LsaFreeReturnBuffer.cs index 1b0349ec02d80..bda15a55eba99 100644 --- a/src/libraries/Common/src/Interop/Windows/SspiCli/Interop.LsaFreeReturnBuffer.cs +++ b/src/libraries/Common/src/Interop/Windows/SspiCli/Interop.LsaFreeReturnBuffer.cs @@ -8,7 +8,12 @@ internal static partial class Interop { internal static partial class SspiCli { +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.SspiCli, SetLastError = true)] + internal static partial int LsaFreeReturnBuffer(IntPtr handle); +#else [DllImport(Interop.Libraries.SspiCli, SetLastError = true)] internal static extern int LsaFreeReturnBuffer(IntPtr handle); +#endif } } diff --git a/src/libraries/Common/src/Interop/Windows/SspiCli/Interop.LsaGetLogonSessionData.cs b/src/libraries/Common/src/Interop/Windows/SspiCli/Interop.LsaGetLogonSessionData.cs index f002e37cdc431..91e800168197b 100644 --- a/src/libraries/Common/src/Interop/Windows/SspiCli/Interop.LsaGetLogonSessionData.cs +++ b/src/libraries/Common/src/Interop/Windows/SspiCli/Interop.LsaGetLogonSessionData.cs @@ -9,7 +9,14 @@ internal static partial class Interop { internal static partial class SspiCli { +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.SspiCli, SetLastError = true)] + internal static partial int LsaGetLogonSessionData( +#else [DllImport(Interop.Libraries.SspiCli, SetLastError = true)] - internal static extern int LsaGetLogonSessionData(ref LUID LogonId, out SafeLsaReturnBufferHandle ppLogonSessionData); + internal static extern int LsaGetLogonSessionData( +#endif + ref LUID LogonId, + out SafeLsaReturnBufferHandle ppLogonSessionData); } } diff --git a/src/libraries/Common/src/Interop/Windows/SspiCli/Interop.LsaLookupAuthenticationPackage.cs b/src/libraries/Common/src/Interop/Windows/SspiCli/Interop.LsaLookupAuthenticationPackage.cs index 059ededf0c412..dbe9a13b52d66 100644 --- a/src/libraries/Common/src/Interop/Windows/SspiCli/Interop.LsaLookupAuthenticationPackage.cs +++ b/src/libraries/Common/src/Interop/Windows/SspiCli/Interop.LsaLookupAuthenticationPackage.cs @@ -9,10 +9,15 @@ internal static partial class Interop { internal static partial class SspiCli { +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Libraries.SspiCli)] + internal static partial int LsaLookupAuthenticationPackage( +#else [DllImport(Libraries.SspiCli)] internal static extern int LsaLookupAuthenticationPackage( +#endif SafeLsaHandle LsaHandle, - [In] ref Advapi32.LSA_STRING PackageName, + ref Advapi32.LSA_STRING PackageName, out int AuthenticationPackage ); } diff --git a/src/libraries/Common/src/Interop/Windows/SspiCli/Interop.SSPI.cs b/src/libraries/Common/src/Interop/Windows/SspiCli/Interop.SSPI.cs index 1694ca539a86a..cc4ee4b7b5904 100644 --- a/src/libraries/Common/src/Interop/Windows/SspiCli/Interop.SSPI.cs +++ b/src/libraries/Common/src/Interop/Windows/SspiCli/Interop.SSPI.cs @@ -330,169 +330,157 @@ internal unsafe struct SecPkgCred_ClientCertPolicy public char* pwszSslCtlIdentifier; } - [DllImport(Interop.Libraries.SspiCli, ExactSpelling = true, SetLastError = true)] - internal static extern int EncryptMessage( - ref CredHandle contextHandle, - [In] uint qualityOfProtection, - [In, Out] ref SecBufferDesc inputOutput, - [In] uint sequenceNumber - ); + [GeneratedDllImport(Interop.Libraries.SspiCli, ExactSpelling = true, SetLastError = true)] + internal static partial int EncryptMessage( + ref CredHandle contextHandle, + uint qualityOfProtection, + ref SecBufferDesc inputOutput, + uint sequenceNumber); - [DllImport(Interop.Libraries.SspiCli, ExactSpelling = true, SetLastError = true)] - internal static extern unsafe int DecryptMessage( - [In] ref CredHandle contextHandle, - [In, Out] ref SecBufferDesc inputOutput, - [In] uint sequenceNumber, - uint* qualityOfProtection - ); + [GeneratedDllImport(Interop.Libraries.SspiCli, ExactSpelling = true, SetLastError = true)] + internal static unsafe partial int DecryptMessage( + ref CredHandle contextHandle, + ref SecBufferDesc inputOutput, + uint sequenceNumber, + uint* qualityOfProtection); [DllImport(Interop.Libraries.SspiCli, ExactSpelling = true, SetLastError = true)] internal static extern int QuerySecurityContextToken( ref CredHandle phContext, - [Out] out SecurityContextTokenHandle handle); - - [DllImport(Interop.Libraries.SspiCli, ExactSpelling = true, SetLastError = true)] - internal static extern int FreeContextBuffer( - [In] IntPtr contextBuffer); - - [DllImport(Interop.Libraries.SspiCli, ExactSpelling = true, SetLastError = true)] - internal static extern int FreeCredentialsHandle( - ref CredHandle handlePtr - ); - - [DllImport(Interop.Libraries.SspiCli, ExactSpelling = true, SetLastError = true)] - internal static extern int DeleteSecurityContext( - ref CredHandle handlePtr - ); - - [DllImport(Interop.Libraries.SspiCli, ExactSpelling = true, SetLastError = true)] - internal static extern unsafe int AcceptSecurityContext( - ref CredHandle credentialHandle, - [In] void* inContextPtr, - [In] SecBufferDesc* inputBuffer, - [In] ContextFlags inFlags, - [In] Endianness endianness, - ref CredHandle outContextPtr, - [In, Out] ref SecBufferDesc outputBuffer, - [In, Out] ref ContextFlags attributes, - out long timeStamp - ); - - [DllImport(Interop.Libraries.SspiCli, ExactSpelling = true, SetLastError = true)] - internal static extern unsafe int QueryContextAttributesW( + out SecurityContextTokenHandle handle); + + [GeneratedDllImport(Interop.Libraries.SspiCli, ExactSpelling = true, SetLastError = true)] + internal static partial int FreeContextBuffer( + IntPtr contextBuffer); + + [GeneratedDllImport(Interop.Libraries.SspiCli, ExactSpelling = true, SetLastError = true)] + internal static partial int FreeCredentialsHandle( + ref CredHandle handlePtr); + + [GeneratedDllImport(Interop.Libraries.SspiCli, ExactSpelling = true, SetLastError = true)] + internal static partial int DeleteSecurityContext( + ref CredHandle handlePtr); + + [GeneratedDllImport(Interop.Libraries.SspiCli, ExactSpelling = true, SetLastError = true)] + internal static unsafe partial int AcceptSecurityContext( + ref CredHandle credentialHandle, + void* inContextPtr, + SecBufferDesc* inputBuffer, + ContextFlags inFlags, + Endianness endianness, + ref CredHandle outContextPtr, + ref SecBufferDesc outputBuffer, + ref ContextFlags attributes, + out long timeStamp); + + [GeneratedDllImport(Interop.Libraries.SspiCli, ExactSpelling = true, SetLastError = true)] + internal static unsafe partial int QueryContextAttributesW( ref CredHandle contextHandle, - [In] ContextAttribute attribute, - [In] void* buffer); + ContextAttribute attribute, + void* buffer); - [DllImport(Interop.Libraries.SspiCli, ExactSpelling = true, SetLastError = true)] - internal static extern int SetContextAttributesW( + [GeneratedDllImport(Interop.Libraries.SspiCli, ExactSpelling = true, SetLastError = true)] + internal static partial int SetContextAttributesW( ref CredHandle contextHandle, - [In] ContextAttribute attribute, - [In] byte[] buffer, - [In] int bufferSize); - - [DllImport(Interop.Libraries.SspiCli, ExactSpelling = true, SetLastError = true)] - internal static extern int EnumerateSecurityPackagesW( - [Out] out int pkgnum, - [Out] out SafeFreeContextBuffer_SECURITY handle); - - [DllImport(Interop.Libraries.SspiCli, ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern unsafe int AcquireCredentialsHandleW( - [In] string? principal, - [In] string moduleName, - [In] int usage, - [In] void* logonID, - [In] IntPtr zero, - [In] void* keyCallback, - [In] void* keyArgument, - ref CredHandle handlePtr, - [Out] out long timeStamp - ); - - [DllImport(Interop.Libraries.SspiCli, ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern unsafe int AcquireCredentialsHandleW( - [In] string? principal, - [In] string moduleName, - [In] int usage, - [In] void* logonID, - [In] SafeSspiAuthDataHandle authdata, - [In] void* keyCallback, - [In] void* keyArgument, - ref CredHandle handlePtr, - [Out] out long timeStamp - ); - - [DllImport(Interop.Libraries.SspiCli, ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern unsafe int AcquireCredentialsHandleW( - [In] string? principal, - [In] string moduleName, - [In] int usage, - [In] void* logonID, - [In] SCHANNEL_CRED* authData, - [In] void* keyCallback, - [In] void* keyArgument, - ref CredHandle handlePtr, - [Out] out long timeStamp - ); - - [DllImport(Interop.Libraries.SspiCli, ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern unsafe int AcquireCredentialsHandleW( - [In] string? principal, - [In] string moduleName, - [In] int usage, - [In] void* logonID, - [In] SCH_CREDENTIALS* authData, - [In] void* keyCallback, - [In] void* keyArgument, - ref CredHandle handlePtr, - [Out] out long timeStamp - ); - - - [DllImport(Interop.Libraries.SspiCli, ExactSpelling = true, SetLastError = true)] - internal static extern unsafe int InitializeSecurityContextW( - ref CredHandle credentialHandle, - [In] void* inContextPtr, - [In] byte* targetName, - [In] ContextFlags inFlags, - [In] int reservedI, - [In] Endianness endianness, - [In] SecBufferDesc* inputBuffer, - [In] int reservedII, - ref CredHandle outContextPtr, - [In, Out] ref SecBufferDesc outputBuffer, - [In, Out] ref ContextFlags attributes, - out long timeStamp - ); - - [DllImport(Interop.Libraries.SspiCli, ExactSpelling = true, SetLastError = true)] - internal static extern unsafe int CompleteAuthToken( - [In] void* inContextPtr, - [In, Out] ref SecBufferDesc inputBuffers - ); - - [DllImport(Interop.Libraries.SspiCli, ExactSpelling = true, SetLastError = true)] - internal static extern unsafe int ApplyControlToken( - [In] void* inContextPtr, - [In, Out] ref SecBufferDesc inputBuffers - ); - - [DllImport(Interop.Libraries.SspiCli, ExactSpelling = true, SetLastError = true)] - internal static extern SECURITY_STATUS SspiFreeAuthIdentity( - [In] IntPtr authData); - - [DllImport(Interop.Libraries.SspiCli, ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern SECURITY_STATUS SspiEncodeStringsAsAuthIdentity( - [In] string userName, - [In] string domainName, - [In] string password, - [Out] out SafeSspiAuthDataHandle authData); - - [DllImport(Interop.Libraries.SspiCli, ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)] + ContextAttribute attribute, + byte[] buffer, + int bufferSize); + + [GeneratedDllImport(Interop.Libraries.SspiCli, ExactSpelling = true, SetLastError = true)] + internal static partial int EnumerateSecurityPackagesW( + out int pkgnum, + out SafeFreeContextBuffer_SECURITY handle); + + [GeneratedDllImport(Interop.Libraries.SspiCli, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] + internal static unsafe partial int AcquireCredentialsHandleW( + string? principal, + string moduleName, + int usage, + void* logonID, + IntPtr zero, + void* keyCallback, + void* keyArgument, + ref CredHandle handlePtr, + out long timeStamp); + + [GeneratedDllImport(Interop.Libraries.SspiCli, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] + internal static unsafe partial int AcquireCredentialsHandleW( + string? principal, + string moduleName, + int usage, + void* logonID, + SafeSspiAuthDataHandle authdata, + void* keyCallback, + void* keyArgument, + ref CredHandle handlePtr, + out long timeStamp); + + [GeneratedDllImport(Interop.Libraries.SspiCli, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] + internal static unsafe partial int AcquireCredentialsHandleW( + string? principal, + string moduleName, + int usage, + void* logonID, + SCHANNEL_CRED* authData, + void* keyCallback, + void* keyArgument, + ref CredHandle handlePtr, + out long timeStamp); + + [GeneratedDllImport(Interop.Libraries.SspiCli, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] + internal static unsafe partial int AcquireCredentialsHandleW( + string? principal, + string moduleName, + int usage, + void* logonID, + SCH_CREDENTIALS* authData, + void* keyCallback, + void* keyArgument, + ref CredHandle handlePtr, + out long timeStamp); + + [GeneratedDllImport(Interop.Libraries.SspiCli, ExactSpelling = true, SetLastError = true)] + internal static unsafe partial int InitializeSecurityContextW( + ref CredHandle credentialHandle, + void* inContextPtr, + byte* targetName, + ContextFlags inFlags, + int reservedI, + Endianness endianness, + SecBufferDesc* inputBuffer, + int reservedII, + ref CredHandle outContextPtr, + ref SecBufferDesc outputBuffer, + ref ContextFlags attributes, + out long timeStamp); + + [GeneratedDllImport(Interop.Libraries.SspiCli, ExactSpelling = true, SetLastError = true)] + internal static unsafe partial int CompleteAuthToken( + void* inContextPtr, + ref SecBufferDesc inputBuffers); + + [GeneratedDllImport(Interop.Libraries.SspiCli, ExactSpelling = true, SetLastError = true)] + internal static unsafe partial int ApplyControlToken( + void* inContextPtr, + ref SecBufferDesc inputBuffers); + + [GeneratedDllImport(Interop.Libraries.SspiCli, ExactSpelling = true, SetLastError = true)] + internal static partial SECURITY_STATUS SspiFreeAuthIdentity( + IntPtr authData); + + [GeneratedDllImport(Interop.Libraries.SspiCli, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] + internal static partial SECURITY_STATUS SspiEncodeStringsAsAuthIdentity( + string userName, + string domainName, + string password, + out SafeSspiAuthDataHandle authData); + + // TODO: Switch to use GeneratedDllImport once we annotate blittable types used in interop in CoreLib (like Guid) + [DllImport(Interop.Libraries.SspiCli, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] internal static extern SECURITY_STATUS SetCredentialsAttributesW( - [In] ref CredHandle handlePtr, - [In] long ulAttribute, - [In] ref SecPkgCred_ClientCertPolicy pBuffer, - [In] long cbBuffer); + in CredHandle handlePtr, + long ulAttribute, + in SecPkgCred_ClientCertPolicy pBuffer, + long cbBuffer); } } diff --git a/src/libraries/Common/src/Interop/Windows/User32/Interop.EnumWindows.cs b/src/libraries/Common/src/Interop/Windows/User32/Interop.EnumWindows.cs index 853738f9a61f3..eff18b1b9d409 100644 --- a/src/libraries/Common/src/Interop/Windows/User32/Interop.EnumWindows.cs +++ b/src/libraries/Common/src/Interop/Windows/User32/Interop.EnumWindows.cs @@ -9,6 +9,6 @@ internal static partial class Interop internal static partial class User32 { [DllImport(Libraries.User32)] - public static extern unsafe bool EnumWindows(delegate* unmanaged callback, IntPtr extraData); + public static extern unsafe Interop.BOOL EnumWindows(delegate* unmanaged callback, IntPtr extraData); } } diff --git a/src/libraries/Common/src/Interop/Windows/User32/Interop.GetWindowTextLengthW.cs b/src/libraries/Common/src/Interop/Windows/User32/Interop.GetWindowTextLengthW.cs index 3acbfa271c7b7..59cf89deed657 100644 --- a/src/libraries/Common/src/Interop/Windows/User32/Interop.GetWindowTextLengthW.cs +++ b/src/libraries/Common/src/Interop/Windows/User32/Interop.GetWindowTextLengthW.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class User32 { - [DllImport(Libraries.User32, SetLastError = true, ExactSpelling = true)] - public static extern int GetWindowTextLengthW(IntPtr hWnd); + [GeneratedDllImport(Libraries.User32, ExactSpelling = true, SetLastError = true)] + public static partial int GetWindowTextLengthW(IntPtr hWnd); } } diff --git a/src/libraries/Common/src/Interop/Windows/User32/Interop.GetWindowTextW.cs b/src/libraries/Common/src/Interop/Windows/User32/Interop.GetWindowTextW.cs index 2590f25f465ec..f83224da351ad 100644 --- a/src/libraries/Common/src/Interop/Windows/User32/Interop.GetWindowTextW.cs +++ b/src/libraries/Common/src/Interop/Windows/User32/Interop.GetWindowTextW.cs @@ -9,7 +9,7 @@ internal static partial class Interop { internal static partial class User32 { - [DllImport(Libraries.User32, ExactSpelling = true, SetLastError = true, CharSet = CharSet.Unicode)] - public static extern unsafe int GetWindowTextW(IntPtr hWnd, char* lpString, int nMaxCount); + [GeneratedDllImport(Libraries.User32, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] + public static unsafe partial int GetWindowTextW(IntPtr hWnd, char* lpString, int nMaxCount); } } diff --git a/src/libraries/Common/src/Interop/Windows/User32/Interop.SendMessageTimeout.cs b/src/libraries/Common/src/Interop/Windows/User32/Interop.SendMessageTimeout.cs index 7472803ade678..c84dfdab7378c 100644 --- a/src/libraries/Common/src/Interop/Windows/User32/Interop.SendMessageTimeout.cs +++ b/src/libraries/Common/src/Interop/Windows/User32/Interop.SendMessageTimeout.cs @@ -9,6 +9,6 @@ internal static partial class Interop internal static partial class User32 { [DllImport(Libraries.User32, EntryPoint = "SendMessageTimeoutW")] - public static extern IntPtr SendMessageTimeout(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam, int flags, int timeout, out IntPtr pdwResult); + public static unsafe extern IntPtr SendMessageTimeout(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam, int flags, int timeout, IntPtr* pdwResult); } } diff --git a/src/libraries/Common/src/Interop/Windows/User32/Interop.WaitForInputIdle.cs b/src/libraries/Common/src/Interop/Windows/User32/Interop.WaitForInputIdle.cs index f6d3667775628..e4f98acb30c55 100644 --- a/src/libraries/Common/src/Interop/Windows/User32/Interop.WaitForInputIdle.cs +++ b/src/libraries/Common/src/Interop/Windows/User32/Interop.WaitForInputIdle.cs @@ -9,7 +9,7 @@ internal static partial class Interop { internal static partial class User32 { - [DllImport(Libraries.User32)] - public static extern int WaitForInputIdle(SafeProcessHandle handle, int milliseconds); + [GeneratedDllImport(Libraries.User32)] + public static partial int WaitForInputIdle(SafeProcessHandle handle, int milliseconds); } } diff --git a/src/libraries/Common/src/Interop/Windows/Version/Interop.GetFileVersionInfoEx.cs b/src/libraries/Common/src/Interop/Windows/Version/Interop.GetFileVersionInfoEx.cs index 5392b85d67360..f5ce78b9bafe4 100644 --- a/src/libraries/Common/src/Interop/Windows/Version/Interop.GetFileVersionInfoEx.cs +++ b/src/libraries/Common/src/Interop/Windows/Version/Interop.GetFileVersionInfoEx.cs @@ -8,8 +8,8 @@ internal static partial class Interop { internal static partial class Version { - [DllImport(Libraries.Version, CharSet = CharSet.Unicode, EntryPoint = "GetFileVersionInfoExW")] - internal static extern bool GetFileVersionInfoEx( + [GeneratedDllImport(Libraries.Version, EntryPoint = "GetFileVersionInfoExW", CharSet = CharSet.Unicode)] + internal static partial bool GetFileVersionInfoEx( uint dwFlags, string lpwstrFilename, uint dwHandle, diff --git a/src/libraries/Common/src/Interop/Windows/Version/Interop.GetFileVersionInfoSizeEx.cs b/src/libraries/Common/src/Interop/Windows/Version/Interop.GetFileVersionInfoSizeEx.cs index e6a703695db18..db3286789798d 100644 --- a/src/libraries/Common/src/Interop/Windows/Version/Interop.GetFileVersionInfoSizeEx.cs +++ b/src/libraries/Common/src/Interop/Windows/Version/Interop.GetFileVersionInfoSizeEx.cs @@ -7,7 +7,7 @@ internal static partial class Interop { internal static partial class Version { - [DllImport(Libraries.Version, CharSet = CharSet.Unicode, EntryPoint = "GetFileVersionInfoSizeExW")] - internal static extern uint GetFileVersionInfoSizeEx(uint dwFlags, string lpwstrFilename, out uint lpdwHandle); + [GeneratedDllImport(Libraries.Version, EntryPoint = "GetFileVersionInfoSizeExW", CharSet = CharSet.Unicode)] + internal static partial uint GetFileVersionInfoSizeEx(uint dwFlags, string lpwstrFilename, out uint lpdwHandle); } } diff --git a/src/libraries/Common/src/Interop/Windows/Version/Interop.VerQueryValue.cs b/src/libraries/Common/src/Interop/Windows/Version/Interop.VerQueryValue.cs index 60c122d07b42e..a3674ed10300a 100644 --- a/src/libraries/Common/src/Interop/Windows/Version/Interop.VerQueryValue.cs +++ b/src/libraries/Common/src/Interop/Windows/Version/Interop.VerQueryValue.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Version { - [DllImport(Libraries.Version, CharSet = CharSet.Unicode, EntryPoint = "VerQueryValueW")] - internal static extern bool VerQueryValue(IntPtr pBlock, string lpSubBlock, out IntPtr lplpBuffer, out uint puLen); + [GeneratedDllImport(Libraries.Version, EntryPoint = "VerQueryValueW", CharSet = CharSet.Unicode)] + internal static partial bool VerQueryValue(IntPtr pBlock, string lpSubBlock, out IntPtr lplpBuffer, out uint puLen); } } diff --git a/src/libraries/Common/src/Interop/Windows/WebSocket/Interop.WebSocketAbortHandle.cs b/src/libraries/Common/src/Interop/Windows/WebSocket/Interop.WebSocketAbortHandle.cs index eadda76c81cbe..9d771af4bcac1 100644 --- a/src/libraries/Common/src/Interop/Windows/WebSocket/Interop.WebSocketAbortHandle.cs +++ b/src/libraries/Common/src/Interop/Windows/WebSocket/Interop.WebSocketAbortHandle.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class WebSocket { - [DllImport(Libraries.WebSocket)] - internal static extern void WebSocketAbortHandle([In] SafeHandle webSocketHandle); + [GeneratedDllImport(Libraries.WebSocket)] + internal static partial void WebSocketAbortHandle(SafeHandle webSocketHandle); } } diff --git a/src/libraries/Common/src/Interop/Windows/WebSocket/Interop.WebSocketCompleteAction.cs b/src/libraries/Common/src/Interop/Windows/WebSocket/Interop.WebSocketCompleteAction.cs index b082e8d1a1540..c79f0292000db 100644 --- a/src/libraries/Common/src/Interop/Windows/WebSocket/Interop.WebSocketCompleteAction.cs +++ b/src/libraries/Common/src/Interop/Windows/WebSocket/Interop.WebSocketCompleteAction.cs @@ -9,10 +9,10 @@ internal static partial class Interop { internal static partial class WebSocket { - [DllImport(Libraries.WebSocket)] - internal static extern void WebSocketCompleteAction( - [In] SafeHandle webSocketHandle, - [In] IntPtr actionContext, - [In] uint bytesTransferred); + [GeneratedDllImport(Libraries.WebSocket)] + internal static partial void WebSocketCompleteAction( + SafeHandle webSocketHandle, + IntPtr actionContext, + uint bytesTransferred); } } diff --git a/src/libraries/Common/src/Interop/Windows/WebSocket/Interop.WebSocketCreateClientHandle.cs b/src/libraries/Common/src/Interop/Windows/WebSocket/Interop.WebSocketCreateClientHandle.cs index 6aeb2d1455228..dac7cc8202004 100644 --- a/src/libraries/Common/src/Interop/Windows/WebSocket/Interop.WebSocketCreateClientHandle.cs +++ b/src/libraries/Common/src/Interop/Windows/WebSocket/Interop.WebSocketCreateClientHandle.cs @@ -10,10 +10,10 @@ internal static partial class Interop { internal static partial class WebSocket { - [DllImport(Libraries.WebSocket)] - internal static extern int WebSocketCreateClientHandle( - [In] Property[] properties, - [In] uint propertyCount, - [Out] out SafeWebSocketHandle webSocketHandle); + [GeneratedDllImport(Libraries.WebSocket)] + internal static partial int WebSocketCreateClientHandle( + Property[] properties, + uint propertyCount, + out SafeWebSocketHandle webSocketHandle); } } diff --git a/src/libraries/Common/src/Interop/Windows/WebSocket/Interop.WebSocketCreateServerHandle.cs b/src/libraries/Common/src/Interop/Windows/WebSocket/Interop.WebSocketCreateServerHandle.cs index 672336c11fa8c..c90142692877a 100644 --- a/src/libraries/Common/src/Interop/Windows/WebSocket/Interop.WebSocketCreateServerHandle.cs +++ b/src/libraries/Common/src/Interop/Windows/WebSocket/Interop.WebSocketCreateServerHandle.cs @@ -9,10 +9,10 @@ internal static partial class Interop { internal static partial class WebSocket { - [DllImport(Libraries.WebSocket)] - internal static extern int WebSocketCreateServerHandle( - [In]Property[] properties, - [In] uint propertyCount, - [Out] out SafeWebSocketHandle webSocketHandle); + [GeneratedDllImport(Libraries.WebSocket)] + internal static partial int WebSocketCreateServerHandle( + Property[] properties, + uint propertyCount, + out SafeWebSocketHandle webSocketHandle); } } diff --git a/src/libraries/Common/src/Interop/Windows/WebSocket/Interop.WebSocketEndServerHandshake.cs b/src/libraries/Common/src/Interop/Windows/WebSocket/Interop.WebSocketEndServerHandshake.cs index f56255fbb2322..8be9ebe0fdcaa 100644 --- a/src/libraries/Common/src/Interop/Windows/WebSocket/Interop.WebSocketEndServerHandshake.cs +++ b/src/libraries/Common/src/Interop/Windows/WebSocket/Interop.WebSocketEndServerHandshake.cs @@ -11,7 +11,7 @@ internal static partial class Interop { internal static partial class WebSocket { - [DllImport(Libraries.WebSocket)] - internal static extern int WebSocketEndServerHandshake([In] SafeHandle webSocketHandle); + [GeneratedDllImport(Libraries.WebSocket)] + internal static partial int WebSocketEndServerHandshake(SafeHandle webSocketHandle); } } diff --git a/src/libraries/Common/src/Interop/Windows/WebSocket/Interop.WebSocketGetAction.cs b/src/libraries/Common/src/Interop/Windows/WebSocket/Interop.WebSocketGetAction.cs index 7cacdd4270670..567705db9f0ca 100644 --- a/src/libraries/Common/src/Interop/Windows/WebSocket/Interop.WebSocketGetAction.cs +++ b/src/libraries/Common/src/Interop/Windows/WebSocket/Interop.WebSocketGetAction.cs @@ -10,15 +10,15 @@ internal static partial class Interop { internal static partial class WebSocket { - [DllImport(Libraries.WebSocket)] - internal static extern int WebSocketGetAction( - [In] SafeHandle webSocketHandle, - [In] ActionQueue actionQueue, - [In, Out] Buffer[] dataBuffers, - [In, Out] ref uint dataBufferCount, - [Out] out System.Net.WebSockets.WebSocketProtocolComponent.Action action, - [Out] out BufferType bufferType, - [Out] out IntPtr applicationContext, - [Out] out IntPtr actionContext); + [GeneratedDllImport(Libraries.WebSocket)] + internal static partial int WebSocketGetAction( + SafeHandle webSocketHandle, + ActionQueue actionQueue, + Buffer[] dataBuffers, + ref uint dataBufferCount, + out System.Net.WebSockets.WebSocketProtocolComponent.Action action, + out BufferType bufferType, + out IntPtr applicationContext, + out IntPtr actionContext); } } diff --git a/src/libraries/Common/src/Interop/Windows/WebSocket/Interop.WebSocketReceive.cs b/src/libraries/Common/src/Interop/Windows/WebSocket/Interop.WebSocketReceive.cs index 41b917b76701c..3d40348d7fa7e 100644 --- a/src/libraries/Common/src/Interop/Windows/WebSocket/Interop.WebSocketReceive.cs +++ b/src/libraries/Common/src/Interop/Windows/WebSocket/Interop.WebSocketReceive.cs @@ -9,10 +9,10 @@ internal static partial class Interop { internal static partial class WebSocket { - [DllImport(Libraries.WebSocket)] - internal static extern int WebSocketReceive( - [In] SafeHandle webSocketHandle, - [In] IntPtr buffers, - [In] IntPtr applicationContext); + [GeneratedDllImport(Libraries.WebSocket)] + internal static partial int WebSocketReceive( + SafeHandle webSocketHandle, + IntPtr buffers, + IntPtr applicationContext); } } diff --git a/src/libraries/Common/src/Interop/Windows/WebSocket/Interop.WebSocketSend.cs b/src/libraries/Common/src/Interop/Windows/WebSocket/Interop.WebSocketSend.cs index 993709ec19c8e..2a6c8fd653897 100644 --- a/src/libraries/Common/src/Interop/Windows/WebSocket/Interop.WebSocketSend.cs +++ b/src/libraries/Common/src/Interop/Windows/WebSocket/Interop.WebSocketSend.cs @@ -10,18 +10,18 @@ internal static partial class Interop { internal static partial class WebSocket { - [DllImport(Libraries.WebSocket, EntryPoint = "WebSocketSend", ExactSpelling = true)] - internal static extern int WebSocketSend_Raw( - [In] SafeHandle webSocketHandle, - [In] BufferType bufferType, - [In] ref Buffer buffer, - [In] IntPtr applicationContext); + [GeneratedDllImport(Libraries.WebSocket, EntryPoint = "WebSocketSend", ExactSpelling = true)] + internal static partial int WebSocketSend_Raw( + SafeHandle webSocketHandle, + BufferType bufferType, + ref Buffer buffer, + IntPtr applicationContext); - [DllImport(Libraries.WebSocket, EntryPoint = "WebSocketSend", ExactSpelling = true)] - internal static extern int WebSocketSendWithoutBody_Raw( - [In] SafeHandle webSocketHandle, - [In] BufferType bufferType, - [In] IntPtr buffer, - [In] IntPtr applicationContext); + [GeneratedDllImport(Libraries.WebSocket, EntryPoint = "WebSocketSend", ExactSpelling = true)] + internal static partial int WebSocketSendWithoutBody_Raw( + SafeHandle webSocketHandle, + BufferType bufferType, + IntPtr buffer, + IntPtr applicationContext); } } diff --git a/src/libraries/Common/src/Interop/Windows/WinHttp/Interop.winhttp.cs b/src/libraries/Common/src/Interop/Windows/WinHttp/Interop.winhttp.cs index 82a8218338ca5..c09f70be31399 100644 --- a/src/libraries/Common/src/Interop/Windows/WinHttp/Interop.winhttp.cs +++ b/src/libraries/Common/src/Interop/Windows/WinHttp/Interop.winhttp.cs @@ -9,27 +9,48 @@ internal static partial class Interop { internal static partial class WinHttp { +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)] + public static partial SafeWinHttpHandle WinHttpOpen( +#else [DllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)] public static extern SafeWinHttpHandle WinHttpOpen( +#endif IntPtr userAgent, uint accessType, string? proxyName, string? proxyBypass, int flags); +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static partial bool WinHttpCloseHandle( +#else [DllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool WinHttpCloseHandle( +#endif IntPtr handle); +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)] + public static partial SafeWinHttpHandle WinHttpConnect( +#else [DllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)] public static extern SafeWinHttpHandle WinHttpConnect( +#endif SafeWinHttpHandle sessionHandle, string serverName, ushort serverPort, uint reserved); +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)] + public static partial SafeWinHttpHandle WinHttpOpenRequest( +#else [DllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)] public static extern SafeWinHttpHandle WinHttpOpenRequest( +#endif SafeWinHttpHandle connectHandle, string verb, string objectName, @@ -48,17 +69,29 @@ public static extern bool WinHttpAddRequestHeaders( uint headersLength, uint modifiers); +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static partial bool WinHttpAddRequestHeaders( +#else [DllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool WinHttpAddRequestHeaders( +#endif SafeWinHttpHandle requestHandle, string headers, uint headersLength, uint modifiers); +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static partial bool WinHttpSendRequest( +#else [DllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool WinHttpSendRequest( +#endif SafeWinHttpHandle requestHandle, IntPtr headers, uint headersLength, @@ -67,29 +100,53 @@ public static extern bool WinHttpSendRequest( uint totalLength, IntPtr context); +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static partial bool WinHttpReceiveResponse( +#else [DllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool WinHttpReceiveResponse( +#endif SafeWinHttpHandle requestHandle, IntPtr reserved); +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static partial bool WinHttpQueryDataAvailable( +#else [DllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool WinHttpQueryDataAvailable( +#endif SafeWinHttpHandle requestHandle, IntPtr parameterIgnoredAndShouldBeNullForAsync); +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static partial bool WinHttpReadData( +#else [DllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool WinHttpReadData( +#endif SafeWinHttpHandle requestHandle, IntPtr buffer, uint bufferSize, IntPtr parameterIgnoredAndShouldBeNullForAsync); +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static partial bool WinHttpQueryHeaders( +#else [DllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool WinHttpQueryHeaders( +#endif SafeWinHttpHandle requestHandle, uint infoLevel, string name, @@ -97,9 +154,15 @@ public static extern bool WinHttpQueryHeaders( ref uint bufferLength, ref uint index); +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static partial bool WinHttpQueryHeaders( +#else [DllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool WinHttpQueryHeaders( +#endif SafeWinHttpHandle requestHandle, uint infoLevel, string name, @@ -107,57 +170,99 @@ public static extern bool WinHttpQueryHeaders( ref uint bufferLength, IntPtr index); +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static partial bool WinHttpQueryOption( +#else [DllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool WinHttpQueryOption( +#endif SafeWinHttpHandle handle, uint option, ref IntPtr buffer, ref uint bufferSize); +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static partial bool WinHttpQueryOption( +#else [DllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool WinHttpQueryOption( +#endif SafeWinHttpHandle handle, uint option, IntPtr buffer, ref uint bufferSize); +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static partial bool WinHttpQueryOption( +#else [DllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool WinHttpQueryOption( +#endif SafeWinHttpHandle handle, uint option, ref uint buffer, ref uint bufferSize); +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static partial bool WinHttpWriteData( +#else [DllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool WinHttpWriteData( +#endif SafeWinHttpHandle requestHandle, IntPtr buffer, uint bufferSize, IntPtr parameterIgnoredAndShouldBeNullForAsync); +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static partial bool WinHttpSetOption( +#else [DllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool WinHttpSetOption( +#endif SafeWinHttpHandle handle, uint option, ref uint optionData, uint optionLength = sizeof(uint)); +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static partial bool WinHttpSetOption( +#else [DllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool WinHttpSetOption( +#endif SafeWinHttpHandle handle, uint option, IntPtr optionData, uint optionLength); +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static partial bool WinHttpSetCredentials( +#else [DllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool WinHttpSetCredentials( +#endif SafeWinHttpHandle requestHandle, uint authTargets, uint authScheme, @@ -165,26 +270,44 @@ public static extern bool WinHttpSetCredentials( string? password, IntPtr reserved); +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static partial bool WinHttpQueryAuthSchemes( +#else [DllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool WinHttpQueryAuthSchemes( +#endif SafeWinHttpHandle requestHandle, out uint supportedSchemes, out uint firstScheme, out uint authTarget); +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static partial bool WinHttpSetTimeouts( +#else [DllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool WinHttpSetTimeouts( +#endif SafeWinHttpHandle handle, int resolveTimeout, int connectTimeout, int sendTimeout, int receiveTimeout); +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)] + [return: MarshalAs(UnmanagedType.Bool)] + public static partial bool WinHttpGetIEProxyConfigForCurrentUser( +#else [DllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool WinHttpGetIEProxyConfigForCurrentUser( +#endif out WINHTTP_CURRENT_USER_IE_PROXY_CONFIG proxyConfig); [DllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)] @@ -194,8 +317,13 @@ public static extern bool WinHttpGetProxyForUrl( ref WINHTTP_AUTOPROXY_OPTIONS autoProxyOptions, out WINHTTP_PROXY_INFO proxyInfo); +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)] + public static partial IntPtr WinHttpSetStatusCallback( +#else [DllImport(Interop.Libraries.WinHttp, CharSet = CharSet.Unicode, SetLastError = true)] public static extern IntPtr WinHttpSetStatusCallback( +#endif SafeWinHttpHandle handle, WINHTTP_STATUS_CALLBACK callback, uint notificationFlags, diff --git a/src/libraries/Common/src/Interop/Windows/WinHttp/Interop.winhttp_types.cs b/src/libraries/Common/src/Interop/Windows/WinHttp/Interop.winhttp_types.cs index 3344e34b0265e..27213cc2a0ed3 100644 --- a/src/libraries/Common/src/Interop/Windows/WinHttp/Interop.winhttp_types.cs +++ b/src/libraries/Common/src/Interop/Windows/WinHttp/Interop.winhttp_types.cs @@ -259,8 +259,7 @@ public struct WINHTTP_AUTOPROXY_OPTIONS [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct WINHTTP_CURRENT_USER_IE_PROXY_CONFIG { - [MarshalAs(UnmanagedType.Bool)] - public bool AutoDetect; + public int AutoDetect; public IntPtr AutoConfigUrl; public IntPtr Proxy; public IntPtr ProxyBypass; diff --git a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.GetAddrInfoExW.cs b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.GetAddrInfoExW.cs index 8129b25332f4d..2467400c6dc3d 100644 --- a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.GetAddrInfoExW.cs +++ b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.GetAddrInfoExW.cs @@ -17,18 +17,18 @@ internal static partial class Winsock internal const int NS_ALL = 0; - [DllImport(Libraries.Ws2_32, ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern unsafe int GetAddrInfoExW( - [In] string pName, - [In] string? pServiceName, - [In] int dwNamespace, - [In] IntPtr lpNspId, - [In] AddressInfoEx* pHints, - [Out] AddressInfoEx** ppResult, - [In] IntPtr timeout, - [In] NativeOverlapped* lpOverlapped, - [In] delegate* unmanaged lpCompletionRoutine, - [Out] IntPtr* lpNameHandle); + [GeneratedDllImport(Libraries.Ws2_32, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] + internal static unsafe partial int GetAddrInfoExW( + string pName, + string? pServiceName, + int dwNamespace, + IntPtr lpNspId, + AddressInfoEx* pHints, + AddressInfoEx** ppResult, + IntPtr timeout, + NativeOverlapped* lpOverlapped, + delegate* unmanaged lpCompletionRoutine, + IntPtr* lpNameHandle); [DllImport(Libraries.Ws2_32, ExactSpelling = true)] internal static extern unsafe int GetAddrInfoExCancel([In] IntPtr* lpHandle); diff --git a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.GetAddrInfoW.cs b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.GetAddrInfoW.cs index 01fdff217eeba..bca3683b7b4fe 100644 --- a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.GetAddrInfoW.cs +++ b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.GetAddrInfoW.cs @@ -9,15 +9,15 @@ internal static partial class Interop { internal static partial class Winsock { - [DllImport(Interop.Libraries.Ws2_32, ExactSpelling = true, CharSet = CharSet.Unicode, BestFitMapping = false, ThrowOnUnmappableChar = true, SetLastError = true)] - internal static extern unsafe int GetAddrInfoW( - [In] string pNameName, - [In] string? pServiceName, - [In] AddressInfo* pHints, - [Out] AddressInfo** ppResult); + [GeneratedDllImport(Interop.Libraries.Ws2_32, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)] + internal static unsafe partial int GetAddrInfoW( + string pNameName, + string? pServiceName, + AddressInfo* pHints, + AddressInfo** ppResult); - [DllImport(Interop.Libraries.Ws2_32, ExactSpelling = true, SetLastError = true)] - internal static extern unsafe void FreeAddrInfoW(AddressInfo* info); + [GeneratedDllImport(Interop.Libraries.Ws2_32, ExactSpelling = true, SetLastError = true)] + internal static unsafe partial void FreeAddrInfoW(AddressInfo* info); [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] internal unsafe struct AddressInfo diff --git a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.GetNameInfoW.cs b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.GetNameInfoW.cs index 13673f2adff7d..7825ed7ac5ae2 100644 --- a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.GetNameInfoW.cs +++ b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.GetNameInfoW.cs @@ -19,8 +19,8 @@ internal enum NameInfoFlags NI_DGRAM = 0x10, /* Service is a datagram service */ } - [DllImport(Interop.Libraries.Ws2_32, CharSet = CharSet.Unicode, BestFitMapping = false, ThrowOnUnmappableChar = true, SetLastError = true)] - internal static extern unsafe SocketError GetNameInfoW( + [GeneratedDllImport(Interop.Libraries.Ws2_32, CharSet = CharSet.Unicode, SetLastError = true)] + internal static unsafe partial SocketError GetNameInfoW( byte* pSockaddr, int SockaddrLength, char* pNodeBuffer, diff --git a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.TransmitFile.cs b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.TransmitFile.cs index c26ce52c41c91..56de7a94d9f7f 100644 --- a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.TransmitFile.cs +++ b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.TransmitFile.cs @@ -10,8 +10,8 @@ internal static partial class Interop { internal static partial class Mswsock { - [DllImport(Interop.Libraries.Mswsock, SetLastError = true)] - internal static extern unsafe bool TransmitFile( + [GeneratedDllImport(Interop.Libraries.Mswsock, SetLastError = true)] + internal static unsafe partial bool TransmitFile( SafeHandle socket, IntPtr fileHandle, int numberOfBytesToWrite, diff --git a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSAConnect.cs b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSAConnect.cs index a15a0d67f0468..6d827d94e2332 100644 --- a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSAConnect.cs +++ b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSAConnect.cs @@ -9,14 +9,14 @@ internal static partial class Interop { internal static partial class Winsock { - [DllImport(Interop.Libraries.Ws2_32, SetLastError = true)] - internal static extern SocketError WSAConnect( + [GeneratedDllImport(Interop.Libraries.Ws2_32, SetLastError = true)] + internal static partial SocketError WSAConnect( SafeSocketHandle socketHandle, - [In] byte[] socketAddress, - [In] int socketAddressSize, - [In] IntPtr inBuffer, - [In] IntPtr outBuffer, - [In] IntPtr sQOS, - [In] IntPtr gQOS); + byte[] socketAddress, + int socketAddressSize, + IntPtr inBuffer, + IntPtr outBuffer, + IntPtr sQOS, + IntPtr gQOS); } } diff --git a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSADuplicateSocket.cs b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSADuplicateSocket.cs index a394ebb519fea..25c50d0522e3a 100644 --- a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSADuplicateSocket.cs +++ b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSADuplicateSocket.cs @@ -8,11 +8,11 @@ internal static partial class Interop { internal static partial class Winsock { - [DllImport(Interop.Libraries.Ws2_32, CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern unsafe int WSADuplicateSocket( - [In] SafeSocketHandle s, - [In] uint dwProcessId, - [In] WSAPROTOCOL_INFOW* lpProtocolInfo + [GeneratedDllImport(Interop.Libraries.Ws2_32, CharSet = CharSet.Unicode, SetLastError = true)] + internal static unsafe partial int WSADuplicateSocket( + SafeSocketHandle s, + uint dwProcessId, + WSAPROTOCOL_INFOW* lpProtocolInfo ); } } diff --git a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSAEventSelect.cs b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSAEventSelect.cs index 9318345ec9387..a3903f29c3dbb 100644 --- a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSAEventSelect.cs +++ b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSAEventSelect.cs @@ -9,11 +9,11 @@ internal static partial class Interop { internal static partial class Winsock { - [DllImport(Interop.Libraries.Ws2_32, SetLastError = true)] - internal static extern SocketError WSAEventSelect( - [In] SafeSocketHandle socketHandle, - [In] SafeHandle Event, - [In] AsyncEventBits NetworkEvents); + [GeneratedDllImport(Interop.Libraries.Ws2_32, SetLastError = true)] + internal static partial SocketError WSAEventSelect( + SafeSocketHandle socketHandle, + SafeHandle Event, + AsyncEventBits NetworkEvents); [Flags] internal enum AsyncEventBits diff --git a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSAGetOverlappedResult.cs b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSAGetOverlappedResult.cs index 51517a2e3c621..4ba107cf46299 100644 --- a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSAGetOverlappedResult.cs +++ b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSAGetOverlappedResult.cs @@ -9,12 +9,12 @@ internal static partial class Interop { internal static partial class Winsock { - [DllImport(Interop.Libraries.Ws2_32, SetLastError = true)] - internal static extern unsafe bool WSAGetOverlappedResult( - [In] SafeSocketHandle socketHandle, - [In] NativeOverlapped* overlapped, - [Out] out uint bytesTransferred, - [In] bool wait, - [Out] out SocketFlags socketFlags); + [GeneratedDllImport(Interop.Libraries.Ws2_32, SetLastError = true)] + internal static unsafe partial bool WSAGetOverlappedResult( + SafeSocketHandle socketHandle, + NativeOverlapped* overlapped, + out uint bytesTransferred, + bool wait, + out SocketFlags socketFlags); } } diff --git a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSAIoctl.cs b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSAIoctl.cs index d067e351f755c..37265789dc827 100644 --- a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSAIoctl.cs +++ b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSAIoctl.cs @@ -22,16 +22,16 @@ internal static extern SocketError WSAIoctl( [In] IntPtr shouldBeNull, [In] IntPtr shouldBeNull2); - [DllImport(Interop.Libraries.Ws2_32, SetLastError = true, EntryPoint = "WSAIoctl")] - internal static extern SocketError WSAIoctl_Blocking( + [GeneratedDllImport(Interop.Libraries.Ws2_32, EntryPoint = "WSAIoctl", SetLastError = true)] + internal static partial SocketError WSAIoctl_Blocking( SafeSocketHandle socketHandle, - [In] int ioControlCode, - [In] byte[]? inBuffer, - [In] int inBufferSize, - [Out] byte[]? outBuffer, - [In] int outBufferSize, - [Out] out int bytesTransferred, - [In] IntPtr overlapped, - [In] IntPtr completionRoutine); + int ioControlCode, + byte[]? inBuffer, + int inBufferSize, + byte[]? outBuffer, + int outBufferSize, + out int bytesTransferred, + IntPtr overlapped, + IntPtr completionRoutine); } } diff --git a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSARecv.cs b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSARecv.cs index e775ebcd775b0..1a9f090bd83c3 100644 --- a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSARecv.cs +++ b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSARecv.cs @@ -11,8 +11,8 @@ internal static partial class Interop { internal static partial class Winsock { - [DllImport(Libraries.Ws2_32, SetLastError = true)] - internal static extern unsafe SocketError WSARecv( + [GeneratedDllImport(Libraries.Ws2_32, SetLastError = true)] + internal static unsafe partial SocketError WSARecv( SafeHandle socketHandle, WSABuffer* buffer, int bufferCount, diff --git a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSARecvFrom.cs b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSARecvFrom.cs index da2667e0bbe66..dc200e6c8fd30 100644 --- a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSARecvFrom.cs +++ b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSARecvFrom.cs @@ -11,8 +11,8 @@ internal static partial class Interop { internal static partial class Winsock { - [DllImport(Interop.Libraries.Ws2_32, SetLastError = true)] - private static extern unsafe SocketError WSARecvFrom( + [GeneratedDllImport(Interop.Libraries.Ws2_32, SetLastError = true)] + private static unsafe partial SocketError WSARecvFrom( SafeHandle socketHandle, WSABuffer* buffers, int bufferCount, diff --git a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSASend.cs b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSASend.cs index 30c2786b664e2..583674f8f4aa8 100644 --- a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSASend.cs +++ b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSASend.cs @@ -11,8 +11,8 @@ internal static partial class Interop { internal static partial class Winsock { - [DllImport(Libraries.Ws2_32, SetLastError = true)] - internal static extern unsafe SocketError WSASend( + [GeneratedDllImport(Libraries.Ws2_32, SetLastError = true)] + internal static unsafe partial SocketError WSASend( SafeHandle socketHandle, WSABuffer* buffers, int bufferCount, diff --git a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSASendTo.cs b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSASendTo.cs index b98509b1ca27d..4896eb8557ad5 100644 --- a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSASendTo.cs +++ b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSASendTo.cs @@ -11,8 +11,8 @@ internal static partial class Interop { internal static partial class Winsock { - [DllImport(Interop.Libraries.Ws2_32, SetLastError = true)] - private static extern unsafe SocketError WSASendTo( + [GeneratedDllImport(Interop.Libraries.Ws2_32, SetLastError = true)] + private static unsafe partial SocketError WSASendTo( SafeHandle socketHandle, WSABuffer* buffers, int bufferCount, diff --git a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSASocketW.SafeCloseSocket.cs b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSASocketW.SafeCloseSocket.cs index 2fca0e1aa269b..fcf408c262a03 100644 --- a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSASocketW.SafeCloseSocket.cs +++ b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSASocketW.SafeCloseSocket.cs @@ -9,13 +9,13 @@ internal static partial class Interop { internal static partial class Winsock { - [DllImport(Interop.Libraries.Ws2_32, CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern IntPtr WSASocketW( - [In] AddressFamily addressFamily, - [In] SocketType socketType, - [In] ProtocolType protocolType, - [In] IntPtr protocolInfo, - [In] uint group, - [In] SocketConstructorFlags flags); + [GeneratedDllImport(Interop.Libraries.Ws2_32, CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial IntPtr WSASocketW( + AddressFamily addressFamily, + SocketType socketType, + ProtocolType protocolType, + IntPtr protocolInfo, + uint group, + SocketConstructorFlags flags); } } diff --git a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSASocketW.cs b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSASocketW.cs index db6e3bda33e66..9f0060b4afdd1 100644 --- a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSASocketW.cs +++ b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.WSASocketW.cs @@ -12,13 +12,13 @@ internal static partial class Interop { internal static partial class Winsock { - [DllImport(Interop.Libraries.Ws2_32, CharSet = CharSet.Unicode, SetLastError = true)] - internal static extern IntPtr WSASocketW( - [In] AddressFamily addressFamily, - [In] SocketType socketType, - [In] int protocolType, - [In] IntPtr protocolInfo, - [In] int group, - [In] int flags); + [GeneratedDllImport(Interop.Libraries.Ws2_32, CharSet = CharSet.Unicode, SetLastError = true)] + internal static partial IntPtr WSASocketW( + AddressFamily addressFamily, + SocketType socketType, + int protocolType, + IntPtr protocolInfo, + int group, + int flags); } } diff --git a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.accept.cs b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.accept.cs index 0e0ae44df5f07..4e34ee8b1fe13 100644 --- a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.accept.cs +++ b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.accept.cs @@ -9,10 +9,10 @@ internal static partial class Interop { internal static partial class Winsock { - [DllImport(Interop.Libraries.Ws2_32, ExactSpelling = true, SetLastError = true)] - internal static extern IntPtr accept( + [GeneratedDllImport(Interop.Libraries.Ws2_32, ExactSpelling = true, SetLastError = true)] + internal static partial IntPtr accept( SafeSocketHandle socketHandle, - [Out] byte[] socketAddress, - [In, Out] ref int socketAddressSize); + byte[] socketAddress, + ref int socketAddressSize); } } diff --git a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.bind.cs b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.bind.cs index e407f134dadb9..a5f8d3b664557 100644 --- a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.bind.cs +++ b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.bind.cs @@ -8,10 +8,10 @@ internal static partial class Interop { internal static partial class Winsock { - [DllImport(Interop.Libraries.Ws2_32, SetLastError = true)] - internal static extern SocketError bind( - [In] SafeSocketHandle socketHandle, - [In] byte[] socketAddress, - [In] int socketAddressSize); + [GeneratedDllImport(Interop.Libraries.Ws2_32, SetLastError = true)] + internal static partial SocketError bind( + SafeSocketHandle socketHandle, + byte[] socketAddress, + int socketAddressSize); } } diff --git a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.closesocket.cs b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.closesocket.cs index 1a1f6406e2901..d80768bccba4b 100644 --- a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.closesocket.cs +++ b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.closesocket.cs @@ -9,7 +9,7 @@ internal static partial class Interop { internal static partial class Winsock { - [DllImport(Interop.Libraries.Ws2_32, ExactSpelling = true, SetLastError = true)] - internal static extern SocketError closesocket([In] IntPtr socketHandle); + [GeneratedDllImport(Interop.Libraries.Ws2_32, ExactSpelling = true, SetLastError = true)] + internal static partial SocketError closesocket(IntPtr socketHandle); } } diff --git a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.gethostname.cs b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.gethostname.cs index 292b73230406c..54b90ef1df81f 100644 --- a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.gethostname.cs +++ b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.gethostname.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Winsock { - [DllImport(Interop.Libraries.Ws2_32, SetLastError = true)] - internal static extern unsafe SocketError gethostname(byte* name, int namelen); + [GeneratedDllImport(Interop.Libraries.Ws2_32, SetLastError = true)] + internal static unsafe partial SocketError gethostname(byte* name, int namelen); } } diff --git a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.getpeername.cs b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.getpeername.cs index a2ce5be9b4a1b..fa7b34683d502 100644 --- a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.getpeername.cs +++ b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.getpeername.cs @@ -9,10 +9,10 @@ internal static partial class Interop { internal static partial class Winsock { - [DllImport(Interop.Libraries.Ws2_32, SetLastError = true)] - internal static extern unsafe SocketError getpeername( - [In] SafeSocketHandle socketHandle, - [Out] byte* socketAddress, - [In, Out] ref int socketAddressSize); + [GeneratedDllImport(Interop.Libraries.Ws2_32, SetLastError = true)] + internal static unsafe partial SocketError getpeername( + SafeSocketHandle socketHandle, + byte* socketAddress, + ref int socketAddressSize); } } diff --git a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.getsockname.cs b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.getsockname.cs index f457ea17c40c1..d177ac70cacae 100644 --- a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.getsockname.cs +++ b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.getsockname.cs @@ -8,8 +8,8 @@ internal static partial class Interop { internal static partial class Winsock { - [DllImport(Interop.Libraries.Ws2_32, SetLastError = true)] - internal static extern unsafe SocketError getsockname( + [GeneratedDllImport(Interop.Libraries.Ws2_32, SetLastError = true)] + internal static unsafe partial SocketError getsockname( SafeSocketHandle socketHandle, byte* socketAddress, int* socketAddressSize); diff --git a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.getsockopt.cs b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.getsockopt.cs index 78deae877c635..bdfd0e49be9f0 100644 --- a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.getsockopt.cs +++ b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.getsockopt.cs @@ -8,29 +8,29 @@ internal static partial class Interop { internal static partial class Winsock { - [DllImport(Interop.Libraries.Ws2_32, SetLastError = true)] - internal static unsafe extern SocketError getsockopt( - [In] SafeSocketHandle socketHandle, - [In] SocketOptionLevel optionLevel, - [In] SocketOptionName optionName, - [Out] byte* optionValue, - [In, Out] ref int optionLength); + [GeneratedDllImport(Interop.Libraries.Ws2_32, SetLastError = true)] + internal static unsafe partial SocketError getsockopt( + SafeSocketHandle socketHandle, + SocketOptionLevel optionLevel, + SocketOptionName optionName, + byte* optionValue, + ref int optionLength); - [DllImport(Interop.Libraries.Ws2_32, SetLastError = true)] - internal static extern SocketError getsockopt( - [In] SafeSocketHandle socketHandle, - [In] SocketOptionLevel optionLevel, - [In] SocketOptionName optionName, - [Out] out Linger optionValue, - [In, Out] ref int optionLength); + [GeneratedDllImport(Interop.Libraries.Ws2_32, SetLastError = true)] + internal static partial SocketError getsockopt( + SafeSocketHandle socketHandle, + SocketOptionLevel optionLevel, + SocketOptionName optionName, + out Linger optionValue, + ref int optionLength); - [DllImport(Interop.Libraries.Ws2_32, SetLastError = true)] - internal static extern SocketError getsockopt( - [In] SafeSocketHandle socketHandle, - [In] SocketOptionLevel optionLevel, - [In] SocketOptionName optionName, - [Out] out IPMulticastRequest optionValue, - [In, Out] ref int optionLength); + [GeneratedDllImport(Interop.Libraries.Ws2_32, SetLastError = true)] + internal static partial SocketError getsockopt( + SafeSocketHandle socketHandle, + SocketOptionLevel optionLevel, + SocketOptionName optionName, + out IPMulticastRequest optionValue, + ref int optionLength); [DllImport(Interop.Libraries.Ws2_32, SetLastError = true)] internal static extern SocketError getsockopt( diff --git a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.ioctlsocket.cs b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.ioctlsocket.cs index f9ed61b46e115..92e32e6d3c561 100644 --- a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.ioctlsocket.cs +++ b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.ioctlsocket.cs @@ -9,16 +9,16 @@ internal static partial class Interop { internal static partial class Winsock { - [DllImport(Interop.Libraries.Ws2_32, ExactSpelling = true, SetLastError = true)] - internal static extern SocketError ioctlsocket( - [In] IntPtr handle, - [In] int cmd, - [In, Out] ref int argp); + [GeneratedDllImport(Interop.Libraries.Ws2_32, ExactSpelling = true, SetLastError = true)] + internal static partial SocketError ioctlsocket( + IntPtr handle, + int cmd, + ref int argp); - [DllImport(Interop.Libraries.Ws2_32, SetLastError = true)] - internal static extern SocketError ioctlsocket( - [In] SafeSocketHandle socketHandle, - [In] int cmd, - [In, Out] ref int argp); + [GeneratedDllImport(Interop.Libraries.Ws2_32, SetLastError = true)] + internal static partial SocketError ioctlsocket( + SafeSocketHandle socketHandle, + int cmd, + ref int argp); } } diff --git a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.listen.cs b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.listen.cs index 3afb3b4fe28bc..a86447206247d 100644 --- a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.listen.cs +++ b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.listen.cs @@ -8,9 +8,9 @@ internal static partial class Interop { internal static partial class Winsock { - [DllImport(Interop.Libraries.Ws2_32, SetLastError = true)] - internal static extern SocketError listen( - [In] SafeSocketHandle socketHandle, - [In] int backlog); + [GeneratedDllImport(Interop.Libraries.Ws2_32, SetLastError = true)] + internal static partial SocketError listen( + SafeSocketHandle socketHandle, + int backlog); } } diff --git a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.recv.cs b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.recv.cs index a4fd9b41ed2e5..20f0a6801a4ab 100644 --- a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.recv.cs +++ b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.recv.cs @@ -9,11 +9,11 @@ internal static partial class Interop { internal static partial class Winsock { - [DllImport(Interop.Libraries.Ws2_32, SetLastError = true)] - internal static extern unsafe int recv( + [GeneratedDllImport(Interop.Libraries.Ws2_32, SetLastError = true)] + internal static unsafe partial int recv( SafeSocketHandle socketHandle, - [In] byte* pinnedBuffer, - [In] int len, - [In] SocketFlags socketFlags); + byte* pinnedBuffer, + int len, + SocketFlags socketFlags); } } diff --git a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.recvfrom.cs b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.recvfrom.cs index 95d1dee327f7e..14daa97315975 100644 --- a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.recvfrom.cs +++ b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.recvfrom.cs @@ -10,13 +10,13 @@ internal static partial class Interop internal static partial class Winsock { // This method is always blocking, so it uses an IntPtr. - [DllImport(Interop.Libraries.Ws2_32, SetLastError = true)] - internal static extern unsafe int recvfrom( + [GeneratedDllImport(Interop.Libraries.Ws2_32, SetLastError = true)] + internal static unsafe partial int recvfrom( SafeSocketHandle socketHandle, - [In] byte* pinnedBuffer, - [In] int len, - [In] SocketFlags socketFlags, - [Out] byte[] socketAddress, - [In, Out] ref int socketAddressSize); + byte* pinnedBuffer, + int len, + SocketFlags socketFlags, + byte[] socketAddress, + ref int socketAddressSize); } } diff --git a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.select.cs b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.select.cs index f6a2670643f2b..889bdeea2aa84 100644 --- a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.select.cs +++ b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.select.cs @@ -8,20 +8,20 @@ internal static partial class Interop { internal static partial class Winsock { - [DllImport(Interop.Libraries.Ws2_32, SetLastError = true)] - internal static extern unsafe int select( - [In] int ignoredParameter, - [In] IntPtr* readfds, - [In] IntPtr* writefds, - [In] IntPtr* exceptfds, - [In] ref TimeValue timeout); + [GeneratedDllImport(Interop.Libraries.Ws2_32, SetLastError = true)] + internal static unsafe partial int select( + int ignoredParameter, + IntPtr* readfds, + IntPtr* writefds, + IntPtr* exceptfds, + ref TimeValue timeout); - [DllImport(Interop.Libraries.Ws2_32, SetLastError = true)] - internal static extern unsafe int select( - [In] int ignoredParameter, - [In] IntPtr* readfds, - [In] IntPtr* writefds, - [In] IntPtr* exceptfds, - [In] IntPtr nullTimeout); + [GeneratedDllImport(Interop.Libraries.Ws2_32, SetLastError = true)] + internal static unsafe partial int select( + int ignoredParameter, + IntPtr* readfds, + IntPtr* writefds, + IntPtr* exceptfds, + IntPtr nullTimeout); } } diff --git a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.send.cs b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.send.cs index 4c1e02d5112cd..4c75af9669fcf 100644 --- a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.send.cs +++ b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.send.cs @@ -9,11 +9,11 @@ internal static partial class Interop { internal static partial class Winsock { - [DllImport(Interop.Libraries.Ws2_32, SetLastError = true)] - internal static extern unsafe int send( + [GeneratedDllImport(Interop.Libraries.Ws2_32, SetLastError = true)] + internal static unsafe partial int send( SafeSocketHandle socketHandle, - [In] byte* pinnedBuffer, - [In] int len, - [In] SocketFlags socketFlags); + byte* pinnedBuffer, + int len, + SocketFlags socketFlags); } } diff --git a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.sendto.cs b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.sendto.cs index 66dd58f82b5d9..c2dfd4801f743 100644 --- a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.sendto.cs +++ b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.sendto.cs @@ -9,13 +9,13 @@ internal static partial class Interop { internal static partial class Winsock { - [DllImport(Interop.Libraries.Ws2_32, SetLastError = true)] - internal static extern unsafe int sendto( + [GeneratedDllImport(Interop.Libraries.Ws2_32, SetLastError = true)] + internal static unsafe partial int sendto( SafeSocketHandle socketHandle, - [In] byte* pinnedBuffer, - [In] int len, - [In] SocketFlags socketFlags, - [In] byte[] socketAddress, - [In] int socketAddressSize); + byte* pinnedBuffer, + int len, + SocketFlags socketFlags, + byte[] socketAddress, + int socketAddressSize); } } diff --git a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.setsockopt.cs b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.setsockopt.cs index 6c5118655e1fb..98a9a3d4f3295 100644 --- a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.setsockopt.cs +++ b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.setsockopt.cs @@ -9,53 +9,53 @@ internal static partial class Interop { internal static partial class Winsock { - [DllImport(Interop.Libraries.Ws2_32, ExactSpelling = true, SetLastError = true)] - internal static extern SocketError setsockopt( - [In] IntPtr handle, - [In] SocketOptionLevel optionLevel, - [In] SocketOptionName optionName, - [In] ref Linger linger, - [In] int optionLength); + [GeneratedDllImport(Interop.Libraries.Ws2_32, ExactSpelling = true, SetLastError = true)] + internal static partial SocketError setsockopt( + IntPtr handle, + SocketOptionLevel optionLevel, + SocketOptionName optionName, + ref Linger linger, + int optionLength); - [DllImport(Interop.Libraries.Ws2_32, SetLastError = true)] - internal static extern SocketError setsockopt( - [In] SafeSocketHandle socketHandle, - [In] SocketOptionLevel optionLevel, - [In] SocketOptionName optionName, - [In] ref int optionValue, - [In] int optionLength); + [GeneratedDllImport(Interop.Libraries.Ws2_32, SetLastError = true)] + internal static partial SocketError setsockopt( + SafeSocketHandle socketHandle, + SocketOptionLevel optionLevel, + SocketOptionName optionName, + ref int optionValue, + int optionLength); - [DllImport(Interop.Libraries.Ws2_32, SetLastError = true)] - internal static unsafe extern SocketError setsockopt( - [In] SafeSocketHandle socketHandle, - [In] SocketOptionLevel optionLevel, - [In] SocketOptionName optionName, - [In] byte* optionValue, - [In] int optionLength); + [GeneratedDllImport(Interop.Libraries.Ws2_32, SetLastError = true)] + internal static unsafe partial SocketError setsockopt( + SafeSocketHandle socketHandle, + SocketOptionLevel optionLevel, + SocketOptionName optionName, + byte* optionValue, + int optionLength); - [DllImport(Interop.Libraries.Ws2_32, SetLastError = true)] - internal static extern SocketError setsockopt( - [In] SafeSocketHandle socketHandle, - [In] SocketOptionLevel optionLevel, - [In] SocketOptionName optionName, - [In] ref IntPtr pointer, - [In] int optionLength); + [GeneratedDllImport(Interop.Libraries.Ws2_32, SetLastError = true)] + internal static partial SocketError setsockopt( + SafeSocketHandle socketHandle, + SocketOptionLevel optionLevel, + SocketOptionName optionName, + ref IntPtr pointer, + int optionLength); - [DllImport(Interop.Libraries.Ws2_32, SetLastError = true)] - internal static extern SocketError setsockopt( - [In] SafeSocketHandle socketHandle, - [In] SocketOptionLevel optionLevel, - [In] SocketOptionName optionName, - [In] ref Linger linger, - [In] int optionLength); + [GeneratedDllImport(Interop.Libraries.Ws2_32, SetLastError = true)] + internal static partial SocketError setsockopt( + SafeSocketHandle socketHandle, + SocketOptionLevel optionLevel, + SocketOptionName optionName, + ref Linger linger, + int optionLength); - [DllImport(Interop.Libraries.Ws2_32, SetLastError = true)] - internal static extern SocketError setsockopt( - [In] SafeSocketHandle socketHandle, - [In] SocketOptionLevel optionLevel, - [In] SocketOptionName optionName, - [In] ref IPMulticastRequest mreq, - [In] int optionLength); + [GeneratedDllImport(Interop.Libraries.Ws2_32, SetLastError = true)] + internal static partial SocketError setsockopt( + SafeSocketHandle socketHandle, + SocketOptionLevel optionLevel, + SocketOptionName optionName, + ref IPMulticastRequest mreq, + int optionLength); [DllImport(Interop.Libraries.Ws2_32, SetLastError = true)] internal static extern SocketError setsockopt( diff --git a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.shutdown.cs b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.shutdown.cs index 99086e04fee27..870a9c3332833 100644 --- a/src/libraries/Common/src/Interop/Windows/WinSock/Interop.shutdown.cs +++ b/src/libraries/Common/src/Interop/Windows/WinSock/Interop.shutdown.cs @@ -8,9 +8,9 @@ internal static partial class Interop { internal static partial class Winsock { - [DllImport(Interop.Libraries.Ws2_32, SetLastError = true)] - internal static extern SocketError shutdown( - [In] SafeSocketHandle socketHandle, - [In] int how); + [GeneratedDllImport(Interop.Libraries.Ws2_32, SetLastError = true)] + internal static partial SocketError shutdown( + SafeSocketHandle socketHandle, + int how); } } diff --git a/src/libraries/Common/src/Microsoft/Win32/SafeHandles/GssSafeHandles.cs b/src/libraries/Common/src/Microsoft/Win32/SafeHandles/GssSafeHandles.cs index e99fbed3c332c..7d1c8874191a9 100644 --- a/src/libraries/Common/src/Microsoft/Win32/SafeHandles/GssSafeHandles.cs +++ b/src/libraries/Common/src/Microsoft/Win32/SafeHandles/GssSafeHandles.cs @@ -52,12 +52,15 @@ public override bool IsInvalid get { return handle == IntPtr.Zero; } } - protected override bool ReleaseHandle() + protected override unsafe bool ReleaseHandle() { Interop.NetSecurityNative.Status minorStatus; - Interop.NetSecurityNative.Status status = Interop.NetSecurityNative.ReleaseName(out minorStatus, ref handle); - SetHandle(IntPtr.Zero); - return status == Interop.NetSecurityNative.Status.GSS_S_COMPLETE; + fixed (IntPtr* handleRef = &handle) + { + Interop.NetSecurityNative.Status status = Interop.NetSecurityNative.ReleaseName(&minorStatus, handleRef); + SetHandle(IntPtr.Zero); + return status == Interop.NetSecurityNative.Status.GSS_S_COMPLETE; + } } public SafeGssNameHandle() @@ -141,12 +144,15 @@ public override bool IsInvalid get { return handle == IntPtr.Zero; } } - protected override bool ReleaseHandle() + protected override unsafe bool ReleaseHandle() { Interop.NetSecurityNative.Status minorStatus; - Interop.NetSecurityNative.Status status = Interop.NetSecurityNative.ReleaseCred(out minorStatus, ref handle); - SetHandle(IntPtr.Zero); - return status == Interop.NetSecurityNative.Status.GSS_S_COMPLETE; + fixed (IntPtr* handlePtr = &handle) + { + Interop.NetSecurityNative.Status status = Interop.NetSecurityNative.ReleaseCred(&minorStatus, handlePtr); + SetHandle(IntPtr.Zero); + return status == Interop.NetSecurityNative.Status.GSS_S_COMPLETE; + } } private static bool InitIsNtlmInstalled() @@ -167,12 +173,15 @@ public override bool IsInvalid get { return handle == IntPtr.Zero; } } - protected override bool ReleaseHandle() + protected override unsafe bool ReleaseHandle() { Interop.NetSecurityNative.Status minorStatus; - Interop.NetSecurityNative.Status status = Interop.NetSecurityNative.DeleteSecContext(out minorStatus, ref handle); - SetHandle(IntPtr.Zero); - return status == Interop.NetSecurityNative.Status.GSS_S_COMPLETE; + fixed (IntPtr* handlePtr = &handle) + { + Interop.NetSecurityNative.Status status = Interop.NetSecurityNative.DeleteSecContext(&minorStatus, handlePtr); + SetHandle(IntPtr.Zero); + return status == Interop.NetSecurityNative.Status.GSS_S_COMPLETE; + } } } } diff --git a/src/libraries/Common/src/System/Net/Http/WinInetProxyHelper.cs b/src/libraries/Common/src/System/Net/Http/WinInetProxyHelper.cs index 04ea230cfd4c6..c30e77bfa1b8b 100644 --- a/src/libraries/Common/src/System/Net/Http/WinInetProxyHelper.cs +++ b/src/libraries/Common/src/System/Net/Http/WinInetProxyHelper.cs @@ -28,7 +28,7 @@ public WinInetProxyHelper() if (Interop.WinHttp.WinHttpGetIEProxyConfigForCurrentUser(out proxyConfig)) { _autoConfigUrl = Marshal.PtrToStringUni(proxyConfig.AutoConfigUrl)!; - _autoDetect = proxyConfig.AutoDetect; + _autoDetect = proxyConfig.AutoDetect != 0; _proxy = Marshal.PtrToStringUni(proxyConfig.Proxy)!; _proxyBypass = Marshal.PtrToStringUni(proxyConfig.ProxyBypass)!; diff --git a/src/libraries/Common/src/System/Net/NetworkInformation/HostInformationPal.Windows.cs b/src/libraries/Common/src/System/Net/NetworkInformation/HostInformationPal.Windows.cs index 27f6ba5d1937d..bfd4127724ac7 100644 --- a/src/libraries/Common/src/System/Net/NetworkInformation/HostInformationPal.Windows.cs +++ b/src/libraries/Common/src/System/Net/NetworkInformation/HostInformationPal.Windows.cs @@ -26,20 +26,20 @@ public static string GetDomainName() return FixedInfo.domainName; } - private static Interop.IpHlpApi.FIXED_INFO GetFixedInfo() + private static unsafe Interop.IpHlpApi.FIXED_INFO GetFixedInfo() { uint size = 0; Interop.IpHlpApi.FIXED_INFO fixedInfo = default; // First we need to get the size of the buffer - uint result = Interop.IpHlpApi.GetNetworkParams(IntPtr.Zero, ref size); + uint result = Interop.IpHlpApi.GetNetworkParams(IntPtr.Zero, &size); while (result == Interop.IpHlpApi.ERROR_BUFFER_OVERFLOW) { IntPtr buffer = Marshal.AllocHGlobal((int)size); try { - result = Interop.IpHlpApi.GetNetworkParams(buffer, ref size); + result = Interop.IpHlpApi.GetNetworkParams(buffer, &size); if (result == Interop.IpHlpApi.ERROR_SUCCESS) { fixedInfo = Marshal.PtrToStructure(buffer); diff --git a/src/libraries/Common/src/System/Net/Security/CertificateValidation.Windows.cs b/src/libraries/Common/src/System/Net/Security/CertificateValidation.Windows.cs index 6b61ce9a25dba..9efcb10f106d9 100644 --- a/src/libraries/Common/src/System/Net/Security/CertificateValidation.Windows.cs +++ b/src/libraries/Common/src/System/Net/Security/CertificateValidation.Windows.cs @@ -51,7 +51,7 @@ internal static SslPolicyErrors BuildChainAndVerifyProperties(X509Chain chain, X fixed (char* namePtr = hostName) { - eppStruct.pwszServerName = namePtr; + eppStruct.pwszServerName = (ushort*)namePtr; cppStruct.dwFlags |= (Interop.Crypt32.CertChainPolicyIgnoreFlags.CERT_CHAIN_POLICY_IGNORE_ALL & ~Interop.Crypt32.CertChainPolicyIgnoreFlags.CERT_CHAIN_POLICY_IGNORE_INVALID_NAME_FLAG); diff --git a/src/libraries/Common/src/System/Runtime/InteropServices/ArrayMarshaller.cs b/src/libraries/Common/src/System/Runtime/InteropServices/ArrayMarshaller.cs new file mode 100644 index 0000000000000..2293743aa87fe --- /dev/null +++ b/src/libraries/Common/src/System/Runtime/InteropServices/ArrayMarshaller.cs @@ -0,0 +1,235 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// +// 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. +// +#if DLLIMPORTGENERATOR_INTERNALUNSAFE +using Internal.Runtime.CompilerServices; +#else +using System.Runtime.CompilerServices; +#endif +using System.Diagnostics; + +namespace System.Runtime.InteropServices.GeneratedMarshalling +{ +#if DLLIMPORT_GENERATOR_TEST + public +#else + internal +#endif + unsafe ref struct ArrayMarshaller + { + private T[]? _managedArray; + private readonly int _sizeOfNativeElement; + private IntPtr _allocatedMemory; + + public ArrayMarshaller(int sizeOfNativeElement) + : this() + { + _sizeOfNativeElement = sizeOfNativeElement; + } + + public ArrayMarshaller(T[]? managed, int sizeOfNativeElement) + { + _allocatedMemory = default; + _sizeOfNativeElement = sizeOfNativeElement; + if (managed is null) + { + _managedArray = null; + NativeValueStorage = default; + return; + } + _managedArray = managed; + // Always allocate at least one byte when the array is zero-length. + int spaceToAllocate = Math.Max(managed.Length * _sizeOfNativeElement, 1); + _allocatedMemory = Marshal.AllocCoTaskMem(spaceToAllocate); + NativeValueStorage = new Span((void*)_allocatedMemory, spaceToAllocate); + } + + public ArrayMarshaller(T[]? managed, Span stackSpace, int sizeOfNativeElement) + { + _allocatedMemory = default; + _sizeOfNativeElement = sizeOfNativeElement; + if (managed is null) + { + _managedArray = null; + NativeValueStorage = default; + return; + } + _managedArray = managed; + // Always allocate at least one byte when the array is zero-length. + int spaceToAllocate = Math.Max(managed.Length * _sizeOfNativeElement, 1); + if (spaceToAllocate <= stackSpace.Length) + { + NativeValueStorage = stackSpace[0..spaceToAllocate]; + } + else + { + _allocatedMemory = Marshal.AllocCoTaskMem(spaceToAllocate); + NativeValueStorage = new Span((void*)_allocatedMemory, spaceToAllocate); + } + } + + /// + /// Stack-alloc threshold set to 256 bytes to enable small arrays to be passed on the stack. + /// Number kept small to ensure that P/Invokes with a lot of array parameters doesn't + /// blow the stack since this is a new optimization in the code-generated interop. + /// + public const int StackBufferSize = 0x200; + + public Span ManagedValues => _managedArray; + + public Span NativeValueStorage { get; private set; } + + public ref byte GetPinnableReference() => ref MemoryMarshal.GetReference(NativeValueStorage); + + public void SetUnmarshalledCollectionLength(int length) + { + _managedArray = new T[length]; + } + + public byte* Value + { + get + { + Debug.Assert(_managedArray is null || _allocatedMemory != IntPtr.Zero); + return (byte*)_allocatedMemory; + } + set + { + if (value == null) + { + _managedArray = null; + NativeValueStorage = default; + } + else + { + _allocatedMemory = (IntPtr)value; + NativeValueStorage = new Span(value, (_managedArray?.Length ?? 0) * _sizeOfNativeElement); + } + } + } + + public T[]? ToManaged() => _managedArray; + + public void FreeNative() + { + if (_allocatedMemory != IntPtr.Zero) + { + Marshal.FreeCoTaskMem(_allocatedMemory); + } + } + } + +#if DLLIMPORT_GENERATOR_TEST + public +#else + internal +#endif + unsafe ref struct PtrArrayMarshaller where T : unmanaged + { + private T*[]? _managedArray; + private readonly int _sizeOfNativeElement; + private IntPtr _allocatedMemory; + + public PtrArrayMarshaller(int sizeOfNativeElement) + : this() + { + _sizeOfNativeElement = sizeOfNativeElement; + } + + public PtrArrayMarshaller(T*[]? managed, int sizeOfNativeElement) + { + _allocatedMemory = default; + _sizeOfNativeElement = sizeOfNativeElement; + if (managed is null) + { + _managedArray = null; + NativeValueStorage = default; + return; + } + _managedArray = managed; + // Always allocate at least one byte when the array is zero-length. + int spaceToAllocate = Math.Max(managed.Length * _sizeOfNativeElement, 1); + _allocatedMemory = Marshal.AllocCoTaskMem(spaceToAllocate); + NativeValueStorage = new Span((void*)_allocatedMemory, spaceToAllocate); + } + + public PtrArrayMarshaller(T*[]? managed, Span stackSpace, int sizeOfNativeElement) + { + _allocatedMemory = default; + _sizeOfNativeElement = sizeOfNativeElement; + if (managed is null) + { + _managedArray = null; + NativeValueStorage = default; + return; + } + _managedArray = managed; + // Always allocate at least one byte when the array is zero-length. + int spaceToAllocate = Math.Max(managed.Length * _sizeOfNativeElement, 1); + if (spaceToAllocate <= stackSpace.Length) + { + NativeValueStorage = stackSpace[0..spaceToAllocate]; + } + else + { + _allocatedMemory = Marshal.AllocCoTaskMem(spaceToAllocate); + NativeValueStorage = new Span((void*)_allocatedMemory, spaceToAllocate); + } + } + + /// + /// Stack-alloc threshold set to 256 bytes to enable small arrays to be passed on the stack. + /// Number kept small to ensure that P/Invokes with a lot of array parameters doesn't + /// blow the stack since this is a new optimization in the code-generated interop. + /// + public const int StackBufferSize = 0x200; + + public Span ManagedValues => Unsafe.As(_managedArray); + + public Span NativeValueStorage { get; private set; } + + public ref byte GetPinnableReference() => ref MemoryMarshal.GetReference(NativeValueStorage); + + public void SetUnmarshalledCollectionLength(int length) + { + _managedArray = new T*[length]; + } + + public byte* Value + { + get + { + Debug.Assert(_managedArray is null || _allocatedMemory != IntPtr.Zero); + return (byte*)_allocatedMemory; + } + set + { + if (value == null) + { + _managedArray = null; + NativeValueStorage = default; + } + else + { + _allocatedMemory = (IntPtr)value; + NativeValueStorage = new Span(value, (_managedArray?.Length ?? 0) * _sizeOfNativeElement); + } + + } + } + + public T*[]? ToManaged() => _managedArray; + + public void FreeNative() + { + if (_allocatedMemory != IntPtr.Zero) + { + Marshal.FreeCoTaskMem(_allocatedMemory); + } + } + } +} diff --git a/src/libraries/Common/src/System/Runtime/InteropServices/GeneratedDllImportAttribute.cs b/src/libraries/Common/src/System/Runtime/InteropServices/GeneratedDllImportAttribute.cs new file mode 100644 index 0000000000000..e6ae47ac8fbfc --- /dev/null +++ b/src/libraries/Common/src/System/Runtime/InteropServices/GeneratedDllImportAttribute.cs @@ -0,0 +1,39 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#nullable enable + +// +// 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 +{ + /// + /// Indicates that method will be generated at compile time and invoke into an unmanaged library entry point + /// + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] +#if DLLIMPORT_GENERATOR_TEST + public +#else + internal +#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) + { + this.Value = dllName; + } + + public string Value { get; private set; } + } +} diff --git a/src/libraries/Common/src/System/Runtime/InteropServices/GeneratedMarshallingAttribute.cs b/src/libraries/Common/src/System/Runtime/InteropServices/GeneratedMarshallingAttribute.cs new file mode 100644 index 0000000000000..2fc73b41e3cb8 --- /dev/null +++ b/src/libraries/Common/src/System/Runtime/InteropServices/GeneratedMarshallingAttribute.cs @@ -0,0 +1,88 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// +// 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 +{ + [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)] +#if DLLIMPORT_GENERATOR_TEST + public +#else + internal +#endif + sealed class GeneratedMarshallingAttribute : Attribute + { + } + + [AttributeUsage(AttributeTargets.Struct)] +#if DLLIMPORT_GENERATOR_TEST + public +#else + internal +#endif + sealed class BlittableTypeAttribute : Attribute + { + } + + [AttributeUsage(AttributeTargets.Struct | AttributeTargets.Class)] +#if DLLIMPORT_GENERATOR_TEST + public +#else + internal +#endif + sealed class NativeMarshallingAttribute : Attribute + { + public NativeMarshallingAttribute(Type nativeType) + { + NativeType = nativeType; + } + + public Type NativeType { get; } + } + + [AttributeUsage(AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.Field, AllowMultiple = true)] +#if DLLIMPORT_GENERATOR_TEST + public +#else + internal +#endif + sealed class MarshalUsingAttribute : Attribute + { + public MarshalUsingAttribute() + { + CountElementName = string.Empty; + } + + public MarshalUsingAttribute(Type nativeType) + : this() + { + NativeType = nativeType; + } + + public Type? NativeType { get; } + + public string CountElementName { get; set; } + + public int ConstantElementCount { get; set; } + + public int ElementIndirectionLevel { get; set; } + + public const string ReturnsCountValue = "return-value"; + } + + [AttributeUsage(AttributeTargets.Struct | AttributeTargets.Class)] +#if DLLIMPORT_GENERATOR_TEST + public +#else + internal +#endif + sealed class GenericContiguousCollectionMarshallerAttribute : Attribute + { + public GenericContiguousCollectionMarshallerAttribute() + { + } + } +} diff --git a/src/libraries/Common/tests/Common.Tests.csproj b/src/libraries/Common/tests/Common.Tests.csproj index ff71eff871a29..37bd031cc647a 100644 --- a/src/libraries/Common/tests/Common.Tests.csproj +++ b/src/libraries/Common/tests/Common.Tests.csproj @@ -4,6 +4,7 @@ true $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Linux;$(NetCoreAppCurrent)-Browser;$(NetCoreAppCurrent)-OSX annotations + true + diff --git a/src/libraries/System.Console/src/System/ConsolePal.Windows.cs b/src/libraries/System.Console/src/System/ConsolePal.Windows.cs index a4f1241e0699d..9542a6ea15345 100644 --- a/src/libraries/System.Console/src/System/ConsolePal.Windows.cs +++ b/src/libraries/System.Console/src/System/ConsolePal.Windows.cs @@ -562,7 +562,7 @@ public static bool CursorVisible if (!Interop.Kernel32.GetConsoleCursorInfo(OutputHandle, out cci)) throw Win32Marshal.GetExceptionForWin32Error(Marshal.GetLastPInvokeError()); - return cci.bVisible; + return cci.bVisible != Interop.BOOL.FALSE; } set { @@ -570,7 +570,7 @@ public static bool CursorVisible if (!Interop.Kernel32.GetConsoleCursorInfo(OutputHandle, out cci)) throw Win32Marshal.GetExceptionForWin32Error(Marshal.GetLastPInvokeError()); - cci.bVisible = value; + cci.bVisible = value ? Interop.BOOL.TRUE : Interop.BOOL.FALSE; if (!Interop.Kernel32.SetConsoleCursorInfo(OutputHandle, ref cci)) throw Win32Marshal.GetExceptionForWin32Error(Marshal.GetLastPInvokeError()); } diff --git a/src/libraries/System.Console/tests/System.Console.Tests.csproj b/src/libraries/System.Console/tests/System.Console.Tests.csproj index 082f61922fe0c..f92a0cdfc4913 100644 --- a/src/libraries/System.Console/tests/System.Console.Tests.csproj +++ b/src/libraries/System.Console/tests/System.Console.Tests.csproj @@ -3,6 +3,7 @@ true true $(NetCoreAppCurrent);$(NetCoreAppCurrent)-windows + true diff --git a/src/libraries/System.Diagnostics.FileVersionInfo/src/System.Diagnostics.FileVersionInfo.csproj b/src/libraries/System.Diagnostics.FileVersionInfo/src/System.Diagnostics.FileVersionInfo.csproj index 564f2f435945f..918384304526b 100644 --- a/src/libraries/System.Diagnostics.FileVersionInfo/src/System.Diagnostics.FileVersionInfo.csproj +++ b/src/libraries/System.Diagnostics.FileVersionInfo/src/System.Diagnostics.FileVersionInfo.csproj @@ -41,7 +41,9 @@ + + diff --git a/src/libraries/System.Diagnostics.Process/src/System.Diagnostics.Process.csproj b/src/libraries/System.Diagnostics.Process/src/System.Diagnostics.Process.csproj index 8fc3f34d19495..b054e6f644913 100644 --- a/src/libraries/System.Diagnostics.Process/src/System.Diagnostics.Process.csproj +++ b/src/libraries/System.Diagnostics.Process/src/System.Diagnostics.Process.csproj @@ -364,6 +364,7 @@ + diff --git a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Win32.cs b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Win32.cs index 07910a0fea474..d333809adaeeb 100644 --- a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Win32.cs +++ b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/Process.Win32.cs @@ -290,7 +290,10 @@ private bool IsRespondingCore() } IntPtr result; - return Interop.User32.SendMessageTimeout(mainWindow, WM_NULL, IntPtr.Zero, IntPtr.Zero, SMTO_ABORTIFHUNG, 5000, out result) != (IntPtr)0; + unsafe + { + return Interop.User32.SendMessageTimeout(mainWindow, WM_NULL, IntPtr.Zero, IntPtr.Zero, SMTO_ABORTIFHUNG, 5000, &result) != (IntPtr)0; + } } public bool Responding diff --git a/src/libraries/System.IO.Compression.Brotli/src/System.IO.Compression.Brotli.csproj b/src/libraries/System.IO.Compression.Brotli/src/System.IO.Compression.Brotli.csproj index 5bb7b0e6b29d1..80ad7a7940bb6 100644 --- a/src/libraries/System.IO.Compression.Brotli/src/System.IO.Compression.Brotli.csproj +++ b/src/libraries/System.IO.Compression.Brotli/src/System.IO.Compression.Brotli.csproj @@ -41,6 +41,7 @@ + diff --git a/src/libraries/System.IO.Compression.ZipFile/src/System.IO.Compression.ZipFile.csproj b/src/libraries/System.IO.Compression.ZipFile/src/System.IO.Compression.ZipFile.csproj index 2110ae810ea63..1e825eda0cb98 100644 --- a/src/libraries/System.IO.Compression.ZipFile/src/System.IO.Compression.ZipFile.csproj +++ b/src/libraries/System.IO.Compression.ZipFile/src/System.IO.Compression.ZipFile.csproj @@ -32,7 +32,9 @@ + + diff --git a/src/libraries/System.IO.Compression.ZipFile/tests/System.IO.Compression.ZipFile.Tests.csproj b/src/libraries/System.IO.Compression.ZipFile/tests/System.IO.Compression.ZipFile.Tests.csproj index 9fbde72eef7b4..7a2fed130efe4 100644 --- a/src/libraries/System.IO.Compression.ZipFile/tests/System.IO.Compression.ZipFile.Tests.csproj +++ b/src/libraries/System.IO.Compression.ZipFile/tests/System.IO.Compression.ZipFile.Tests.csproj @@ -1,5 +1,7 @@  + true + true $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Unix;$(NetCoreAppCurrent)-Browser diff --git a/src/libraries/System.IO.Compression/src/System.IO.Compression.csproj b/src/libraries/System.IO.Compression/src/System.IO.Compression.csproj index e8f806f3fbe47..be3f42bcd86f5 100644 --- a/src/libraries/System.IO.Compression/src/System.IO.Compression.csproj +++ b/src/libraries/System.IO.Compression/src/System.IO.Compression.csproj @@ -56,6 +56,7 @@ + diff --git a/src/libraries/System.IO.FileSystem.DriveInfo/src/System.IO.FileSystem.DriveInfo.csproj b/src/libraries/System.IO.FileSystem.DriveInfo/src/System.IO.FileSystem.DriveInfo.csproj index 94b6ed97635eb..f9f7f0dfcfb6b 100644 --- a/src/libraries/System.IO.FileSystem.DriveInfo/src/System.IO.FileSystem.DriveInfo.csproj +++ b/src/libraries/System.IO.FileSystem.DriveInfo/src/System.IO.FileSystem.DriveInfo.csproj @@ -73,6 +73,7 @@ + diff --git a/src/libraries/System.IO.FileSystem.Watcher/src/System.IO.FileSystem.Watcher.csproj b/src/libraries/System.IO.FileSystem.Watcher/src/System.IO.FileSystem.Watcher.csproj index c864ab3ca6f5d..c813f682fa406 100644 --- a/src/libraries/System.IO.FileSystem.Watcher/src/System.IO.FileSystem.Watcher.csproj +++ b/src/libraries/System.IO.FileSystem.Watcher/src/System.IO.FileSystem.Watcher.csproj @@ -116,6 +116,7 @@ + diff --git a/src/libraries/System.IO.FileSystem.Watcher/tests/System.IO.FileSystem.Watcher.Tests.csproj b/src/libraries/System.IO.FileSystem.Watcher/tests/System.IO.FileSystem.Watcher.Tests.csproj index 1139f2ecf2a0c..0fd7e9a74423c 100644 --- a/src/libraries/System.IO.FileSystem.Watcher/tests/System.IO.FileSystem.Watcher.Tests.csproj +++ b/src/libraries/System.IO.FileSystem.Watcher/tests/System.IO.FileSystem.Watcher.Tests.csproj @@ -1,8 +1,10 @@ + true true $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Linux;$(NetCoreAppCurrent)-OSX;$(NetCoreAppCurrent)-MacCatalyst;$(NetCoreAppCurrent)-FreeBSD true + true diff --git a/src/libraries/System.IO.FileSystem/tests/DisabledFileLockingTests/System.IO.FileSystem.DisabledFileLocking.Tests.csproj b/src/libraries/System.IO.FileSystem/tests/DisabledFileLockingTests/System.IO.FileSystem.DisabledFileLocking.Tests.csproj index 87afaa0fb079f..b9739cb42fb81 100644 --- a/src/libraries/System.IO.FileSystem/tests/DisabledFileLockingTests/System.IO.FileSystem.DisabledFileLocking.Tests.csproj +++ b/src/libraries/System.IO.FileSystem/tests/DisabledFileLockingTests/System.IO.FileSystem.DisabledFileLocking.Tests.csproj @@ -2,6 +2,7 @@ true true + true $(NetCoreAppCurrent)-Unix diff --git a/src/libraries/System.IO.FileSystem/tests/System.IO.FileSystem.Tests.csproj b/src/libraries/System.IO.FileSystem/tests/System.IO.FileSystem.Tests.csproj index 5533ba6a1a1ba..abf73ff35986c 100644 --- a/src/libraries/System.IO.FileSystem/tests/System.IO.FileSystem.Tests.csproj +++ b/src/libraries/System.IO.FileSystem/tests/System.IO.FileSystem.Tests.csproj @@ -5,6 +5,7 @@ $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Unix;$(NetCoreAppCurrent)-Browser --working-dir=/test-dir + true diff --git a/src/libraries/System.IO.MemoryMappedFiles/src/System.IO.MemoryMappedFiles.csproj b/src/libraries/System.IO.MemoryMappedFiles/src/System.IO.MemoryMappedFiles.csproj index bd15c52faebb1..b473091e6ed1b 100644 --- a/src/libraries/System.IO.MemoryMappedFiles/src/System.IO.MemoryMappedFiles.csproj +++ b/src/libraries/System.IO.MemoryMappedFiles/src/System.IO.MemoryMappedFiles.csproj @@ -115,7 +115,9 @@ + + diff --git a/src/libraries/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedView.Windows.cs b/src/libraries/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedView.Windows.cs index c47852bbb0140..b974d4a0bdd98 100644 --- a/src/libraries/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedView.Windows.cs +++ b/src/libraries/System.IO.MemoryMappedFiles/src/System/IO/MemoryMappedFiles/MemoryMappedView.Windows.cs @@ -148,7 +148,10 @@ public unsafe void Flush(UIntPtr capacity) private static int GetSystemPageAllocationGranularity() { Interop.Kernel32.SYSTEM_INFO info; - Interop.Kernel32.GetSystemInfo(out info); + unsafe + { + Interop.Kernel32.GetSystemInfo(&info); + } return (int)info.dwAllocationGranularity; } diff --git a/src/libraries/System.IO.Pipes/src/System.IO.Pipes.csproj b/src/libraries/System.IO.Pipes/src/System.IO.Pipes.csproj index bb2390be9ff31..ae48db64440d4 100644 --- a/src/libraries/System.IO.Pipes/src/System.IO.Pipes.csproj +++ b/src/libraries/System.IO.Pipes/src/System.IO.Pipes.csproj @@ -173,6 +173,7 @@ + diff --git a/src/libraries/System.IO.Pipes/tests/System.IO.Pipes.Tests.csproj b/src/libraries/System.IO.Pipes/tests/System.IO.Pipes.Tests.csproj index b639953aff844..52ce3056b534d 100644 --- a/src/libraries/System.IO.Pipes/tests/System.IO.Pipes.Tests.csproj +++ b/src/libraries/System.IO.Pipes/tests/System.IO.Pipes.Tests.csproj @@ -4,6 +4,7 @@ true $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Unix;$(NetCoreAppCurrent) true + true diff --git a/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpCertificateHelper.cs b/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpCertificateHelper.cs index 472116113faca..915b35c09d546 100644 --- a/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpCertificateHelper.cs +++ b/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpCertificateHelper.cs @@ -64,7 +64,7 @@ public static void BuildChain( fixed (char* namePtr = hostName) { - eppStruct.pwszServerName = namePtr; + eppStruct.pwszServerName = (ushort*)namePtr; // The native field is WCHAR*, so we can just cast to ushort in this case cppStruct.dwFlags = Interop.Crypt32.CertChainPolicyIgnoreFlags.CERT_CHAIN_POLICY_IGNORE_ALL & ~Interop.Crypt32.CertChainPolicyIgnoreFlags.CERT_CHAIN_POLICY_IGNORE_INVALID_NAME_FLAG; diff --git a/src/libraries/System.Net.Http.WinHttpHandler/tests/UnitTests/FakeInterop.cs b/src/libraries/System.Net.Http.WinHttpHandler/tests/UnitTests/FakeInterop.cs index e26f1976418d6..eff52860f70ff 100644 --- a/src/libraries/System.Net.Http.WinHttpHandler/tests/UnitTests/FakeInterop.cs +++ b/src/libraries/System.Net.Http.WinHttpHandler/tests/UnitTests/FakeInterop.cs @@ -614,7 +614,7 @@ public static bool WinHttpGetIEProxyConfigForCurrentUser( { if (FakeRegistry.WinInetProxySettings.RegistryKeyMissing) { - proxyConfig.AutoDetect = false; + proxyConfig.AutoDetect = 0; proxyConfig.AutoConfigUrl = IntPtr.Zero; proxyConfig.Proxy = IntPtr.Zero; proxyConfig.ProxyBypass = IntPtr.Zero; @@ -623,7 +623,7 @@ public static bool WinHttpGetIEProxyConfigForCurrentUser( return false; } - proxyConfig.AutoDetect = FakeRegistry.WinInetProxySettings.AutoDetect; + proxyConfig.AutoDetect = FakeRegistry.WinInetProxySettings.AutoDetect ? 1 : 0; proxyConfig.AutoConfigUrl = Marshal.StringToHGlobalUni(FakeRegistry.WinInetProxySettings.AutoConfigUrl); proxyConfig.Proxy = Marshal.StringToHGlobalUni(FakeRegistry.WinInetProxySettings.Proxy); proxyConfig.ProxyBypass = Marshal.StringToHGlobalUni(FakeRegistry.WinInetProxySettings.ProxyBypass); diff --git a/src/libraries/System.Net.Http/src/System.Net.Http.csproj b/src/libraries/System.Net.Http/src/System.Net.Http.csproj index 3ed58c4ba64cf..e84065bf73e68 100644 --- a/src/libraries/System.Net.Http/src/System.Net.Http.csproj +++ b/src/libraries/System.Net.Http/src/System.Net.Http.csproj @@ -666,6 +666,7 @@ + diff --git a/src/libraries/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj b/src/libraries/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj index 718551f9b65d5..29bbd6f8f083e 100644 --- a/src/libraries/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj +++ b/src/libraries/System.Net.Http/tests/FunctionalTests/System.Net.Http.Functional.Tests.csproj @@ -7,6 +7,7 @@ true true $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Linux;$(NetCoreAppCurrent)-Browser;$(NetCoreAppCurrent)-OSX + true diff --git a/src/libraries/System.Net.HttpListener/src/System.Net.HttpListener.csproj b/src/libraries/System.Net.HttpListener/src/System.Net.HttpListener.csproj index 0e4ac2ffad7f3..a3bf458eccd43 100644 --- a/src/libraries/System.Net.HttpListener/src/System.Net.HttpListener.csproj +++ b/src/libraries/System.Net.HttpListener/src/System.Net.HttpListener.csproj @@ -23,6 +23,7 @@ + diff --git a/src/libraries/System.Net.Mail/src/System.Net.Mail.csproj b/src/libraries/System.Net.Mail/src/System.Net.Mail.csproj index d1d9176a5e879..0fa2b09742513 100644 --- a/src/libraries/System.Net.Mail/src/System.Net.Mail.csproj +++ b/src/libraries/System.Net.Mail/src/System.Net.Mail.csproj @@ -268,6 +268,7 @@ + diff --git a/src/libraries/System.Net.Mail/tests/Unit/System.Net.Mail.Unit.Tests.csproj b/src/libraries/System.Net.Mail/tests/Unit/System.Net.Mail.Unit.Tests.csproj index 2132010f6a7d4..0716680169067 100644 --- a/src/libraries/System.Net.Mail/tests/Unit/System.Net.Mail.Unit.Tests.csproj +++ b/src/libraries/System.Net.Mail/tests/Unit/System.Net.Mail.Unit.Tests.csproj @@ -4,6 +4,7 @@ ../../src/Resources/Strings.resx $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Unix;$(NetCoreAppCurrent)-Browser annotations + true diff --git a/src/libraries/System.Net.NameResolution/src/System.Net.NameResolution.csproj b/src/libraries/System.Net.NameResolution/src/System.Net.NameResolution.csproj index 1642f1fff33dd..7626f207fa6fe 100644 --- a/src/libraries/System.Net.NameResolution/src/System.Net.NameResolution.csproj +++ b/src/libraries/System.Net.NameResolution/src/System.Net.NameResolution.csproj @@ -120,6 +120,7 @@ + diff --git a/src/libraries/System.Net.NameResolution/tests/PalTests/System.Net.NameResolution.Pal.Tests.csproj b/src/libraries/System.Net.NameResolution/tests/PalTests/System.Net.NameResolution.Pal.Tests.csproj index 3b9a81c4ee5d3..752a1effae111 100644 --- a/src/libraries/System.Net.NameResolution/tests/PalTests/System.Net.NameResolution.Pal.Tests.csproj +++ b/src/libraries/System.Net.NameResolution/tests/PalTests/System.Net.NameResolution.Pal.Tests.csproj @@ -5,6 +5,7 @@ $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Unix;$(NetCoreAppCurrent)-Browser annotations true + true diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/BsdIPv4GlobalStatistics.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/BsdIPv4GlobalStatistics.cs index 23fc63b2424bc..a2333229a7a2e 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/BsdIPv4GlobalStatistics.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/BsdIPv4GlobalStatistics.cs @@ -46,7 +46,7 @@ private static unsafe void ProcessIpv4Address(void* pContext, byte* ifaceName, I public unsafe BsdIPv4GlobalStatistics() { Interop.Sys.IPv4GlobalStatistics statistics; - if (Interop.Sys.GetIPv4GlobalStatistics(out statistics) == -1) + if (Interop.Sys.GetIPv4GlobalStatistics(&statistics) == -1) { throw new NetworkInformationException(SR.net_PInvokeError); } diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/BsdIcmpV4Statistics.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/BsdIcmpV4Statistics.cs index 7850d022c865f..a08b986917cba 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/BsdIcmpV4Statistics.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/BsdIcmpV4Statistics.cs @@ -30,10 +30,10 @@ internal sealed class BsdIcmpV4Statistics : IcmpV4Statistics private readonly long _timestampRequestsReceived; private readonly long _timestampRequestsSent; - public BsdIcmpV4Statistics() + public unsafe BsdIcmpV4Statistics() { Interop.Sys.Icmpv4GlobalStatistics statistics; - if (Interop.Sys.GetIcmpv4GlobalStatistics(out statistics) != 0) + if (Interop.Sys.GetIcmpv4GlobalStatistics(&statistics) != 0) { throw new NetworkInformationException(SR.net_PInvokeError); } diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/BsdIcmpV6Statistics.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/BsdIcmpV6Statistics.cs index 2cd514a16bbdb..8c2b6ee798a00 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/BsdIcmpV6Statistics.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/BsdIcmpV6Statistics.cs @@ -36,10 +36,10 @@ internal sealed class BsdIcmpV6Statistics : IcmpV6Statistics private readonly long _timeExceededMessagesReceived; private readonly long _timeExceededMessagesSent; - public BsdIcmpV6Statistics() + public unsafe BsdIcmpV6Statistics() { Interop.Sys.Icmpv6GlobalStatistics statistics; - if (Interop.Sys.GetIcmpv6GlobalStatistics(out statistics) != 0) + if (Interop.Sys.GetIcmpv6GlobalStatistics(&statistics) != 0) { throw new NetworkInformationException(SR.net_PInvokeError); } diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/BsdTcpStatistics.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/BsdTcpStatistics.cs index d6eab5d2daec8..6d7ee8cce3d0f 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/BsdTcpStatistics.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/BsdTcpStatistics.cs @@ -17,10 +17,10 @@ internal sealed class BsdTcpStatistics : TcpStatistics private readonly long _segmentsReceived; private readonly int _currentConnections; - public BsdTcpStatistics() + public unsafe BsdTcpStatistics() { Interop.Sys.TcpGlobalStatistics statistics; - if (Interop.Sys.GetTcpGlobalStatistics(out statistics) != 0) + if (Interop.Sys.GetTcpGlobalStatistics(&statistics) != 0) { throw new NetworkInformationException(SR.net_PInvokeError); } diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/BsdUdpStatistics.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/BsdUdpStatistics.cs index c60a62173e6da..248afb771c665 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/BsdUdpStatistics.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/BsdUdpStatistics.cs @@ -13,10 +13,10 @@ internal sealed class BsdUdpStatistics : UdpStatistics private readonly long _incomingErrors; private readonly int _numListeners; - public BsdUdpStatistics() + public unsafe BsdUdpStatistics() { Interop.Sys.UdpGlobalStatistics statistics; - if (Interop.Sys.GetUdpGlobalStatistics(out statistics) == -1) + if (Interop.Sys.GetUdpGlobalStatistics(&statistics) == -1) { throw new NetworkInformationException(SR.net_PInvokeError); } diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/LinuxNetworkInterface.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/LinuxNetworkInterface.cs index a44a3bb315d5e..d411e38bef2a6 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/LinuxNetworkInterface.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/LinuxNetworkInterface.cs @@ -79,7 +79,7 @@ public static unsafe NetworkInterface[] GetLinuxNetworkInterfaces() Interop.Sys.IpAddressInfo * ai = null; IntPtr globalMemory = (IntPtr)null; - if (Interop.Sys.GetNetworkInterfaces(ref interfaceCount, ref nii, ref addressCount, ref ai) != 0) + if (Interop.Sys.GetNetworkInterfaces(&interfaceCount, &nii, &addressCount, &ai) != 0) { string message = Interop.Sys.GetLastErrorInfo().GetErrorMessage(); throw new NetworkInformationException(message); diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkAddressChange.Unix.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkAddressChange.Unix.cs index a0ad6c92bab7e..5d95e8b2b9733 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkAddressChange.Unix.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkAddressChange.Unix.cs @@ -138,11 +138,11 @@ public static event NetworkAvailabilityChangedEventHandler? NetworkAvailabilityC } } - private static void CreateSocket() + private static unsafe void CreateSocket() { Debug.Assert(s_socket == 0, "s_socket != 0, must close existing socket before opening another."); int newSocket; - Interop.Error result = Interop.Sys.CreateNetworkChangeListenerSocket(out newSocket); + Interop.Error result = Interop.Sys.CreateNetworkChangeListenerSocket(&newSocket); if (result != Interop.Error.SUCCESS) { string message = Interop.Sys.GetLastErrorInfo().GetErrorMessage(); diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemIPGlobalProperties.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemIPGlobalProperties.cs index dff0aad267f73..7a65e6e7a16c8 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemIPGlobalProperties.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemIPGlobalProperties.cs @@ -112,7 +112,7 @@ private unsafe List GetAllTcpConnections() if (Socket.OSSupportsIPv4) { // Get the buffer size needed. - result = Interop.IpHlpApi.GetTcpTable(IntPtr.Zero, ref size, true); + result = Interop.IpHlpApi.GetTcpTable(IntPtr.Zero, &size, order: true); while (result == Interop.IpHlpApi.ERROR_INSUFFICIENT_BUFFER) { @@ -120,7 +120,7 @@ private unsafe List GetAllTcpConnections() IntPtr buffer = Marshal.AllocHGlobal((int)size); try { - result = Interop.IpHlpApi.GetTcpTable(buffer, ref size, true); + result = Interop.IpHlpApi.GetTcpTable(buffer, &size, order: true); if (result == Interop.IpHlpApi.ERROR_SUCCESS) { @@ -159,7 +159,7 @@ private unsafe List GetAllTcpConnections() { // Get the buffer size needed. size = 0; - result = Interop.IpHlpApi.GetExtendedTcpTable(IntPtr.Zero, ref size, true, + result = Interop.IpHlpApi.GetExtendedTcpTable(IntPtr.Zero, &size, order: true, (uint)AddressFamily.InterNetworkV6, Interop.IpHlpApi.TcpTableClass.TcpTableOwnerPidAll, 0); @@ -169,7 +169,7 @@ private unsafe List GetAllTcpConnections() IntPtr buffer = Marshal.AllocHGlobal((int)size); try { - result = Interop.IpHlpApi.GetExtendedTcpTable(buffer, ref size, true, + result = Interop.IpHlpApi.GetExtendedTcpTable(buffer, &size, order: true, (uint)AddressFamily.InterNetworkV6, Interop.IpHlpApi.TcpTableClass.TcpTableOwnerPidAll, 0); if (result == Interop.IpHlpApi.ERROR_SUCCESS) @@ -221,7 +221,7 @@ public unsafe override IPEndPoint[] GetActiveUdpListeners() if (Socket.OSSupportsIPv4) { // Get the buffer size needed. - result = Interop.IpHlpApi.GetUdpTable(IntPtr.Zero, ref size, true); + result = Interop.IpHlpApi.GetUdpTable(IntPtr.Zero, &size, order: true); while (result == Interop.IpHlpApi.ERROR_INSUFFICIENT_BUFFER) { // Allocate the buffer and get the UDP table. @@ -229,7 +229,7 @@ public unsafe override IPEndPoint[] GetActiveUdpListeners() try { - result = Interop.IpHlpApi.GetUdpTable(buffer, ref size, true); + result = Interop.IpHlpApi.GetUdpTable(buffer, &size, order: true); if (result == Interop.IpHlpApi.ERROR_SUCCESS) { @@ -273,7 +273,7 @@ public unsafe override IPEndPoint[] GetActiveUdpListeners() { // Get the buffer size needed. size = 0; - result = Interop.IpHlpApi.GetExtendedUdpTable(IntPtr.Zero, ref size, true, + result = Interop.IpHlpApi.GetExtendedUdpTable(IntPtr.Zero, &size, order: true, (uint)AddressFamily.InterNetworkV6, Interop.IpHlpApi.UdpTableClass.UdpTableOwnerPid, 0); while (result == Interop.IpHlpApi.ERROR_INSUFFICIENT_BUFFER) @@ -282,7 +282,7 @@ public unsafe override IPEndPoint[] GetActiveUdpListeners() IntPtr buffer = Marshal.AllocHGlobal((int)size); try { - result = Interop.IpHlpApi.GetExtendedUdpTable(buffer, ref size, true, + result = Interop.IpHlpApi.GetExtendedUdpTable(buffer, &size, order: true, (uint)AddressFamily.InterNetworkV6, Interop.IpHlpApi.UdpTableClass.UdpTableOwnerPid, 0); diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemIPGlobalStatistics.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemIPGlobalStatistics.cs index e8838b31d0c24..353671e9b1897 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemIPGlobalStatistics.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemIPGlobalStatistics.cs @@ -12,17 +12,19 @@ internal sealed class SystemIPGlobalStatistics : IPGlobalStatistics private SystemIPGlobalStatistics() { } - internal SystemIPGlobalStatistics(AddressFamily family) + internal unsafe SystemIPGlobalStatistics(AddressFamily family) { - uint result = Interop.IpHlpApi.GetIpStatisticsEx(out _stats, family); - - if (result != Interop.IpHlpApi.ERROR_SUCCESS) + fixed (Interop.IpHlpApi.MibIpStats* pStats = &_stats) { - throw new NetworkInformationException((int)result); + uint result = Interop.IpHlpApi.GetIpStatisticsEx(pStats, family); + if (result != Interop.IpHlpApi.ERROR_SUCCESS) + { + throw new NetworkInformationException((int)result); + } } } - public override bool ForwardingEnabled { get { return _stats.forwardingEnabled; } } + public override bool ForwardingEnabled { get { return _stats.forwardingEnabled != 0; } } public override int DefaultTtl { get { return (int)_stats.defaultTtl; } } diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemIPv4InterfaceProperties.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemIPv4InterfaceProperties.cs index 72accfe9f4514..7c455b47b455b 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemIPv4InterfaceProperties.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemIPv4InterfaceProperties.cs @@ -75,20 +75,20 @@ public override int Index } } - private void GetPerAdapterInfo(uint index) + private unsafe void GetPerAdapterInfo(uint index) { if (index != 0) { uint size = 0; - uint result = Interop.IpHlpApi.GetPerAdapterInfo(index, IntPtr.Zero, ref size); + uint result = Interop.IpHlpApi.GetPerAdapterInfo(index, IntPtr.Zero, &size); while (result == Interop.IpHlpApi.ERROR_BUFFER_OVERFLOW) { // Now we allocate the buffer and read the network parameters. IntPtr buffer = Marshal.AllocHGlobal((int)size); try { - result = Interop.IpHlpApi.GetPerAdapterInfo(index, buffer, ref size); + result = Interop.IpHlpApi.GetPerAdapterInfo(index, buffer, &size); if (result == Interop.IpHlpApi.ERROR_SUCCESS) { Interop.IpHlpApi.IpPerAdapterInfo ipPerAdapterInfo = diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemIcmpV4Statistics.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemIcmpV4Statistics.cs index a2294d8ad5ef6..18f4dd555c267 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemIcmpV4Statistics.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemIcmpV4Statistics.cs @@ -8,9 +8,11 @@ internal sealed class SystemIcmpV4Statistics : IcmpV4Statistics { private readonly Interop.IpHlpApi.MibIcmpInfo _stats; - internal SystemIcmpV4Statistics() + internal unsafe SystemIcmpV4Statistics() { - uint result = Interop.IpHlpApi.GetIcmpStatistics(out _stats); + uint result; + fixed (Interop.IpHlpApi.MibIcmpInfo* pStats = &_stats) + result = Interop.IpHlpApi.GetIcmpStatistics(pStats); if (result != Interop.IpHlpApi.ERROR_SUCCESS) { diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemNetworkInterface.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemNetworkInterface.cs index f2196e3b79a4d..ed806788ae92d 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemNetworkInterface.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemNetworkInterface.cs @@ -42,14 +42,17 @@ internal static int InternalIPv6LoopbackInterfaceIndex } } - private static int GetBestInterfaceForAddress(IPAddress addr) + private static unsafe int GetBestInterfaceForAddress(IPAddress addr) { int index; Internals.SocketAddress address = new Internals.SocketAddress(addr); - int error = (int)Interop.IpHlpApi.GetBestInterfaceEx(address.Buffer, out index); - if (error != 0) + fixed (byte* buffer = address.Buffer) { - throw new NetworkInformationException(error); + int error = (int)Interop.IpHlpApi.GetBestInterfaceEx(buffer, &index); + if (error != 0) + { + throw new NetworkInformationException(error); + } } return index; @@ -77,7 +80,7 @@ internal static bool InternalGetIsNetworkAvailable() return false; } - internal static NetworkInterface[] GetNetworkInterfaces() + internal static unsafe NetworkInterface[] GetNetworkInterfaces() { AddressFamily family = AddressFamily.Unspecified; uint bufferSize = 0; @@ -91,7 +94,7 @@ internal static NetworkInterface[] GetNetworkInterfaces() // Figure out the right buffer size for the adapter information. uint result = Interop.IpHlpApi.GetAdaptersAddresses( - family, (uint)flags, IntPtr.Zero, IntPtr.Zero, ref bufferSize); + family, (uint)flags, IntPtr.Zero, IntPtr.Zero, &bufferSize); while (result == Interop.IpHlpApi.ERROR_BUFFER_OVERFLOW) { @@ -101,7 +104,7 @@ internal static NetworkInterface[] GetNetworkInterfaces() try { result = Interop.IpHlpApi.GetAdaptersAddresses( - family, (uint)flags, IntPtr.Zero, buffer, ref bufferSize); + family, (uint)flags, IntPtr.Zero, buffer, &bufferSize); // If succeeded, we're going to add each new interface. if (result == Interop.IpHlpApi.ERROR_SUCCESS) diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemTcpStatistics.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemTcpStatistics.cs index 32453ce74c6a3..9f276ed0ffcc8 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemTcpStatistics.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemTcpStatistics.cs @@ -12,13 +12,15 @@ internal sealed class SystemTcpStatistics : TcpStatistics private SystemTcpStatistics() { } - internal SystemTcpStatistics(AddressFamily family) + internal unsafe SystemTcpStatistics(AddressFamily family) { - uint result = Interop.IpHlpApi.GetTcpStatisticsEx(out _stats, family); - - if (result != Interop.IpHlpApi.ERROR_SUCCESS) + fixed (Interop.IpHlpApi.MibTcpStats* pStats = &_stats) { - throw new NetworkInformationException((int)result); + uint result = Interop.IpHlpApi.GetTcpStatisticsEx(pStats, family); + if (result != Interop.IpHlpApi.ERROR_SUCCESS) + { + throw new NetworkInformationException((int)result); + } } } diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemUdpStatistics.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemUdpStatistics.cs index 20869e1f8c684..5827702b07022 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemUdpStatistics.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/SystemUdpStatistics.cs @@ -12,13 +12,15 @@ internal sealed class SystemUdpStatistics : UdpStatistics private SystemUdpStatistics() { } - internal SystemUdpStatistics(AddressFamily family) + internal unsafe SystemUdpStatistics(AddressFamily family) { - uint result = Interop.IpHlpApi.GetUdpStatisticsEx(out _stats, family); - - if (result != Interop.IpHlpApi.ERROR_SUCCESS) + fixed (Interop.IpHlpApi.MibUdpStats* pStats = &_stats) { - throw new NetworkInformationException((int)result); + uint result = Interop.IpHlpApi.GetUdpStatisticsEx(pStats, family); + if (result != Interop.IpHlpApi.ERROR_SUCCESS) + { + throw new NetworkInformationException((int)result); + } } } diff --git a/src/libraries/System.Net.Ping/src/System.Net.Ping.csproj b/src/libraries/System.Net.Ping/src/System.Net.Ping.csproj index 571583be6c379..63e45d7e1cbd8 100644 --- a/src/libraries/System.Net.Ping/src/System.Net.Ping.csproj +++ b/src/libraries/System.Net.Ping/src/System.Net.Ping.csproj @@ -111,6 +111,7 @@ + diff --git a/src/libraries/System.Net.Ping/tests/FunctionalTests/System.Net.Ping.Functional.Tests.csproj b/src/libraries/System.Net.Ping/tests/FunctionalTests/System.Net.Ping.Functional.Tests.csproj index 90acc7605d8ab..52825142299cd 100644 --- a/src/libraries/System.Net.Ping/tests/FunctionalTests/System.Net.Ping.Functional.Tests.csproj +++ b/src/libraries/System.Net.Ping/tests/FunctionalTests/System.Net.Ping.Functional.Tests.csproj @@ -4,6 +4,7 @@ true true true + true diff --git a/src/libraries/System.Net.Primitives/tests/PalTests/System.Net.Primitives.Pal.Tests.csproj b/src/libraries/System.Net.Primitives/tests/PalTests/System.Net.Primitives.Pal.Tests.csproj index 4652679d91bf6..fc4e4d4e55f4e 100644 --- a/src/libraries/System.Net.Primitives/tests/PalTests/System.Net.Primitives.Pal.Tests.csproj +++ b/src/libraries/System.Net.Primitives/tests/PalTests/System.Net.Primitives.Pal.Tests.csproj @@ -3,9 +3,10 @@ true ../../src/Resources/Strings.resx $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Unix;$(NetCoreAppCurrent)-Browser + true - $(DefineConstants);SYSTEM_NET_PRIMITIVES_DLL @@ -118,4 +119,4 @@ - \ No newline at end of file + diff --git a/src/libraries/System.Net.Quic/src/System.Net.Quic.csproj b/src/libraries/System.Net.Quic/src/System.Net.Quic.csproj index 4feb5f9e2fac0..83686eb88a2b1 100644 --- a/src/libraries/System.Net.Quic/src/System.Net.Quic.csproj +++ b/src/libraries/System.Net.Quic/src/System.Net.Quic.csproj @@ -119,6 +119,7 @@ + diff --git a/src/libraries/System.Net.Security/src/System.Net.Security.csproj b/src/libraries/System.Net.Security/src/System.Net.Security.csproj index aaf56dd14bed4..21273ecd7515e 100644 --- a/src/libraries/System.Net.Security/src/System.Net.Security.csproj +++ b/src/libraries/System.Net.Security/src/System.Net.Security.csproj @@ -422,6 +422,7 @@ + diff --git a/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.Windows.cs b/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.Windows.cs index 29ab3bed0ee8c..7a6f39b3d2e26 100644 --- a/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.Windows.cs +++ b/src/libraries/System.Net.Security/src/System/Net/Security/SslStreamPal.Windows.cs @@ -141,9 +141,9 @@ private static unsafe void AttachCertificateStore(SafeFreeCredentials cred, X509 { clientCertPolicy.pwszSslCtlStoreName = ptr; Interop.SECURITY_STATUS errorCode = Interop.SspiCli.SetCredentialsAttributesW( - ref cred._handle, + cred._handle, (long)Interop.SspiCli.ContextAttribute.SECPKG_ATTR_CLIENT_CERT_POLICY, - ref clientCertPolicy, + clientCertPolicy, sizeof(Interop.SspiCli.SecPkgCred_ClientCertPolicy)); if (errorCode != Interop.SECURITY_STATUS.OK) diff --git a/src/libraries/System.Net.Security/tests/FunctionalTests/System.Net.Security.Tests.csproj b/src/libraries/System.Net.Security/tests/FunctionalTests/System.Net.Security.Tests.csproj index 3dc537ad91deb..a6a21cc91e155 100644 --- a/src/libraries/System.Net.Security/tests/FunctionalTests/System.Net.Security.Tests.csproj +++ b/src/libraries/System.Net.Security/tests/FunctionalTests/System.Net.Security.Tests.csproj @@ -5,6 +5,7 @@ $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Unix;$(NetCoreAppCurrent)-Browser;$(NetCoreAppCurrent)-OSX;$(NetCoreAppCurrent)-iOS annotations true + true diff --git a/src/libraries/System.Net.Sockets/src/System.Net.Sockets.csproj b/src/libraries/System.Net.Sockets/src/System.Net.Sockets.csproj index 496c628956f8c..0a2f6aac79ea9 100644 --- a/src/libraries/System.Net.Sockets/src/System.Net.Sockets.csproj +++ b/src/libraries/System.Net.Sockets/src/System.Net.Sockets.csproj @@ -287,6 +287,7 @@ + @@ -295,6 +296,5 @@ - diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEngine.Unix.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEngine.Unix.cs index 983ca51ed27ee..aafcf158518a9 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEngine.Unix.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/SocketAsyncEngine.Unix.cs @@ -140,15 +140,23 @@ private SocketAsyncEngine() // // Create the event port and buffer // - Interop.Error err = Interop.Sys.CreateSocketEventPort(out _port); - if (err != Interop.Error.SUCCESS) + Interop.Error err; + fixed (IntPtr* portPtr = &_port) { - throw new InternalException(err); + err = Interop.Sys.CreateSocketEventPort(portPtr); + if (err != Interop.Error.SUCCESS) + { + throw new InternalException(err); + } } - err = Interop.Sys.CreateSocketEventBuffer(EventBufferCount, out _buffer); - if (err != Interop.Error.SUCCESS) + + fixed (Interop.Sys.SocketEvent** bufferPtr = &_buffer) { - throw new InternalException(err); + err = Interop.Sys.CreateSocketEventBuffer(EventBufferCount, bufferPtr); + if (err != Interop.Error.SUCCESS) + { + throw new InternalException(err); + } } var thread = new Thread(static s => ((SocketAsyncEngine)s!).EventLoop()) diff --git a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/UnixDomainSocketEndPoint.Unix.cs b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/UnixDomainSocketEndPoint.Unix.cs index d5bd57db6f8e1..bb08eca42864e 100644 --- a/src/libraries/System.Net.Sockets/src/System/Net/Sockets/UnixDomainSocketEndPoint.Unix.cs +++ b/src/libraries/System.Net.Sockets/src/System/Net/Sockets/UnixDomainSocketEndPoint.Unix.cs @@ -15,7 +15,15 @@ public sealed partial class UnixDomainSocketEndPoint : EndPoint static UnixDomainSocketEndPoint() { - Interop.Sys.GetDomainSocketSizes(out s_nativePathOffset, out s_nativePathLength, out s_nativeAddressSize); + unsafe + { + fixed (int* pathOffset = &s_nativePathOffset) + fixed (int* pathLength = &s_nativePathLength) + fixed (int* addressSize = &s_nativeAddressSize) + { + Interop.Sys.GetDomainSocketSizes(pathOffset, pathLength, addressSize); + } + } Debug.Assert(s_nativePathOffset >= 0, "Expected path offset to be positive"); Debug.Assert(s_nativePathOffset + s_nativePathLength <= s_nativeAddressSize, "Expected address size to include all of the path length"); diff --git a/src/libraries/System.Private.CoreLib/src/System/Environment.Win32.cs b/src/libraries/System.Private.CoreLib/src/System/Environment.Win32.cs index 8e8e8c5e6898b..a4d6468084f09 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Environment.Win32.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Environment.Win32.cs @@ -55,7 +55,8 @@ private static void SetEnvironmentVariableFromRegistry(string variable, string? // send a WM_SETTINGCHANGE message to all windows fixed (char* lParam = "Environment") { - IntPtr r = Interop.User32.SendMessageTimeout(new IntPtr(Interop.User32.HWND_BROADCAST), Interop.User32.WM_SETTINGCHANGE, IntPtr.Zero, (IntPtr)lParam, 0, 1000, out IntPtr _); + IntPtr unused; + IntPtr r = Interop.User32.SendMessageTimeout(new IntPtr(Interop.User32.HWND_BROADCAST), Interop.User32.WM_SETTINGCHANGE, IntPtr.Zero, (IntPtr)lParam, 0, 1000, &unused); Debug.Assert(r != IntPtr.Zero, $"SetEnvironmentVariable failed: {Marshal.GetLastPInvokeError()}"); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Environment.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/Environment.Windows.cs index c040dae4f3be4..7ac8ecd5bc1d2 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Environment.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Environment.Windows.cs @@ -55,7 +55,12 @@ private static string CurrentDirectoryCore private static int GetSystemPageSize() { - Interop.Kernel32.GetSystemInfo(out Interop.Kernel32.SYSTEM_INFO info); + Interop.Kernel32.SYSTEM_INFO info; + unsafe + { + Interop.Kernel32.GetSystemInfo(&info); + } + return info.dwPageSize; } diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEnumerator.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEnumerator.Unix.cs index a2c83ab03d65e..faf7bb8eee696 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEnumerator.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEnumerator.Unix.cs @@ -175,7 +175,12 @@ private unsafe void FindNextEntry() private unsafe void FindNextEntry(byte* entryBufferPtr, int bufferLength) { - int result = Interop.Sys.ReadDirR(_directoryHandle, entryBufferPtr, bufferLength, out _entry); + int result; + fixed (Interop.Sys.DirectoryEntry* e = &_entry) + { + result = Interop.Sys.ReadDirR(_directoryHandle, entryBufferPtr, bufferLength, e); + } + switch (result) { case -1: diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/MemoryFailPoint.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/MemoryFailPoint.Windows.cs index d5d1952e7a150..593df35d978f8 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/MemoryFailPoint.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/MemoryFailPoint.Windows.cs @@ -9,7 +9,12 @@ public sealed partial class MemoryFailPoint { private static ulong GetTopOfMemory() { - Interop.Kernel32.GetSystemInfo(out Interop.Kernel32.SYSTEM_INFO info); + Interop.Kernel32.SYSTEM_INFO info; + unsafe + { + Interop.Kernel32.GetSystemInfo(&info); + } + return (ulong)info.lpMaximumApplicationAddress; } diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.NonAndroid.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.NonAndroid.cs index d7e54e1ebab2e..0c3e38566825c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.NonAndroid.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.NonAndroid.cs @@ -200,7 +200,7 @@ private static unsafe void EnumerateFilesRecursively(string path, Predicate + + diff --git a/src/libraries/System.Runtime.InteropServices.RuntimeInformation/src/System/Runtime/InteropServices/RuntimeInformation/RuntimeInformation.Windows.cs b/src/libraries/System.Runtime.InteropServices.RuntimeInformation/src/System/Runtime/InteropServices/RuntimeInformation/RuntimeInformation.Windows.cs index 2cd38459dc7b2..636b5fd96df16 100644 --- a/src/libraries/System.Runtime.InteropServices.RuntimeInformation/src/System/Runtime/InteropServices/RuntimeInformation/RuntimeInformation.Windows.cs +++ b/src/libraries/System.Runtime.InteropServices.RuntimeInformation/src/System/Runtime/InteropServices/RuntimeInformation/RuntimeInformation.Windows.cs @@ -42,7 +42,12 @@ public static Architecture OSArchitecture if (osArch == -1) { - Interop.Kernel32.GetNativeSystemInfo(out Interop.Kernel32.SYSTEM_INFO sysInfo); + Interop.Kernel32.SYSTEM_INFO sysInfo; + unsafe + { + Interop.Kernel32.GetNativeSystemInfo(&sysInfo); + } + osArch = s_osArch = (int)Map((Interop.Kernel32.ProcessorArchitecture)sysInfo.wProcessorArchitecture); } @@ -60,7 +65,12 @@ public static Architecture ProcessArchitecture if (processArch == -1) { - Interop.Kernel32.GetSystemInfo(out Interop.Kernel32.SYSTEM_INFO sysInfo); + Interop.Kernel32.SYSTEM_INFO sysInfo; + unsafe + { + Interop.Kernel32.GetSystemInfo(&sysInfo); + } + processArch = s_processArch = (int)Map((Interop.Kernel32.ProcessorArchitecture)sysInfo.wProcessorArchitecture); } diff --git a/src/libraries/System.Runtime.InteropServices/System.Runtime.InteropServices.sln b/src/libraries/System.Runtime.InteropServices/System.Runtime.InteropServices.sln index fa50a214c401d..a53cf6e074c08 100644 --- a/src/libraries/System.Runtime.InteropServices/System.Runtime.InteropServices.sln +++ b/src/libraries/System.Runtime.InteropServices/System.Runtime.InteropServices.sln @@ -7,13 +7,27 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.CompilerServ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.CompilerServices.Unsafe", "..\System.Runtime.CompilerServices.Unsafe\src\System.Runtime.CompilerServices.Unsafe.ilproj", "{04BA3E3C-6979-4792-B19E-C797AD607F42}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Interop.DllImportGenerator", "gen\DllImportGenerator\DllImportGenerator.csproj", "{07F19F91-D438-428D-99F0-61DAD87E78BA}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Interop.SourceGeneration", "gen\Microsoft.Interop.SourceGeneration\Microsoft.Interop.SourceGeneration.csproj", "{768B77B0-EA45-469D-B39E-545EB72F5A43}" +EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.InteropServices", "ref\System.Runtime.InteropServices.csproj", "{8671F164-F78C-44FA-93B7-A310F67890FE}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.InteropServices", "src\System.Runtime.InteropServices.csproj", "{4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.InteropServices.ComDisabled.Tests", "tests\ComDisabled\System.Runtime.InteropServices.ComDisabled.Tests.csproj", "{6D2197E6-D3DF-43AE-9BEE-3573018639F9}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Interop.Ancillary", "tests\Ancillary.Interop\Ancillary.Interop.csproj", "{79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DllImportGenerator.Tests", "tests\DllImportGenerator.Tests\DllImportGenerator.Tests.csproj", "{57A1A6FD-9231-4DFB-8619-F0EDEDA208E3}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DllImportGenerator.UnitTests", "tests\DllImportGenerator.UnitTests\DllImportGenerator.UnitTests.csproj", "{4B516949-4AD4-44D6-AF86-C2E6058608D5}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.InteropServices.ComDisabled.Tests", "tests\System.Runtime.InteropServices.ComDisabled.UnitTests\System.Runtime.InteropServices.ComDisabled.Tests.csproj", "{25D66424-2EAF-464D-8460-10C04EDEF3C3}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.InteropServices.Tests", "tests\System.Runtime.InteropServices.UnitTests\System.Runtime.InteropServices.Tests.csproj", "{049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Interop.Tests.NativeExports", "tests\TestAssets\NativeExports\NativeExports.csproj", "{866D295E-424A-4747-9417-CD7746936138}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.InteropServices.Tests", "tests\System.Runtime.InteropServices.Tests.csproj", "{E249BD6A-85DB-4CE4-BD82-8D67EBAC5664}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SharedTypes", "tests\TestAssets\SharedTypes\SharedTypes.csproj", "{D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{B1678CCD-95C8-4419-B9F9-14A03061BE4B}" EndProject @@ -106,6 +120,42 @@ Global {04BA3E3C-6979-4792-B19E-C797AD607F42}.Checked|x64.Build.0 = Debug|Any CPU {04BA3E3C-6979-4792-B19E-C797AD607F42}.Checked|x86.ActiveCfg = Debug|Any CPU {04BA3E3C-6979-4792-B19E-C797AD607F42}.Checked|x86.Build.0 = Debug|Any CPU + {07F19F91-D438-428D-99F0-61DAD87E78BA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {07F19F91-D438-428D-99F0-61DAD87E78BA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {07F19F91-D438-428D-99F0-61DAD87E78BA}.Debug|x64.ActiveCfg = Debug|Any CPU + {07F19F91-D438-428D-99F0-61DAD87E78BA}.Debug|x64.Build.0 = Debug|Any CPU + {07F19F91-D438-428D-99F0-61DAD87E78BA}.Debug|x86.ActiveCfg = Debug|Any CPU + {07F19F91-D438-428D-99F0-61DAD87E78BA}.Debug|x86.Build.0 = Debug|Any CPU + {07F19F91-D438-428D-99F0-61DAD87E78BA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {07F19F91-D438-428D-99F0-61DAD87E78BA}.Release|Any CPU.Build.0 = Release|Any CPU + {07F19F91-D438-428D-99F0-61DAD87E78BA}.Release|x64.ActiveCfg = Release|Any CPU + {07F19F91-D438-428D-99F0-61DAD87E78BA}.Release|x64.Build.0 = Release|Any CPU + {07F19F91-D438-428D-99F0-61DAD87E78BA}.Release|x86.ActiveCfg = Release|Any CPU + {07F19F91-D438-428D-99F0-61DAD87E78BA}.Release|x86.Build.0 = Release|Any CPU + {07F19F91-D438-428D-99F0-61DAD87E78BA}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {07F19F91-D438-428D-99F0-61DAD87E78BA}.Checked|Any CPU.Build.0 = Debug|Any CPU + {07F19F91-D438-428D-99F0-61DAD87E78BA}.Checked|x64.ActiveCfg = Debug|Any CPU + {07F19F91-D438-428D-99F0-61DAD87E78BA}.Checked|x64.Build.0 = Debug|Any CPU + {07F19F91-D438-428D-99F0-61DAD87E78BA}.Checked|x86.ActiveCfg = Debug|Any CPU + {07F19F91-D438-428D-99F0-61DAD87E78BA}.Checked|x86.Build.0 = Debug|Any CPU + {768B77B0-EA45-469D-B39E-545EB72F5A43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {768B77B0-EA45-469D-B39E-545EB72F5A43}.Debug|Any CPU.Build.0 = Debug|Any CPU + {768B77B0-EA45-469D-B39E-545EB72F5A43}.Debug|x64.ActiveCfg = Debug|Any CPU + {768B77B0-EA45-469D-B39E-545EB72F5A43}.Debug|x64.Build.0 = Debug|Any CPU + {768B77B0-EA45-469D-B39E-545EB72F5A43}.Debug|x86.ActiveCfg = Debug|Any CPU + {768B77B0-EA45-469D-B39E-545EB72F5A43}.Debug|x86.Build.0 = Debug|Any CPU + {768B77B0-EA45-469D-B39E-545EB72F5A43}.Release|Any CPU.ActiveCfg = Release|Any CPU + {768B77B0-EA45-469D-B39E-545EB72F5A43}.Release|Any CPU.Build.0 = Release|Any CPU + {768B77B0-EA45-469D-B39E-545EB72F5A43}.Release|x64.ActiveCfg = Release|Any CPU + {768B77B0-EA45-469D-B39E-545EB72F5A43}.Release|x64.Build.0 = Release|Any CPU + {768B77B0-EA45-469D-B39E-545EB72F5A43}.Release|x86.ActiveCfg = Release|Any CPU + {768B77B0-EA45-469D-B39E-545EB72F5A43}.Release|x86.Build.0 = Release|Any CPU + {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|Any CPU.Build.0 = Debug|Any CPU + {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|x64.ActiveCfg = Debug|Any CPU + {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|x64.Build.0 = Debug|Any CPU + {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|x86.ActiveCfg = Debug|Any CPU + {768B77B0-EA45-469D-B39E-545EB72F5A43}.Checked|x86.Build.0 = Debug|Any CPU {8671F164-F78C-44FA-93B7-A310F67890FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8671F164-F78C-44FA-93B7-A310F67890FE}.Debug|Any CPU.Build.0 = Debug|Any CPU {8671F164-F78C-44FA-93B7-A310F67890FE}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -142,42 +192,132 @@ Global {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|x64.Build.0 = Debug|Any CPU {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|x86.ActiveCfg = Debug|Any CPU {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1}.Checked|x86.Build.0 = Debug|Any CPU - {6D2197E6-D3DF-43AE-9BEE-3573018639F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6D2197E6-D3DF-43AE-9BEE-3573018639F9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6D2197E6-D3DF-43AE-9BEE-3573018639F9}.Debug|x64.ActiveCfg = Debug|Any CPU - {6D2197E6-D3DF-43AE-9BEE-3573018639F9}.Debug|x64.Build.0 = Debug|Any CPU - {6D2197E6-D3DF-43AE-9BEE-3573018639F9}.Debug|x86.ActiveCfg = Debug|Any CPU - {6D2197E6-D3DF-43AE-9BEE-3573018639F9}.Debug|x86.Build.0 = Debug|Any CPU - {6D2197E6-D3DF-43AE-9BEE-3573018639F9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6D2197E6-D3DF-43AE-9BEE-3573018639F9}.Release|Any CPU.Build.0 = Release|Any CPU - {6D2197E6-D3DF-43AE-9BEE-3573018639F9}.Release|x64.ActiveCfg = Release|Any CPU - {6D2197E6-D3DF-43AE-9BEE-3573018639F9}.Release|x64.Build.0 = Release|Any CPU - {6D2197E6-D3DF-43AE-9BEE-3573018639F9}.Release|x86.ActiveCfg = Release|Any CPU - {6D2197E6-D3DF-43AE-9BEE-3573018639F9}.Release|x86.Build.0 = Release|Any CPU - {6D2197E6-D3DF-43AE-9BEE-3573018639F9}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {6D2197E6-D3DF-43AE-9BEE-3573018639F9}.Checked|Any CPU.Build.0 = Debug|Any CPU - {6D2197E6-D3DF-43AE-9BEE-3573018639F9}.Checked|x64.ActiveCfg = Debug|Any CPU - {6D2197E6-D3DF-43AE-9BEE-3573018639F9}.Checked|x64.Build.0 = Debug|Any CPU - {6D2197E6-D3DF-43AE-9BEE-3573018639F9}.Checked|x86.ActiveCfg = Debug|Any CPU - {6D2197E6-D3DF-43AE-9BEE-3573018639F9}.Checked|x86.Build.0 = Debug|Any CPU - {E249BD6A-85DB-4CE4-BD82-8D67EBAC5664}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E249BD6A-85DB-4CE4-BD82-8D67EBAC5664}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E249BD6A-85DB-4CE4-BD82-8D67EBAC5664}.Debug|x64.ActiveCfg = Debug|Any CPU - {E249BD6A-85DB-4CE4-BD82-8D67EBAC5664}.Debug|x64.Build.0 = Debug|Any CPU - {E249BD6A-85DB-4CE4-BD82-8D67EBAC5664}.Debug|x86.ActiveCfg = Debug|Any CPU - {E249BD6A-85DB-4CE4-BD82-8D67EBAC5664}.Debug|x86.Build.0 = Debug|Any CPU - {E249BD6A-85DB-4CE4-BD82-8D67EBAC5664}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E249BD6A-85DB-4CE4-BD82-8D67EBAC5664}.Release|Any CPU.Build.0 = Release|Any CPU - {E249BD6A-85DB-4CE4-BD82-8D67EBAC5664}.Release|x64.ActiveCfg = Release|Any CPU - {E249BD6A-85DB-4CE4-BD82-8D67EBAC5664}.Release|x64.Build.0 = Release|Any CPU - {E249BD6A-85DB-4CE4-BD82-8D67EBAC5664}.Release|x86.ActiveCfg = Release|Any CPU - {E249BD6A-85DB-4CE4-BD82-8D67EBAC5664}.Release|x86.Build.0 = Release|Any CPU - {E249BD6A-85DB-4CE4-BD82-8D67EBAC5664}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {E249BD6A-85DB-4CE4-BD82-8D67EBAC5664}.Checked|Any CPU.Build.0 = Debug|Any CPU - {E249BD6A-85DB-4CE4-BD82-8D67EBAC5664}.Checked|x64.ActiveCfg = Debug|Any CPU - {E249BD6A-85DB-4CE4-BD82-8D67EBAC5664}.Checked|x64.Build.0 = Debug|Any CPU - {E249BD6A-85DB-4CE4-BD82-8D67EBAC5664}.Checked|x86.ActiveCfg = Debug|Any CPU - {E249BD6A-85DB-4CE4-BD82-8D67EBAC5664}.Checked|x86.Build.0 = Debug|Any CPU + {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Debug|x64.ActiveCfg = Debug|Any CPU + {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Debug|x64.Build.0 = Debug|Any CPU + {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Debug|x86.ActiveCfg = Debug|Any CPU + {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Debug|x86.Build.0 = Debug|Any CPU + {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Release|Any CPU.Build.0 = Release|Any CPU + {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Release|x64.ActiveCfg = Release|Any CPU + {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Release|x64.Build.0 = Release|Any CPU + {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Release|x86.ActiveCfg = Release|Any CPU + {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Release|x86.Build.0 = Release|Any CPU + {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|Any CPU.Build.0 = Debug|Any CPU + {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|x64.ActiveCfg = Debug|Any CPU + {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|x64.Build.0 = Debug|Any CPU + {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|x86.ActiveCfg = Debug|Any CPU + {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E}.Checked|x86.Build.0 = Debug|Any CPU + {57A1A6FD-9231-4DFB-8619-F0EDEDA208E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {57A1A6FD-9231-4DFB-8619-F0EDEDA208E3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {57A1A6FD-9231-4DFB-8619-F0EDEDA208E3}.Debug|x64.ActiveCfg = Debug|Any CPU + {57A1A6FD-9231-4DFB-8619-F0EDEDA208E3}.Debug|x64.Build.0 = Debug|Any CPU + {57A1A6FD-9231-4DFB-8619-F0EDEDA208E3}.Debug|x86.ActiveCfg = Debug|Any CPU + {57A1A6FD-9231-4DFB-8619-F0EDEDA208E3}.Debug|x86.Build.0 = Debug|Any CPU + {57A1A6FD-9231-4DFB-8619-F0EDEDA208E3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {57A1A6FD-9231-4DFB-8619-F0EDEDA208E3}.Release|Any CPU.Build.0 = Release|Any CPU + {57A1A6FD-9231-4DFB-8619-F0EDEDA208E3}.Release|x64.ActiveCfg = Release|Any CPU + {57A1A6FD-9231-4DFB-8619-F0EDEDA208E3}.Release|x64.Build.0 = Release|Any CPU + {57A1A6FD-9231-4DFB-8619-F0EDEDA208E3}.Release|x86.ActiveCfg = Release|Any CPU + {57A1A6FD-9231-4DFB-8619-F0EDEDA208E3}.Release|x86.Build.0 = Release|Any CPU + {57A1A6FD-9231-4DFB-8619-F0EDEDA208E3}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {57A1A6FD-9231-4DFB-8619-F0EDEDA208E3}.Checked|Any CPU.Build.0 = Debug|Any CPU + {57A1A6FD-9231-4DFB-8619-F0EDEDA208E3}.Checked|x64.ActiveCfg = Debug|Any CPU + {57A1A6FD-9231-4DFB-8619-F0EDEDA208E3}.Checked|x64.Build.0 = Debug|Any CPU + {57A1A6FD-9231-4DFB-8619-F0EDEDA208E3}.Checked|x86.ActiveCfg = Debug|Any CPU + {57A1A6FD-9231-4DFB-8619-F0EDEDA208E3}.Checked|x86.Build.0 = Debug|Any CPU + {4B516949-4AD4-44D6-AF86-C2E6058608D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4B516949-4AD4-44D6-AF86-C2E6058608D5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4B516949-4AD4-44D6-AF86-C2E6058608D5}.Debug|x64.ActiveCfg = Debug|Any CPU + {4B516949-4AD4-44D6-AF86-C2E6058608D5}.Debug|x64.Build.0 = Debug|Any CPU + {4B516949-4AD4-44D6-AF86-C2E6058608D5}.Debug|x86.ActiveCfg = Debug|Any CPU + {4B516949-4AD4-44D6-AF86-C2E6058608D5}.Debug|x86.Build.0 = Debug|Any CPU + {4B516949-4AD4-44D6-AF86-C2E6058608D5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4B516949-4AD4-44D6-AF86-C2E6058608D5}.Release|Any CPU.Build.0 = Release|Any CPU + {4B516949-4AD4-44D6-AF86-C2E6058608D5}.Release|x64.ActiveCfg = Release|Any CPU + {4B516949-4AD4-44D6-AF86-C2E6058608D5}.Release|x64.Build.0 = Release|Any CPU + {4B516949-4AD4-44D6-AF86-C2E6058608D5}.Release|x86.ActiveCfg = Release|Any CPU + {4B516949-4AD4-44D6-AF86-C2E6058608D5}.Release|x86.Build.0 = Release|Any CPU + {4B516949-4AD4-44D6-AF86-C2E6058608D5}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {4B516949-4AD4-44D6-AF86-C2E6058608D5}.Checked|Any CPU.Build.0 = Debug|Any CPU + {4B516949-4AD4-44D6-AF86-C2E6058608D5}.Checked|x64.ActiveCfg = Debug|Any CPU + {4B516949-4AD4-44D6-AF86-C2E6058608D5}.Checked|x64.Build.0 = Debug|Any CPU + {4B516949-4AD4-44D6-AF86-C2E6058608D5}.Checked|x86.ActiveCfg = Debug|Any CPU + {4B516949-4AD4-44D6-AF86-C2E6058608D5}.Checked|x86.Build.0 = Debug|Any CPU + {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Debug|x64.ActiveCfg = Debug|Any CPU + {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Debug|x64.Build.0 = Debug|Any CPU + {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Debug|x86.ActiveCfg = Debug|Any CPU + {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Debug|x86.Build.0 = Debug|Any CPU + {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Release|Any CPU.Build.0 = Release|Any CPU + {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Release|x64.ActiveCfg = Release|Any CPU + {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Release|x64.Build.0 = Release|Any CPU + {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Release|x86.ActiveCfg = Release|Any CPU + {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Release|x86.Build.0 = Release|Any CPU + {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|Any CPU.Build.0 = Debug|Any CPU + {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|x64.ActiveCfg = Debug|Any CPU + {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|x64.Build.0 = Debug|Any CPU + {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|x86.ActiveCfg = Debug|Any CPU + {25D66424-2EAF-464D-8460-10C04EDEF3C3}.Checked|x86.Build.0 = Debug|Any CPU + {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Debug|x64.ActiveCfg = Debug|Any CPU + {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Debug|x64.Build.0 = Debug|Any CPU + {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Debug|x86.ActiveCfg = Debug|Any CPU + {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Debug|x86.Build.0 = Debug|Any CPU + {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Release|Any CPU.Build.0 = Release|Any CPU + {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Release|x64.ActiveCfg = Release|Any CPU + {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Release|x64.Build.0 = Release|Any CPU + {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Release|x86.ActiveCfg = Release|Any CPU + {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Release|x86.Build.0 = Release|Any CPU + {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|Any CPU.Build.0 = Debug|Any CPU + {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|x64.ActiveCfg = Debug|Any CPU + {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|x64.Build.0 = Debug|Any CPU + {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|x86.ActiveCfg = Debug|Any CPU + {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF}.Checked|x86.Build.0 = Debug|Any CPU + {866D295E-424A-4747-9417-CD7746936138}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {866D295E-424A-4747-9417-CD7746936138}.Debug|Any CPU.Build.0 = Debug|Any CPU + {866D295E-424A-4747-9417-CD7746936138}.Debug|x64.ActiveCfg = Debug|Any CPU + {866D295E-424A-4747-9417-CD7746936138}.Debug|x64.Build.0 = Debug|Any CPU + {866D295E-424A-4747-9417-CD7746936138}.Debug|x86.ActiveCfg = Debug|Any CPU + {866D295E-424A-4747-9417-CD7746936138}.Debug|x86.Build.0 = Debug|Any CPU + {866D295E-424A-4747-9417-CD7746936138}.Release|Any CPU.ActiveCfg = Release|Any CPU + {866D295E-424A-4747-9417-CD7746936138}.Release|Any CPU.Build.0 = Release|Any CPU + {866D295E-424A-4747-9417-CD7746936138}.Release|x64.ActiveCfg = Release|Any CPU + {866D295E-424A-4747-9417-CD7746936138}.Release|x64.Build.0 = Release|Any CPU + {866D295E-424A-4747-9417-CD7746936138}.Release|x86.ActiveCfg = Release|Any CPU + {866D295E-424A-4747-9417-CD7746936138}.Release|x86.Build.0 = Release|Any CPU + {866D295E-424A-4747-9417-CD7746936138}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {866D295E-424A-4747-9417-CD7746936138}.Checked|Any CPU.Build.0 = Debug|Any CPU + {866D295E-424A-4747-9417-CD7746936138}.Checked|x64.ActiveCfg = Debug|Any CPU + {866D295E-424A-4747-9417-CD7746936138}.Checked|x64.Build.0 = Debug|Any CPU + {866D295E-424A-4747-9417-CD7746936138}.Checked|x86.ActiveCfg = Debug|Any CPU + {866D295E-424A-4747-9417-CD7746936138}.Checked|x86.Build.0 = Debug|Any CPU + {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Debug|x64.ActiveCfg = Debug|Any CPU + {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Debug|x64.Build.0 = Debug|Any CPU + {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Debug|x86.ActiveCfg = Debug|Any CPU + {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Debug|x86.Build.0 = Debug|Any CPU + {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Release|Any CPU.Build.0 = Release|Any CPU + {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Release|x64.ActiveCfg = Release|Any CPU + {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Release|x64.Build.0 = Release|Any CPU + {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Release|x86.ActiveCfg = Release|Any CPU + {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Release|x86.Build.0 = Release|Any CPU + {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|Any CPU.Build.0 = Debug|Any CPU + {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|x64.ActiveCfg = Debug|Any CPU + {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|x64.Build.0 = Debug|Any CPU + {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|x86.ActiveCfg = Debug|Any CPU + {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5}.Checked|x86.Build.0 = Debug|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -185,10 +325,17 @@ Global GlobalSection(NestedProjects) = preSolution {94B59BA0-491F-4B59-ADFF-A057EC3EC835} = {B1678CCD-95C8-4419-B9F9-14A03061BE4B} {04BA3E3C-6979-4792-B19E-C797AD607F42} = {B1678CCD-95C8-4419-B9F9-14A03061BE4B} + {07F19F91-D438-428D-99F0-61DAD87E78BA} = {B1678CCD-95C8-4419-B9F9-14A03061BE4B} + {768B77B0-EA45-469D-B39E-545EB72F5A43} = {B1678CCD-95C8-4419-B9F9-14A03061BE4B} {4FC33B9B-1BCF-4D16-B886-DCA8F2B823C1} = {B1678CCD-95C8-4419-B9F9-14A03061BE4B} {1FF4CC8E-49C3-42A0-A6E0-2E5908455FBA} = {FB99AC59-1744-4F12-A4B0-0D54FCA048BF} - {6D2197E6-D3DF-43AE-9BEE-3573018639F9} = {FB99AC59-1744-4F12-A4B0-0D54FCA048BF} - {E249BD6A-85DB-4CE4-BD82-8D67EBAC5664} = {FB99AC59-1744-4F12-A4B0-0D54FCA048BF} + {79F7BE0E-01AA-4AFB-B047-CF7C0B38F81E} = {FB99AC59-1744-4F12-A4B0-0D54FCA048BF} + {57A1A6FD-9231-4DFB-8619-F0EDEDA208E3} = {FB99AC59-1744-4F12-A4B0-0D54FCA048BF} + {4B516949-4AD4-44D6-AF86-C2E6058608D5} = {FB99AC59-1744-4F12-A4B0-0D54FCA048BF} + {25D66424-2EAF-464D-8460-10C04EDEF3C3} = {FB99AC59-1744-4F12-A4B0-0D54FCA048BF} + {049B7FD4-ACEF-4BCD-A7A7-75C9BBEC4EBF} = {FB99AC59-1744-4F12-A4B0-0D54FCA048BF} + {866D295E-424A-4747-9417-CD7746936138} = {FB99AC59-1744-4F12-A4B0-0D54FCA048BF} + {D3A329E3-0FEB-4136-9CB6-B38319B0FFA5} = {FB99AC59-1744-4F12-A4B0-0D54FCA048BF} {5BB5F99F-1052-4EB4-B12E-7863805661F3} = {D893B9AA-57C5-49E3-97B1-12CC62D84307} {8671F164-F78C-44FA-93B7-A310F67890FE} = {D893B9AA-57C5-49E3-97B1-12CC62D84307} EndGlobalSection diff --git a/src/libraries/System.Runtime.InteropServices/gen/.gitignore b/src/libraries/System.Runtime.InteropServices/gen/.gitignore new file mode 100644 index 0000000000000..6b22273110c17 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/.gitignore @@ -0,0 +1,5 @@ +.vs/ +**/bin +**/obj +*.binlog +BenchmarkDotNet.Artifacts \ No newline at end of file diff --git a/src/libraries/System.Runtime.InteropServices/gen/Directory.Build.props b/src/libraries/System.Runtime.InteropServices/gen/Directory.Build.props new file mode 100644 index 0000000000000..9eff2af744867 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/Directory.Build.props @@ -0,0 +1,12 @@ + + + + false + false + + false + true + false + false + + \ No newline at end of file diff --git a/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/AnalyzerReleases.Shipped.md b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/AnalyzerReleases.Shipped.md new file mode 100644 index 0000000000000..2bf479656968a --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/AnalyzerReleases.Shipped.md @@ -0,0 +1 @@ +; Shipped analyzer releases \ No newline at end of file diff --git a/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/AnalyzerReleases.Unshipped.md b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/AnalyzerReleases.Unshipped.md new file mode 100644 index 0000000000000..87ac29a463b2f --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/AnalyzerReleases.Unshipped.md @@ -0,0 +1,24 @@ +### New Rules + +Rule ID | Category | Severity | Notes +--------|----------|----------|------- +DLLIMPORTGEN001 | SourceGeneration | Error | TypeNotSupported +DLLIMPORTGEN002 | SourceGeneration | Error | ConfigurationNotSupported +DLLIMPORTGEN003 | SourceGeneration | Error | TargetFrameworkNotSupported +DLLIMPORTGENANALYZER001 | Usage | Error | BlittableTypeMustBeBlittable +DLLIMPORTGENANALYZER002 | Usage | Error | CannotHaveMultipleMarshallingAttributes +DLLIMPORTGENANALYZER003 | Usage | Error | NativeTypeMustBeNonNull +DLLIMPORTGENANALYZER004 | Usage | Error | NativeTypeMustBeBlittable +DLLIMPORTGENANALYZER005 | Usage | Error | GetPinnableReferenceReturnTypeBlittable +DLLIMPORTGENANALYZER006 | Usage | Error | NativeTypeMustBePointerSized +DLLIMPORTGENANALYZER007 | Usage | Error | NativeTypeMustHaveRequiredShape +DLLIMPORTGENANALYZER008 | Usage | Error | ValuePropertyMustHaveSetter +DLLIMPORTGENANALYZER009 | Usage | Error | ValuePropertyMustHaveGetter +DLLIMPORTGENANALYZER010 | Usage | Warning | GetPinnableReferenceShouldSupportAllocatingMarshallingFallback +DLLIMPORTGENANALYZER011 | Usage | Warning | StackallocMarshallingShouldSupportAllocatingMarshallingFallback +DLLIMPORTGENANALYZER012 | Usage | Error | StackallocConstructorMustHaveStackBufferSizeConstant +DLLIMPORTGENANALYZER013 | Usage | Warning | GeneratedDllImportMissingRequiredModifiers +DLLIMPORTGENANALYZER014 | Usage | Error | RefValuePropertyUnsupported +DLLIMPORTGENANALYZER015 | Interoperability | Disabled | ConvertToGeneratedDllImportAnalyzer +DLLIMPORTGENANALYZER016 | Usage | Error | GenericTypeMustBeClosed +DLLIMPORTGENANALYZER017 | Usage | Warning | GeneratedDllImportContainingTypeMissingModifiers diff --git a/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/Analyzers/AnalyzerDiagnostics.cs b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/Analyzers/AnalyzerDiagnostics.cs new file mode 100644 index 0000000000000..4f4d7690fe05f --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/Analyzers/AnalyzerDiagnostics.cs @@ -0,0 +1,46 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.CodeAnalysis; + +namespace Microsoft.Interop.Analyzers +{ + internal static class AnalyzerDiagnostics + { + /// + /// Analyzer rule IDs + /// + public static class Ids + { + public const string Prefix = "DLLIMPORTGENANALYZER"; + + // ManualTypeMarshalling + public const string BlittableTypeMustBeBlittable = Prefix + "001"; + public const string CannotHaveMultipleMarshallingAttributes = Prefix + "002"; + public const string NativeTypeMustBeNonNull = Prefix + "003"; + public const string NativeTypeMustBeBlittable = Prefix + "004"; + public const string GetPinnableReferenceReturnTypeBlittable = Prefix + "005"; + public const string NativeTypeMustBePointerSized = Prefix + "006"; + public const string NativeTypeMustHaveRequiredShape = Prefix + "007"; + public const string ValuePropertyMustHaveSetter = Prefix + "008"; + public const string ValuePropertyMustHaveGetter = Prefix + "009"; + public const string GetPinnableReferenceShouldSupportAllocatingMarshallingFallback = Prefix + "010"; + public const string StackallocMarshallingShouldSupportAllocatingMarshallingFallback = Prefix + "011"; + public const string StackallocConstructorMustHaveStackBufferSizeConstant = Prefix + "012"; + public const string RefValuePropertyUnsupported = Prefix + "014"; + public const string NativeGenericTypeMustBeClosedOrMatchArity = Prefix + "016"; + + // GeneratedDllImport + public const string GeneratedDllImportMissingRequiredModifiers = Prefix + "013"; + public const string GeneratedDllImportContaiingTypeMissingRequiredModifiers = Prefix + "017"; + + // Migration from DllImport to GeneratedDllImport + public const string ConvertToGeneratedDllImport = Prefix + "015"; + } + + internal static LocalizableResourceString GetResourceString(string resourceName) + { + return new LocalizableResourceString(resourceName, Resources.ResourceManager, typeof(Resources)); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/Analyzers/ConvertToGeneratedDllImportAnalyzer.cs b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/Analyzers/ConvertToGeneratedDllImportAnalyzer.cs new file mode 100644 index 0000000000000..cf1437251279b --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/Analyzers/ConvertToGeneratedDllImportAnalyzer.cs @@ -0,0 +1,118 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; +using System.Runtime.InteropServices; + +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; + +using static Microsoft.Interop.Analyzers.AnalyzerDiagnostics; + +namespace Microsoft.Interop.Analyzers +{ + [DiagnosticAnalyzer(LanguageNames.CSharp)] + public class ConvertToGeneratedDllImportAnalyzer : DiagnosticAnalyzer + { + private const string Category = "Interoperability"; + + public static readonly DiagnosticDescriptor ConvertToGeneratedDllImport = + new DiagnosticDescriptor( + Ids.ConvertToGeneratedDllImport, + GetResourceString(nameof(Resources.ConvertToGeneratedDllImportTitle)), + GetResourceString(nameof(Resources.ConvertToGeneratedDllImportMessage)), + Category, + DiagnosticSeverity.Info, + isEnabledByDefault: false, + description: GetResourceString(nameof(Resources.ConvertToGeneratedDllImportDescription))); + + public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(ConvertToGeneratedDllImport); + + public override void Initialize(AnalysisContext context) + { + // Don't analyze generated code + context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); + context.EnableConcurrentExecution(); + context.RegisterCompilationStartAction( + compilationContext => + { + // Nothing to do if the GeneratedDllImportAttribute is not in the compilation + INamedTypeSymbol? generatedDllImportAttrType = compilationContext.Compilation.GetTypeByMetadataName(TypeNames.GeneratedDllImportAttribute); + if (generatedDllImportAttrType == null) + return; + + INamedTypeSymbol? dllImportAttrType = compilationContext.Compilation.GetTypeByMetadataName(typeof(DllImportAttribute).FullName); + if (dllImportAttrType == null) + return; + + compilationContext.RegisterSymbolAction(symbolContext => AnalyzeSymbol(symbolContext, dllImportAttrType), SymbolKind.Method); + }); + } + + private static void AnalyzeSymbol(SymbolAnalysisContext context, INamedTypeSymbol dllImportAttrType) + { + var method = (IMethodSymbol)context.Symbol; + + // Check if method is a DllImport + DllImportData? dllImportData = method.GetDllImportData(); + if (dllImportData == null) + return; + + // Ignore QCalls + if (dllImportData.ModuleName == "QCall") + return; + + if (RequiresMarshalling(method, dllImportData, dllImportAttrType)) + { + context.ReportDiagnostic(method.CreateDiagnostic(ConvertToGeneratedDllImport, method.Name)); + } + } + + private static bool RequiresMarshalling(IMethodSymbol method, DllImportData dllImportData, INamedTypeSymbol dllImportAttrType) + { + // SetLastError=true requires marshalling + if (dllImportData.SetLastError) + return true; + + // Check if return value requires marshalling + if (!method.ReturnsVoid && !method.ReturnType.IsConsideredBlittable()) + return true; + + // Check if parameters require marshalling + foreach (IParameterSymbol paramType in method.Parameters) + { + if (paramType.RefKind != RefKind.None) + return true; + + if (!paramType.Type.IsConsideredBlittable()) + return true; + } + + // DllImportData does not expose all information (e.g. PreserveSig), so we still need to get the attribute data + AttributeData? dllImportAttr = null; + foreach (AttributeData attr in method.GetAttributes()) + { + if (!SymbolEqualityComparer.Default.Equals(attr.AttributeClass, dllImportAttrType)) + continue; + + dllImportAttr = attr; + break; + } + + Debug.Assert(dllImportAttr != null); + foreach (KeyValuePair namedArg in dllImportAttr!.NamedArguments) + { + if (namedArg.Key != nameof(DllImportAttribute.PreserveSig)) + continue; + + // PreserveSig=false requires marshalling + if (!(bool)namedArg.Value.Value!) + return true; + } + + return false; + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/Analyzers/ConvertToGeneratedDllImportFixer.cs b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/Analyzers/ConvertToGeneratedDllImportFixer.cs new file mode 100644 index 0000000000000..4b4a719057b5d --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/Analyzers/ConvertToGeneratedDllImportFixer.cs @@ -0,0 +1,302 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; + +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Editing; + +using static Microsoft.Interop.Analyzers.AnalyzerDiagnostics; + +namespace Microsoft.Interop.Analyzers +{ + [ExportCodeFixProvider(LanguageNames.CSharp)] + public sealed class ConvertToGeneratedDllImportFixer : CodeFixProvider + { + public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(Ids.ConvertToGeneratedDllImport); + + public override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer; + + public const string NoPreprocessorDefinesKey = "ConvertToGeneratedDllImport"; + public const string WithPreprocessorDefinesKey = "ConvertToGeneratedDllImportPreprocessor"; + + public override async Task RegisterCodeFixesAsync(CodeFixContext context) + { + // Get the syntax root and semantic model + Document doc = context.Document; + SyntaxNode? root = await doc.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false); + SemanticModel? model = await doc.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false); + if (root == null || model == null) + return; + + // Nothing to do if the GeneratedDllImportAttribute is not in the compilation + INamedTypeSymbol? generatedDllImportAttrType = model.Compilation.GetTypeByMetadataName(TypeNames.GeneratedDllImportAttribute); + if (generatedDllImportAttrType == null) + return; + + INamedTypeSymbol? dllImportAttrType = model.Compilation.GetTypeByMetadataName(typeof(DllImportAttribute).FullName); + if (dllImportAttrType == null) + return; + + // Get the syntax node tied to the diagnostic and check that it is a method declaration + if (root.FindNode(context.Span) is not MethodDeclarationSyntax methodSyntax) + return; + + if (model.GetDeclaredSymbol(methodSyntax, context.CancellationToken) is not IMethodSymbol methodSymbol) + return; + + // Make sure the method has the DllImportAttribute + if (!TryGetAttribute(methodSymbol, dllImportAttrType, out AttributeData? dllImportAttr)) + return; + + // Register code fixes with two options for the fix - using preprocessor or not. + context.RegisterCodeFix( + CodeAction.Create( + Resources.ConvertToGeneratedDllImportNoPreprocessor, + cancelToken => ConvertToGeneratedDllImport( + context.Document, + methodSyntax, + methodSymbol, + dllImportAttr!, + generatedDllImportAttrType, + usePreprocessorDefines: false, + cancelToken), + equivalenceKey: NoPreprocessorDefinesKey), + context.Diagnostics); + + context.RegisterCodeFix( + CodeAction.Create( + Resources.ConvertToGeneratedDllImportWithPreprocessor, + cancelToken => ConvertToGeneratedDllImport( + context.Document, + methodSyntax, + methodSymbol, + dllImportAttr!, + generatedDllImportAttrType, + usePreprocessorDefines: true, + cancelToken), + equivalenceKey: WithPreprocessorDefinesKey), + context.Diagnostics); + } + + private async Task ConvertToGeneratedDllImport( + Document doc, + MethodDeclarationSyntax methodSyntax, + IMethodSymbol methodSymbol, + AttributeData dllImportAttr, + INamedTypeSymbol generatedDllImportAttrType, + bool usePreprocessorDefines, + CancellationToken cancellationToken) + { + DocumentEditor editor = await DocumentEditor.CreateAsync(doc, cancellationToken).ConfigureAwait(false); + SyntaxGenerator generator = editor.Generator; + + var dllImportSyntax = (AttributeSyntax)dllImportAttr!.ApplicationSyntaxReference!.GetSyntax(cancellationToken); + + // Create GeneratedDllImport attribute based on the DllImport attribute + SyntaxNode generatedDllImportSyntax = GetGeneratedDllImportAttribute( + editor, + generator, + dllImportSyntax, + methodSymbol.GetDllImportData()!, + generatedDllImportAttrType, + out SyntaxNode? unmanagedCallConvAttributeMaybe); + + // Add annotation about potential behavioural and compatibility changes + generatedDllImportSyntax = generatedDllImportSyntax.WithAdditionalAnnotations( + WarningAnnotation.Create(string.Format(Resources.ConvertToGeneratedDllImportWarning, "[TODO] Documentation link"))); + + // Replace DllImport with GeneratedDllImport + SyntaxNode generatedDeclaration = generator.ReplaceNode(methodSyntax, dllImportSyntax, generatedDllImportSyntax); + + if (unmanagedCallConvAttributeMaybe is not null) + { + generatedDeclaration = generator.AddAttributes(generatedDeclaration, unmanagedCallConvAttributeMaybe); + } + + // Replace extern keyword with partial keyword + generatedDeclaration = generator.WithModifiers( + generatedDeclaration, + generator.GetModifiers(methodSyntax) + .WithIsExtern(false) + .WithPartial(true)); + + if (!usePreprocessorDefines) + { + // Replace the original method with the updated one + editor.ReplaceNode(methodSyntax, generatedDeclaration); + } + else + { + // #if DLLIMPORTGENERATOR_ENABLED + generatedDeclaration = generatedDeclaration.WithLeadingTrivia( + generatedDeclaration.GetLeadingTrivia() + .AddRange(new[] { + SyntaxFactory.Trivia(SyntaxFactory.IfDirectiveTrivia(SyntaxFactory.IdentifierName("DLLIMPORTGENERATOR_ENABLED"), isActive: true, branchTaken: true, conditionValue: true)), + SyntaxFactory.ElasticMarker + })); + + // #else + generatedDeclaration = generatedDeclaration.WithTrailingTrivia( + generatedDeclaration.GetTrailingTrivia() + .AddRange(new[] { + SyntaxFactory.Trivia(SyntaxFactory.ElseDirectiveTrivia(isActive: false, branchTaken: false)), + SyntaxFactory.ElasticMarker + })); + + // Remove existing leading trivia - it will be on the GeneratedDllImport method + MethodDeclarationSyntax updatedDeclaration = methodSyntax.WithLeadingTrivia(); + + // #endif + updatedDeclaration = updatedDeclaration.WithTrailingTrivia( + methodSyntax.GetTrailingTrivia() + .AddRange(new[] { + SyntaxFactory.Trivia(SyntaxFactory.EndIfDirectiveTrivia(isActive: true)), + SyntaxFactory.ElasticMarker + })); + + // Add the GeneratedDllImport method + editor.InsertBefore(methodSyntax, generatedDeclaration); + + // Replace the original method with the updated DllImport method + editor.ReplaceNode(methodSyntax, updatedDeclaration); + } + + return editor.GetChangedDocument(); + } + + private SyntaxNode GetGeneratedDllImportAttribute( + DocumentEditor editor, + SyntaxGenerator generator, + AttributeSyntax dllImportSyntax, + DllImportData dllImportData, + INamedTypeSymbol generatedDllImportAttrType, + out SyntaxNode? unmanagedCallConvAttributeMaybe) + { + unmanagedCallConvAttributeMaybe = null; + // Create GeneratedDllImport based on the DllImport attribute + SyntaxNode generatedDllImportSyntax = generator.ReplaceNode(dllImportSyntax, + dllImportSyntax.Name, + generator.TypeExpression(generatedDllImportAttrType)); + + // Update attribute arguments for GeneratedDllImport + List argumentsToRemove = new List(); + foreach (SyntaxNode argument in generator.GetAttributeArguments(generatedDllImportSyntax)) + { + if (argument is not AttributeArgumentSyntax attrArg) + continue; + + if (dllImportData.BestFitMapping != null + && !dllImportData.BestFitMapping.Value + && IsMatchingNamedArg(attrArg, nameof(DllImportAttribute.BestFitMapping))) + { + // BestFitMapping=false is explicitly set + // GeneratedDllImport does not support setting BestFitMapping. The generated code + // has the equivalent behaviour of BestFitMapping=false, so we can remove the argument. + argumentsToRemove.Add(argument); + } + else if (dllImportData.ThrowOnUnmappableCharacter != null + && !dllImportData.ThrowOnUnmappableCharacter.Value + && IsMatchingNamedArg(attrArg, nameof(DllImportAttribute.ThrowOnUnmappableChar))) + { + // ThrowOnUnmappableChar=false is explicitly set + // GeneratedDllImport does not support setting ThrowOnUnmappableChar. The generated code + // has the equivalent behaviour of ThrowOnUnmappableChar=false, so we can remove the argument. + argumentsToRemove.Add(argument); + } + else if (IsMatchingNamedArg(attrArg, nameof(DllImportAttribute.CallingConvention))) + { + if (TryCreateUnmanagedCallConvAttributeToEmit( + editor, + generator, + dllImportData.CallingConvention, + out unmanagedCallConvAttributeMaybe)) + { + argumentsToRemove.Add(argument); + } + } + } + + return generator.RemoveNodes(generatedDllImportSyntax, argumentsToRemove); + } + + private bool TryCreateUnmanagedCallConvAttributeToEmit( + DocumentEditor editor, + SyntaxGenerator generator, + CallingConvention callingConvention, + out SyntaxNode? unmanagedCallConvAttribute) + { + if (editor.SemanticModel.Compilation.GetTypeByMetadataName(TypeNames.UnmanagedCallConvAttribute) is null) + { + unmanagedCallConvAttribute = null; + return false; + } + + if (callingConvention == CallingConvention.Winapi) + { + // Winapi is the default, so we return true that we've created the attribute to emit, + // but set the attribute-to-emit to null since we don't need to emit an attribute. + unmanagedCallConvAttribute = null; + return true; + } + + ITypeSymbol? callingConventionType = callingConvention switch + { + CallingConvention.Cdecl => editor.SemanticModel.Compilation.ObjectType.ContainingAssembly. + GetTypeByMetadataName($"System.Runtime.CompilerServices.CallConvCdecl"), + CallingConvention.StdCall => editor.SemanticModel.Compilation.ObjectType.ContainingAssembly. + GetTypeByMetadataName($"System.Runtime.CompilerServices.CallConvStdcall"), + CallingConvention.ThisCall => editor.SemanticModel.Compilation.ObjectType.ContainingAssembly. + GetTypeByMetadataName($"System.Runtime.CompilerServices.CallConvThiscall"), + CallingConvention.FastCall => editor.SemanticModel.Compilation.ObjectType.ContainingAssembly. + GetTypeByMetadataName($"System.Runtime.CompilerServices.CallConvFastcall"), + _ => null + }; + + // The user is using a calling convention type that doesn't have a matching CallConv type. + // There are no calling conventions like this, so we're already in a state that won't work at runtime. + // Leave the value as-is for now and let the user handle this however they see fit. + if (callingConventionType is null) + { + unmanagedCallConvAttribute = null; + return false; + } + + unmanagedCallConvAttribute = generator.Attribute(TypeNames.UnmanagedCallConvAttribute, + generator.AttributeArgument("CallConvs", + generator.ArrayCreationExpression( + generator.TypeExpression(editor.SemanticModel.Compilation.GetTypeByMetadataName(TypeNames.System_Type)), + new[] { generator.TypeOfExpression(generator.TypeExpression(callingConventionType)) }))); + + return true; + } + + private static bool TryGetAttribute(IMethodSymbol method, INamedTypeSymbol attributeType, out AttributeData? attr) + { + attr = default; + foreach (AttributeData attrLocal in method.GetAttributes()) + { + if (SymbolEqualityComparer.Default.Equals(attrLocal.AttributeClass, attributeType)) + { + attr = attrLocal; + return true; + } + } + + return false; + } + + private static bool IsMatchingNamedArg(AttributeArgumentSyntax arg, string nameToMatch) + { + return arg.NameEquals != null && arg.NameEquals.Name.Identifier.Text == nameToMatch; + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/Analyzers/GeneratedDllImportAnalyzer.cs b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/Analyzers/GeneratedDllImportAnalyzer.cs new file mode 100644 index 0000000000000..b3d2b3a5cf38a --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/Analyzers/GeneratedDllImportAnalyzer.cs @@ -0,0 +1,104 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Immutable; +using System.Linq; + +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Diagnostics; + +using static Microsoft.Interop.Analyzers.AnalyzerDiagnostics; + +namespace Microsoft.Interop.Analyzers +{ + [DiagnosticAnalyzer(LanguageNames.CSharp)] + public class GeneratedDllImportAnalyzer : DiagnosticAnalyzer + { + private const string Category = "Usage"; + + public static readonly DiagnosticDescriptor GeneratedDllImportMissingModifiers = + new DiagnosticDescriptor( + Ids.GeneratedDllImportMissingRequiredModifiers, + GetResourceString(nameof(Resources.GeneratedDllImportMissingModifiersTitle)), + GetResourceString(nameof(Resources.GeneratedDllImportMissingModifiersMessage)), + Category, + DiagnosticSeverity.Warning, + isEnabledByDefault: true, + description: GetResourceString(nameof(Resources.GeneratedDllImportMissingModifiersDescription))); + + public static readonly DiagnosticDescriptor GeneratedDllImportContainingTypeMissingModifiers = + new DiagnosticDescriptor( + Ids.GeneratedDllImportContaiingTypeMissingRequiredModifiers, + GetResourceString(nameof(Resources.GeneratedDllImportContainingTypeMissingModifiersTitle)), + GetResourceString(nameof(Resources.GeneratedDllImportContainingTypeMissingModifiersMessage)), + Category, + DiagnosticSeverity.Warning, + isEnabledByDefault: true, + description: GetResourceString(nameof(Resources.GeneratedDllImportContainingTypeMissingModifiersDescription))); + + public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(GeneratedDllImportMissingModifiers, GeneratedDllImportContainingTypeMissingModifiers); + + public override void Initialize(AnalysisContext context) + { + // Don't analyze generated code + context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); + context.EnableConcurrentExecution(); + context.RegisterCompilationStartAction( + compilationContext => + { + INamedTypeSymbol? generatedDllImportAttributeType = compilationContext.Compilation.GetTypeByMetadataName(TypeNames.GeneratedDllImportAttribute); + if (generatedDllImportAttributeType == null) + return; + + compilationContext.RegisterSymbolAction(symbolContext => AnalyzeSymbol(symbolContext, generatedDllImportAttributeType), SymbolKind.Method); + }); + } + + private static void AnalyzeSymbol(SymbolAnalysisContext context, INamedTypeSymbol generatedDllImportAttributeType) + { + var methodSymbol = (IMethodSymbol)context.Symbol; + + // Check if method is marked with GeneratedDllImportAttribute + ImmutableArray attributes = methodSymbol.GetAttributes(); + if (!attributes.Any(attr => SymbolEqualityComparer.Default.Equals(attr.AttributeClass, generatedDllImportAttributeType))) + return; + + if (!methodSymbol.IsStatic) + { + // Must be marked static + context.ReportDiagnostic(methodSymbol.CreateDiagnostic(GeneratedDllImportMissingModifiers, methodSymbol.Name)); + } + else + { + // Make sure declarations are marked partial. Technically, we can just check one + // declaration, since Roslyn would error on inconsistent partial declarations. + foreach (SyntaxReference reference in methodSymbol.DeclaringSyntaxReferences) + { + SyntaxNode syntax = reference.GetSyntax(context.CancellationToken); + if (syntax is MethodDeclarationSyntax methodSyntax && !methodSyntax.Modifiers.Any(SyntaxKind.PartialKeyword)) + { + // Must be marked partial + context.ReportDiagnostic(methodSymbol.CreateDiagnostic(GeneratedDllImportMissingModifiers, methodSymbol.Name)); + break; + } + } + + for (INamedTypeSymbol? typeSymbol = methodSymbol.ContainingType; typeSymbol is not null; typeSymbol = typeSymbol.ContainingType) + { + foreach (SyntaxReference reference in typeSymbol.DeclaringSyntaxReferences) + { + SyntaxNode syntax = reference.GetSyntax(context.CancellationToken); + if (syntax is TypeDeclarationSyntax typeSyntax && !typeSyntax.Modifiers.Any(SyntaxKind.PartialKeyword)) + { + // Must be marked partial + context.ReportDiagnostic(typeSymbol.CreateDiagnostic(GeneratedDllImportContainingTypeMissingModifiers, typeSymbol.Name)); + break; + } + } + } + } + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/Analyzers/ManualTypeMarshallingAnalyzer.cs b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/Analyzers/ManualTypeMarshallingAnalyzer.cs new file mode 100644 index 0000000000000..f975a68c58f37 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/Analyzers/ManualTypeMarshallingAnalyzer.cs @@ -0,0 +1,561 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Immutable; +using System.Linq; + +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; + +using static Microsoft.Interop.Analyzers.AnalyzerDiagnostics; + +namespace Microsoft.Interop.Analyzers +{ + [DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)] + public class ManualTypeMarshallingAnalyzer : DiagnosticAnalyzer + { + private const string Category = "Usage"; + + public static readonly DiagnosticDescriptor BlittableTypeMustBeBlittableRule = + new DiagnosticDescriptor( + Ids.BlittableTypeMustBeBlittable, + "BlittableTypeMustBeBlittable", + GetResourceString(nameof(Resources.BlittableTypeMustBeBlittableMessage)), + Category, + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: GetResourceString(nameof(Resources.BlittableTypeMustBeBlittableDescription))); + + public static readonly DiagnosticDescriptor CannotHaveMultipleMarshallingAttributesRule = + new DiagnosticDescriptor( + Ids.CannotHaveMultipleMarshallingAttributes, + "CannotHaveMultipleMarshallingAttributes", + GetResourceString(nameof(Resources.CannotHaveMultipleMarshallingAttributesMessage)), + Category, + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: GetResourceString(nameof(Resources.CannotHaveMultipleMarshallingAttributesDescription))); + + public static readonly DiagnosticDescriptor NativeTypeMustBeNonNullRule = + new DiagnosticDescriptor( + Ids.NativeTypeMustBeNonNull, + "NativeTypeMustBeNonNull", + GetResourceString(nameof(Resources.NativeTypeMustBeNonNullMessage)), + Category, + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: GetResourceString(nameof(Resources.NativeTypeMustBeNonNullDescription))); + + public static readonly DiagnosticDescriptor NativeTypeMustBeBlittableRule = + new DiagnosticDescriptor( + Ids.NativeTypeMustBeBlittable, + "NativeTypeMustBeBlittable", + GetResourceString(nameof(Resources.NativeTypeMustBeBlittableMessage)), + Category, + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: GetResourceString(nameof(Resources.BlittableTypeMustBeBlittableDescription))); + + public static readonly DiagnosticDescriptor GetPinnableReferenceReturnTypeBlittableRule = + new DiagnosticDescriptor( + Ids.GetPinnableReferenceReturnTypeBlittable, + "GetPinnableReferenceReturnTypeBlittable", + GetResourceString(nameof(Resources.GetPinnableReferenceReturnTypeBlittableMessage)), + Category, + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: GetResourceString(nameof(Resources.GetPinnableReferenceReturnTypeBlittableDescription))); + + public static readonly DiagnosticDescriptor NativeTypeMustBePointerSizedRule = + new DiagnosticDescriptor( + Ids.NativeTypeMustBePointerSized, + "NativeTypeMustBePointerSized", + GetResourceString(nameof(Resources.NativeTypeMustBePointerSizedMessage)), + Category, + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: GetResourceString(nameof(Resources.NativeTypeMustBePointerSizedDescription))); + + public static readonly DiagnosticDescriptor NativeTypeMustHaveRequiredShapeRule = + new DiagnosticDescriptor( + Ids.NativeTypeMustHaveRequiredShape, + "NativeTypeMustHaveRequiredShape", + GetResourceString(nameof(Resources.NativeTypeMustHaveRequiredShapeMessage)), + Category, + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: GetResourceString(nameof(Resources.NativeTypeMustHaveRequiredShapeDescription))); + + public static readonly DiagnosticDescriptor CollectionNativeTypeMustHaveRequiredShapeRule = + new DiagnosticDescriptor( + Ids.NativeTypeMustHaveRequiredShape, + "NativeTypeMustHaveRequiredShape", + GetResourceString(nameof(Resources.CollectionNativeTypeMustHaveRequiredShapeMessage)), + Category, + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: GetResourceString(nameof(Resources.CollectionNativeTypeMustHaveRequiredShapeDescription))); + + public static readonly DiagnosticDescriptor ValuePropertyMustHaveSetterRule = + new DiagnosticDescriptor( + Ids.ValuePropertyMustHaveSetter, + "ValuePropertyMustHaveSetter", + GetResourceString(nameof(Resources.ValuePropertyMustHaveSetterMessage)), + Category, + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: GetResourceString(nameof(Resources.ValuePropertyMustHaveSetterDescription))); + + public static readonly DiagnosticDescriptor ValuePropertyMustHaveGetterRule = + new DiagnosticDescriptor( + Ids.ValuePropertyMustHaveGetter, + "ValuePropertyMustHaveGetter", + GetResourceString(nameof(Resources.ValuePropertyMustHaveGetterMessage)), + Category, + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: GetResourceString(nameof(Resources.ValuePropertyMustHaveGetterDescription))); + + public static readonly DiagnosticDescriptor GetPinnableReferenceShouldSupportAllocatingMarshallingFallbackRule = + new DiagnosticDescriptor( + Ids.GetPinnableReferenceShouldSupportAllocatingMarshallingFallback, + "GetPinnableReferenceShouldSupportAllocatingMarshallingFallback", + GetResourceString(nameof(Resources.GetPinnableReferenceShouldSupportAllocatingMarshallingFallbackMessage)), + Category, + DiagnosticSeverity.Warning, + isEnabledByDefault: true, + description: GetResourceString(nameof(Resources.GetPinnableReferenceShouldSupportAllocatingMarshallingFallbackDescription))); + + public static readonly DiagnosticDescriptor StackallocMarshallingShouldSupportAllocatingMarshallingFallbackRule = + new DiagnosticDescriptor( + Ids.StackallocMarshallingShouldSupportAllocatingMarshallingFallback, + "StackallocMarshallingShouldSupportAllocatingMarshallingFallback", + GetResourceString(nameof(Resources.StackallocMarshallingShouldSupportAllocatingMarshallingFallbackMessage)), + Category, + DiagnosticSeverity.Warning, + isEnabledByDefault: true, + description: GetResourceString(nameof(Resources.StackallocMarshallingShouldSupportAllocatingMarshallingFallbackDescription))); + + public static readonly DiagnosticDescriptor StackallocConstructorMustHaveStackBufferSizeConstantRule = + new DiagnosticDescriptor( + Ids.StackallocConstructorMustHaveStackBufferSizeConstant, + "StackallocConstructorMustHaveStackBufferSizeConstant", + GetResourceString(nameof(Resources.StackallocConstructorMustHaveStackBufferSizeConstantMessage)), + Category, + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: GetResourceString(nameof(Resources.StackallocConstructorMustHaveStackBufferSizeConstantDescription))); + + public static readonly DiagnosticDescriptor RefValuePropertyUnsupportedRule = + new DiagnosticDescriptor( + Ids.RefValuePropertyUnsupported, + "RefValuePropertyUnsupported", + GetResourceString(nameof(Resources.RefValuePropertyUnsupportedMessage)), + Category, + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: GetResourceString(nameof(Resources.RefValuePropertyUnsupportedDescription))); + + public static readonly DiagnosticDescriptor NativeGenericTypeMustBeClosedOrMatchArityRule = + new DiagnosticDescriptor( + Ids.NativeGenericTypeMustBeClosedOrMatchArity, + "NativeGenericTypeMustBeClosedOrMatchArity", + GetResourceString(nameof(Resources.NativeGenericTypeMustBeClosedOrMatchArityMessage)), + Category, + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: GetResourceString(nameof(Resources.NativeGenericTypeMustBeClosedOrMatchArityDescription))); + + public override ImmutableArray SupportedDiagnostics => + ImmutableArray.Create( + BlittableTypeMustBeBlittableRule, + CannotHaveMultipleMarshallingAttributesRule, + NativeTypeMustBeNonNullRule, + NativeTypeMustBeBlittableRule, + GetPinnableReferenceReturnTypeBlittableRule, + NativeTypeMustBePointerSizedRule, + NativeTypeMustHaveRequiredShapeRule, + CollectionNativeTypeMustHaveRequiredShapeRule, + ValuePropertyMustHaveSetterRule, + ValuePropertyMustHaveGetterRule, + GetPinnableReferenceShouldSupportAllocatingMarshallingFallbackRule, + StackallocMarshallingShouldSupportAllocatingMarshallingFallbackRule, + StackallocConstructorMustHaveStackBufferSizeConstantRule, + RefValuePropertyUnsupportedRule, + NativeGenericTypeMustBeClosedOrMatchArityRule); + + public override void Initialize(AnalysisContext context) + { + // Don't analyze generated code + context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); + context.EnableConcurrentExecution(); + context.RegisterCompilationStartAction(PrepareForAnalysis); + } + + private void PrepareForAnalysis(CompilationStartAnalysisContext context) + { + INamedTypeSymbol? generatedMarshallingAttribute = context.Compilation.GetTypeByMetadataName(TypeNames.GeneratedMarshallingAttribute); + INamedTypeSymbol? blittableTypeAttribute = context.Compilation.GetTypeByMetadataName(TypeNames.BlittableTypeAttribute); + INamedTypeSymbol? nativeMarshallingAttribute = context.Compilation.GetTypeByMetadataName(TypeNames.NativeMarshallingAttribute); + INamedTypeSymbol? marshalUsingAttribute = context.Compilation.GetTypeByMetadataName(TypeNames.MarshalUsingAttribute); + INamedTypeSymbol? genericContiguousCollectionMarshallerAttribute = context.Compilation.GetTypeByMetadataName(TypeNames.GenericContiguousCollectionMarshallerAttribute); + INamedTypeSymbol? spanOfByte = context.Compilation.GetTypeByMetadataName(TypeNames.System_Span_Metadata)!.Construct(context.Compilation.GetSpecialType(SpecialType.System_Byte)); + + if (generatedMarshallingAttribute is not null + && blittableTypeAttribute is not null + && nativeMarshallingAttribute is not null + && marshalUsingAttribute is not null + && genericContiguousCollectionMarshallerAttribute is not null + && spanOfByte is not null) + { + var perCompilationAnalyzer = new PerCompilationAnalyzer( + generatedMarshallingAttribute, + blittableTypeAttribute, + nativeMarshallingAttribute, + marshalUsingAttribute, + genericContiguousCollectionMarshallerAttribute, + spanOfByte, + context.Compilation.GetTypeByMetadataName(TypeNames.System_Runtime_InteropServices_StructLayoutAttribute)!); + context.RegisterSymbolAction(context => perCompilationAnalyzer.AnalyzeTypeDefinition(context), SymbolKind.NamedType); + context.RegisterSymbolAction(context => perCompilationAnalyzer.AnalyzeElement(context), SymbolKind.Parameter, SymbolKind.Field); + context.RegisterSymbolAction(context => perCompilationAnalyzer.AnalyzeReturnType(context), SymbolKind.Method); + } + } + + private class PerCompilationAnalyzer + { + private readonly INamedTypeSymbol _generatedMarshallingAttribute; + private readonly INamedTypeSymbol _blittableTypeAttribute; + private readonly INamedTypeSymbol _nativeMarshallingAttribute; + private readonly INamedTypeSymbol _marshalUsingAttribute; + private readonly INamedTypeSymbol _genericContiguousCollectionMarshallerAttribute; + private readonly INamedTypeSymbol _spanOfByte; + private readonly INamedTypeSymbol _structLayoutAttribute; + + public PerCompilationAnalyzer(INamedTypeSymbol generatedMarshallingAttribute, + INamedTypeSymbol blittableTypeAttribute, + INamedTypeSymbol nativeMarshallingAttribute, + INamedTypeSymbol marshalUsingAttribute, + INamedTypeSymbol genericContiguousCollectionMarshallerAttribute, + INamedTypeSymbol spanOfByte, + INamedTypeSymbol structLayoutAttribute) + { + _generatedMarshallingAttribute = generatedMarshallingAttribute; + _blittableTypeAttribute = blittableTypeAttribute; + _nativeMarshallingAttribute = nativeMarshallingAttribute; + _marshalUsingAttribute = marshalUsingAttribute; + _genericContiguousCollectionMarshallerAttribute = genericContiguousCollectionMarshallerAttribute; + _spanOfByte = spanOfByte; + _structLayoutAttribute = structLayoutAttribute; + } + + public void AnalyzeTypeDefinition(SymbolAnalysisContext context) + { + INamedTypeSymbol type = (INamedTypeSymbol)context.Symbol; + + AttributeData? blittableTypeAttributeData = null; + AttributeData? nativeMarshallingAttributeData = null; + foreach (AttributeData attr in type.GetAttributes()) + { + if (SymbolEqualityComparer.Default.Equals(attr.AttributeClass, _generatedMarshallingAttribute)) + { + // If the type has the GeneratedMarshallingAttribute, + // we let the source generator handle error checking. + return; + } + else if (SymbolEqualityComparer.Default.Equals(attr.AttributeClass, _blittableTypeAttribute)) + { + blittableTypeAttributeData = attr; + } + else if (SymbolEqualityComparer.Default.Equals(attr.AttributeClass, _nativeMarshallingAttribute)) + { + nativeMarshallingAttributeData = attr; + } + } + + if (HasMultipleMarshallingAttributes(blittableTypeAttributeData, nativeMarshallingAttributeData)) + { + context.ReportDiagnostic( + blittableTypeAttributeData!.CreateDiagnostic( + CannotHaveMultipleMarshallingAttributesRule, + type.ToDisplayString())); + } + else if (blittableTypeAttributeData is not null && (!type.HasOnlyBlittableFields() || type.IsAutoLayout(_structLayoutAttribute))) + { + context.ReportDiagnostic( + blittableTypeAttributeData.CreateDiagnostic( + BlittableTypeMustBeBlittableRule, + type.ToDisplayString())); + } + else if (nativeMarshallingAttributeData is not null) + { + AnalyzeNativeMarshalerType(context, type, nativeMarshallingAttributeData, isNativeMarshallingAttribute: true); + } + } + + private bool HasMultipleMarshallingAttributes(AttributeData? blittableTypeAttributeData, AttributeData? nativeMarshallingAttributeData) + { + return (blittableTypeAttributeData, nativeMarshallingAttributeData) switch + { + (null, null) => false, + (not null, null) => false, + (null, not null) => false, + _ => true + }; + } + + public void AnalyzeElement(SymbolAnalysisContext context) + { + AttributeData? attrData = context.Symbol.GetAttributes().FirstOrDefault(attr => SymbolEqualityComparer.Default.Equals(_marshalUsingAttribute, attr.AttributeClass)); + if (attrData is not null) + { + if (context.Symbol is IParameterSymbol param) + { + AnalyzeNativeMarshalerType(context, param.Type, attrData, isNativeMarshallingAttribute: false); + } + else if (context.Symbol is IFieldSymbol field) + { + AnalyzeNativeMarshalerType(context, field.Type, attrData, isNativeMarshallingAttribute: false); + } + } + } + + public void AnalyzeReturnType(SymbolAnalysisContext context) + { + var method = (IMethodSymbol)context.Symbol; + AttributeData? attrData = method.GetReturnTypeAttributes().FirstOrDefault(attr => SymbolEqualityComparer.Default.Equals(_marshalUsingAttribute, attr.AttributeClass)); + if (attrData is not null) + { + AnalyzeNativeMarshalerType(context, method.ReturnType, attrData, isNativeMarshallingAttribute: false); + } + } + + private void AnalyzeNativeMarshalerType(SymbolAnalysisContext context, ITypeSymbol type, AttributeData nativeMarshalerAttributeData, bool isNativeMarshallingAttribute) + { + if (nativeMarshalerAttributeData.ConstructorArguments.Length == 0) + { + // This is a MarshalUsing with just count information. + return; + } + + if (nativeMarshalerAttributeData.ConstructorArguments[0].IsNull) + { + context.ReportDiagnostic( + nativeMarshalerAttributeData.CreateDiagnostic( + NativeTypeMustBeNonNullRule, + type.ToDisplayString())); + return; + } + + ITypeSymbol nativeType = (ITypeSymbol)nativeMarshalerAttributeData.ConstructorArguments[0].Value!; + ISymbol nativeTypeDiagnosticsTargetSymbol = nativeType; + + if (nativeType is not INamedTypeSymbol marshalerType) + { + context.ReportDiagnostic( + GetDiagnosticLocations(context, nativeType, nativeMarshalerAttributeData).CreateDiagnostic( + NativeTypeMustHaveRequiredShapeRule, + nativeType.ToDisplayString(), + type.ToDisplayString())); + return; + } + + DiagnosticDescriptor requiredShapeRule = NativeTypeMustHaveRequiredShapeRule; + + ManualTypeMarshallingHelper.NativeTypeMarshallingVariant variant = ManualTypeMarshallingHelper.NativeTypeMarshallingVariant.Standard; + if (marshalerType.GetAttributes().Any(a => SymbolEqualityComparer.Default.Equals(_genericContiguousCollectionMarshallerAttribute, a.AttributeClass))) + { + variant = ManualTypeMarshallingHelper.NativeTypeMarshallingVariant.ContiguousCollection; + requiredShapeRule = CollectionNativeTypeMustHaveRequiredShapeRule; + if (!ManualTypeMarshallingHelper.TryGetManagedValuesProperty(marshalerType, out _) + || !ManualTypeMarshallingHelper.HasNativeValueStorageProperty(marshalerType, _spanOfByte)) + { + context.ReportDiagnostic( + GetDiagnosticLocations(context, marshalerType, nativeMarshalerAttributeData).CreateDiagnostic( + requiredShapeRule, + nativeType.ToDisplayString(), + type.ToDisplayString())); + return; + } + } + + if (!nativeType.IsValueType) + { + context.ReportDiagnostic( + GetDiagnosticLocations(context, nativeType, nativeMarshalerAttributeData).CreateDiagnostic( + requiredShapeRule, + nativeType.ToDisplayString(), + type.ToDisplayString())); + return; + } + + if (marshalerType.IsUnboundGenericType) + { + if (!isNativeMarshallingAttribute) + { + context.ReportDiagnostic( + nativeMarshalerAttributeData.CreateDiagnostic( + NativeGenericTypeMustBeClosedOrMatchArityRule, + nativeType.ToDisplayString(), + type.ToDisplayString())); + return; + } + if (type is not INamedTypeSymbol namedType || marshalerType.TypeArguments.Length != namedType.TypeArguments.Length) + { + context.ReportDiagnostic( + nativeMarshalerAttributeData.CreateDiagnostic( + NativeGenericTypeMustBeClosedOrMatchArityRule, + nativeType.ToDisplayString(), + type.ToDisplayString())); + return; + } + // Construct the marshaler type around the same type arguments as the managed type. + nativeType = marshalerType = marshalerType.ConstructedFrom.Construct(namedType.TypeArguments, namedType.TypeArgumentNullableAnnotations); + } + + bool hasConstructor = false; + bool hasStackallocConstructor = false; + foreach (IMethodSymbol ctor in marshalerType.Constructors) + { + if (ctor.IsStatic) + { + continue; + } + + hasConstructor = hasConstructor || ManualTypeMarshallingHelper.IsManagedToNativeConstructor(ctor, type, variant); + + if (!hasStackallocConstructor && ManualTypeMarshallingHelper.IsStackallocConstructor(ctor, type, _spanOfByte, variant)) + { + hasStackallocConstructor = true; + IFieldSymbol stackAllocSizeField = nativeType.GetMembers("StackBufferSize").OfType().FirstOrDefault(); + if (stackAllocSizeField is null or { DeclaredAccessibility: not Accessibility.Public } or { IsConst: false } or { Type: not { SpecialType: SpecialType.System_Int32 } }) + { + context.ReportDiagnostic( + GetDiagnosticLocations(context, ctor, nativeMarshalerAttributeData).CreateDiagnostic( + StackallocConstructorMustHaveStackBufferSizeConstantRule, + nativeType.ToDisplayString())); + } + } + } + + bool hasToManaged = ManualTypeMarshallingHelper.HasToManagedMethod(marshalerType, type); + + // Validate that the native type has at least one marshalling method (either managed to native or native to managed) + if (!hasConstructor && !hasStackallocConstructor && !hasToManaged) + { + context.ReportDiagnostic( + GetDiagnosticLocations(context, marshalerType, nativeMarshalerAttributeData).CreateDiagnostic( + requiredShapeRule, + marshalerType.ToDisplayString(), + type.ToDisplayString())); + } + + // Validate that this type can support marshalling when stackalloc is not usable. + if (isNativeMarshallingAttribute && hasStackallocConstructor && !hasConstructor) + { + context.ReportDiagnostic( + GetDiagnosticLocations(context, marshalerType, nativeMarshalerAttributeData).CreateDiagnostic( + StackallocMarshallingShouldSupportAllocatingMarshallingFallbackRule, + marshalerType.ToDisplayString())); + } + + IPropertySymbol? valueProperty = ManualTypeMarshallingHelper.FindValueProperty(nativeType); + bool valuePropertyIsRefReturn = valueProperty is { ReturnsByRef: true } or { ReturnsByRefReadonly: true }; + + if (valueProperty is not null) + { + if (valuePropertyIsRefReturn) + { + context.ReportDiagnostic( + GetDiagnosticLocations(context, valueProperty, nativeMarshalerAttributeData).CreateDiagnostic( + RefValuePropertyUnsupportedRule, + marshalerType.ToDisplayString())); + } + + nativeType = valueProperty.Type; + nativeTypeDiagnosticsTargetSymbol = valueProperty; + + // Validate that we don't have partial implementations. + // We error if either of the conditions below are partially met but not fully met: + // - a constructor and a Value property getter + // - a ToManaged method and a Value property setter + if ((hasConstructor || hasStackallocConstructor) && valueProperty.GetMethod is null) + { + context.ReportDiagnostic( + GetDiagnosticLocations(context, valueProperty, nativeMarshalerAttributeData).CreateDiagnostic( + ValuePropertyMustHaveGetterRule, + marshalerType.ToDisplayString())); + } + if (hasToManaged && valueProperty.SetMethod is null) + { + context.ReportDiagnostic( + GetDiagnosticLocations(context, valueProperty, nativeMarshalerAttributeData).CreateDiagnostic( + ValuePropertyMustHaveSetterRule, + marshalerType.ToDisplayString())); + } + } + + if (!nativeType.IsConsideredBlittable()) + { + context.ReportDiagnostic( + GetDiagnosticLocations(context, nativeTypeDiagnosticsTargetSymbol, nativeMarshalerAttributeData).CreateDiagnostic( + NativeTypeMustBeBlittableRule, + nativeType.ToDisplayString(), + type.ToDisplayString())); + } + + // Use a tuple here instead of an anonymous type so we can do the reassignment and pattern matching below. + var getPinnableReferenceMethods = new + { + Managed = isNativeMarshallingAttribute ? ManualTypeMarshallingHelper.FindGetPinnableReference(type) : null, + Marshaler = ManualTypeMarshallingHelper.FindGetPinnableReference(marshalerType) + }; + + if (getPinnableReferenceMethods.Managed is not null) + { + if (!getPinnableReferenceMethods.Managed.ReturnType.IsConsideredBlittable()) + { + context.ReportDiagnostic(getPinnableReferenceMethods.Managed.CreateDiagnostic(GetPinnableReferenceReturnTypeBlittableRule)); + } + // Validate that our marshaler supports scenarios where GetPinnableReference cannot be used. + if (isNativeMarshallingAttribute && (!hasConstructor || valueProperty is { GetMethod: null })) + { + context.ReportDiagnostic( + nativeMarshalerAttributeData.CreateDiagnostic( + GetPinnableReferenceShouldSupportAllocatingMarshallingFallbackRule, + type.ToDisplayString())); + } + } + + if ((getPinnableReferenceMethods.Managed is not null + || getPinnableReferenceMethods.Marshaler is not null) + && !valuePropertyIsRefReturn // Ref returns are already reported above as invalid, so don't issue another warning here about them + && nativeType is not ( + IPointerTypeSymbol _ or + { SpecialType: SpecialType.System_IntPtr } or + { SpecialType: SpecialType.System_UIntPtr })) + { + IMethodSymbol getPinnableReferenceMethodToMention = getPinnableReferenceMethods.Managed ?? getPinnableReferenceMethods.Marshaler!; + + context.ReportDiagnostic( + GetDiagnosticLocations(context, nativeTypeDiagnosticsTargetSymbol, nativeMarshalerAttributeData).CreateDiagnostic( + NativeTypeMustBePointerSizedRule, + nativeType.ToDisplayString(), + getPinnableReferenceMethodToMention.ContainingType.ToDisplayString())); + } + } + + private ImmutableArray GetDiagnosticLocations(SymbolAnalysisContext context, ISymbol targetSymbol, AttributeData marshallingAttribute) + { + // If we're using a compilation that references another compilation, the symbol locations can be in source in the wrong compilation, + // which can cause exceptions when reporting diagnostics. Make sure the symbol is defined in the current Compilation's source module before using its locations. + // If the symbol is not defined in the current Compilation's source module, report the diagnostic at the marshalling attribute's location. + if (SymbolEqualityComparer.Default.Equals(context.Compilation.SourceModule, targetSymbol.ContainingModule)) + { + return targetSymbol.Locations; + } + return ImmutableArray.Create(marshallingAttribute.ApplicationSyntaxReference?.GetSyntax().GetLocation() ?? Location.None); + } + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/Comparers.cs b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/Comparers.cs new file mode 100644 index 0000000000000..71ecae6a88860 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/Comparers.cs @@ -0,0 +1,98 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; + +namespace Microsoft.Interop +{ + internal static class Comparers + { + /// + /// Comparer for the set of all of the generated stubs and diagnostics generated for each of them. + /// + public static readonly IEqualityComparer)>> GeneratedSourceSet = new ImmutableArraySequenceEqualComparer<(string, ImmutableArray)>(new CustomValueTupleElementComparer>(EqualityComparer.Default, new ImmutableArraySequenceEqualComparer(EqualityComparer.Default))); + + /// + /// Comparer for an individual generated stub source as a string and the generated diagnostics for the stub. + /// + public static readonly IEqualityComparer<(string, ImmutableArray)> GeneratedSource = new CustomValueTupleElementComparer>(EqualityComparer.Default, new ImmutableArraySequenceEqualComparer(EqualityComparer.Default)); + + /// + /// Comparer for an individual generated stub source as a syntax tree and the generated diagnostics for the stub. + /// + public static readonly IEqualityComparer<(MemberDeclarationSyntax Syntax, ImmutableArray Diagnostics)> GeneratedSyntax = new CustomValueTupleElementComparer>(new SyntaxEquivalentComparer(), new ImmutableArraySequenceEqualComparer(EqualityComparer.Default)); + + /// + /// Comparer for the context used to generate a stub and the original user-provided syntax that triggered stub creation. + /// + public static readonly IEqualityComparer<(MethodDeclarationSyntax Syntax, DllImportGenerator.IncrementalStubGenerationContext StubContext)> CalculatedContextWithSyntax = new CustomValueTupleElementComparer(new SyntaxEquivalentComparer(), EqualityComparer.Default); + } + + /// + /// Generic comparer to compare two instances element by element. + /// + /// The type of immutable array element. + internal class ImmutableArraySequenceEqualComparer : IEqualityComparer> + { + private readonly IEqualityComparer _elementComparer; + + /// + /// Creates an with a custom comparer for the elements of the collection. + /// + /// The comparer instance for the collection elements. + public ImmutableArraySequenceEqualComparer(IEqualityComparer elementComparer) + { + _elementComparer = elementComparer; + } + + public bool Equals(ImmutableArray x, ImmutableArray y) + { + return x.SequenceEqual(y, _elementComparer); + } + + public int GetHashCode(ImmutableArray obj) + { + throw new UnreachableException(); + } + } + + internal class SyntaxEquivalentComparer : IEqualityComparer + { + public bool Equals(SyntaxNode x, SyntaxNode y) + { + return x.IsEquivalentTo(y); + } + + public int GetHashCode(SyntaxNode obj) + { + throw new UnreachableException(); + } + } + + internal class CustomValueTupleElementComparer : IEqualityComparer<(T, U)> + { + private readonly IEqualityComparer _item1Comparer; + private readonly IEqualityComparer _item2Comparer; + + public CustomValueTupleElementComparer(IEqualityComparer item1Comparer, IEqualityComparer item2Comparer) + { + _item1Comparer = item1Comparer; + _item2Comparer = item2Comparer; + } + + public bool Equals((T, U) x, (T, U) y) + { + return _item1Comparer.Equals(x.Item1, y.Item1) && _item2Comparer.Equals(x.Item2, y.Item2); + } + + public int GetHashCode((T, U) obj) + { + throw new UnreachableException(); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/Diagnostics/Events.cs b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/Diagnostics/Events.cs new file mode 100644 index 0000000000000..785d253bdcd9e --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/Diagnostics/Events.cs @@ -0,0 +1,66 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Diagnostics.Tracing; + +namespace Microsoft.Interop.Diagnostics +{ + [EventSource(Name = "Microsoft-Interop-SourceGeneration-Events")] + internal sealed class Events : EventSource + { + public static class Keywords + { + public const EventKeywords SourceGeneration = (EventKeywords)1; + } + + public static readonly Events Logger = new Events(); + + private const int StartSourceGenerationEventId = 1; + private const int StopSourceGenerationEventId = StartSourceGenerationEventId + 1; + + private Events() + { } + + /// + /// Utility function that wraps emitting start/stop events for the source generation event. + /// + /// The number of methods being generated + /// An instance that will fire the "stop" event when Disposed. + [NonEvent] + public static IDisposable SourceGenerationStartStop(int methodCount) + { + return new StartStopEvent(methodCount); + } + + // N.B. The 'Start' and 'Stop' suffixes for event names (i.e. "xxxStart" and "xxxStop") + // have special meaning in EventSource. They enable creating 'activities' if they are + // paired and the Stop event's ID is +1 the Start event's ID. + // See https://blogs.msdn.microsoft.com/vancem/2015/09/14/exploring-eventsource-activity-correlation-and-causation-features/ + + /// + /// Indicates the interop's DllImport Roslyn Source Generator has started source generation. + /// + /// The number of methods being generated + [Event(StartSourceGenerationEventId, Level = EventLevel.Informational, Keywords = Keywords.SourceGeneration)] + public void SourceGenerationStart(int methodCount) + { + WriteEvent(StartSourceGenerationEventId, methodCount); + } + + /// + /// Indicates the interop's DllImport Roslyn Source Generator has stopped source generation. + /// + [Event(StopSourceGenerationEventId, Level = EventLevel.Informational, Keywords = Keywords.SourceGeneration)] + public void SourceGenerationStop() + { + WriteEvent(StopSourceGenerationEventId); + } + + private class StartStopEvent : IDisposable + { + public StartStopEvent(int methodCount) => Logger.SourceGenerationStart(methodCount); + public void Dispose() => Logger.SourceGenerationStop(); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/DllImportGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/DllImportGenerator.cs new file mode 100644 index 0000000000000..dcc977e49d581 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/DllImportGenerator.cs @@ -0,0 +1,683 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; + +[assembly: System.Resources.NeutralResourcesLanguage("en-US")] + +namespace Microsoft.Interop +{ + [Generator] + public sealed class DllImportGenerator : IIncrementalGenerator + { + private const string GeneratedDllImport = nameof(GeneratedDllImport); + private const string GeneratedDllImportAttribute = nameof(GeneratedDllImportAttribute); + + private static readonly Version s_minimumSupportedFrameworkVersion = new Version(5, 0); + + internal sealed record IncrementalStubGenerationContext(DllImportStubContext StubContext, ImmutableArray ForwardedAttributes, GeneratedDllImportData DllImportData, ImmutableArray Diagnostics) + { + public bool Equals(IncrementalStubGenerationContext? other) + { + return other is not null + && StubContext.Equals(other.StubContext) + && DllImportData.Equals(other.DllImportData) + && ForwardedAttributes.SequenceEqual(other.ForwardedAttributes, (IEqualityComparer)new SyntaxEquivalentComparer()) + && Diagnostics.SequenceEqual(other.Diagnostics); + } + + public override int GetHashCode() + { + throw new UnreachableException(); + } + } + + public class IncrementalityTracker + { + public enum StepName + { + CalculateStubInformation, + GenerateSingleStub, + NormalizeWhitespace, + ConcatenateStubs, + OutputSourceFile + } + + public record ExecutedStepInfo(StepName Step, object Input); + + private readonly List _executedSteps = new(); + public IEnumerable ExecutedSteps => _executedSteps; + + internal void RecordExecutedStep(ExecutedStepInfo step) => _executedSteps.Add(step); + } + + /// + /// This property provides a test-only hook to enable testing the incrementality of the source generator. + /// This will be removed when https://github.com/dotnet/roslyn/issues/54832 is implemented and can be consumed. + /// + public IncrementalityTracker? IncrementalTracker { get; set; } + + public void Initialize(IncrementalGeneratorInitializationContext context) + { + var methodsToGenerate = context.SyntaxProvider + .CreateSyntaxProvider( + static (node, ct) => ShouldVisitNode(node), + static (context, ct) => + new + { + Syntax = (MethodDeclarationSyntax)context.Node, + Symbol = (IMethodSymbol)context.SemanticModel.GetDeclaredSymbol(context.Node, ct)! + }) + .Where( + static modelData => modelData.Symbol.IsStatic && modelData.Symbol.GetAttributes().Any( + static attribute => attribute.AttributeClass?.ToDisplayString() == TypeNames.GeneratedDllImportAttribute) + ); + + IncrementalValueProvider<(Compilation compilation, bool isSupported, Version targetFrameworkVersion)> compilationAndTargetFramework = context.CompilationProvider + .Select(static (compilation, ct) => + { + bool isSupported = IsSupportedTargetFramework(compilation, out Version targetFrameworkVersion); + return (compilation, isSupported, targetFrameworkVersion); + }); + + context.RegisterSourceOutput( + compilationAndTargetFramework + .Combine(methodsToGenerate.Collect()), + static (context, data) => + { + if (!data.Left.isSupported && data.Right.Any()) + { + // We don't block source generation when the TFM is unsupported. + // This allows a user to copy generated source and use it as a starting point + // for manual marshalling if desired. + context.ReportDiagnostic( + Diagnostic.Create( + GeneratorDiagnostics.TargetFrameworkNotSupported, + Location.None, + s_minimumSupportedFrameworkVersion.ToString(2))); + } + }); + + IncrementalValueProvider stubOptions = context.AnalyzerConfigOptionsProvider + .Select((options, ct) => new DllImportGeneratorOptions(options.GlobalOptions)); + + IncrementalValueProvider stubEnvironment = compilationAndTargetFramework + .Combine(stubOptions) + .Select( + static (data, ct) => + new StubEnvironment( + data.Left.compilation, + data.Left.isSupported, + data.Left.targetFrameworkVersion, + data.Left.compilation.SourceModule.GetAttributes().Any(attr => attr.AttributeClass?.ToDisplayString() == TypeNames.System_Runtime_CompilerServices_SkipLocalsInitAttribute), + data.Right) + ); + + IncrementalValueProvider<(string, ImmutableArray)> methodSourceAndDiagnostics = methodsToGenerate + .Combine(stubEnvironment) + .Select(static (data, ct) => new + { + data.Left.Syntax, + data.Left.Symbol, + Environment = data.Right + }) + .Select( + (data, ct) => + { + IncrementalTracker?.RecordExecutedStep(new IncrementalityTracker.ExecutedStepInfo(IncrementalityTracker.StepName.CalculateStubInformation, data)); + return (data.Syntax, StubContext: CalculateStubInformation(data.Syntax, data.Symbol, data.Environment, ct)); + } + ) + .WithComparer(Comparers.CalculatedContextWithSyntax) + .Combine(stubOptions) + .Select( + (data, ct) => + { + IncrementalTracker?.RecordExecutedStep(new IncrementalityTracker.ExecutedStepInfo(IncrementalityTracker.StepName.GenerateSingleStub, data)); + return GenerateSource(data.Left.StubContext, data.Left.Syntax, data.Right); + } + ) + .WithComparer(Comparers.GeneratedSyntax) + // Handle NormalizeWhitespace as a separate stage for incremental runs since it is an expensive operation. + .Select( + (data, ct) => + { + IncrementalTracker?.RecordExecutedStep(new IncrementalityTracker.ExecutedStepInfo(IncrementalityTracker.StepName.NormalizeWhitespace, data)); + return (data.Item1.NormalizeWhitespace().ToFullString(), data.Item2); + }) + .Collect() + .WithComparer(Comparers.GeneratedSourceSet) + .Select((generatedSources, ct) => + { + IncrementalTracker?.RecordExecutedStep(new IncrementalityTracker.ExecutedStepInfo(IncrementalityTracker.StepName.ConcatenateStubs, generatedSources)); + StringBuilder source = new(); + // Mark in source that the file is auto-generated. + source.AppendLine("// "); + ImmutableArray.Builder diagnostics = ImmutableArray.CreateBuilder(); + foreach ((string, ImmutableArray) generated in generatedSources) + { + source.AppendLine(generated.Item1); + diagnostics.AddRange(generated.Item2); + } + return (source: source.ToString(), diagnostics: diagnostics.ToImmutable()); + }) + .WithComparer(Comparers.GeneratedSource); + + context.RegisterSourceOutput(methodSourceAndDiagnostics, + (context, data) => + { + IncrementalTracker?.RecordExecutedStep(new IncrementalityTracker.ExecutedStepInfo(IncrementalityTracker.StepName.OutputSourceFile, data)); + foreach (Diagnostic diagnostic in data.Item2) + { + context.ReportDiagnostic(diagnostic); + } + + context.AddSource("GeneratedDllImports.g.cs", data.Item1); + }); + } + + private static List GenerateSyntaxForForwardedAttributes(AttributeData? suppressGCTransitionAttribute, AttributeData? unmanagedCallConvAttribute) + { + const string CallConvsField = "CallConvs"; + // Manually rehydrate the forwarded attributes with fully qualified types so we don't have to worry about any using directives. + List attributes = new(); + + if (suppressGCTransitionAttribute is not null) + { + attributes.Add(Attribute(ParseName(TypeNames.SuppressGCTransitionAttribute))); + } + if (unmanagedCallConvAttribute is not null) + { + AttributeSyntax unmanagedCallConvSyntax = Attribute(ParseName(TypeNames.UnmanagedCallConvAttribute)); + foreach (KeyValuePair arg in unmanagedCallConvAttribute.NamedArguments) + { + if (arg.Key == CallConvsField) + { + InitializerExpressionSyntax callConvs = InitializerExpression(SyntaxKind.ArrayInitializerExpression); + foreach (TypedConstant callConv in arg.Value.Values) + { + callConvs = callConvs.AddExpressions( + TypeOfExpression(((ITypeSymbol)callConv.Value!).AsTypeSyntax())); + } + + ArrayTypeSyntax arrayOfSystemType = ArrayType(ParseTypeName(TypeNames.System_Type), SingletonList(ArrayRankSpecifier())); + + unmanagedCallConvSyntax = unmanagedCallConvSyntax.AddArgumentListArguments( + AttributeArgument( + ArrayCreationExpression(arrayOfSystemType) + .WithInitializer(callConvs)) + .WithNameEquals(NameEquals(IdentifierName(CallConvsField)))); + } + } + attributes.Add(unmanagedCallConvSyntax); + } + return attributes; + } + + private static SyntaxTokenList StripTriviaFromModifiers(SyntaxTokenList tokenList) + { + SyntaxToken[] strippedTokens = new SyntaxToken[tokenList.Count]; + for (int i = 0; i < tokenList.Count; i++) + { + strippedTokens[i] = tokenList[i].WithoutTrivia(); + } + return new SyntaxTokenList(strippedTokens); + } + + private static TypeDeclarationSyntax CreateTypeDeclarationWithoutTrivia(TypeDeclarationSyntax typeDeclaration) + { + return TypeDeclaration( + typeDeclaration.Kind(), + typeDeclaration.Identifier) + .WithTypeParameterList(typeDeclaration.TypeParameterList) + .WithModifiers(typeDeclaration.Modifiers); + } + + private static MemberDeclarationSyntax PrintGeneratedSource( + MethodDeclarationSyntax userDeclaredMethod, + DllImportStubContext stub, + BlockSyntax stubCode) + { + // Create stub function + MethodDeclarationSyntax stubMethod = MethodDeclaration(stub.StubReturnType, userDeclaredMethod.Identifier) + .AddAttributeLists(stub.AdditionalAttributes.ToArray()) + .WithModifiers(StripTriviaFromModifiers(userDeclaredMethod.Modifiers)) + .WithParameterList(ParameterList(SeparatedList(stub.StubParameters))) + .WithBody(stubCode); + + // Stub should have at least one containing type + Debug.Assert(stub.StubContainingTypes.Any()); + + // Add stub function and DllImport declaration to the first (innermost) containing + MemberDeclarationSyntax containingType = CreateTypeDeclarationWithoutTrivia(stub.StubContainingTypes.First()) + .AddMembers(stubMethod); + + // Add type to the remaining containing types (skipping the first which was handled above) + foreach (TypeDeclarationSyntax typeDecl in stub.StubContainingTypes.Skip(1)) + { + containingType = CreateTypeDeclarationWithoutTrivia(typeDecl) + .WithMembers(SingletonList(containingType)); + } + + MemberDeclarationSyntax toPrint = containingType; + + // Add type to the containing namespace + if (stub.StubTypeNamespace is not null) + { + toPrint = NamespaceDeclaration(IdentifierName(stub.StubTypeNamespace)) + .AddMembers(toPrint); + } + + return toPrint; + } + + private static bool IsSupportedTargetFramework(Compilation compilation, out Version version) + { + IAssemblySymbol systemAssembly = compilation.GetSpecialType(SpecialType.System_Object).ContainingAssembly; + version = systemAssembly.Identity.Version; + + return systemAssembly.Identity.Name switch + { + // .NET Framework + "mscorlib" => false, + // .NET Standard + "netstandard" => false, + // .NET Core (when version < 5.0) or .NET + "System.Runtime" or "System.Private.CoreLib" => version >= s_minimumSupportedFrameworkVersion, + _ => false, + }; + } + + private static GeneratedDllImportData ProcessGeneratedDllImportAttribute(AttributeData attrData) + { + // Found the GeneratedDllImport, but it has an error so report the error. + // This is most likely an issue with targeting an incorrect TFM. + if (attrData.AttributeClass?.TypeKind is null or TypeKind.Error) + { + // [TODO] Report GeneratedDllImport has an error - corrupt metadata? + throw new InvalidProgramException(); + } + + + // Default values for these properties are based on the + // 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; + + var stubDllImportData = new GeneratedDllImportData(attrData.ConstructorArguments[0].Value!.ToString()); + + // All other data on attribute is defined as NamedArguments. + foreach (KeyValuePair namedArg in attrData.NamedArguments) + { + switch (namedArg.Key) + { + 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!; + break; + case nameof(GeneratedDllImportData.EntryPoint): + userDefinedValues |= DllImportMember.EntryPoint; + entryPoint = (string)namedArg.Value.Value!; + break; + case nameof(GeneratedDllImportData.ExactSpelling): + userDefinedValues |= DllImportMember.ExactSpelling; + exactSpelling = (bool)namedArg.Value.Value!; + break; + case nameof(GeneratedDllImportData.PreserveSig): + userDefinedValues |= DllImportMember.PreserveSig; + preserveSig = (bool)namedArg.Value.Value!; + break; + case nameof(GeneratedDllImportData.SetLastError): + 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 + }; + } + + private static IncrementalStubGenerationContext CalculateStubInformation(MethodDeclarationSyntax syntax, IMethodSymbol symbol, StubEnvironment environment, CancellationToken ct) + { + INamedTypeSymbol? lcidConversionAttrType = environment.Compilation.GetTypeByMetadataName(TypeNames.LCIDConversionAttribute); + INamedTypeSymbol? suppressGCTransitionAttrType = environment.Compilation.GetTypeByMetadataName(TypeNames.SuppressGCTransitionAttribute); + INamedTypeSymbol? unmanagedCallConvAttrType = environment.Compilation.GetTypeByMetadataName(TypeNames.UnmanagedCallConvAttribute); + // Get any attributes of interest on the method + AttributeData? generatedDllImportAttr = null; + AttributeData? lcidConversionAttr = null; + AttributeData? suppressGCTransitionAttribute = null; + AttributeData? unmanagedCallConvAttribute = null; + foreach (AttributeData attr in symbol.GetAttributes()) + { + if (attr.AttributeClass is not null + && attr.AttributeClass.ToDisplayString() == TypeNames.GeneratedDllImportAttribute) + { + generatedDllImportAttr = attr; + } + else if (lcidConversionAttrType != null && SymbolEqualityComparer.Default.Equals(attr.AttributeClass, lcidConversionAttrType)) + { + lcidConversionAttr = attr; + } + else if (suppressGCTransitionAttrType != null && SymbolEqualityComparer.Default.Equals(attr.AttributeClass, suppressGCTransitionAttrType)) + { + suppressGCTransitionAttribute = attr; + } + else if (unmanagedCallConvAttrType != null && SymbolEqualityComparer.Default.Equals(attr.AttributeClass, unmanagedCallConvAttrType)) + { + unmanagedCallConvAttribute = attr; + } + } + + Debug.Assert(generatedDllImportAttr is not null); + + var generatorDiagnostics = new GeneratorDiagnostics(); + + // 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 additionalAttributes = GenerateSyntaxForForwardedAttributes(suppressGCTransitionAttribute, unmanagedCallConvAttribute); + + // Create the stub. + var dllImportStub = DllImportStubContext.Create(symbol, stubDllImportData, environment, generatorDiagnostics, ct); + + return new IncrementalStubGenerationContext(dllImportStub, additionalAttributes.ToImmutableArray(), stubDllImportData, generatorDiagnostics.Diagnostics.ToImmutableArray()); + } + + private (MemberDeclarationSyntax, ImmutableArray) GenerateSource( + IncrementalStubGenerationContext dllImportStub, + MethodDeclarationSyntax originalSyntax, + DllImportGeneratorOptions options) + { + var diagnostics = new GeneratorDiagnostics(); + + // Generate stub code + var stubGenerator = new PInvokeStubCodeGenerator( + dllImportStub.StubContext.ElementTypeInformation, + dllImportStub.DllImportData.SetLastError && !options.GenerateForwarders, + (elementInfo, ex) => diagnostics.ReportMarshallingNotSupported(originalSyntax, elementInfo, ex.NotSupportedDetails), + dllImportStub.StubContext.GeneratorFactory); + + ImmutableArray forwardedAttributes = dllImportStub.ForwardedAttributes; + + const string innerPInvokeName = "__PInvoke__"; + + BlockSyntax code = stubGenerator.GeneratePInvokeBody(innerPInvokeName); + + LocalFunctionStatementSyntax dllImport = CreateTargetFunctionAsLocalStatement( + stubGenerator, + dllImportStub.StubContext.Options, + dllImportStub.DllImportData, + innerPInvokeName, + originalSyntax.Identifier.Text); + + if (!forwardedAttributes.IsEmpty) + { + dllImport = dllImport.AddAttributeLists(AttributeList(SeparatedList(forwardedAttributes))); + } + + code = code.AddStatements(dllImport); + + return (PrintGeneratedSource(originalSyntax, dllImportStub.StubContext, code), dllImportStub.Diagnostics.AddRange(diagnostics.Diagnostics)); + } + + + private static LocalFunctionStatementSyntax CreateTargetFunctionAsLocalStatement( + PInvokeStubCodeGenerator stubGenerator, + DllImportGeneratorOptions options, + GeneratedDllImportData dllImportData, + string stubTargetName, + string stubMethodName) + { + (ParameterListSyntax parameterList, TypeSyntax returnType, AttributeListSyntax returnTypeAttributes) = stubGenerator.GenerateTargetMethodSignatureData(); + LocalFunctionStatementSyntax localDllImport = LocalFunctionStatement(returnType, stubTargetName) + .AddModifiers( + Token(SyntaxKind.ExternKeyword), + Token(SyntaxKind.StaticKeyword), + Token(SyntaxKind.UnsafeKeyword)) + .WithSemicolonToken(Token(SyntaxKind.SemicolonToken)) + .WithAttributeLists( + SingletonList(AttributeList( + SingletonSeparatedList( + CreateDllImportAttributeForTarget( + GetTargetDllImportDataFromStubData( + dllImportData, + stubMethodName, + options.GenerateForwarders)))))) + .WithParameterList(parameterList); + if (returnTypeAttributes is not null) + { + localDllImport = localDllImport.AddAttributeLists(returnTypeAttributes.WithTarget(AttributeTargetSpecifier(Token(SyntaxKind.ReturnKeyword)))); + } + return localDllImport; + } + + private static AttributeSyntax CreateDllImportAttributeForTarget(GeneratedDllImportData targetDllImportData) + { + var newAttributeArgs = new List + { + AttributeArgument(LiteralExpression( + SyntaxKind.StringLiteralExpression, + Literal(targetDllImportData.ModuleName))), + AttributeArgument( + NameEquals(nameof(DllImportAttribute.EntryPoint)), + null, + 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 = CreateEnumExpressionSyntax(targetDllImportData.CharSet); + newAttributeArgs.Add(AttributeArgument(name, null, value)); + } + if (targetDllImportData.IsUserDefined.HasFlag(DllImportMember.ExactSpelling)) + { + NameEqualsSyntax name = NameEquals(nameof(DllImportAttribute.ExactSpelling)); + ExpressionSyntax value = CreateBoolExpressionSyntax(targetDllImportData.ExactSpelling); + newAttributeArgs.Add(AttributeArgument(name, null, value)); + } + if (targetDllImportData.IsUserDefined.HasFlag(DllImportMember.PreserveSig)) + { + NameEqualsSyntax name = NameEquals(nameof(DllImportAttribute.PreserveSig)); + ExpressionSyntax value = CreateBoolExpressionSyntax(targetDllImportData.PreserveSig); + newAttributeArgs.Add(AttributeArgument(name, null, value)); + } + if (targetDllImportData.IsUserDefined.HasFlag(DllImportMember.SetLastError)) + { + NameEqualsSyntax name = NameEquals(nameof(DllImportAttribute.SetLastError)); + 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( + ParseName(typeof(DllImportAttribute).FullName), + AttributeArgumentList(SeparatedList(newAttributeArgs))); + + static ExpressionSyntax CreateBoolExpressionSyntax(bool trueOrFalse) + { + return LiteralExpression( + trueOrFalse + ? SyntaxKind.TrueLiteralExpression + : SyntaxKind.FalseLiteralExpression); + } + + static ExpressionSyntax CreateStringExpressionSyntax(string str) + { + return LiteralExpression( + SyntaxKind.StringLiteralExpression, + Literal(str)); + } + + static ExpressionSyntax CreateEnumExpressionSyntax(T value) where T : Enum + { + return MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + IdentifierName(typeof(T).FullName), + IdentifierName(value.ToString())); + } + } + + private static GeneratedDllImportData GetTargetDllImportDataFromStubData(GeneratedDllImportData dllImportData, string originalMethodName, bool forwardAll) + { + DllImportMember membersToForward = DllImportMember.All + // https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.dllimportattribute.preservesig + // If PreserveSig=false (default is true), the P/Invoke stub checks/converts a returned HRESULT to an exception. + & ~DllImportMember.PreserveSig + // https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.dllimportattribute.setlasterror + // If SetLastError=true (default is false), the P/Invoke stub gets/caches the last error after invoking the native function. + & ~DllImportMember.SetLastError; + if (forwardAll) + { + membersToForward = DllImportMember.All; + } + + 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 + }; + + // If the EntryPoint property is not set, we will compute and + // add it based on existing semantics (i.e. method name). + // + // N.B. The export discovery logic is identical regardless of where + // the name is defined (i.e. method name vs EntryPoint property). + if (!targetDllImportData.IsUserDefined.HasFlag(DllImportMember.EntryPoint)) + { + targetDllImportData = targetDllImportData with { EntryPoint = originalMethodName }; + } + + return targetDllImportData; + } + + private static bool ShouldVisitNode(SyntaxNode syntaxNode) + { + // We only support C# method declarations. + if (syntaxNode.Language != LanguageNames.CSharp + || !syntaxNode.IsKind(SyntaxKind.MethodDeclaration)) + { + return false; + } + + var methodSyntax = (MethodDeclarationSyntax)syntaxNode; + + // Verify the method has no generic types or defined implementation + // and is marked static and partial. + if (methodSyntax.TypeParameterList is not null + || methodSyntax.Body is not null + || !methodSyntax.Modifiers.Any(SyntaxKind.StaticKeyword) + || !methodSyntax.Modifiers.Any(SyntaxKind.PartialKeyword)) + { + return false; + } + + // Verify that the types the method is declared in are marked partial. + for (SyntaxNode? parentNode = methodSyntax.Parent; parentNode is TypeDeclarationSyntax typeDecl; parentNode = parentNode.Parent) + { + if (!typeDecl.Modifiers.Any(SyntaxKind.PartialKeyword)) + { + return false; + } + } + + // Filter out methods with no attributes early. + if (methodSyntax.AttributeLists.Count == 0) + { + return false; + } + + return true; + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/DllImportGenerator.csproj b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/DllImportGenerator.csproj new file mode 100644 index 0000000000000..0648253ef2c94 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/DllImportGenerator.csproj @@ -0,0 +1,72 @@ + + + + Microsoft.Interop.DllImportGenerator + netstandard2.0 + false + true + True + true + Preview + enable + Microsoft.Interop + true + true + + + + Microsoft + https://github.com/dotnet/runtimelab/tree/feature/DllImportGenerator + https://github.com/dotnet/runtimelab/tree/feature/DllImportGenerator + false + DllImportGenerator + Summary of changes made in this release of the package. + Copyright + DllImportGenerator, analyzers + true + + + + https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet5/nuget/v3/index.json ;$(RestoreAdditionalProjectSources) + + + + + + + + + + + + + + + + + + + True + True + Resources.resx + + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + + + + + + + + + + diff --git a/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/DllImportGeneratorOptions.cs b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/DllImportGeneratorOptions.cs new file mode 100644 index 0000000000000..4e7f296e4d8d2 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/DllImportGeneratorOptions.cs @@ -0,0 +1,35 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.CodeAnalysis.Diagnostics; + +namespace Microsoft.Interop +{ + internal record DllImportGeneratorOptions(bool GenerateForwarders, bool UseMarshalType, bool UseInternalUnsafeType) + { + public DllImportGeneratorOptions(AnalyzerConfigOptions options) + : this(options.GenerateForwarders(), options.UseMarshalType(), options.UseInternalUnsafeType()) + { + } + } + + public static class OptionsHelper + { + public const string UseMarshalTypeOption = "build_property.DllImportGenerator_UseMarshalType"; + public const string GenerateForwardersOption = "build_property.DllImportGenerator_GenerateForwarders"; + public const string UseInternalUnsafeTypeOption = "build_property.DllImportGenerator_UseInternalUnsafeType"; + + private static bool GetBoolOption(this AnalyzerConfigOptions options, string key) + { + return options.TryGetValue(key, out string? value) + && bool.TryParse(value, out bool result) + && result; + } + + internal static bool UseMarshalType(this AnalyzerConfigOptions options) => options.GetBoolOption(UseMarshalTypeOption); + + internal static bool GenerateForwarders(this AnalyzerConfigOptions options) => options.GetBoolOption(GenerateForwardersOption); + + internal static bool UseInternalUnsafeType(this AnalyzerConfigOptions options) => options.GetBoolOption(UseInternalUnsafeTypeOption); + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/DllImportStubContext.cs b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/DllImportStubContext.cs new file mode 100644 index 0000000000000..853422ab5a1ff --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/DllImportStubContext.cs @@ -0,0 +1,276 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Runtime.InteropServices; +using System.Threading; + +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Diagnostics; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; + +namespace Microsoft.Interop +{ + internal record StubEnvironment( + Compilation Compilation, + bool SupportedTargetFramework, + Version TargetFrameworkVersion, + bool ModuleSkipLocalsInit, + DllImportGeneratorOptions Options); + + internal sealed class DllImportStubContext : IEquatable + { + // We don't need the warnings around not setting the various + // non-nullable fields/properties on this type in the constructor + // since we always use a property initializer. +#pragma warning disable 8618 + private DllImportStubContext() + { + } +#pragma warning restore + + public ImmutableArray ElementTypeInformation { get; init; } + + public string? StubTypeNamespace { get; init; } + + public ImmutableArray StubContainingTypes { get; init; } + + public TypeSyntax StubReturnType { get; init; } + + public IEnumerable StubParameters + { + get + { + foreach (TypePositionInfo typeInfo in ElementTypeInformation) + { + if (typeInfo.ManagedIndex != TypePositionInfo.UnsetIndex + && typeInfo.ManagedIndex != TypePositionInfo.ReturnIndex) + { + yield return Parameter(Identifier(typeInfo.InstanceIdentifier)) + .WithType(typeInfo.ManagedType.Syntax) + .WithModifiers(TokenList(Token(typeInfo.RefKindSyntax))); + } + } + } + } + + public ImmutableArray AdditionalAttributes { get; init; } + + public DllImportGeneratorOptions Options { get; init; } + + public IMarshallingGeneratorFactory GeneratorFactory { get; init; } + + public static DllImportStubContext Create( + IMethodSymbol method, + GeneratedDllImportData dllImportData, + StubEnvironment env, + GeneratorDiagnostics diagnostics, + CancellationToken token) + { + // Cancel early if requested + token.ThrowIfCancellationRequested(); + + // Determine the namespace + string? stubTypeNamespace = null; + if (!(method.ContainingNamespace is null) + && !method.ContainingNamespace.IsGlobalNamespace) + { + stubTypeNamespace = method.ContainingNamespace.ToString(); + } + + // Determine containing type(s) + ImmutableArray.Builder containingTypes = ImmutableArray.CreateBuilder(); + INamedTypeSymbol currType = method.ContainingType; + while (!(currType is null)) + { + // Use the declaring syntax as a basis for this type declaration. + // Since we're generating source for the method, we know that the current type + // has to be declared in source. + TypeDeclarationSyntax typeDecl = (TypeDeclarationSyntax)currType.DeclaringSyntaxReferences[0].GetSyntax(token); + // Remove current members, attributes, and base list so we don't double declare them. + typeDecl = typeDecl.WithMembers(List()) + .WithAttributeLists(List()) + .WithBaseList(null); + + containingTypes.Add(typeDecl); + + currType = currType.ContainingType; + } + + (ImmutableArray typeInfos, IMarshallingGeneratorFactory generatorFactory) = GenerateTypeInformation(method, dllImportData, diagnostics, env); + + ImmutableArray.Builder additionalAttrs = ImmutableArray.CreateBuilder(); + + // Define additional attributes for the stub definition. + if (env.TargetFrameworkVersion >= new Version(5, 0) && !MethodIsSkipLocalsInit(env, method)) + { + additionalAttrs.Add( + AttributeList( + SeparatedList(new[] + { + // Adding the skip locals init indiscriminately since the source generator is + // targeted at non-blittable method signatures which typically will contain locals + // in the generated code. + Attribute(ParseName(TypeNames.System_Runtime_CompilerServices_SkipLocalsInitAttribute)) + }))); + } + + return new DllImportStubContext() + { + StubReturnType = method.ReturnType.AsTypeSyntax(), + ElementTypeInformation = typeInfos, + StubTypeNamespace = stubTypeNamespace, + StubContainingTypes = containingTypes.ToImmutable(), + AdditionalAttributes = additionalAttrs.ToImmutable(), + Options = env.Options, + GeneratorFactory = generatorFactory + }; + } + + private static (ImmutableArray, IMarshallingGeneratorFactory) GenerateTypeInformation(IMethodSymbol method, GeneratedDllImportData dllImportData, GeneratorDiagnostics diagnostics, StubEnvironment env) + { + // Compute the current default string encoding value. + CharEncoding defaultEncoding = CharEncoding.Undefined; + if (dllImportData.IsUserDefined.HasFlag(DllImportMember.CharSet)) + { + defaultEncoding = dllImportData.CharSet switch + { + CharSet.Unicode => CharEncoding.Utf16, + CharSet.Auto => CharEncoding.PlatformDefined, + CharSet.Ansi => CharEncoding.Ansi, + _ => CharEncoding.Undefined, // [Compat] Do not assume a specific value for None + }; + } + + var defaultInfo = new DefaultMarshallingInfo(defaultEncoding); + + var marshallingAttributeParser = new MarshallingAttributeInfoParser(env.Compilation, diagnostics, defaultInfo, method); + + // Determine parameter and return types + ImmutableArray.Builder typeInfos = ImmutableArray.CreateBuilder(); + for (int i = 0; i < method.Parameters.Length; i++) + { + IParameterSymbol param = method.Parameters[i]; + MarshallingInfo marshallingInfo = marshallingAttributeParser.ParseMarshallingInfo(param.Type, param.GetAttributes()); + var typeInfo = TypePositionInfo.CreateForParameter(param, marshallingInfo, env.Compilation); + typeInfo = typeInfo with + { + ManagedIndex = i, + NativeIndex = typeInfos.Count + }; + typeInfos.Add(typeInfo); + + } + + TypePositionInfo retTypeInfo = new(ManagedTypeInfo.CreateTypeInfoForTypeSymbol(method.ReturnType), marshallingAttributeParser.ParseMarshallingInfo(method.ReturnType, method.GetReturnTypeAttributes())); + retTypeInfo = retTypeInfo with + { + ManagedIndex = TypePositionInfo.ReturnIndex, + NativeIndex = TypePositionInfo.ReturnIndex + }; + + InteropGenerationOptions options = new(env.Options.UseMarshalType, env.Options.UseInternalUnsafeType); + IMarshallingGeneratorFactory generatorFactory; + + if (env.Options.GenerateForwarders) + { + generatorFactory = new ForwarderMarshallingGeneratorFactory(); + } + else + { + generatorFactory = new DefaultMarshallingGeneratorFactory(options); + AttributedMarshallingModelGeneratorFactory attributedMarshallingFactory = new(generatorFactory, options); + generatorFactory = attributedMarshallingFactory; + if (!dllImportData.PreserveSig) + { + // Create type info for native out param + if (!method.ReturnsVoid) + { + // Transform the managed return type info into an out parameter and add it as the last param + TypePositionInfo nativeOutInfo = retTypeInfo with + { + InstanceIdentifier = PInvokeStubCodeGenerator.ReturnIdentifier, + RefKind = RefKind.Out, + RefKindSyntax = SyntaxKind.OutKeyword, + ManagedIndex = TypePositionInfo.ReturnIndex, + NativeIndex = typeInfos.Count + }; + typeInfos.Add(nativeOutInfo); + } + + // Use a marshalling generator that supports the HRESULT return->exception marshalling. + generatorFactory = new NoPreserveSigMarshallingGeneratorFactory(generatorFactory); + + // Create type info for native HRESULT return + retTypeInfo = new TypePositionInfo(SpecialTypeInfo.Int32, NoMarshallingInfo.Instance); + retTypeInfo = retTypeInfo with + { + NativeIndex = TypePositionInfo.ReturnIndex + }; + } + + generatorFactory = new ByValueContentsMarshalKindValidator(generatorFactory); + attributedMarshallingFactory.ElementMarshallingGeneratorFactory = generatorFactory; + } + typeInfos.Add(retTypeInfo); + + return (typeInfos.ToImmutable(), generatorFactory); + } + + public override bool Equals(object obj) + { + return obj is DllImportStubContext other && Equals(other); + } + + public bool Equals(DllImportStubContext other) + { + // We don't check if the generator factories are equal since + // the generator factory is deterministically created based on the ElementTypeInformation and Options. + return other is not null + && StubTypeNamespace == other.StubTypeNamespace + && ElementTypeInformation.SequenceEqual(other.ElementTypeInformation) + && StubContainingTypes.SequenceEqual(other.StubContainingTypes, (IEqualityComparer)new SyntaxEquivalentComparer()) + && StubReturnType.IsEquivalentTo(other.StubReturnType) + && AdditionalAttributes.SequenceEqual(other.AdditionalAttributes, (IEqualityComparer)new SyntaxEquivalentComparer()) + && Options.Equals(other.Options); + } + + public override int GetHashCode() + { + throw new UnreachableException(); + } + + private static bool MethodIsSkipLocalsInit(StubEnvironment env, IMethodSymbol method) + { + if (env.ModuleSkipLocalsInit) + { + return true; + } + + if (method.GetAttributes().Any(a => IsSkipLocalsInitAttribute(a))) + { + return true; + } + + for (INamedTypeSymbol type = method.ContainingType; type is not null; type = type.ContainingType) + { + if (type.GetAttributes().Any(a => IsSkipLocalsInitAttribute(a))) + { + return true; + } + } + + // We check the module case earlier, so we don't need to do it here. + + return false; + + static bool IsSkipLocalsInitAttribute(AttributeData a) + => a.AttributeClass?.ToDisplayString() == TypeNames.System_Runtime_CompilerServices_SkipLocalsInitAttribute; + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/ForwarderMarshallingGeneratorFactory.cs b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/ForwarderMarshallingGeneratorFactory.cs new file mode 100644 index 0000000000000..53fb3235c2d8b --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/ForwarderMarshallingGeneratorFactory.cs @@ -0,0 +1,16 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Microsoft.Interop +{ + internal class ForwarderMarshallingGeneratorFactory : IMarshallingGeneratorFactory + { + private static readonly Forwarder s_forwarder = new Forwarder(); + + public IMarshallingGenerator Create(TypePositionInfo info, StubCodeContext context) => s_forwarder; + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/GeneratedDllImportData.cs b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/GeneratedDllImportData.cs new file mode 100644 index 0000000000000..d3157782f488c --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/GeneratedDllImportData.cs @@ -0,0 +1,51 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Text; + +namespace Microsoft.Interop +{ + /// + /// Flags used to indicate members on GeneratedDllImport attribute. + /// + [Flags] + 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, + All = ~None + } + + /// + /// GeneratedDllImportAttribute data + /// + /// + /// The names of these members map directly to those on the + /// DllImportAttribute and should not be changed. + /// + public sealed record GeneratedDllImportData(string ModuleName) + { + /// + /// Value set by the user on the original declaration. + /// + 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; } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/GeneratorDiagnostics.cs b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/GeneratorDiagnostics.cs new file mode 100644 index 0000000000000..0ebfe4830d8ba --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/GeneratorDiagnostics.cs @@ -0,0 +1,282 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; +using System.Text; + +namespace Microsoft.Interop +{ + + /// + /// Class for reporting diagnostics in the DLL import generator + /// + public class GeneratorDiagnostics : IGeneratorDiagnostics + { + public class Ids + { + public const string Prefix = "DLLIMPORTGEN"; + public const string TypeNotSupported = Prefix + "001"; + public const string ConfigurationNotSupported = Prefix + "002"; + public const string TargetFrameworkNotSupported = Prefix + "003"; + } + + private const string Category = "SourceGeneration"; + + public static readonly DiagnosticDescriptor ParameterTypeNotSupported = + new DiagnosticDescriptor( + Ids.TypeNotSupported, + GetResourceString(nameof(Resources.TypeNotSupportedTitle)), + GetResourceString(nameof(Resources.TypeNotSupportedMessageParameter)), + Category, + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: GetResourceString(nameof(Resources.TypeNotSupportedDescription))); + + public static readonly DiagnosticDescriptor ReturnTypeNotSupported = + new DiagnosticDescriptor( + Ids.TypeNotSupported, + GetResourceString(nameof(Resources.TypeNotSupportedTitle)), + GetResourceString(nameof(Resources.TypeNotSupportedMessageReturn)), + Category, + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: GetResourceString(nameof(Resources.TypeNotSupportedDescription))); + + public static readonly DiagnosticDescriptor ParameterTypeNotSupportedWithDetails = + new DiagnosticDescriptor( + Ids.TypeNotSupported, + GetResourceString(nameof(Resources.TypeNotSupportedTitle)), + GetResourceString(nameof(Resources.TypeNotSupportedMessageParameterWithDetails)), + Category, + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: GetResourceString(nameof(Resources.TypeNotSupportedDescription))); + + public static readonly DiagnosticDescriptor ReturnTypeNotSupportedWithDetails = + new DiagnosticDescriptor( + Ids.TypeNotSupported, + GetResourceString(nameof(Resources.TypeNotSupportedTitle)), + GetResourceString(nameof(Resources.TypeNotSupportedMessageReturnWithDetails)), + Category, + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: GetResourceString(nameof(Resources.TypeNotSupportedDescription))); + + public static readonly DiagnosticDescriptor ParameterConfigurationNotSupported = + new DiagnosticDescriptor( + Ids.ConfigurationNotSupported, + GetResourceString(nameof(Resources.ConfigurationNotSupportedTitle)), + GetResourceString(nameof(Resources.ConfigurationNotSupportedMessageParameter)), + Category, + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: GetResourceString(nameof(Resources.ConfigurationNotSupportedDescription))); + + public static readonly DiagnosticDescriptor ReturnConfigurationNotSupported = + new DiagnosticDescriptor( + Ids.ConfigurationNotSupported, + GetResourceString(nameof(Resources.ConfigurationNotSupportedTitle)), + GetResourceString(nameof(Resources.ConfigurationNotSupportedMessageReturn)), + Category, + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: GetResourceString(nameof(Resources.ConfigurationNotSupportedDescription))); + + public static readonly DiagnosticDescriptor ConfigurationNotSupported = + new DiagnosticDescriptor( + Ids.ConfigurationNotSupported, + GetResourceString(nameof(Resources.ConfigurationNotSupportedTitle)), + GetResourceString(nameof(Resources.ConfigurationNotSupportedMessage)), + Category, + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: GetResourceString(nameof(Resources.ConfigurationNotSupportedDescription))); + + public static readonly DiagnosticDescriptor ConfigurationValueNotSupported = + new DiagnosticDescriptor( + Ids.ConfigurationNotSupported, + GetResourceString(nameof(Resources.ConfigurationNotSupportedTitle)), + GetResourceString(nameof(Resources.ConfigurationNotSupportedMessageValue)), + Category, + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: GetResourceString(nameof(Resources.ConfigurationNotSupportedDescription))); + + public static readonly DiagnosticDescriptor MarshallingAttributeConfigurationNotSupported = + new DiagnosticDescriptor( + Ids.ConfigurationNotSupported, + GetResourceString(nameof(Resources.ConfigurationNotSupportedTitle)), + GetResourceString(nameof(Resources.ConfigurationNotSupportedMessageMarshallingInfo)), + Category, + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: GetResourceString(nameof(Resources.ConfigurationNotSupportedDescription))); + + public static readonly DiagnosticDescriptor TargetFrameworkNotSupported = + new DiagnosticDescriptor( + Ids.TargetFrameworkNotSupported, + GetResourceString(nameof(Resources.TargetFrameworkNotSupportedTitle)), + GetResourceString(nameof(Resources.TargetFrameworkNotSupportedMessage)), + Category, + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: GetResourceString(nameof(Resources.TargetFrameworkNotSupportedDescription))); + + private readonly List _diagnostics = new List(); + + public IEnumerable Diagnostics => _diagnostics; + + /// + /// Report diagnostic for configuration that is not supported by the DLL import source generator + /// + /// Attribute specifying the unsupported configuration + /// Name of the configuration + /// [Optiona] Unsupported configuration value + public void ReportConfigurationNotSupported( + AttributeData attributeData, + string configurationName, + string? unsupportedValue = null) + { + if (unsupportedValue == null) + { + _diagnostics.Add( + attributeData.CreateDiagnostic( + GeneratorDiagnostics.ConfigurationNotSupported, + configurationName)); + } + else + { + _diagnostics.Add( + attributeData.CreateDiagnostic( + GeneratorDiagnostics.ConfigurationValueNotSupported, + unsupportedValue, + configurationName)); + } + } + + /// + /// Report diagnostic for marshalling of a parameter/return that is not supported + /// + /// Method with the parameter/return + /// Type info for the parameter/return + /// [Optional] Specific reason for lack of support + public void ReportMarshallingNotSupported( + MethodDeclarationSyntax method, + TypePositionInfo info, + string? notSupportedDetails) + { + Location diagnosticLocation = Location.None; + string elementName = string.Empty; + + if (info.IsManagedReturnPosition) + { + diagnosticLocation = Location.Create(method.SyntaxTree, method.Identifier.Span); + elementName = method.Identifier.ValueText; + } + else + { + Debug.Assert(info.ManagedIndex <= method.ParameterList.Parameters.Count); + ParameterSyntax param = method.ParameterList.Parameters[info.ManagedIndex]; + diagnosticLocation = Location.Create(param.SyntaxTree, param.Identifier.Span); + elementName = param.Identifier.ValueText; + } + + if (!string.IsNullOrEmpty(notSupportedDetails)) + { + // Report the specific not-supported reason. + if (info.IsManagedReturnPosition) + { + _diagnostics.Add( + diagnosticLocation.CreateDiagnostic( + GeneratorDiagnostics.ReturnTypeNotSupportedWithDetails, + notSupportedDetails!, + elementName)); + } + else + { + _diagnostics.Add( + diagnosticLocation.CreateDiagnostic( + GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails, + notSupportedDetails!, + elementName)); + } + } + else if (info.MarshallingAttributeInfo is MarshalAsInfo) + { + // Report that the specified marshalling configuration is not supported. + // We don't forward marshalling attributes, so this is reported differently + // than when there is no attribute and the type itself is not supported. + if (info.IsManagedReturnPosition) + { + _diagnostics.Add( + diagnosticLocation.CreateDiagnostic( + GeneratorDiagnostics.ReturnConfigurationNotSupported, + nameof(System.Runtime.InteropServices.MarshalAsAttribute), + elementName)); + } + else + { + _diagnostics.Add( + diagnosticLocation.CreateDiagnostic( + GeneratorDiagnostics.ParameterConfigurationNotSupported, + nameof(System.Runtime.InteropServices.MarshalAsAttribute), + elementName)); + } + } + else + { + // Report that the type is not supported + if (info.IsManagedReturnPosition) + { + _diagnostics.Add( + diagnosticLocation.CreateDiagnostic( + GeneratorDiagnostics.ReturnTypeNotSupported, + info.ManagedType.DiagnosticFormattedName, + elementName)); + } + else + { + _diagnostics.Add( + diagnosticLocation.CreateDiagnostic( + GeneratorDiagnostics.ParameterTypeNotSupported, + info.ManagedType.DiagnosticFormattedName, + elementName)); + } + } + } + + public void ReportInvalidMarshallingAttributeInfo( + AttributeData attributeData, + string reasonResourceName, + params string[] reasonArgs) + { + _diagnostics.Add( + attributeData.CreateDiagnostic( + GeneratorDiagnostics.MarshallingAttributeConfigurationNotSupported, + new LocalizableResourceString(reasonResourceName, Resources.ResourceManager, typeof(Resources), reasonArgs))); + } + + /// + /// Report diagnostic for targeting a framework that is not supported + /// + /// Minimum supported version of .NET + public void ReportTargetFrameworkNotSupported(Version minimumSupportedVersion) + { + _diagnostics.Add( + Diagnostic.Create( + TargetFrameworkNotSupported, + Location.None, + minimumSupportedVersion.ToString(2))); + } + + private static LocalizableResourceString GetResourceString(string resourceName) + { + return new LocalizableResourceString(resourceName, Resources.ResourceManager, typeof(Resources)); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/LanguageSupport.cs b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/LanguageSupport.cs new file mode 100644 index 0000000000000..0f983ddc28671 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/LanguageSupport.cs @@ -0,0 +1,11 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// Types defined to enable language support of various features +// in the source generator. +namespace System.Runtime.CompilerServices +{ + // Define IsExternalInit type to support records. + internal class IsExternalInit + { } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/Microsoft.Interop.DllImportGenerator.props b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/Microsoft.Interop.DllImportGenerator.props new file mode 100644 index 0000000000000..550d474720ea1 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/Microsoft.Interop.DllImportGenerator.props @@ -0,0 +1,27 @@ + + + + + + + + + + + + $(DefineConstants);DLLIMPORTGENERATOR_ENABLED + + diff --git a/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/NoPreserveSigMarshallingGeneratorFactory.cs b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/NoPreserveSigMarshallingGeneratorFactory.cs new file mode 100644 index 0000000000000..d06e7db251cfd --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/NoPreserveSigMarshallingGeneratorFactory.cs @@ -0,0 +1,33 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Microsoft.Interop +{ + internal class NoPreserveSigMarshallingGeneratorFactory : IMarshallingGeneratorFactory + { + private static readonly HResultExceptionMarshaller s_hResultException = new HResultExceptionMarshaller(); + private readonly IMarshallingGeneratorFactory _inner; + + public NoPreserveSigMarshallingGeneratorFactory(IMarshallingGeneratorFactory inner) + { + _inner = inner; + } + + public IMarshallingGenerator Create(TypePositionInfo info, StubCodeContext context) + { + if (info.IsNativeReturnPosition && !info.IsManagedReturnPosition) + { + // Use marshaller for native HRESULT return / exception throwing + System.Diagnostics.Debug.Assert(info.ManagedType.Equals(SpecialTypeInfo.Int32)); + return s_hResultException; + } + return _inner.Create(info, context); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/PInvokeStubCodeGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/PInvokeStubCodeGenerator.cs new file mode 100644 index 0000000000000..aa7242694afb1 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/PInvokeStubCodeGenerator.cs @@ -0,0 +1,493 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; + +namespace Microsoft.Interop +{ + /// + /// Base code generator for generating the body of a source-generated P/Invoke and providing customization for how to invoke/define the native method. + /// + /// + /// This type enables multiple code generators for P/Invoke-style marshalling + /// to reuse the same basic method body, but with different designs of how to emit the target native method. + /// This enables users to write code generators that work with slightly different semantics. + /// For example, the source generator for [GeneratedDllImport] emits the target P/Invoke as + /// a local function inside the generated stub body. + /// However, other managed-to-native code generators using a P/Invoke style might want to define + /// the target DllImport outside of the stub as a static non-local function or as a function pointer field. + /// This refactoring allows the code generator to have control over where the target method is declared + /// and how it is declared. + /// + internal sealed class PInvokeStubCodeGenerator : StubCodeContext + { + private record struct BoundGenerator(TypePositionInfo TypeInfo, IMarshallingGenerator Generator); + + public override bool SingleFrameSpansNativeContext => true; + + public override bool AdditionalTemporaryStateLivesAcrossStages => true; + + /// + /// Identifier for managed return value + /// + public const string ReturnIdentifier = "__retVal"; + + /// + /// Identifier for native return value + /// + /// Same as the managed identifier by default + public string ReturnNativeIdentifier { get; } = ReturnIdentifier; + + private const string InvokeReturnIdentifier = "__invokeRetVal"; + private const string LastErrorIdentifier = "__lastError"; + private const string InvokeSucceededIdentifier = "__invokeSucceeded"; + + // Error code representing success. This maps to S_OK for Windows HRESULT semantics and 0 for POSIX errno semantics. + private const int SuccessErrorCode = 0; + + private readonly bool _setLastError; + private readonly List _paramMarshallers; + private readonly BoundGenerator _retMarshaller; + private readonly List _sortedMarshallers; + private readonly bool _stubReturnsVoid; + + public PInvokeStubCodeGenerator( + IEnumerable argTypes, + bool setLastError, + Action marshallingNotSupportedCallback, + IMarshallingGeneratorFactory generatorFactory) + { + _setLastError = setLastError; + + List allMarshallers = new(); + List paramMarshallers = new(); + bool foundNativeRetMarshaller = false; + bool foundManagedRetMarshaller = false; + BoundGenerator nativeRetMarshaller = new(new TypePositionInfo(SpecialTypeInfo.Void, NoMarshallingInfo.Instance), new Forwarder()); + BoundGenerator managedRetMarshaller = new(new TypePositionInfo(SpecialTypeInfo.Void, NoMarshallingInfo.Instance), new Forwarder()); + + foreach (TypePositionInfo argType in argTypes) + { + BoundGenerator generator = CreateGenerator(argType); + allMarshallers.Add(generator); + if (argType.IsManagedReturnPosition) + { + Debug.Assert(!foundManagedRetMarshaller); + managedRetMarshaller = generator; + foundManagedRetMarshaller = true; + } + if (argType.IsNativeReturnPosition) + { + Debug.Assert(!foundNativeRetMarshaller); + nativeRetMarshaller = generator; + foundNativeRetMarshaller = true; + } + if (!argType.IsManagedReturnPosition && !argType.IsNativeReturnPosition) + { + paramMarshallers.Add(generator); + } + } + + _stubReturnsVoid = managedRetMarshaller.TypeInfo.ManagedType == SpecialTypeInfo.Void; + + if (!managedRetMarshaller.TypeInfo.IsNativeReturnPosition && !_stubReturnsVoid) + { + // If the managed ret marshaller isn't the native ret marshaller, then the managed ret marshaller + // is a parameter. + paramMarshallers.Add(managedRetMarshaller); + } + + _retMarshaller = nativeRetMarshaller; + _paramMarshallers = paramMarshallers; + + // We are doing a topological sort of our marshallers to ensure that each parameter/return value's + // dependencies are unmarshalled before their dependents. This comes up in the case of contiguous + // collections, where the number of elements in a collection are provided via another parameter/return value. + // When using nested collections, the parameter that represents the number of elements of each element of the + // outer collection is another collection. As a result, there are two options on how to retrieve the size. + // Either we partially unmarshal the collection of counts while unmarshalling the collection of elements, + // or we unmarshal our parameters and return value in an order such that we can use the managed identifiers + // for our lengths. + // Here's an example signature where the dependency shows up: + // + // [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "transpose_matrix")] + // [return: MarshalUsing(CountElementName = "numColumns")] + // [return: MarshalUsing(CountElementName = "numRows", ElementIndirectionLevel = 1)] + // public static partial int[][] TransposeMatrix( + // int[][] matrix, + // [MarshalUsing(CountElementName="numColumns")] ref int[] numRows, + // int numColumns); + // + // In this scenario, we'd traditionally unmarshal the return value and then each parameter. However, since + // the return value has dependencies on numRows and numColumns and numRows has a dependency on numColumns, + // we want to unmarshal numColumns, then numRows, then the return value. + // A topological sort ensures we get this order correct. + _sortedMarshallers = MarshallerHelpers.GetTopologicallySortedElements( + allMarshallers, + static m => GetInfoIndex(m.TypeInfo), + static m => GetInfoDependencies(m.TypeInfo)) + .ToList(); + + if (managedRetMarshaller.Generator.UsesNativeIdentifier(managedRetMarshaller.TypeInfo, this)) + { + // Update the native identifier for the return value + ReturnNativeIdentifier = $"{ReturnIdentifier}{GeneratedNativeIdentifierSuffix}"; + } + + static IEnumerable GetInfoDependencies(TypePositionInfo info) + { + // A parameter without a managed index cannot have any dependencies. + if (info.ManagedIndex == TypePositionInfo.UnsetIndex) + { + return Array.Empty(); + } + return MarshallerHelpers.GetDependentElementsOfMarshallingInfo(info.MarshallingAttributeInfo) + .Select(static info => GetInfoIndex(info)).ToList(); + } + + static int GetInfoIndex(TypePositionInfo info) + { + if (info.ManagedIndex == TypePositionInfo.UnsetIndex) + { + // A TypePositionInfo needs to have either a managed or native index. + // We use negative values of the native index to distinguish them from the managed index. + return -info.NativeIndex; + } + return info.ManagedIndex; + } + + BoundGenerator CreateGenerator(TypePositionInfo p) + { + try + { + return new BoundGenerator(p, generatorFactory.Create(p, this)); + } + catch (MarshallingNotSupportedException e) + { + marshallingNotSupportedCallback(p, e); + return new BoundGenerator(p, new Forwarder()); + } + } + } + + public override (string managed, string native) GetIdentifiers(TypePositionInfo info) + { + // If the info is in the managed return position, then we need to generate a name to use + // for both the managed and native values since there is no name in the signature for the return value. + if (info.IsManagedReturnPosition) + { + return (ReturnIdentifier, ReturnNativeIdentifier); + } + // If the info is in the native return position but is not in the managed return position, + // then that means that the stub is introducing an additional info for the return position. + // This means that there is no name in source for this info, so we must provide one here. + // We can't use ReturnIdentifier or ReturnNativeIdentifier since that will be used by the managed return value. + // Additionally, since all use cases today of a TypePositionInfo in the native position but not the managed + // are for infos that aren't in the managed signature at all (PreserveSig scenario), we don't have a name + // that we can use from source. As a result, we generate another name for the native return value + // and use the same name for native and managed. + else if (info.IsNativeReturnPosition) + { + Debug.Assert(info.ManagedIndex == TypePositionInfo.UnsetIndex); + return (InvokeReturnIdentifier, InvokeReturnIdentifier); + } + else + { + // If the info isn't in either the managed or native return position, + // then we can use the base implementation since we have an identifier name provided + // in the original metadata. + return base.GetIdentifiers(info); + } + } + + public BlockSyntax GeneratePInvokeBody(string dllImportName) + { + var setupStatements = new List(); + + foreach (BoundGenerator marshaller in _paramMarshallers) + { + TypePositionInfo info = marshaller.TypeInfo; + if (info.IsManagedReturnPosition) + continue; + + if (info.RefKind == RefKind.Out) + { + // Assign out params to default + setupStatements.Add(ExpressionStatement( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + IdentifierName(info.InstanceIdentifier), + LiteralExpression( + SyntaxKind.DefaultLiteralExpression, + Token(SyntaxKind.DefaultKeyword))))); + } + + // Declare variables for parameters + AppendVariableDeclations(setupStatements, info, marshaller.Generator); + } + + bool invokeReturnsVoid = _retMarshaller.TypeInfo.ManagedType == SpecialTypeInfo.Void; + + // Stub return is not the same as invoke return + if (!_stubReturnsVoid && !_retMarshaller.TypeInfo.IsManagedReturnPosition) + { + // Stub return should be the last parameter for the invoke + Debug.Assert(_paramMarshallers.Any() && _paramMarshallers.Last().TypeInfo.IsManagedReturnPosition, "Expected stub return to be the last parameter for the invoke"); + + (TypePositionInfo stubRetTypeInfo, IMarshallingGenerator stubRetGenerator) = _paramMarshallers.Last(); + + // Declare variables for stub return value + AppendVariableDeclations(setupStatements, stubRetTypeInfo, stubRetGenerator); + } + + if (!invokeReturnsVoid) + { + // Declare variables for invoke return value + AppendVariableDeclations(setupStatements, _retMarshaller.TypeInfo, _retMarshaller.Generator); + } + + // Do not manually handle SetLastError when generating forwarders. + // We want the runtime to handle everything. + if (_setLastError) + { + // Declare variable for last error + setupStatements.Add(MarshallerHelpers.DeclareWithDefault( + PredefinedType(Token(SyntaxKind.IntKeyword)), + LastErrorIdentifier)); + } + + var tryStatements = new List(); + var guaranteedUnmarshalStatements = new List(); + var cleanupStatements = new List(); + InvocationExpressionSyntax invoke = InvocationExpression(IdentifierName(dllImportName)); + + // Handle GuaranteedUnmarshal first since that stage producing statements affects multiple other stages. + GenerateStatementsForStage(Stage.GuaranteedUnmarshal, guaranteedUnmarshalStatements); + if (guaranteedUnmarshalStatements.Count > 0) + { + setupStatements.Add(MarshallerHelpers.DeclareWithDefault(PredefinedType(Token(SyntaxKind.BoolKeyword)), InvokeSucceededIdentifier)); + } + + GenerateStatementsForStage(Stage.Setup, setupStatements); + GenerateStatementsForStage(Stage.Marshal, tryStatements); + GenerateStatementsForInvoke(tryStatements, invoke); + GenerateStatementsForStage(Stage.KeepAlive, tryStatements); + GenerateStatementsForStage(Stage.Unmarshal, tryStatements); + GenerateStatementsForStage(Stage.Cleanup, cleanupStatements); + + List allStatements = setupStatements; + List finallyStatements = new List(); + if (guaranteedUnmarshalStatements.Count > 0) + { + finallyStatements.Add(IfStatement(IdentifierName(InvokeSucceededIdentifier), Block(guaranteedUnmarshalStatements))); + } + + finallyStatements.AddRange(cleanupStatements); + if (finallyStatements.Count > 0) + { + // Add try-finally block if there are any statements in the finally block + allStatements.Add( + TryStatement(Block(tryStatements), default, FinallyClause(Block(finallyStatements)))); + } + else + { + allStatements.AddRange(tryStatements); + } + + if (_setLastError) + { + // Marshal.SetLastPInvokeError(); + allStatements.Add(ExpressionStatement( + InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + ParseName(TypeNames.System_Runtime_InteropServices_Marshal), + IdentifierName("SetLastPInvokeError")), + ArgumentList(SingletonSeparatedList( + Argument(IdentifierName(LastErrorIdentifier))))))); + } + + // Return + if (!_stubReturnsVoid) + allStatements.Add(ReturnStatement(IdentifierName(ReturnIdentifier))); + + // Wrap all statements in an unsafe block + return Block(UnsafeStatement(Block(allStatements))); + + void GenerateStatementsForStage(Stage stage, List statementsToUpdate) + { + int initialCount = statementsToUpdate.Count; + CurrentStage = stage; + + if (!invokeReturnsVoid && (stage is Stage.Setup or Stage.Cleanup)) + { + IEnumerable retStatements = _retMarshaller.Generator.Generate(_retMarshaller.TypeInfo, this); + statementsToUpdate.AddRange(retStatements); + } + + if (stage is Stage.Unmarshal or Stage.GuaranteedUnmarshal) + { + // For Unmarshal and GuaranteedUnmarshal stages, use the topologically sorted + // marshaller list to generate the marshalling statements + + foreach (BoundGenerator marshaller in _sortedMarshallers) + { + statementsToUpdate.AddRange(marshaller.Generator.Generate(marshaller.TypeInfo, this)); + } + } + else + { + // Generate code for each parameter for the current stage in declaration order. + foreach (BoundGenerator marshaller in _paramMarshallers) + { + IEnumerable generatedStatements = marshaller.Generator.Generate(marshaller.TypeInfo, this); + statementsToUpdate.AddRange(generatedStatements); + } + } + + if (statementsToUpdate.Count > initialCount) + { + // Comment separating each stage + SyntaxTriviaList newLeadingTrivia = TriviaList( + Comment($"//"), + Comment($"// {stage}"), + Comment($"//")); + StatementSyntax firstStatementInStage = statementsToUpdate[initialCount]; + newLeadingTrivia = newLeadingTrivia.AddRange(firstStatementInStage.GetLeadingTrivia()); + statementsToUpdate[initialCount] = firstStatementInStage.WithLeadingTrivia(newLeadingTrivia); + } + } + + void GenerateStatementsForInvoke(List statementsToUpdate, InvocationExpressionSyntax invoke) + { + var fixedStatements = new List(); + CurrentStage = Stage.Pin; + // Generate code for each parameter for the current stage + foreach (BoundGenerator marshaller in _paramMarshallers) + { + IEnumerable generatedStatements = marshaller.Generator.Generate(marshaller.TypeInfo, this); + // Collect all the fixed statements. These will be used in the Invoke stage. + foreach (StatementSyntax statement in generatedStatements) + { + if (statement is not FixedStatementSyntax fixedStatement) + continue; + + fixedStatements.Add(fixedStatement); + } + } + + CurrentStage = Stage.Invoke; + // Generate code for each parameter for the current stage + foreach (BoundGenerator marshaller in _paramMarshallers) + { + // Get arguments for invocation + ArgumentSyntax argSyntax = marshaller.Generator.AsArgument(marshaller.TypeInfo, this); + invoke = invoke.AddArgumentListArguments(argSyntax); + } + + StatementSyntax invokeStatement; + // Assign to return value if necessary + if (invokeReturnsVoid) + { + invokeStatement = ExpressionStatement(invoke); + } + else + { + invokeStatement = ExpressionStatement( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + IdentifierName(GetIdentifiers(_retMarshaller.TypeInfo).native), + invoke)); + } + + // Do not manually handle SetLastError when generating forwarders. + // We want the runtime to handle everything. + if (_setLastError) + { + // Marshal.SetLastSystemError(0); + ExpressionStatementSyntax clearLastError = ExpressionStatement( + InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + ParseName(TypeNames.System_Runtime_InteropServices_Marshal), + IdentifierName("SetLastSystemError")), + ArgumentList(SingletonSeparatedList( + Argument(LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(SuccessErrorCode))))))); + + // = Marshal.GetLastSystemError(); + ExpressionStatementSyntax getLastError = ExpressionStatement( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + IdentifierName(LastErrorIdentifier), + InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + ParseName(TypeNames.System_Runtime_InteropServices_Marshal), + IdentifierName("GetLastSystemError"))))); + + invokeStatement = Block(clearLastError, invokeStatement, getLastError); + } + // Nest invocation in fixed statements + if (fixedStatements.Any()) + { + fixedStatements.Reverse(); + invokeStatement = fixedStatements.First().WithStatement(invokeStatement); + foreach (FixedStatementSyntax fixedStatement in fixedStatements.Skip(1)) + { + invokeStatement = fixedStatement.WithStatement(Block(invokeStatement)); + } + } + + statementsToUpdate.Add(invokeStatement); + // = true; + if (guaranteedUnmarshalStatements.Count > 0) + { + statementsToUpdate.Add(ExpressionStatement(AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, + IdentifierName(InvokeSucceededIdentifier), + LiteralExpression(SyntaxKind.TrueLiteralExpression)))); + } + } + } + + public (ParameterListSyntax ParameterList, TypeSyntax ReturnType, AttributeListSyntax? ReturnTypeAttributes) GenerateTargetMethodSignatureData() + { + return ( + ParameterList( + SeparatedList( + _paramMarshallers.Select(marshaler => marshaler.Generator.AsParameter(marshaler.TypeInfo)))), + _retMarshaller.Generator.AsNativeType(_retMarshaller.TypeInfo), + _retMarshaller.Generator is IAttributedReturnTypeMarshallingGenerator attributedReturn + ? attributedReturn.GenerateAttributesForReturnType(_retMarshaller.TypeInfo) + : null + ); + } + + private void AppendVariableDeclations(List statementsToUpdate, TypePositionInfo info, IMarshallingGenerator generator) + { + (string managed, string native) = GetIdentifiers(info); + + // Declare variable for return value + if (info.IsManagedReturnPosition || info.IsNativeReturnPosition) + { + statementsToUpdate.Add(MarshallerHelpers.DeclareWithDefault( + info.ManagedType.Syntax, + managed)); + } + + // Declare variable with native type for parameter or return value + if (generator.UsesNativeIdentifier(info, this)) + { + statementsToUpdate.Add(MarshallerHelpers.DeclareWithDefault( + generator.AsNativeType(info), + native)); + } + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/Resources.Designer.cs b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/Resources.Designer.cs new file mode 100644 index 0000000000000..eb6bfa6e52e08 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/Resources.Designer.cs @@ -0,0 +1,630 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Microsoft.Interop { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.Interop.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to A type marked with 'BlittableTypeAttribute' must be blittable.. + /// + internal static string BlittableTypeMustBeBlittableDescription { + get { + return ResourceManager.GetString("BlittableTypeMustBeBlittableDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Type '{0}' is marked with 'BlittableTypeAttribute' but is not blittable. + /// + internal static string BlittableTypeMustBeBlittableMessage { + get { + return ResourceManager.GetString("BlittableTypeMustBeBlittableMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The 'BlittableTypeAttribute' and 'NativeMarshallingAttribute' attributes are mutually exclusive.. + /// + internal static string CannotHaveMultipleMarshallingAttributesDescription { + get { + return ResourceManager.GetString("CannotHaveMultipleMarshallingAttributesDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Type '{0}' is marked with 'BlittableTypeAttribute' and 'NativeMarshallingAttribute'. A type can only have one of these two attributes.. + /// + internal static string CannotHaveMultipleMarshallingAttributesMessage { + get { + return ResourceManager.GetString("CannotHaveMultipleMarshallingAttributesMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to A native type with the 'GenericContiguousCollectionMarshallerAttribute' must have at least one of the two marshalling methods as well as a 'ManagedValues' property of type 'Span<T>' for some 'T' and a 'NativeValueStorage' property of type 'Span<byte>' to enable marshalling the managed type.. + /// + internal static string CollectionNativeTypeMustHaveRequiredShapeDescription { + get { + return ResourceManager.GetString("CollectionNativeTypeMustHaveRequiredShapeDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The native type '{0}' must be a value type and have a constructor that takes two parameters, one of type '{1}' and an 'int', or have a parameterless instance method named 'ToManaged' that returns '{1}' as well as a 'ManagedValues' property of type 'Span<T>' for some 'T' and a 'NativeValueStorage' property of type 'Span<byte>'. + /// + internal static string CollectionNativeTypeMustHaveRequiredShapeMessage { + get { + return ResourceManager.GetString("CollectionNativeTypeMustHaveRequiredShapeMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Source-generated P/Invokes will ignore any configuration that is not supported.. + /// + internal static string ConfigurationNotSupportedDescription { + get { + return ResourceManager.GetString("ConfigurationNotSupportedDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The '{0}' configuration is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead.. + /// + internal static string ConfigurationNotSupportedMessage { + get { + return ResourceManager.GetString("ConfigurationNotSupportedMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The specified marshalling configuration is not supported by source-generated P/Invokes. {0}.. + /// + internal static string ConfigurationNotSupportedMessageMarshallingInfo { + get { + return ResourceManager.GetString("ConfigurationNotSupportedMessageMarshallingInfo", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The specified '{0}' configuration for parameter '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead.. + /// + internal static string ConfigurationNotSupportedMessageParameter { + get { + return ResourceManager.GetString("ConfigurationNotSupportedMessageParameter", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The specified '{0}' configuration for the return value of method '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead.. + /// + internal static string ConfigurationNotSupportedMessageReturn { + get { + return ResourceManager.GetString("ConfigurationNotSupportedMessageReturn", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The specified value '{0}' for '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead.. + /// + internal static string ConfigurationNotSupportedMessageValue { + get { + return ResourceManager.GetString("ConfigurationNotSupportedMessageValue", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Specified configuration is not supported by source-generated P/Invokes.. + /// + internal static string ConfigurationNotSupportedTitle { + get { + return ResourceManager.GetString("ConfigurationNotSupportedTitle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Only one of 'ConstantElementCount' or 'ElementCountInfo' may be used in a 'MarshalUsingAttribute' for a given 'ElementIndirectionLevel'. + /// + internal static string ConstantAndElementCountInfoDisallowed { + get { + return ResourceManager.GetString("ConstantAndElementCountInfoDisallowed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Use 'GeneratedDllImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time. + /// + internal static string ConvertToGeneratedDllImportDescription { + get { + return ResourceManager.GetString("ConvertToGeneratedDllImportDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Mark the method '{0}' with 'GeneratedDllImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time. + /// + internal static string ConvertToGeneratedDllImportMessage { + get { + return ResourceManager.GetString("ConvertToGeneratedDllImportMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Convert to 'GeneratedDllImport'. + /// + internal static string ConvertToGeneratedDllImportNoPreprocessor { + get { + return ResourceManager.GetString("ConvertToGeneratedDllImportNoPreprocessor", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Use 'GeneratedDllImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time. + /// + internal static string ConvertToGeneratedDllImportTitle { + get { + return ResourceManager.GetString("ConvertToGeneratedDllImportTitle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Conversion to 'GeneratedDllImport' may change behavior and compatibility. See {0} for more information.. + /// + internal static string ConvertToGeneratedDllImportWarning { + get { + return ResourceManager.GetString("ConvertToGeneratedDllImportWarning", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Convert to 'GeneratedDllImport' under a preprocessor define. + /// + internal static string ConvertToGeneratedDllImportWithPreprocessor { + get { + return ResourceManager.GetString("ConvertToGeneratedDllImportWithPreprocessor", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The specified parameter needs to be marshalled from managed to native, but the native type '{0}' does not support it.. + /// + internal static string CustomTypeMarshallingManagedToNativeUnsupported { + get { + return ResourceManager.GetString("CustomTypeMarshallingManagedToNativeUnsupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The specified parameter needs to be marshalled from native to managed, but the native type '{0}' does not support it.. + /// + internal static string CustomTypeMarshallingNativeToManagedUnsupported { + get { + return ResourceManager.GetString("CustomTypeMarshallingNativeToManagedUnsupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Types that contain methods marked with 'GeneratedDllImportAttribute' must be 'partial'. P/Invoke source generation will ignore methods contained within non-partial types.. + /// + internal static string GeneratedDllImportContainingTypeMissingModifiersDescription { + get { + return ResourceManager.GetString("GeneratedDllImportContainingTypeMissingModifiersDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Type '{0}' contains methods marked with 'GeneratedDllImportAttribute' and should be 'partial'. P/Invoke source generation will ignore methods contained within non-partial types.. + /// + internal static string GeneratedDllImportContainingTypeMissingModifiersMessage { + get { + return ResourceManager.GetString("GeneratedDllImportContainingTypeMissingModifiersMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Types that contain methods marked with 'GeneratedDllImportAttribute' must be 'partial'.. + /// + internal static string GeneratedDllImportContainingTypeMissingModifiersTitle { + get { + return ResourceManager.GetString("GeneratedDllImportContainingTypeMissingModifiersTitle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Methods marked with 'GeneratedDllImportAttribute' should be 'static' and 'partial'. P/Invoke source generation will ignore methods that are not 'static' and 'partial'.. + /// + internal static string GeneratedDllImportMissingModifiersDescription { + get { + return ResourceManager.GetString("GeneratedDllImportMissingModifiersDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Method '{0}' should be 'static' and 'partial' when marked with 'GeneratedDllImportAttribute'. P/Invoke source generation will ignore methods that are not 'static' and 'partial'.. + /// + internal static string GeneratedDllImportMissingModifiersMessage { + get { + return ResourceManager.GetString("GeneratedDllImportMissingModifiersMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Method marked with 'GeneratedDllImportAttribute' should be 'static' and 'partial'. + /// + internal static string GeneratedDllImportMissingModifiersTitle { + get { + return ResourceManager.GetString("GeneratedDllImportMissingModifiersTitle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The return type of 'GetPinnableReference' (after accounting for 'ref') must be blittable.. + /// + internal static string GetPinnableReferenceReturnTypeBlittableDescription { + get { + return ResourceManager.GetString("GetPinnableReferenceReturnTypeBlittableDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The dereferenced type of the return type of the 'GetPinnableReference' method must be blittable. + /// + internal static string GetPinnableReferenceReturnTypeBlittableMessage { + get { + return ResourceManager.GetString("GetPinnableReferenceReturnTypeBlittableMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to A type that supports marshalling from managed to native by pinning should also support marshalling from managed to native where pinning is impossible.. + /// + internal static string GetPinnableReferenceShouldSupportAllocatingMarshallingFallbackDescription { + get { + return ResourceManager.GetString("GetPinnableReferenceShouldSupportAllocatingMarshallingFallbackDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Type '{0}' has a 'GetPinnableReference' method but its native type does not support marshalling in scenarios where pinning is impossible. + /// + internal static string GetPinnableReferenceShouldSupportAllocatingMarshallingFallbackMessage { + get { + return ResourceManager.GetString("GetPinnableReferenceShouldSupportAllocatingMarshallingFallbackMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The native type '{0}' must be a closed generic so the emitted code can use a specific instantiation.. + /// + internal static string NativeGenericTypeMustBeClosedDescription { + get { + return ResourceManager.GetString("NativeGenericTypeMustBeClosedDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The native type '{0}' must be a closed generic or have the same number of generic parameters as the managed type so the emitted code can use a specific instantiation.. + /// + internal static string NativeGenericTypeMustBeClosedOrMatchArityDescription { + get { + return ResourceManager.GetString("NativeGenericTypeMustBeClosedOrMatchArityDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The native type '{0}' for managed type '{1}' must be a closed generic type or have the same arity as the managed type.. + /// + internal static string NativeGenericTypeMustBeClosedOrMatchArityMessage { + get { + return ResourceManager.GetString("NativeGenericTypeMustBeClosedOrMatchArityMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to A native type for a given type must be blittable.. + /// + internal static string NativeTypeMustBeBlittableDescription { + get { + return ResourceManager.GetString("NativeTypeMustBeBlittableDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The native type '{0}' for the type '{1}' is not blittable. + /// + internal static string NativeTypeMustBeBlittableMessage { + get { + return ResourceManager.GetString("NativeTypeMustBeBlittableMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to A native type for a given type must be non-null.. + /// + internal static string NativeTypeMustBeNonNullDescription { + get { + return ResourceManager.GetString("NativeTypeMustBeNonNullDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The native type for the type '{0}' is null. + /// + internal static string NativeTypeMustBeNonNullMessage { + get { + return ResourceManager.GetString("NativeTypeMustBeNonNullMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The native type must be pointer sized so the pinned result of 'GetPinnableReference' can be cast to the native type.. + /// + internal static string NativeTypeMustBePointerSizedDescription { + get { + return ResourceManager.GetString("NativeTypeMustBePointerSizedDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The native type '{0}' must be pointer sized because the managed type '{1}' has a 'GetPinnableReference' method. + /// + internal static string NativeTypeMustBePointerSizedMessage { + get { + return ResourceManager.GetString("NativeTypeMustBePointerSizedMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The native type must have at least one of the two marshalling methods to enable marshalling the managed type.. + /// + internal static string NativeTypeMustHaveRequiredShapeDescription { + get { + return ResourceManager.GetString("NativeTypeMustHaveRequiredShapeDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The native type '{0}' must be a value type and have a constructor that takes one parameter of type '{1}' or a parameterless instance method named 'ToManaged' that returns '{1}'. + /// + internal static string NativeTypeMustHaveRequiredShapeMessage { + get { + return ResourceManager.GetString("NativeTypeMustHaveRequiredShapeMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The 'Value' property must not be a 'ref' or 'readonly ref' property.. + /// + internal static string RefValuePropertyUnsupportedDescription { + get { + return ResourceManager.GetString("RefValuePropertyUnsupportedDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The 'Value' property on the native type '{0}' must not be a 'ref' or 'readonly ref' property.. + /// + internal static string RefValuePropertyUnsupportedMessage { + get { + return ResourceManager.GetString("RefValuePropertyUnsupportedMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to An abstract type derived from 'SafeHandle' cannot be marshalled by reference. The provided type must be concrete.. + /// + internal static string SafeHandleByRefMustBeConcrete { + get { + return ResourceManager.GetString("SafeHandleByRefMustBeConcrete", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to When constructor taking a Span<byte> is specified on the native type, the type must also have a public integer constant named StackBufferSize to provide the size of the stack-allocated buffer.. + /// + internal static string StackallocConstructorMustHaveStackBufferSizeConstantDescription { + get { + return ResourceManager.GetString("StackallocConstructorMustHaveStackBufferSizeConstantDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The native type '{0}' must have a 'public const int StackBufferSize' field that specifies the size of the stack buffer because it has a constructor that takes a stack-allocated Span<byte>. + /// + internal static string StackallocConstructorMustHaveStackBufferSizeConstantMessage { + get { + return ResourceManager.GetString("StackallocConstructorMustHaveStackBufferSizeConstantMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to A type that supports marshalling from managed to native by stack allocation should also support marshalling from managed to native where stack allocation is impossible.. + /// + internal static string StackallocMarshallingShouldSupportAllocatingMarshallingFallbackDescription { + get { + return ResourceManager.GetString("StackallocMarshallingShouldSupportAllocatingMarshallingFallbackDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Native type '{0}' has a stack-allocating constructor does not support marshalling in scenarios where stack allocation is impossible. + /// + internal static string StackallocMarshallingShouldSupportAllocatingMarshallingFallbackMessage { + get { + return ResourceManager.GetString("StackallocMarshallingShouldSupportAllocatingMarshallingFallbackMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to P/Invoke source generation is only supported on .NET {0} or above. The generated source will not be compatible with other frameworks.. + /// + internal static string TargetFrameworkNotSupportedDescription { + get { + return ResourceManager.GetString("TargetFrameworkNotSupportedDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to 'GeneratedDllImportAttribute' cannot be used for source-generated P/Invokes on the current target framework. Source-generated P/Invokes require .NET {0} or above.. + /// + internal static string TargetFrameworkNotSupportedMessage { + get { + return ResourceManager.GetString("TargetFrameworkNotSupportedMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Current target framework is not supported by source-generated P/Invokes. + /// + internal static string TargetFrameworkNotSupportedTitle { + get { + return ResourceManager.GetString("TargetFrameworkNotSupportedTitle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to For types that are not supported by source-generated P/Invokes, the resulting P/Invoke will rely on the underlying runtime to marshal the specified type.. + /// + internal static string TypeNotSupportedDescription { + get { + return ResourceManager.GetString("TypeNotSupportedDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The type '{0}' is not supported by source-generated P/Invokes. The generated source will not handle marshalling of parameter '{1}'.. + /// + internal static string TypeNotSupportedMessageParameter { + get { + return ResourceManager.GetString("TypeNotSupportedMessageParameter", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0} The generated source will not handle marshalling of parameter '{1}'.. + /// + internal static string TypeNotSupportedMessageParameterWithDetails { + get { + return ResourceManager.GetString("TypeNotSupportedMessageParameterWithDetails", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The type '{0}' is not supported by source-generated P/Invokes. The generated source will not handle marshalling of the return value of method '{1}'.. + /// + internal static string TypeNotSupportedMessageReturn { + get { + return ResourceManager.GetString("TypeNotSupportedMessageReturn", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to {0} The generated source will not handle marshalling of the return value of method '{1}'.. + /// + internal static string TypeNotSupportedMessageReturnWithDetails { + get { + return ResourceManager.GetString("TypeNotSupportedMessageReturnWithDetails", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Specified type is not supported by source-generated P/Invokes. + /// + internal static string TypeNotSupportedTitle { + get { + return ResourceManager.GetString("TypeNotSupportedTitle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The native type's 'Value' property must have a getter to support marshalling from managed to native.. + /// + internal static string ValuePropertyMustHaveGetterDescription { + get { + return ResourceManager.GetString("ValuePropertyMustHaveGetterDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The 'Value' property on the native type '{0}' must have a getter. + /// + internal static string ValuePropertyMustHaveGetterMessage { + get { + return ResourceManager.GetString("ValuePropertyMustHaveGetterMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The native type's 'Value' property must have a setter to support marshalling from native to managed.. + /// + internal static string ValuePropertyMustHaveSetterDescription { + get { + return ResourceManager.GetString("ValuePropertyMustHaveSetterDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The 'Value' property on the native type '{0}' must have a setter. + /// + internal static string ValuePropertyMustHaveSetterMessage { + get { + return ResourceManager.GetString("ValuePropertyMustHaveSetterMessage", resourceCulture); + } + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/Resources.resx b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/Resources.resx new file mode 100644 index 0000000000000..3124872bc3175 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/Resources.resx @@ -0,0 +1,316 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + A type marked with 'BlittableTypeAttribute' must be blittable. + + + Type '{0}' is marked with 'BlittableTypeAttribute' but is not blittable + + + The 'BlittableTypeAttribute' and 'NativeMarshallingAttribute' attributes are mutually exclusive. + + + Type '{0}' is marked with 'BlittableTypeAttribute' and 'NativeMarshallingAttribute'. A type can only have one of these two attributes. + + + A native type with the 'GenericContiguousCollectionMarshallerAttribute' must have at least one of the two marshalling methods as well as a 'ManagedValues' property of type 'Span<T>' for some 'T' and a 'NativeValueStorage' property of type 'Span<byte>' to enable marshalling the managed type. + + + The native type '{0}' must be a value type and have a constructor that takes two parameters, one of type '{1}' and an 'int', or have a parameterless instance method named 'ToManaged' that returns '{1}' as well as a 'ManagedValues' property of type 'Span<T>' for some 'T' and a 'NativeValueStorage' property of type 'Span<byte>' + + + Source-generated P/Invokes will ignore any configuration that is not supported. + + + The '{0}' configuration is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + + + The specified marshalling configuration is not supported by source-generated P/Invokes. {0}. + + + The specified '{0}' configuration for parameter '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + + + The specified '{0}' configuration for the return value of method '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + + + The specified value '{0}' for '{1}' is not supported by source-generated P/Invokes. If the specified configuration is required, use a regular `DllImport` instead. + + + Specified configuration is not supported by source-generated P/Invokes. + + + Only one of 'ConstantElementCount' or 'ElementCountInfo' may be used in a 'MarshalUsingAttribute' for a given 'ElementIndirectionLevel' + + + Use 'GeneratedDllImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time + + + Mark the method '{0}' with 'GeneratedDllImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time + + + Convert to 'GeneratedDllImport' + + + Use 'GeneratedDllImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time + + + Conversion to 'GeneratedDllImport' may change behavior and compatibility. See {0} for more information. + {0} is a documentation link + + + Convert to 'GeneratedDllImport' under a preprocessor define + + + The specified parameter needs to be marshalled from managed to native, but the native type '{0}' does not support it. + + + The specified parameter needs to be marshalled from native to managed, but the native type '{0}' does not support it. + + + Types that contain methods marked with 'GeneratedDllImportAttribute' must be 'partial'. P/Invoke source generation will ignore methods contained within non-partial types. + + + Type '{0}' contains methods marked with 'GeneratedDllImportAttribute' and should be 'partial'. P/Invoke source generation will ignore methods contained within non-partial types. + + + Types that contain methods marked with 'GeneratedDllImportAttribute' must be 'partial'. + + + Methods marked with 'GeneratedDllImportAttribute' should be 'static' and 'partial'. P/Invoke source generation will ignore methods that are not 'static' and 'partial'. + + + Method '{0}' should be 'static' and 'partial' when marked with 'GeneratedDllImportAttribute'. P/Invoke source generation will ignore methods that are not 'static' and 'partial'. + + + Method marked with 'GeneratedDllImportAttribute' should be 'static' and 'partial' + + + The return type of 'GetPinnableReference' (after accounting for 'ref') must be blittable. + + + The dereferenced type of the return type of the 'GetPinnableReference' method must be blittable + + + A type that supports marshalling from managed to native by pinning should also support marshalling from managed to native where pinning is impossible. + + + Type '{0}' has a 'GetPinnableReference' method but its native type does not support marshalling in scenarios where pinning is impossible + + + The native type '{0}' must be a closed generic so the emitted code can use a specific instantiation. + + + The native type '{0}' must be a closed generic or have the same number of generic parameters as the managed type so the emitted code can use a specific instantiation. + + + The native type '{0}' for managed type '{1}' must be a closed generic type or have the same arity as the managed type. + + + A native type for a given type must be blittable. + + + The native type '{0}' for the type '{1}' is not blittable + + + A native type for a given type must be non-null. + + + The native type for the type '{0}' is null + + + The native type must be pointer sized so the pinned result of 'GetPinnableReference' can be cast to the native type. + + + The native type '{0}' must be pointer sized because the managed type '{1}' has a 'GetPinnableReference' method + + + The native type must have at least one of the two marshalling methods to enable marshalling the managed type. + + + The native type '{0}' must be a value type and have a constructor that takes one parameter of type '{1}' or a parameterless instance method named 'ToManaged' that returns '{1}' + + + The 'Value' property must not be a 'ref' or 'readonly ref' property. + + + The 'Value' property on the native type '{0}' must not be a 'ref' or 'readonly ref' property. + + + An abstract type derived from 'SafeHandle' cannot be marshalled by reference. The provided type must be concrete. + + + When constructor taking a Span<byte> is specified on the native type, the type must also have a public integer constant named StackBufferSize to provide the size of the stack-allocated buffer. + + + The native type '{0}' must have a 'public const int StackBufferSize' field that specifies the size of the stack buffer because it has a constructor that takes a stack-allocated Span<byte> + + + A type that supports marshalling from managed to native by stack allocation should also support marshalling from managed to native where stack allocation is impossible. + + + Native type '{0}' has a stack-allocating constructor does not support marshalling in scenarios where stack allocation is impossible + + + P/Invoke source generation is only supported on .NET {0} or above. The generated source will not be compatible with other frameworks. + {0} is a version number + + + 'GeneratedDllImportAttribute' cannot be used for source-generated P/Invokes on the current target framework. Source-generated P/Invokes require .NET {0} or above. + {0} is a version number + + + Current target framework is not supported by source-generated P/Invokes + + + For types that are not supported by source-generated P/Invokes, the resulting P/Invoke will rely on the underlying runtime to marshal the specified type. + + + The type '{0}' is not supported by source-generated P/Invokes. The generated source will not handle marshalling of parameter '{1}'. + + + {0} The generated source will not handle marshalling of parameter '{1}'. + {0} is a message containing additional details about what is not supported +{1} is the name of the parameter + + + The type '{0}' is not supported by source-generated P/Invokes. The generated source will not handle marshalling of the return value of method '{1}'. + + + {0} The generated source will not handle marshalling of the return value of method '{1}'. + {0} is a message containing additional details about what is not supported +{1} is the name of the method + + + Specified type is not supported by source-generated P/Invokes + + + The native type's 'Value' property must have a getter to support marshalling from managed to native. + + + The 'Value' property on the native type '{0}' must have a getter + + + The native type's 'Value' property must have a setter to support marshalling from native to managed. + + + The 'Value' property on the native type '{0}' must have a setter + + \ No newline at end of file diff --git a/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/UnreachableException.cs b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/UnreachableException.cs new file mode 100644 index 0000000000000..ef9da5905e4b2 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/DllImportGenerator/UnreachableException.cs @@ -0,0 +1,16 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Microsoft.Interop +{ + /// + /// An exception that should be thrown on code-paths that are unreachable. + /// + internal class UnreachableException : Exception + { + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ContiguousCollectionElementMarshallingCodeContext.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ContiguousCollectionElementMarshallingCodeContext.cs new file mode 100644 index 0000000000000..02d965c9f29ce --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ContiguousCollectionElementMarshallingCodeContext.cs @@ -0,0 +1,70 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.Interop +{ + internal sealed class ContiguousCollectionElementMarshallingCodeContext : StubCodeContext + { + private readonly string _nativeSpanIdentifier; + + public override bool SingleFrameSpansNativeContext => false; + + public override bool AdditionalTemporaryStateLivesAcrossStages => false; + + public string IndexerIdentifier { get; } + + /// + /// Create a for marshalling elements of an collection. + /// + /// The current marshalling stage. + /// The indexer in the loop to get the element to marshal from the collection. + /// The identifier of the native value storage cast to the target element type. + /// The parent context. + public ContiguousCollectionElementMarshallingCodeContext( + Stage currentStage, + string nativeSpanIdentifier, + StubCodeContext parentContext) + { + CurrentStage = currentStage; + IndexerIdentifier = CalculateIndexerIdentifierBasedOnParentContext(parentContext); + _nativeSpanIdentifier = nativeSpanIdentifier; + ParentContext = parentContext; + } + + /// + /// Get managed and native instance identifiers for the + /// + /// Object for which to get identifiers + /// Managed and native identifiers + public override (string managed, string native) GetIdentifiers(TypePositionInfo info) + { + (string _, string native) = ParentContext!.GetIdentifiers(info); + return ( + $"{native}.ManagedValues[{IndexerIdentifier}]", + $"{_nativeSpanIdentifier}[{IndexerIdentifier}]" + ); + } + + public override string GetAdditionalIdentifier(TypePositionInfo info, string name) + { + return $"{_nativeSpanIdentifier}__{IndexerIdentifier}__{name}"; + } + + private static string CalculateIndexerIdentifierBasedOnParentContext(StubCodeContext? parentContext) + { + int i = 0; + while (parentContext is StubCodeContext context) + { + if (context is ContiguousCollectionElementMarshallingCodeContext) + { + i++; + } + parentContext = context.ParentContext; + } + + // Follow a progression of indexers of the following form: + // __i0, __i1, __i2, __i3, etc/ + return $"__i{i}"; + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/IGeneratorDiagnostics.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/IGeneratorDiagnostics.cs new file mode 100644 index 0000000000000..58375bd955ef6 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/IGeneratorDiagnostics.cs @@ -0,0 +1,102 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; +using System.Linq; + +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace Microsoft.Interop +{ + public static class DiagnosticExtensions + { + public static Diagnostic CreateDiagnostic( + this ISymbol symbol, + DiagnosticDescriptor descriptor, + params object[] args) + { + return symbol.Locations.CreateDiagnostic(descriptor, args); + } + + public static Diagnostic CreateDiagnostic( + this AttributeData attributeData, + DiagnosticDescriptor descriptor, + params object[] args) + { + SyntaxReference? syntaxReference = attributeData.ApplicationSyntaxReference; + Location location = syntaxReference is not null + ? syntaxReference.GetSyntax().GetLocation() + : Location.None; + + return location.CreateDiagnostic(descriptor, args); + } + + public static Diagnostic CreateDiagnostic( + this ImmutableArray locations, + DiagnosticDescriptor descriptor, + params object[] args) + { + IEnumerable locationsInSource = locations.Where(l => l.IsInSource); + if (!locationsInSource.Any()) + return Diagnostic.Create(descriptor, Location.None, args); + + return Diagnostic.Create( + descriptor, + location: locationsInSource.First(), + additionalLocations: locationsInSource.Skip(1), + messageArgs: args); + } + + public static Diagnostic CreateDiagnostic( + this Location location, + DiagnosticDescriptor descriptor, + params object[] args) + { + return Diagnostic.Create( + descriptor, + location: location.IsInSource ? location : Location.None, + messageArgs: args); + } + } + + + public interface IGeneratorDiagnostics + { + /// + /// Report diagnostic for marshalling of a parameter/return that is not supported + /// + /// Method with the parameter/return + /// Type info for the parameter/return + /// [Optional] Specific reason for lack of support + void ReportMarshallingNotSupported( + MethodDeclarationSyntax method, + TypePositionInfo info, + string? notSupportedDetails); + + /// + /// Report diagnostic for configuration that is not supported by the DLL import source generator + /// + /// Attribute specifying the unsupported configuration + /// Name of the configuration + /// [Optiona] Unsupported configuration value + void ReportConfigurationNotSupported( + AttributeData attributeData, + string configurationName, + string? unsupportedValue); + + void ReportInvalidMarshallingAttributeInfo( + AttributeData attributeData, + string reasonResourceName, + params string[] reasonArgs); + } + + public static class IGeneratorDiagnosticsExtensions + { + public static void ReportConfigurationNotSupported(this IGeneratorDiagnostics diagnostics, AttributeData attributeData, string configurationName) + => diagnostics.ReportConfigurationNotSupported(attributeData, configurationName, null); + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/InteropGenerationOptions.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/InteropGenerationOptions.cs new file mode 100644 index 0000000000000..cb3f7dbe62ddb --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/InteropGenerationOptions.cs @@ -0,0 +1,11 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Microsoft.Interop +{ + public record InteropGenerationOptions(bool UseMarshalType, bool UseInternalUnsafeType); +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/LanguageSupport.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/LanguageSupport.cs new file mode 100644 index 0000000000000..0f983ddc28671 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/LanguageSupport.cs @@ -0,0 +1,11 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// Types defined to enable language support of various features +// in the source generator. +namespace System.Runtime.CompilerServices +{ + // Define IsExternalInit type to support records. + internal class IsExternalInit + { } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ManagedTypeInfo.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ManagedTypeInfo.cs new file mode 100644 index 0000000000000..2151a1a0dc447 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ManagedTypeInfo.cs @@ -0,0 +1,77 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Microsoft.Interop +{ + /// + /// A discriminated union that contains enough info about a managed type to determine a marshalling generator and generate code. + /// + public abstract record ManagedTypeInfo(string FullTypeName, string DiagnosticFormattedName) + { + public TypeSyntax Syntax { get; } = SyntaxFactory.ParseTypeName(FullTypeName); + + public static ManagedTypeInfo CreateTypeInfoForTypeSymbol(ITypeSymbol type) + { + string typeName = type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); + string diagonsticFormattedName = type.ToDisplayString(); + if (type.SpecialType != SpecialType.None) + { + return new SpecialTypeInfo(typeName, diagonsticFormattedName, type.SpecialType); + } + if (type.TypeKind == TypeKind.Enum) + { + return new EnumTypeInfo(typeName, diagonsticFormattedName, ((INamedTypeSymbol)type).EnumUnderlyingType!.SpecialType); + } + if (type.TypeKind == TypeKind.Pointer) + { + return new PointerTypeInfo(typeName, diagonsticFormattedName, IsFunctionPointer: false); + } + if (type.TypeKind == TypeKind.FunctionPointer) + { + return new PointerTypeInfo(typeName, diagonsticFormattedName, IsFunctionPointer: true); + } + if (type.TypeKind == TypeKind.Array && type is IArrayTypeSymbol { IsSZArray: true } arraySymbol) + { + return new SzArrayType(CreateTypeInfoForTypeSymbol(arraySymbol.ElementType)); + } + if (type.TypeKind == TypeKind.Delegate) + { + return new DelegateTypeInfo(typeName, diagonsticFormattedName); + } + return new SimpleManagedTypeInfo(typeName, diagonsticFormattedName); + } + } + + public sealed record SpecialTypeInfo(string FullTypeName, string DiagnosticFormattedName, SpecialType SpecialType) : ManagedTypeInfo(FullTypeName, DiagnosticFormattedName) + { + public static readonly SpecialTypeInfo Int32 = new("int", "int", SpecialType.System_Int32); + public static readonly SpecialTypeInfo Void = new("void", "void", SpecialType.System_Void); + + public bool Equals(SpecialTypeInfo? other) + { + return other is not null && SpecialType == other.SpecialType; + } + + public override int GetHashCode() + { + return (int)SpecialType; + } + } + + public sealed record EnumTypeInfo(string FullTypeName, string DiagnosticFormattedName, SpecialType UnderlyingType) : ManagedTypeInfo(FullTypeName, DiagnosticFormattedName); + + public sealed record PointerTypeInfo(string FullTypeName, string DiagnosticFormattedName, bool IsFunctionPointer) : ManagedTypeInfo(FullTypeName, DiagnosticFormattedName); + + public sealed record SzArrayType(ManagedTypeInfo ElementTypeInfo) : ManagedTypeInfo($"{ElementTypeInfo.FullTypeName}[]", $"{ElementTypeInfo.DiagnosticFormattedName}[]"); + + public sealed record DelegateTypeInfo(string FullTypeName, string DiagnosticFormattedName) : ManagedTypeInfo(FullTypeName, DiagnosticFormattedName); + + public sealed record SimpleManagedTypeInfo(string FullTypeName, string DiagnosticFormattedName) : ManagedTypeInfo(FullTypeName, DiagnosticFormattedName); +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ManualTypeMarshallingHelper.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ManualTypeMarshallingHelper.cs new file mode 100644 index 0000000000000..503cae185ec9d --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ManualTypeMarshallingHelper.cs @@ -0,0 +1,146 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Linq; +using Microsoft.CodeAnalysis; + +namespace Microsoft.Interop +{ + public static class ManualTypeMarshallingHelper + { + public const string ValuePropertyName = "Value"; + public const string GetPinnableReferenceName = "GetPinnableReference"; + public const string StackBufferSizeFieldName = "StackBufferSize"; + public const string ToManagedMethodName = "ToManaged"; + public const string FreeNativeMethodName = "FreeNative"; + public const string ManagedValuesPropertyName = "ManagedValues"; + public const string NativeValueStoragePropertyName = "NativeValueStorage"; + public const string SetUnmarshalledCollectionLengthMethodName = "SetUnmarshalledCollectionLength"; + + public static class MarshalUsingProperties + { + public const string ElementIndirectionLevel = nameof(ElementIndirectionLevel); + public const string CountElementName = nameof(CountElementName); + public const string ConstantElementCount = nameof(ConstantElementCount); + } + + public enum NativeTypeMarshallingVariant + { + Standard, + ContiguousCollection + } + + public static bool HasToManagedMethod(ITypeSymbol nativeType, ITypeSymbol managedType) + { + return nativeType.GetMembers(ToManagedMethodName) + .OfType() + .Any(m => m.Parameters.IsEmpty + && !m.ReturnsByRef + && !m.ReturnsByRefReadonly + && SymbolEqualityComparer.Default.Equals(m.ReturnType, managedType) + && !m.IsStatic); + } + + public static bool IsManagedToNativeConstructor( + IMethodSymbol ctor, + ITypeSymbol managedType, + NativeTypeMarshallingVariant variant) + { + if (variant == NativeTypeMarshallingVariant.ContiguousCollection) + { + return ctor.Parameters.Length == 2 + && SymbolEqualityComparer.Default.Equals(managedType, ctor.Parameters[0].Type) + && ctor.Parameters[1].Type.SpecialType == SpecialType.System_Int32; + } + return ctor.Parameters.Length == 1 + && SymbolEqualityComparer.Default.Equals(managedType, ctor.Parameters[0].Type); + } + + public static bool IsStackallocConstructor( + IMethodSymbol ctor, + ITypeSymbol managedType, + ITypeSymbol spanOfByte, + NativeTypeMarshallingVariant variant) + { + if (variant == NativeTypeMarshallingVariant.ContiguousCollection) + { + return ctor.Parameters.Length == 3 + && SymbolEqualityComparer.Default.Equals(managedType, ctor.Parameters[0].Type) + && SymbolEqualityComparer.Default.Equals(spanOfByte, ctor.Parameters[1].Type) + && ctor.Parameters[2].Type.SpecialType == SpecialType.System_Int32; + } + return ctor.Parameters.Length == 2 + && SymbolEqualityComparer.Default.Equals(managedType, ctor.Parameters[0].Type) + && SymbolEqualityComparer.Default.Equals(spanOfByte, ctor.Parameters[1].Type); + } + + public static IMethodSymbol? FindGetPinnableReference(ITypeSymbol type) + { + // Lookup a GetPinnableReference method based on the spec for the pattern-based + // fixed statement. We aren't supporting a GetPinnableReference extension method + // (which is apparently supported in the compiler). + // https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-7.3/pattern-based-fixed + return type.GetMembers(GetPinnableReferenceName) + .OfType() + .FirstOrDefault(m => m is { Parameters: { Length: 0 } } and + ({ ReturnsByRef: true } or { ReturnsByRefReadonly: true })); + } + + public static IPropertySymbol? FindValueProperty(ITypeSymbol type) + { + return type.GetMembers(ValuePropertyName) + .OfType() + .FirstOrDefault(p => !p.IsStatic); + } + + public static bool HasFreeNativeMethod(ITypeSymbol type) + { + return type.GetMembers(FreeNativeMethodName) + .OfType() + .Any(m => m is { IsStatic: false, Parameters: { Length: 0 }, ReturnType: { SpecialType: SpecialType.System_Void } }); + } + + public static bool TryGetManagedValuesProperty(ITypeSymbol type, out IPropertySymbol managedValuesProperty) + { + managedValuesProperty = type + .GetMembers(ManagedValuesPropertyName) + .OfType() + .FirstOrDefault(p => p is { IsStatic: false, GetMethod: not null, ReturnsByRef: false, ReturnsByRefReadonly: false }); + return managedValuesProperty is not null; + } + + public static bool TryGetElementTypeFromContiguousCollectionMarshaller(ITypeSymbol type, out ITypeSymbol elementType) + { + if (!TryGetManagedValuesProperty(type, out IPropertySymbol managedValuesProperty)) + { + elementType = null!; + return false; + } + + elementType = ((INamedTypeSymbol)managedValuesProperty.Type).TypeArguments[0]; + return true; + } + + public static bool HasSetUnmarshalledCollectionLengthMethod(ITypeSymbol type) + { + return type.GetMembers(SetUnmarshalledCollectionLengthMethodName) + .OfType() + .Any(m => m is + { + IsStatic: false, + Parameters: { Length: 1 }, + ReturnType: { SpecialType: SpecialType.System_Void } + } && m.Parameters[0].Type.SpecialType == SpecialType.System_Int32); + } + + public static bool HasNativeValueStorageProperty(ITypeSymbol type, ITypeSymbol spanOfByte) + { + return type + .GetMembers(NativeValueStoragePropertyName) + .OfType() + .Any(p => p is { IsStatic: false, GetMethod: not null, ReturnsByRef: false, ReturnsByRefReadonly: false } + && SymbolEqualityComparer.Default.Equals(p.Type, spanOfByte)); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ArrayMarshaller.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ArrayMarshaller.cs new file mode 100644 index 0000000000000..82ee55861816f --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ArrayMarshaller.cs @@ -0,0 +1,146 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; + +namespace Microsoft.Interop +{ + public sealed class ArrayMarshaller : IMarshallingGenerator + { + private readonly IMarshallingGenerator _manualMarshallingGenerator; + private readonly TypeSyntax _elementType; + private readonly bool _enablePinning; + private readonly InteropGenerationOptions _options; + + public ArrayMarshaller(IMarshallingGenerator manualMarshallingGenerator, TypeSyntax elementType, bool enablePinning, InteropGenerationOptions options) + { + _manualMarshallingGenerator = manualMarshallingGenerator; + _elementType = elementType; + _enablePinning = enablePinning; + _options = options; + } + + public ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context) + { + if (IsPinningPathSupported(info, context)) + { + string identifier = context.GetIdentifiers(info).native; + return Argument(CastExpression(AsNativeType(info), IdentifierName(identifier))); + } + return _manualMarshallingGenerator.AsArgument(info, context); + } + + public TypeSyntax AsNativeType(TypePositionInfo info) + { + return _manualMarshallingGenerator.AsNativeType(info); + } + + public ParameterSyntax AsParameter(TypePositionInfo info) + { + return _manualMarshallingGenerator.AsParameter(info); + } + + public IEnumerable Generate(TypePositionInfo info, StubCodeContext context) + { + if (IsPinningPathSupported(info, context)) + { + return GeneratePinningPath(info, context); + } + return _manualMarshallingGenerator.Generate(info, context); + } + + public bool SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, StubCodeContext context) + { + if (context.SingleFrameSpansNativeContext && _enablePinning) + { + return false; + } + return marshalKind.HasFlag(ByValueContentsMarshalKind.Out); + } + + public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) + { + if (IsPinningPathSupported(info, context)) + { + return false; + } + return _manualMarshallingGenerator.UsesNativeIdentifier(info, context); + } + + private bool IsPinningPathSupported(TypePositionInfo info, StubCodeContext context) + { + return context.SingleFrameSpansNativeContext && _enablePinning && !info.IsByRef && !info.IsManagedReturnPosition; + } + + private IEnumerable GeneratePinningPath(TypePositionInfo info, StubCodeContext context) + { + (string managedIdentifer, string nativeIdentifier) = context.GetIdentifiers(info); + string byRefIdentifier = $"__byref_{managedIdentifer}"; + TypeSyntax arrayElementType = _elementType; + if (context.CurrentStage == StubCodeContext.Stage.Marshal) + { + // [COMPAT] We use explicit byref calculations here instead of just using a fixed statement + // since a fixed statement converts a zero-length array to a null pointer. + // Many native APIs, such as GDI+, ICU, etc. validate that an array parameter is non-null + // even when the passed in array length is zero. To avoid breaking customers that want to move + // to source-generated interop in subtle ways, we explicitly pass a reference to the 0-th element + // of an array as long as it is non-null, matching the behavior of the built-in interop system + // for single-dimensional zero-based arrays. + + // ref = == null ? ref *(); + PrefixUnaryExpressionSyntax nullRef = + PrefixUnaryExpression(SyntaxKind.PointerIndirectionExpression, + CastExpression( + PointerType(arrayElementType), + LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(0)))); + + InvocationExpressionSyntax getArrayDataReference = + InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + ParseTypeName(TypeNames.System_Runtime_InteropServices_MemoryMarshal), + IdentifierName("GetArrayDataReference")), + ArgumentList(SingletonSeparatedList( + Argument(IdentifierName(managedIdentifer))))); + + yield return LocalDeclarationStatement( + VariableDeclaration( + RefType(arrayElementType)) + .WithVariables(SingletonSeparatedList( + VariableDeclarator(Identifier(byRefIdentifier)) + .WithInitializer(EqualsValueClause( + RefExpression(ParenthesizedExpression( + ConditionalExpression( + BinaryExpression( + SyntaxKind.EqualsExpression, + IdentifierName(managedIdentifer), + LiteralExpression( + SyntaxKind.NullLiteralExpression)), + RefExpression(nullRef), + RefExpression(getArrayDataReference))))))))); + } + if (context.CurrentStage == StubCodeContext.Stage.Pin) + { + // fixed ( = &Unsafe.As(ref )) + yield return FixedStatement( + VariableDeclaration(AsNativeType(info), SingletonSeparatedList( + VariableDeclarator(nativeIdentifier) + .WithInitializer(EqualsValueClause( + PrefixUnaryExpression(SyntaxKind.AddressOfExpression, + InvocationExpression( + MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, + ParseTypeName(TypeNames.Unsafe(_options)), + GenericName("As").AddTypeArgumentListArguments( + arrayElementType, + PredefinedType(Token(SyntaxKind.ByteKeyword))))) + .AddArgumentListArguments( + Argument(IdentifierName(byRefIdentifier)) + .WithRefKindKeyword(Token(SyntaxKind.RefKeyword)))))))), + EmptyStatement()); + } + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/AttributedMarshallingModelGeneratorFactory.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/AttributedMarshallingModelGeneratorFactory.cs new file mode 100644 index 0000000000000..69114bfc341e3 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/AttributedMarshallingModelGeneratorFactory.cs @@ -0,0 +1,292 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; + +namespace Microsoft.Interop +{ + public class AttributedMarshallingModelGeneratorFactory : IMarshallingGeneratorFactory + { + private static readonly BlittableMarshaller s_blittable = new BlittableMarshaller(); + private static readonly Forwarder s_forwarder = new Forwarder(); + + private readonly IMarshallingGeneratorFactory _innerMarshallingGenerator; + + public AttributedMarshallingModelGeneratorFactory(IMarshallingGeneratorFactory innerMarshallingGenerator, InteropGenerationOptions options) + { + Options = options; + _innerMarshallingGenerator = innerMarshallingGenerator; + ElementMarshallingGeneratorFactory = this; + } + + public InteropGenerationOptions Options { get; } + + /// + /// The to use for collection elements. + /// This property is settable to enable decorating factories to ensure that element marshalling also goes through the decorator support. + /// + public IMarshallingGeneratorFactory ElementMarshallingGeneratorFactory { get; set; } + + public IMarshallingGenerator Create(TypePositionInfo info, StubCodeContext context) + { + return info.MarshallingAttributeInfo switch + { + NativeMarshallingAttributeInfo marshalInfo => CreateCustomNativeTypeMarshaller(info, context, marshalInfo), + BlittableTypeAttributeInfo => s_blittable, + GeneratedNativeMarshallingAttributeInfo => s_forwarder, + _ => _innerMarshallingGenerator.Create(info, context) + }; + } + + private static ExpressionSyntax GetNumElementsExpressionFromMarshallingInfo(TypePositionInfo info, CountInfo count, StubCodeContext context) + { + return count switch + { + SizeAndParamIndexInfo(int size, SizeAndParamIndexInfo.UnspecifiedParam) => GetConstSizeExpression(size), + ConstSizeCountInfo(int size) => GetConstSizeExpression(size), + SizeAndParamIndexInfo(SizeAndParamIndexInfo.UnspecifiedConstSize, TypePositionInfo param) => CheckedExpression(SyntaxKind.CheckedExpression, GetExpressionForParam(param)), + SizeAndParamIndexInfo(int size, TypePositionInfo param) => CheckedExpression(SyntaxKind.CheckedExpression, BinaryExpression(SyntaxKind.AddExpression, GetConstSizeExpression(size), GetExpressionForParam(param))), + CountElementCountInfo(TypePositionInfo elementInfo) => CheckedExpression(SyntaxKind.CheckedExpression, GetExpressionForParam(elementInfo)), + _ => throw new MarshallingNotSupportedException(info, context) + { + NotSupportedDetails = Resources.ArraySizeMustBeSpecified + }, + }; + + static LiteralExpressionSyntax GetConstSizeExpression(int size) + { + return LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(size)); + } + + ExpressionSyntax GetExpressionForParam(TypePositionInfo paramInfo) + { + ExpressionSyntax numElementsExpression = GetIndexedNumElementsExpression( + context, + paramInfo, + out int numIndirectionLevels); + + ManagedTypeInfo type = paramInfo.ManagedType; + MarshallingInfo marshallingInfo = paramInfo.MarshallingAttributeInfo; + + for (int i = 0; i < numIndirectionLevels; i++) + { + if (marshallingInfo is NativeContiguousCollectionMarshallingInfo collectionInfo) + { + type = collectionInfo.ElementType; + marshallingInfo = collectionInfo.ElementMarshallingInfo; + } + else + { + throw new MarshallingNotSupportedException(info, context) + { + NotSupportedDetails = Resources.CollectionSizeParamTypeMustBeIntegral + }; + } + } + + if (type is not SpecialTypeInfo specialType || !specialType.SpecialType.IsIntegralType()) + { + throw new MarshallingNotSupportedException(info, context) + { + NotSupportedDetails = Resources.CollectionSizeParamTypeMustBeIntegral + }; + } + + return CastExpression( + PredefinedType(Token(SyntaxKind.IntKeyword)), + ParenthesizedExpression(numElementsExpression)); + } + + static ExpressionSyntax GetIndexedNumElementsExpression(StubCodeContext context, TypePositionInfo numElementsInfo, out int numIndirectionLevels) + { + Stack indexerStack = new(); + + StubCodeContext? currentContext = context; + StubCodeContext lastContext = null!; + + while (currentContext is not null) + { + if (currentContext is ContiguousCollectionElementMarshallingCodeContext collectionContext) + { + indexerStack.Push(collectionContext.IndexerIdentifier); + } + lastContext = currentContext; + currentContext = currentContext.ParentContext; + } + + numIndirectionLevels = indexerStack.Count; + + ExpressionSyntax indexedNumElements = IdentifierName(lastContext.GetIdentifiers(numElementsInfo).managed); + while (indexerStack.Count > 0) + { + NameSyntax indexer = IdentifierName(indexerStack.Pop()); + indexedNumElements = ElementAccessExpression(indexedNumElements) + .AddArgumentListArguments(Argument(indexer)); + } + + return indexedNumElements; + } + } + + private IMarshallingGenerator CreateCustomNativeTypeMarshaller(TypePositionInfo info, StubCodeContext context, NativeMarshallingAttributeInfo marshalInfo) + { + ValidateCustomNativeTypeMarshallingSupported(info, context, marshalInfo); + + ICustomNativeTypeMarshallingStrategy marshallingStrategy = new SimpleCustomNativeTypeMarshalling(marshalInfo.NativeMarshallingType.Syntax); + + if ((marshalInfo.MarshallingFeatures & CustomMarshallingFeatures.ManagedToNativeStackalloc) != 0) + { + marshallingStrategy = new StackallocOptimizationMarshalling(marshallingStrategy); + } + + if ((marshalInfo.MarshallingFeatures & CustomMarshallingFeatures.FreeNativeResources) != 0) + { + marshallingStrategy = new FreeNativeCleanupStrategy(marshallingStrategy); + } + + // Collections have extra configuration, so handle them here. + if (marshalInfo is NativeContiguousCollectionMarshallingInfo collectionMarshallingInfo) + { + return CreateNativeCollectionMarshaller(info, context, collectionMarshallingInfo, marshallingStrategy); + } + + if (marshalInfo.ValuePropertyType is not null) + { + marshallingStrategy = DecorateWithValuePropertyStrategy(marshalInfo, marshallingStrategy); + } + + IMarshallingGenerator marshallingGenerator = new CustomNativeTypeMarshallingGenerator(marshallingStrategy, enableByValueContentsMarshalling: false); + + if ((marshalInfo.MarshallingFeatures & CustomMarshallingFeatures.ManagedTypePinning) != 0) + { + return new PinnableManagedValueMarshaller(marshallingGenerator); + } + + return marshallingGenerator; + } + + private void ValidateCustomNativeTypeMarshallingSupported(TypePositionInfo info, StubCodeContext context, NativeMarshallingAttributeInfo marshalInfo) + { + // The marshalling method for this type doesn't support marshalling from native to managed, + // but our scenario requires marshalling from native to managed. + if ((info.RefKind == RefKind.Ref || info.RefKind == RefKind.Out || info.IsManagedReturnPosition) + && (marshalInfo.MarshallingFeatures & CustomMarshallingFeatures.NativeToManaged) == 0) + { + throw new MarshallingNotSupportedException(info, context) + { + NotSupportedDetails = string.Format(Resources.CustomTypeMarshallingNativeToManagedUnsupported, marshalInfo.NativeMarshallingType.FullTypeName) + }; + } + // The marshalling method for this type doesn't support marshalling from managed to native by value, + // but our scenario requires marshalling from managed to native by value. + else if (!info.IsByRef + && (marshalInfo.MarshallingFeatures & CustomMarshallingFeatures.ManagedToNative) == 0 + && (context.SingleFrameSpansNativeContext && (marshalInfo.MarshallingFeatures & (CustomMarshallingFeatures.ManagedTypePinning | CustomMarshallingFeatures.ManagedToNativeStackalloc)) == 0)) + { + throw new MarshallingNotSupportedException(info, context) + { + NotSupportedDetails = string.Format(Resources.CustomTypeMarshallingManagedToNativeUnsupported, marshalInfo.NativeMarshallingType.FullTypeName) + }; + } + // The marshalling method for this type doesn't support marshalling from managed to native by reference, + // but our scenario requires marshalling from managed to native by reference. + // "in" byref supports stack marshalling. + else if (info.RefKind == RefKind.In + && (marshalInfo.MarshallingFeatures & CustomMarshallingFeatures.ManagedToNative) == 0 + && !(context.SingleFrameSpansNativeContext && (marshalInfo.MarshallingFeatures & CustomMarshallingFeatures.ManagedToNativeStackalloc) != 0)) + { + throw new MarshallingNotSupportedException(info, context) + { + NotSupportedDetails = string.Format(Resources.CustomTypeMarshallingManagedToNativeUnsupported, marshalInfo.NativeMarshallingType.FullTypeName) + }; + } + // The marshalling method for this type doesn't support marshalling from managed to native by reference, + // but our scenario requires marshalling from managed to native by reference. + // "ref" byref marshalling doesn't support stack marshalling + else if (info.RefKind == RefKind.Ref + && (marshalInfo.MarshallingFeatures & CustomMarshallingFeatures.ManagedToNative) == 0) + { + throw new MarshallingNotSupportedException(info, context) + { + NotSupportedDetails = string.Format(Resources.CustomTypeMarshallingManagedToNativeUnsupported, marshalInfo.NativeMarshallingType.FullTypeName) + }; + } + } + + private ICustomNativeTypeMarshallingStrategy DecorateWithValuePropertyStrategy(NativeMarshallingAttributeInfo marshalInfo, ICustomNativeTypeMarshallingStrategy nativeTypeMarshaller) + { + TypeSyntax valuePropertyTypeSyntax = marshalInfo.ValuePropertyType!.Syntax; + + if ((marshalInfo.MarshallingFeatures & CustomMarshallingFeatures.NativeTypePinning) != 0) + { + return new PinnableMarshallerTypeMarshalling(nativeTypeMarshaller, valuePropertyTypeSyntax); + } + + return new CustomNativeTypeWithValuePropertyMarshalling(nativeTypeMarshaller, valuePropertyTypeSyntax); + } + + private IMarshallingGenerator CreateNativeCollectionMarshaller( + TypePositionInfo info, + StubCodeContext context, + NativeContiguousCollectionMarshallingInfo collectionInfo, + ICustomNativeTypeMarshallingStrategy marshallingStrategy) + { + var elementInfo = new TypePositionInfo(collectionInfo.ElementType, collectionInfo.ElementMarshallingInfo) { ManagedIndex = info.ManagedIndex }; + IMarshallingGenerator elementMarshaller = Create( + elementInfo, + new ContiguousCollectionElementMarshallingCodeContext(StubCodeContext.Stage.Setup, string.Empty, context)); + TypeSyntax elementType = elementMarshaller.AsNativeType(elementInfo); + + bool isBlittable = elementMarshaller is BlittableMarshaller; + + if (isBlittable) + { + marshallingStrategy = new ContiguousBlittableElementCollectionMarshalling(marshallingStrategy, collectionInfo.ElementType.Syntax); + } + else + { + marshallingStrategy = new ContiguousNonBlittableElementCollectionMarshalling(marshallingStrategy, elementMarshaller, elementInfo); + } + + // Explicitly insert the Value property handling here (before numElements handling) so that the numElements handling will be emitted before the Value property handling in unmarshalling. + if (collectionInfo.ValuePropertyType is not null) + { + marshallingStrategy = DecorateWithValuePropertyStrategy(collectionInfo, marshallingStrategy); + } + + ExpressionSyntax numElementsExpression = LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(0)); + if (info.IsManagedReturnPosition || (info.IsByRef && info.RefKind != RefKind.In)) + { + // In this case, we need a numElementsExpression supplied from metadata, so we'll calculate it here. + numElementsExpression = GetNumElementsExpressionFromMarshallingInfo(info, collectionInfo.ElementCountInfo, context); + } + + marshallingStrategy = new NumElementsExpressionMarshalling( + marshallingStrategy, + numElementsExpression, + SizeOfExpression(elementType)); + + if (collectionInfo.UseDefaultMarshalling && info.ManagedType is SzArrayType) + { + return new ArrayMarshaller( + new CustomNativeTypeMarshallingGenerator(marshallingStrategy, enableByValueContentsMarshalling: true), + elementType, + isBlittable, + Options); + } + + IMarshallingGenerator marshallingGenerator = new CustomNativeTypeMarshallingGenerator(marshallingStrategy, enableByValueContentsMarshalling: false); + + if ((collectionInfo.MarshallingFeatures & CustomMarshallingFeatures.ManagedTypePinning) != 0) + { + return new PinnableManagedValueMarshaller(marshallingGenerator); + } + + return marshallingGenerator; + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/BlittableMarshaller.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/BlittableMarshaller.cs new file mode 100644 index 0000000000000..c68037306af57 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/BlittableMarshaller.cs @@ -0,0 +1,108 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; + +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; + +namespace Microsoft.Interop +{ + public sealed class BlittableMarshaller : IMarshallingGenerator + { + public TypeSyntax AsNativeType(TypePositionInfo info) + { + return info.ManagedType.Syntax; + } + + public ParameterSyntax AsParameter(TypePositionInfo info) + { + TypeSyntax type = info.IsByRef + ? PointerType(AsNativeType(info)) + : AsNativeType(info); + return Parameter(Identifier(info.InstanceIdentifier)) + .WithType(type); + } + + public ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context) + { + if (!info.IsByRef) + { + return Argument(IdentifierName(info.InstanceIdentifier)); + } + else if (context.SingleFrameSpansNativeContext && !info.IsManagedReturnPosition) + { + return Argument(IdentifierName(context.GetIdentifiers(info).native)); + } + return Argument( + PrefixUnaryExpression( + SyntaxKind.AddressOfExpression, + IdentifierName(context.GetIdentifiers(info).native))); + } + + public IEnumerable Generate(TypePositionInfo info, StubCodeContext context) + { + if (!info.IsByRef || info.IsManagedReturnPosition) + yield break; + + (string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(info); + + if (context.SingleFrameSpansNativeContext) + { + if (context.CurrentStage == StubCodeContext.Stage.Pin) + { + yield return FixedStatement( + VariableDeclaration( + PointerType(AsNativeType(info)), + SingletonSeparatedList( + VariableDeclarator(Identifier(nativeIdentifier)) + .WithInitializer(EqualsValueClause( + PrefixUnaryExpression(SyntaxKind.AddressOfExpression, + IdentifierName(managedIdentifier)) + )) + ) + ), + EmptyStatement() + ); + } + yield break; + } + + switch (context.CurrentStage) + { + case StubCodeContext.Stage.Setup: + break; + case StubCodeContext.Stage.Marshal: + if (info.RefKind == RefKind.Ref) + { + yield return ExpressionStatement( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + IdentifierName(nativeIdentifier), + IdentifierName(managedIdentifier))); + } + + break; + case StubCodeContext.Stage.Unmarshal: + yield return ExpressionStatement( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + IdentifierName(managedIdentifier), + IdentifierName(nativeIdentifier))); + break; + default: + break; + } + } + + public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) + { + return info.IsByRef && !info.IsManagedReturnPosition && !context.SingleFrameSpansNativeContext; + } + + public bool SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, StubCodeContext context) => false; + } + +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/BoolMarshaller.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/BoolMarshaller.cs new file mode 100644 index 0000000000000..a11a5243575fa --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/BoolMarshaller.cs @@ -0,0 +1,154 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Diagnostics; + +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; + +namespace Microsoft.Interop +{ + public abstract class BoolMarshallerBase : IMarshallingGenerator + { + private readonly PredefinedTypeSyntax _nativeType; + private readonly int _trueValue; + private readonly int _falseValue; + private readonly bool _compareToTrue; + + protected BoolMarshallerBase(PredefinedTypeSyntax nativeType, int trueValue, int falseValue, bool compareToTrue) + { + _nativeType = nativeType; + _trueValue = trueValue; + _falseValue = falseValue; + _compareToTrue = compareToTrue; + } + + public TypeSyntax AsNativeType(TypePositionInfo info) + { + Debug.Assert(info.ManagedType is SpecialTypeInfo(_, _, SpecialType.System_Boolean)); + return _nativeType; + } + + public ParameterSyntax AsParameter(TypePositionInfo info) + { + TypeSyntax type = info.IsByRef + ? PointerType(AsNativeType(info)) + : AsNativeType(info); + return Parameter(Identifier(info.InstanceIdentifier)) + .WithType(type); + } + + public ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context) + { + string identifier = context.GetIdentifiers(info).native; + if (info.IsByRef) + { + return Argument( + PrefixUnaryExpression( + SyntaxKind.AddressOfExpression, + IdentifierName(identifier))); + } + + return Argument(IdentifierName(identifier)); + } + + public IEnumerable Generate(TypePositionInfo info, StubCodeContext context) + { + (string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(info); + switch (context.CurrentStage) + { + case StubCodeContext.Stage.Setup: + break; + case StubCodeContext.Stage.Marshal: + // = ()( ? _trueValue : _falseValue); + if (info.RefKind != RefKind.Out) + { + yield return ExpressionStatement( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + IdentifierName(nativeIdentifier), + CastExpression( + AsNativeType(info), + ParenthesizedExpression( + ConditionalExpression(IdentifierName(managedIdentifier), + LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(_trueValue)), + LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(_falseValue))))))); + } + + break; + case StubCodeContext.Stage.Unmarshal: + if (info.IsManagedReturnPosition || (info.IsByRef && info.RefKind != RefKind.In)) + { + // = == _trueValue; + // or + // = != _falseValue; + (SyntaxKind binaryOp, int comparand) = _compareToTrue ? (SyntaxKind.EqualsExpression, _trueValue) : (SyntaxKind.NotEqualsExpression, _falseValue); + + yield return ExpressionStatement( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + IdentifierName(managedIdentifier), + BinaryExpression( + binaryOp, + IdentifierName(nativeIdentifier), + LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(comparand))))); + } + break; + default: + break; + } + } + + public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) => true; + + public bool SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, StubCodeContext context) => false; + } + + /// + /// Marshals a boolean value as 1 byte. + /// + /// + /// This boolean type is the natural size of a boolean in the CLR (ECMA-335 (III.1.1.2)). + /// + /// This is typically compatible with C99 + /// and C++, but those is implementation defined. + /// Consult your compiler specification. + /// + public sealed class ByteBoolMarshaller : BoolMarshallerBase + { + public ByteBoolMarshaller() + : base(PredefinedType(Token(SyntaxKind.ByteKeyword)), trueValue: 1, falseValue: 0, compareToTrue: false) + { + } + } + + /// + /// Marshals a boolean value as a 4-byte integer. + /// + /// + /// Corresponds to the definition of BOOL. + /// + public sealed class WinBoolMarshaller : BoolMarshallerBase + { + public WinBoolMarshaller() + : base(PredefinedType(Token(SyntaxKind.IntKeyword)), trueValue: 1, falseValue: 0, compareToTrue: false) + { + } + } + + /// + /// Marshal a boolean value as a VARIANT_BOOL (Windows OLE/Automation type). + /// + public sealed class VariantBoolMarshaller : BoolMarshallerBase + { + private const short VARIANT_TRUE = -1; + private const short VARIANT_FALSE = 0; + public VariantBoolMarshaller() + : base(PredefinedType(Token(SyntaxKind.ShortKeyword)), trueValue: VARIANT_TRUE, falseValue: VARIANT_FALSE, compareToTrue: true) + { + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ByValueContentsMarshalKindValidator.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ByValueContentsMarshalKindValidator.cs new file mode 100644 index 0000000000000..1d36a8789c925 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ByValueContentsMarshalKindValidator.cs @@ -0,0 +1,54 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Microsoft.Interop +{ + /// + /// An implementation that wraps an inner instance and validates that the on the provided is valid in the current marshalling scenario. + /// + public class ByValueContentsMarshalKindValidator : IMarshallingGeneratorFactory + { + private readonly IMarshallingGeneratorFactory _inner; + + public ByValueContentsMarshalKindValidator(IMarshallingGeneratorFactory inner) + { + _inner = inner; + } + + public IMarshallingGenerator Create(TypePositionInfo info, StubCodeContext context) + { + return ValidateByValueMarshalKind(info, context, _inner.Create(info, context)); + } + + private static IMarshallingGenerator ValidateByValueMarshalKind(TypePositionInfo info, StubCodeContext context, IMarshallingGenerator generator) + { + if (info.IsByRef && info.ByValueContentsMarshalKind != ByValueContentsMarshalKind.Default) + { + throw new MarshallingNotSupportedException(info, context) + { + NotSupportedDetails = Resources.InOutAttributeByRefNotSupported + }; + } + else if (info.ByValueContentsMarshalKind == ByValueContentsMarshalKind.In) + { + throw new MarshallingNotSupportedException(info, context) + { + NotSupportedDetails = Resources.InAttributeNotSupportedWithoutOut + }; + } + else if (info.ByValueContentsMarshalKind != ByValueContentsMarshalKind.Default + && !generator.SupportsByValueMarshalKind(info.ByValueContentsMarshalKind, context)) + { + throw new MarshallingNotSupportedException(info, context) + { + NotSupportedDetails = Resources.InOutAttributeMarshalerNotSupported + }; + } + return generator; + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/CharMarshaller.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/CharMarshaller.cs new file mode 100644 index 0000000000000..fb18cb531f513 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/CharMarshaller.cs @@ -0,0 +1,142 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Diagnostics; + +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; + +namespace Microsoft.Interop +{ + public sealed class Utf16CharMarshaller : IMarshallingGenerator + { + private static readonly PredefinedTypeSyntax s_nativeType = PredefinedType(Token(SyntaxKind.UShortKeyword)); + + public Utf16CharMarshaller() + { + } + + public ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context) + { + (string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(info); + if (!info.IsByRef) + { + // (ushort) + return Argument( + CastExpression( + AsNativeType(info), + IdentifierName(managedIdentifier))); + } + else if (IsPinningPathSupported(info, context)) + { + // (ushort*) + return Argument( + CastExpression( + PointerType(AsNativeType(info)), + IdentifierName(PinnedIdentifier(info.InstanceIdentifier)))); + } + + // & + return Argument( + PrefixUnaryExpression( + SyntaxKind.AddressOfExpression, + IdentifierName(nativeIdentifier))); + } + + public TypeSyntax AsNativeType(TypePositionInfo info) + { + Debug.Assert(info.ManagedType is SpecialTypeInfo(_, _, SpecialType.System_Char)); + return s_nativeType; + } + + public ParameterSyntax AsParameter(TypePositionInfo info) + { + TypeSyntax type = info.IsByRef + ? PointerType(AsNativeType(info)) + : AsNativeType(info); + return Parameter(Identifier(info.InstanceIdentifier)) + .WithType(type); + } + + public IEnumerable Generate(TypePositionInfo info, StubCodeContext context) + { + (string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(info); + + if (IsPinningPathSupported(info, context)) + { + if (context.CurrentStage == StubCodeContext.Stage.Pin) + { + // fixed (char* = &) + yield return FixedStatement( + VariableDeclaration( + PointerType(PredefinedType(Token(SyntaxKind.CharKeyword))), + SingletonSeparatedList( + VariableDeclarator(Identifier(PinnedIdentifier(info.InstanceIdentifier))) + .WithInitializer(EqualsValueClause( + PrefixUnaryExpression( + SyntaxKind.AddressOfExpression, + IdentifierName(Identifier(managedIdentifier))) + )) + ) + ), + EmptyStatement() + ); + } + yield break; + } + + switch (context.CurrentStage) + { + case StubCodeContext.Stage.Setup: + break; + case StubCodeContext.Stage.Marshal: + if (info.IsByRef && info.RefKind != RefKind.Out) + { + yield return ExpressionStatement( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + IdentifierName(nativeIdentifier), + IdentifierName(managedIdentifier))); + } + + break; + case StubCodeContext.Stage.Unmarshal: + if (info.IsManagedReturnPosition || (info.IsByRef && info.RefKind != RefKind.In)) + { + yield return ExpressionStatement( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + IdentifierName(managedIdentifier), + CastExpression( + PredefinedType( + Token(SyntaxKind.CharKeyword)), + IdentifierName(nativeIdentifier)))); + } + + break; + default: + break; + } + } + + public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) + { + return info.IsManagedReturnPosition || (info.IsByRef && !context.SingleFrameSpansNativeContext); + } + + public bool SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, StubCodeContext context) => false; + + private bool IsPinningPathSupported(TypePositionInfo info, StubCodeContext context) + { + return context.SingleFrameSpansNativeContext + && !info.IsManagedReturnPosition + && info.IsByRef; + } + + private static string PinnedIdentifier(string identifier) => $"{identifier}__pinned"; + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ConditionalStackallocMarshallingGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ConditionalStackallocMarshallingGenerator.cs new file mode 100644 index 0000000000000..2b638538904e0 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ConditionalStackallocMarshallingGenerator.cs @@ -0,0 +1,248 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; + +namespace Microsoft.Interop +{ + public abstract class ConditionalStackallocMarshallingGenerator : IMarshallingGenerator + { + protected static string GetAllocationMarkerIdentifier(TypePositionInfo info, StubCodeContext context) => context.GetAdditionalIdentifier(info, "allocated"); + + private static string GetByteLengthIdentifier(TypePositionInfo info, StubCodeContext context) => context.GetAdditionalIdentifier(info, "bytelen"); + + private static string GetStackAllocIdentifier(TypePositionInfo info, StubCodeContext context) => context.GetAdditionalIdentifier(info, "stackptr"); + + protected bool UsesConditionalStackAlloc(TypePositionInfo info, StubCodeContext context) + { + return context.SingleFrameSpansNativeContext + && (!info.IsByRef || info.RefKind == RefKind.In) + && !info.IsManagedReturnPosition + && context.AdditionalTemporaryStateLivesAcrossStages; + } + + protected bool TryGenerateSetupSyntax(TypePositionInfo info, StubCodeContext context, out StatementSyntax statement) + { + statement = EmptyStatement(); + + if (!UsesConditionalStackAlloc(info, context)) + return false; + + string allocationMarkerIdentifier = GetAllocationMarkerIdentifier(info, context); + + // bool = false; + statement = LocalDeclarationStatement( + VariableDeclaration( + PredefinedType(Token(SyntaxKind.BoolKeyword)), + SingletonSeparatedList( + VariableDeclarator(allocationMarkerIdentifier) + .WithInitializer(EqualsValueClause(LiteralExpression(SyntaxKind.FalseLiteralExpression)))))); + return true; + } + + protected IEnumerable GenerateConditionalAllocationSyntax( + TypePositionInfo info, + StubCodeContext context, + int stackallocMaxSize) + { + (_, string nativeIdentifier) = context.GetIdentifiers(info); + + string allocationMarkerIdentifier = GetAllocationMarkerIdentifier(info, context); + string byteLenIdentifier = GetByteLengthIdentifier(info, context); + string stackAllocPtrIdentifier = GetStackAllocIdentifier(info, context); + // = ; + ExpressionStatementSyntax allocationStatement = ExpressionStatement( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + IdentifierName(nativeIdentifier), + GenerateAllocationExpression(info, context, Identifier(byteLenIdentifier), out bool allocationRequiresByteLength))); + + // int = ; + LocalDeclarationStatementSyntax byteLenAssignment = LocalDeclarationStatement( + VariableDeclaration( + PredefinedType(Token(SyntaxKind.IntKeyword)), + SingletonSeparatedList( + VariableDeclarator(byteLenIdentifier) + .WithInitializer(EqualsValueClause( + GenerateByteLengthCalculationExpression(info, context)))))); + + if (!UsesConditionalStackAlloc(info, context)) + { + List statements = new List(); + if (allocationRequiresByteLength) + { + statements.Add(byteLenAssignment); + } + statements.Add(allocationStatement); + yield return ExpressionStatement(AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, + IdentifierName(nativeIdentifier), + LiteralExpression(SyntaxKind.NullLiteralExpression))); + yield return IfStatement( + GenerateNullCheckExpression(info, context), + Block(statements)); + yield break; + } + + // Code block for stackalloc if number of bytes is below threshold size + BlockSyntax marshalOnStack = Block( + // byte* = stackalloc byte[]; + LocalDeclarationStatement( + VariableDeclaration( + PointerType(PredefinedType(Token(SyntaxKind.ByteKeyword))), + SingletonSeparatedList( + VariableDeclarator(stackAllocPtrIdentifier) + .WithInitializer(EqualsValueClause( + StackAllocArrayCreationExpression( + ArrayType( + PredefinedType(Token(SyntaxKind.ByteKeyword)), + SingletonList( + ArrayRankSpecifier(SingletonSeparatedList( + IdentifierName(byteLenIdentifier))))))))))), + GenerateStackallocOnlyValueMarshalling(info, context, Identifier(byteLenIdentifier), Identifier(stackAllocPtrIdentifier)), + // = ; + ExpressionStatement( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + IdentifierName(nativeIdentifier), + CastExpression( + AsNativeType(info), + IdentifierName(stackAllocPtrIdentifier))))); + + // if ( > ) + // { + // ; + // = true; + // } + // else + // { + // byte* = stackalloc byte[]; + // ; + // = (); + // } + IfStatementSyntax allocBlock = IfStatement( + BinaryExpression( + SyntaxKind.GreaterThanExpression, + IdentifierName(byteLenIdentifier), + LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(stackallocMaxSize))), + Block( + allocationStatement, + ExpressionStatement( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + IdentifierName(allocationMarkerIdentifier), + LiteralExpression(SyntaxKind.TrueLiteralExpression)))), + ElseClause(marshalOnStack)); + + yield return IfStatement( + GenerateNullCheckExpression(info, context), + Block(byteLenAssignment, allocBlock)); + } + + protected StatementSyntax GenerateConditionalAllocationFreeSyntax( + TypePositionInfo info, + StubCodeContext context) + { + string allocationMarkerIdentifier = GetAllocationMarkerIdentifier(info, context); + if (!UsesConditionalStackAlloc(info, context)) + { + return ExpressionStatement(GenerateFreeExpression(info, context)); + } + else + { + // if () + // { + // ; + // } + return IfStatement( + IdentifierName(allocationMarkerIdentifier), + Block(ExpressionStatement(GenerateFreeExpression(info, context)))); + } + } + + /// + /// Generate an expression that allocates memory for the native representation of the object. + /// + /// Object to marshal + /// Code generation context + /// An identifier that represents how many bytes must be allocated. + /// If the allocation expression uses , true; otherwise false. + /// An expression that allocates memory for the native representation of the object. + protected abstract ExpressionSyntax GenerateAllocationExpression( + TypePositionInfo info, + StubCodeContext context, + SyntaxToken byteLengthIdentifier, + out bool allocationRequiresByteLength); + + /// + /// Generates an expression that represents the number of bytes that need to be allocated. + /// + /// Object to marshal + /// Code generation context + /// An expression that results in the number of bytes to allocate as a C# int. + protected abstract ExpressionSyntax GenerateByteLengthCalculationExpression( + TypePositionInfo info, + StubCodeContext context); + + /// + /// Generate a statement that is only executed when memory is stack allocated. + /// + /// Object to marshal + /// Code generation context + /// An identifier that represents the number of bytes allocated. + /// An identifier that represents a pointer to the stack allocated memory (of type byte*). + /// A statement that is only executed when memory is stack allocated. + protected abstract StatementSyntax GenerateStackallocOnlyValueMarshalling( + TypePositionInfo info, + StubCodeContext context, + SyntaxToken byteLengthIdentifier, + SyntaxToken stackAllocPtrIdentifier); + + /// + /// Generate code to free native allocated memory used during marshalling. + /// + /// Object to marshal + /// Code generation context + /// An expression that frees allocated memory. + protected abstract ExpressionSyntax GenerateFreeExpression( + TypePositionInfo info, + StubCodeContext context); + + /// + /// Generate code to check if the managed value is not null. + /// + /// Object to marshal + /// Code generation context + /// An expression that checks if the managed value is not null. + protected virtual ExpressionSyntax GenerateNullCheckExpression( + TypePositionInfo info, + StubCodeContext context) + { + return BinaryExpression( + SyntaxKind.NotEqualsExpression, + IdentifierName(context.GetIdentifiers(info).managed), + LiteralExpression(SyntaxKind.NullLiteralExpression)); + } + + /// + public abstract TypeSyntax AsNativeType(TypePositionInfo info); + + /// + public abstract ParameterSyntax AsParameter(TypePositionInfo info); + + /// + public abstract ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context); + + /// + public abstract IEnumerable Generate(TypePositionInfo info, StubCodeContext context); + + /// + public abstract bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context); + + /// + public abstract bool SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, StubCodeContext context); + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/CustomNativeTypeMarshallingGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/CustomNativeTypeMarshallingGenerator.cs new file mode 100644 index 0000000000000..f01c2741ea7e0 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/CustomNativeTypeMarshallingGenerator.cs @@ -0,0 +1,91 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; + +namespace Microsoft.Interop +{ + /// + /// Implements generating code for an instance. + /// + internal sealed class CustomNativeTypeMarshallingGenerator : IMarshallingGenerator + { + private readonly ICustomNativeTypeMarshallingStrategy _nativeTypeMarshaller; + private readonly bool _enableByValueContentsMarshalling; + + public CustomNativeTypeMarshallingGenerator(ICustomNativeTypeMarshallingStrategy nativeTypeMarshaller, bool enableByValueContentsMarshalling) + { + _nativeTypeMarshaller = nativeTypeMarshaller; + _enableByValueContentsMarshalling = enableByValueContentsMarshalling; + } + + public ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context) + { + return _nativeTypeMarshaller.AsArgument(info, context); + } + + public TypeSyntax AsNativeType(TypePositionInfo info) + { + return _nativeTypeMarshaller.AsNativeType(info); + } + + public ParameterSyntax AsParameter(TypePositionInfo info) + { + TypeSyntax type = info.IsByRef + ? PointerType(AsNativeType(info)) + : AsNativeType(info); + return Parameter(Identifier(info.InstanceIdentifier)) + .WithType(type); + } + + public IEnumerable Generate(TypePositionInfo info, StubCodeContext context) + { + // Although custom native type marshalling doesn't support [In] or [Out] by value marshalling, + // other marshallers that wrap this one might, so we handle the correct cases here. + switch (context.CurrentStage) + { + case StubCodeContext.Stage.Setup: + return _nativeTypeMarshaller.GenerateSetupStatements(info, context); + case StubCodeContext.Stage.Marshal: + if (!info.IsManagedReturnPosition && info.RefKind != RefKind.Out) + { + return _nativeTypeMarshaller.GenerateMarshalStatements(info, context, _nativeTypeMarshaller.GetNativeTypeConstructorArguments(info, context)); + } + break; + case StubCodeContext.Stage.Pin: + if (!info.IsByRef || info.RefKind == RefKind.In) + { + return _nativeTypeMarshaller.GeneratePinStatements(info, context); + } + break; + case StubCodeContext.Stage.Unmarshal: + if (info.IsManagedReturnPosition || (info.IsByRef && info.RefKind != RefKind.In) + || (_enableByValueContentsMarshalling && !info.IsByRef && info.ByValueContentsMarshalKind.HasFlag(ByValueContentsMarshalKind.Out))) + { + return _nativeTypeMarshaller.GenerateUnmarshalStatements(info, context); + } + break; + case StubCodeContext.Stage.Cleanup: + return _nativeTypeMarshaller.GenerateCleanupStatements(info, context); + default: + break; + } + + return Array.Empty(); + } + + public bool SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, StubCodeContext context) + { + return _enableByValueContentsMarshalling; + } + + public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) + { + return _nativeTypeMarshaller.UsesNativeIdentifier(info, context); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/DelegateMarshaller.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/DelegateMarshaller.cs new file mode 100644 index 0000000000000..32fe10c6ec9c7 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/DelegateMarshaller.cs @@ -0,0 +1,118 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; + +namespace Microsoft.Interop +{ + public sealed class DelegateMarshaller : IMarshallingGenerator + { + public TypeSyntax AsNativeType(TypePositionInfo info) + { + return MarshallerHelpers.SystemIntPtrType; + } + + public ParameterSyntax AsParameter(TypePositionInfo info) + { + TypeSyntax type = info.IsByRef + ? PointerType(AsNativeType(info)) + : AsNativeType(info); + return Parameter(Identifier(info.InstanceIdentifier)) + .WithType(type); + } + + public ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context) + { + string identifier = context.GetIdentifiers(info).native; + if (info.IsByRef) + { + return Argument( + PrefixUnaryExpression( + SyntaxKind.AddressOfExpression, + IdentifierName(identifier))); + } + + return Argument(IdentifierName(identifier)); + } + + public IEnumerable Generate(TypePositionInfo info, StubCodeContext context) + { + // [TODO] Handle byrefs in a more common place? + // This pattern will become very common (arrays and strings will also use it) + (string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(info); + switch (context.CurrentStage) + { + case StubCodeContext.Stage.Setup: + break; + case StubCodeContext.Stage.Marshal: + if (info.RefKind != RefKind.Out) + { + // = != null ? Marshal.GetFunctionPointerForDelegate() : default; + yield return ExpressionStatement( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + IdentifierName(nativeIdentifier), + ConditionalExpression( + BinaryExpression( + SyntaxKind.NotEqualsExpression, + IdentifierName(managedIdentifier), + LiteralExpression(SyntaxKind.NullLiteralExpression) + ), + InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + ParseName(TypeNames.System_Runtime_InteropServices_Marshal), + IdentifierName("GetFunctionPointerForDelegate")), + ArgumentList(SingletonSeparatedList(Argument(IdentifierName(managedIdentifier))))), + LiteralExpression(SyntaxKind.DefaultLiteralExpression)))); + } + break; + case StubCodeContext.Stage.Unmarshal: + if (info.IsManagedReturnPosition || (info.IsByRef && info.RefKind != RefKind.In)) + { + // = != default : Marshal.GetDelegateForFunctionPointer<>() : null; + yield return ExpressionStatement( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + IdentifierName(managedIdentifier), + ConditionalExpression( + BinaryExpression( + SyntaxKind.NotEqualsExpression, + IdentifierName(nativeIdentifier), + LiteralExpression(SyntaxKind.DefaultLiteralExpression)), + InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + ParseName(TypeNames.System_Runtime_InteropServices_Marshal), + GenericName(Identifier("GetDelegateForFunctionPointer")) + .WithTypeArgumentList( + TypeArgumentList( + SingletonSeparatedList( + info.ManagedType.Syntax)))), + ArgumentList(SingletonSeparatedList(Argument(IdentifierName(nativeIdentifier))))), + LiteralExpression(SyntaxKind.NullLiteralExpression)))); + } + break; + case StubCodeContext.Stage.KeepAlive: + if (info.RefKind != RefKind.Out) + { + yield return ExpressionStatement( + InvocationExpression( + ParseName("global::System.GC.KeepAlive"), + ArgumentList(SingletonSeparatedList(Argument(IdentifierName(managedIdentifier)))))); + } + break; + default: + break; + } + } + + public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) => true; + + public bool SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, StubCodeContext context) => false; + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/Forwarder.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/Forwarder.cs new file mode 100644 index 0000000000000..fd4ca6a37ae62 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/Forwarder.cs @@ -0,0 +1,127 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; + +namespace Microsoft.Interop +{ + public sealed class Forwarder : IMarshallingGenerator, IAttributedReturnTypeMarshallingGenerator + { + public TypeSyntax AsNativeType(TypePositionInfo info) + { + return info.ManagedType.Syntax; + } + + private bool TryRehydrateMarshalAsAttribute(TypePositionInfo info, out AttributeSyntax marshalAsAttribute) + { + marshalAsAttribute = null!; + // If the parameter has [MarshalAs] marshalling, we resurface that + // in the forwarding target since the built-in system understands it. + // ICustomMarshaller marshalling requires additional information that we throw away earlier since it's unsupported, + // so explicitly do not resurface a [MarshalAs(UnmanagdType.CustomMarshaler)] attribute. + if (info.MarshallingAttributeInfo is MarshalAsInfo { UnmanagedType: not UnmanagedType.CustomMarshaler } marshalAs) + { + marshalAsAttribute = Attribute(ParseName(TypeNames.System_Runtime_InteropServices_MarshalAsAttribute)) + .WithArgumentList(AttributeArgumentList(SingletonSeparatedList(AttributeArgument( + CastExpression(ParseTypeName(TypeNames.System_Runtime_InteropServices_UnmanagedType), + LiteralExpression(SyntaxKind.NumericLiteralExpression, + Literal((int)marshalAs.UnmanagedType))))))); + return true; + } + + if (info.MarshallingAttributeInfo is NativeContiguousCollectionMarshallingInfo collectionMarshalling + && collectionMarshalling.UseDefaultMarshalling + && collectionMarshalling.ElementCountInfo is NoCountInfo or SizeAndParamIndexInfo + && collectionMarshalling.ElementMarshallingInfo is NoMarshallingInfo or MarshalAsInfo { UnmanagedType: not UnmanagedType.CustomMarshaler } + && info.ManagedType is IArrayTypeSymbol) + { + List marshalAsArguments = new List + { + AttributeArgument( + CastExpression(ParseTypeName(TypeNames.System_Runtime_InteropServices_UnmanagedType), + LiteralExpression(SyntaxKind.NumericLiteralExpression, + Literal((int)UnmanagedType.LPArray)))) + }; + + if (collectionMarshalling.ElementCountInfo is SizeAndParamIndexInfo countInfo) + { + if (countInfo.ConstSize != SizeAndParamIndexInfo.UnspecifiedConstSize) + { + marshalAsArguments.Add( + AttributeArgument(NameEquals("SizeConst"), null, + LiteralExpression(SyntaxKind.NumericLiteralExpression, + Literal(countInfo.ConstSize))) + ); + } + if (countInfo.ParamAtIndex is { ManagedIndex: int paramIndex }) + { + marshalAsArguments.Add( + AttributeArgument(NameEquals("SizeParamIndex"), null, + LiteralExpression(SyntaxKind.NumericLiteralExpression, + Literal(paramIndex))) + ); + } + } + + if (collectionMarshalling.ElementMarshallingInfo is MarshalAsInfo elementMarshalAs) + { + marshalAsArguments.Add( + AttributeArgument(NameEquals("ArraySubType"), null, + CastExpression(ParseTypeName(TypeNames.System_Runtime_InteropServices_UnmanagedType), + LiteralExpression(SyntaxKind.NumericLiteralExpression, + Literal((int)elementMarshalAs.UnmanagedType)))) + ); + } + marshalAsAttribute = Attribute(ParseName(TypeNames.System_Runtime_InteropServices_MarshalAsAttribute)) + .WithArgumentList(AttributeArgumentList(SeparatedList(marshalAsArguments))); + return true; + } + + return false; + } + + public ParameterSyntax AsParameter(TypePositionInfo info) + { + ParameterSyntax param = Parameter(Identifier(info.InstanceIdentifier)) + .WithModifiers(TokenList(Token(info.RefKindSyntax))) + .WithType(info.ManagedType.Syntax); + + if (TryRehydrateMarshalAsAttribute(info, out AttributeSyntax marshalAsAttribute)) + { + param = param.AddAttributeLists(AttributeList(SingletonSeparatedList(marshalAsAttribute))); + } + + return param; + } + + public ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context) + { + return Argument(IdentifierName(info.InstanceIdentifier)) + .WithRefKindKeyword(Token(info.RefKindSyntax)); + } + + public IEnumerable Generate(TypePositionInfo info, StubCodeContext context) + { + return Array.Empty(); + } + + public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) => false; + + public bool SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, StubCodeContext context) => true; + + public AttributeListSyntax? GenerateAttributesForReturnType(TypePositionInfo info) + { + if (!TryRehydrateMarshalAsAttribute(info, out AttributeSyntax marshalAsAttribute)) + { + return null; + } + return AttributeList(SingletonSeparatedList(marshalAsAttribute)); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/HResultExceptionMarshaller.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/HResultExceptionMarshaller.cs new file mode 100644 index 0000000000000..446750e2bc5ca --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/HResultExceptionMarshaller.cs @@ -0,0 +1,51 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Diagnostics; +using System.Collections.Generic; + +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; + +namespace Microsoft.Interop +{ + public sealed class HResultExceptionMarshaller : IMarshallingGenerator + { + private static readonly TypeSyntax s_nativeType = PredefinedType(Token(SyntaxKind.IntKeyword)); + + public TypeSyntax AsNativeType(TypePositionInfo info) + { + Debug.Assert(info.ManagedType is SpecialTypeInfo(_, _, SpecialType.System_Int32)); + return s_nativeType; + } + + // Should only be used for return value + public ParameterSyntax AsParameter(TypePositionInfo info) => throw new InvalidOperationException(); + public ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context) => throw new InvalidOperationException(); + + public IEnumerable Generate(TypePositionInfo info, StubCodeContext context) + { + if (context.CurrentStage != StubCodeContext.Stage.Unmarshal) + yield break; + + // Marshal.ThrowExceptionForHR() + string identifier = context.GetIdentifiers(info).managed; + yield return ExpressionStatement( + InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + MarshallerHelpers.InteropServicesMarshalType, + IdentifierName(nameof(System.Runtime.InteropServices.Marshal.ThrowExceptionForHR))), + ArgumentList(SingletonSeparatedList( + Argument(IdentifierName(identifier)))))); + } + + public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) => false; + + public bool SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, StubCodeContext context) => false; + } + +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ICustomNativeTypeMarshallingStrategy.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ICustomNativeTypeMarshallingStrategy.cs new file mode 100644 index 0000000000000..338c7ee379b0d --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/ICustomNativeTypeMarshallingStrategy.cs @@ -0,0 +1,1047 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; + +namespace Microsoft.Interop +{ + /// + /// The base interface for implementing various different aspects of the custom native type and collection marshalling specs. + /// + internal interface ICustomNativeTypeMarshallingStrategy + { + TypeSyntax AsNativeType(TypePositionInfo info); + + ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context); + + IEnumerable GetNativeTypeConstructorArguments(TypePositionInfo info, StubCodeContext context); + + IEnumerable GenerateMarshalStatements(TypePositionInfo info, StubCodeContext context, IEnumerable nativeTypeConstructorArguments); + + IEnumerable GenerateSetupStatements(TypePositionInfo info, StubCodeContext context); + + IEnumerable GenerateCleanupStatements(TypePositionInfo info, StubCodeContext context); + + IEnumerable GeneratePinStatements(TypePositionInfo info, StubCodeContext context); + + IEnumerable GenerateUnmarshalStatements(TypePositionInfo info, StubCodeContext context); + + bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context); + } + + /// + /// Marshalling support for a type that has a custom native type. + /// + internal sealed class SimpleCustomNativeTypeMarshalling : ICustomNativeTypeMarshallingStrategy + { + private readonly TypeSyntax _nativeTypeSyntax; + + public SimpleCustomNativeTypeMarshalling(TypeSyntax nativeTypeSyntax) + { + _nativeTypeSyntax = nativeTypeSyntax; + } + + public ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context) + { + string identifier = context.GetIdentifiers(info).native; + if (info.IsByRef) + { + return Argument( + PrefixUnaryExpression( + SyntaxKind.AddressOfExpression, + IdentifierName(identifier))); + } + + return Argument(IdentifierName(identifier)); + } + + public TypeSyntax AsNativeType(TypePositionInfo info) + { + return _nativeTypeSyntax; + } + + public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) + { + return true; + } + + public IEnumerable GenerateCleanupStatements(TypePositionInfo info, StubCodeContext context) + { + return Array.Empty(); + } + + public IEnumerable GenerateMarshalStatements(TypePositionInfo info, StubCodeContext context, IEnumerable nativeTypeConstructorArguments) + { + // = new(); + yield return ExpressionStatement( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + IdentifierName(context.GetIdentifiers(info).native), + ImplicitObjectCreationExpression() + .WithArgumentList(ArgumentList(SeparatedList(nativeTypeConstructorArguments))))); + } + + public IEnumerable GenerateUnmarshalStatements(TypePositionInfo info, StubCodeContext context) + { + // If the current element is being marshalled by-value [Out], then don't call the ToManaged method and do the assignment. + // The assignment will end up being a no-op and will not be observed. + if (!info.IsByRef && info.ByValueContentsMarshalKind.HasFlag(ByValueContentsMarshalKind.Out)) + { + yield break; + } + + (string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(info); + // = .ToManaged(); + yield return ExpressionStatement( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + IdentifierName(managedIdentifier), + InvocationExpression( + MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, + IdentifierName(nativeIdentifier), + IdentifierName(ManualTypeMarshallingHelper.ToManagedMethodName))))); + } + + public IEnumerable GetNativeTypeConstructorArguments(TypePositionInfo info, StubCodeContext context) + { + yield return Argument(IdentifierName(context.GetIdentifiers(info).managed)); + } + + public IEnumerable GenerateSetupStatements(TypePositionInfo info, StubCodeContext context) + { + return Array.Empty(); + } + + public IEnumerable GeneratePinStatements(TypePositionInfo info, StubCodeContext context) + { + return Array.Empty(); + } + } + + /// + /// A context that redefines the 'native' identifier for a TypePositionInfo to be the marshaller identifier. + /// + internal class CustomNativeTypeWithValuePropertyStubContext : StubCodeContext + { + public CustomNativeTypeWithValuePropertyStubContext(StubCodeContext parentContext) + { + ParentContext = parentContext; + CurrentStage = parentContext.CurrentStage; + } + + public override bool SingleFrameSpansNativeContext => ParentContext!.SingleFrameSpansNativeContext; + + public override bool AdditionalTemporaryStateLivesAcrossStages => ParentContext!.AdditionalTemporaryStateLivesAcrossStages; + + public override (string managed, string native) GetIdentifiers(TypePositionInfo info) + { + return (ParentContext!.GetIdentifiers(info).managed, MarshallerHelpers.GetMarshallerIdentifier(info, ParentContext)); + } + } + + /// + /// Marshaller that enables support of a Value property on a native type. + /// + internal sealed class CustomNativeTypeWithValuePropertyMarshalling : ICustomNativeTypeMarshallingStrategy + { + private readonly ICustomNativeTypeMarshallingStrategy _innerMarshaller; + private readonly TypeSyntax _valuePropertyType; + + public CustomNativeTypeWithValuePropertyMarshalling(ICustomNativeTypeMarshallingStrategy innerMarshaller, TypeSyntax valuePropertyType) + { + _innerMarshaller = innerMarshaller; + _valuePropertyType = valuePropertyType; + } + + public ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context) + { + string identifier = context.GetIdentifiers(info).native; + if (info.IsByRef) + { + return Argument( + PrefixUnaryExpression( + SyntaxKind.AddressOfExpression, + IdentifierName(identifier))); + } + + return Argument(IdentifierName(identifier)); + } + + public TypeSyntax AsNativeType(TypePositionInfo info) + { + return _valuePropertyType; + } + + public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) + { + return true; + } + + public IEnumerable GenerateCleanupStatements(TypePositionInfo info, StubCodeContext context) + { + var subContext = new CustomNativeTypeWithValuePropertyStubContext(context); + + // When temporary state does not live across stages, the marshaller state is uninitialized + // in any stage other than Marshal and Unmarshal. So, we need to reinitialize it here in Cleanup + // from the native value so we can safely run any cleanup functionality in the marshaller. + if (!context.AdditionalTemporaryStateLivesAcrossStages) + { + yield return GenerateValuePropertyAssignment(info, context, subContext); + } + + foreach (StatementSyntax statement in _innerMarshaller.GenerateCleanupStatements(info, subContext)) + { + yield return statement; + } + } + + public IEnumerable GenerateMarshalStatements(TypePositionInfo info, StubCodeContext context, IEnumerable nativeTypeConstructorArguments) + { + var subContext = new CustomNativeTypeWithValuePropertyStubContext(context); + foreach (StatementSyntax statement in _innerMarshaller.GenerateMarshalStatements(info, subContext, nativeTypeConstructorArguments)) + { + yield return statement; + } + + // = .Value; + yield return ExpressionStatement( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + IdentifierName(context.GetIdentifiers(info).native), + MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, + IdentifierName(subContext.GetIdentifiers(info).native), + IdentifierName(ManualTypeMarshallingHelper.ValuePropertyName)))); + } + + private StatementSyntax GenerateValuePropertyAssignment(TypePositionInfo info, StubCodeContext context, CustomNativeTypeWithValuePropertyStubContext subContext) + { + // .Value = ; + return ExpressionStatement( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, + IdentifierName(subContext.GetIdentifiers(info).native), + IdentifierName(ManualTypeMarshallingHelper.ValuePropertyName)), + IdentifierName(context.GetIdentifiers(info).native))); + } + + public IEnumerable GenerateUnmarshalStatements(TypePositionInfo info, StubCodeContext context) + { + var subContext = new CustomNativeTypeWithValuePropertyStubContext(context); + + yield return GenerateValuePropertyAssignment(info, context, subContext); + + foreach (StatementSyntax statement in _innerMarshaller.GenerateUnmarshalStatements(info, subContext)) + { + yield return statement; + } + } + + public IEnumerable GetNativeTypeConstructorArguments(TypePositionInfo info, StubCodeContext context) + { + var subContext = new CustomNativeTypeWithValuePropertyStubContext(context); + return _innerMarshaller.GetNativeTypeConstructorArguments(info, subContext); + } + + public IEnumerable GenerateSetupStatements(TypePositionInfo info, StubCodeContext context) + { + var subContext = new CustomNativeTypeWithValuePropertyStubContext(context); + yield return LocalDeclarationStatement( + VariableDeclaration( + _innerMarshaller.AsNativeType(info), + SingletonSeparatedList( + VariableDeclarator(subContext.GetIdentifiers(info).native) + .WithInitializer(EqualsValueClause(LiteralExpression(SyntaxKind.DefaultLiteralExpression)))))); + + foreach (StatementSyntax statement in _innerMarshaller.GenerateSetupStatements(info, subContext)) + { + yield return statement; + } + } + + public IEnumerable GeneratePinStatements(TypePositionInfo info, StubCodeContext context) + { + var subContext = new CustomNativeTypeWithValuePropertyStubContext(context); + return _innerMarshaller.GeneratePinStatements(info, subContext); + } + } + + /// + /// Marshaller that enables support for a stackalloc constructor variant on a native type. + /// + internal sealed class StackallocOptimizationMarshalling : ICustomNativeTypeMarshallingStrategy + { + private readonly ICustomNativeTypeMarshallingStrategy _innerMarshaller; + + public StackallocOptimizationMarshalling(ICustomNativeTypeMarshallingStrategy innerMarshaller) + { + _innerMarshaller = innerMarshaller; + } + + public ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context) + { + return _innerMarshaller.AsArgument(info, context); + } + + public TypeSyntax AsNativeType(TypePositionInfo info) + { + return _innerMarshaller.AsNativeType(info); + } + + public IEnumerable GenerateCleanupStatements(TypePositionInfo info, StubCodeContext context) + { + return _innerMarshaller.GenerateCleanupStatements(info, context); + } + + public IEnumerable GenerateMarshalStatements(TypePositionInfo info, StubCodeContext context, IEnumerable nativeTypeConstructorArguments) + { + if (StackAllocOptimizationValid(info, context)) + { + // byte* __stackptr = stackalloc byte[<_nativeLocalType>.StackBufferSize]; + yield return LocalDeclarationStatement( + VariableDeclaration( + PointerType(PredefinedType(Token(SyntaxKind.ByteKeyword))), + SingletonSeparatedList( + VariableDeclarator(GetStackAllocPointerIdentifier(info, context)) + .WithInitializer(EqualsValueClause( + StackAllocArrayCreationExpression( + ArrayType( + PredefinedType(Token(SyntaxKind.ByteKeyword)), + SingletonList(ArrayRankSpecifier(SingletonSeparatedList( + MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, + AsNativeType(info), + IdentifierName(ManualTypeMarshallingHelper.StackBufferSizeFieldName)) + )))))))))); + } + + foreach (StatementSyntax statement in _innerMarshaller.GenerateMarshalStatements(info, context, nativeTypeConstructorArguments)) + { + yield return statement; + } + } + + private static bool StackAllocOptimizationValid(TypePositionInfo info, StubCodeContext context) + { + return context.SingleFrameSpansNativeContext && (!info.IsByRef || info.RefKind == RefKind.In); + } + + private static string GetStackAllocPointerIdentifier(TypePositionInfo info, StubCodeContext context) + { + return context.GetAdditionalIdentifier(info, "stackptr"); + } + + public IEnumerable GeneratePinStatements(TypePositionInfo info, StubCodeContext context) + { + return _innerMarshaller.GeneratePinStatements(info, context); + } + + public IEnumerable GenerateSetupStatements(TypePositionInfo info, StubCodeContext context) + { + return _innerMarshaller.GenerateSetupStatements(info, context); + } + + public IEnumerable GenerateUnmarshalStatements(TypePositionInfo info, StubCodeContext context) + { + return _innerMarshaller.GenerateUnmarshalStatements(info, context); + } + + public IEnumerable GetNativeTypeConstructorArguments(TypePositionInfo info, StubCodeContext context) + { + foreach (ArgumentSyntax arg in _innerMarshaller.GetNativeTypeConstructorArguments(info, context)) + { + yield return arg; + } + if (StackAllocOptimizationValid(info, context)) + { + yield return Argument( + ObjectCreationExpression( + GenericName(Identifier(TypeNames.System_Span), + TypeArgumentList(SingletonSeparatedList( + PredefinedType(Token(SyntaxKind.ByteKeyword)))))) + .WithArgumentList( + ArgumentList(SeparatedList(new ArgumentSyntax[] + { + Argument(IdentifierName(GetStackAllocPointerIdentifier(info, context))), + Argument(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, + AsNativeType(info), + IdentifierName(ManualTypeMarshallingHelper.StackBufferSizeFieldName))) + })))); + } + } + + public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) + { + return _innerMarshaller.UsesNativeIdentifier(info, context); + } + } + + /// + /// Marshaller that enables support for a FreeNative method on a native type. + /// + internal sealed class FreeNativeCleanupStrategy : ICustomNativeTypeMarshallingStrategy + { + private readonly ICustomNativeTypeMarshallingStrategy _innerMarshaller; + + public FreeNativeCleanupStrategy(ICustomNativeTypeMarshallingStrategy innerMarshaller) + { + _innerMarshaller = innerMarshaller; + } + + public ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context) + { + return _innerMarshaller.AsArgument(info, context); + } + + public TypeSyntax AsNativeType(TypePositionInfo info) + { + return _innerMarshaller.AsNativeType(info); + } + + public IEnumerable GenerateCleanupStatements(TypePositionInfo info, StubCodeContext context) + { + foreach (StatementSyntax statement in _innerMarshaller.GenerateCleanupStatements(info, context)) + { + yield return statement; + } + + // .FreeNative(); + yield return ExpressionStatement( + InvocationExpression( + MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, + IdentifierName(context.GetIdentifiers(info).native), + IdentifierName(ManualTypeMarshallingHelper.FreeNativeMethodName)))); + } + + public IEnumerable GenerateMarshalStatements(TypePositionInfo info, StubCodeContext context, IEnumerable nativeTypeConstructorArguments) + { + return _innerMarshaller.GenerateMarshalStatements(info, context, nativeTypeConstructorArguments); + } + + public IEnumerable GeneratePinStatements(TypePositionInfo info, StubCodeContext context) + { + return _innerMarshaller.GeneratePinStatements(info, context); + } + + public IEnumerable GenerateSetupStatements(TypePositionInfo info, StubCodeContext context) + { + return _innerMarshaller.GenerateSetupStatements(info, context); + } + + public IEnumerable GenerateUnmarshalStatements(TypePositionInfo info, StubCodeContext context) + { + return _innerMarshaller.GenerateUnmarshalStatements(info, context); + } + + public IEnumerable GetNativeTypeConstructorArguments(TypePositionInfo info, StubCodeContext context) + { + return _innerMarshaller.GetNativeTypeConstructorArguments(info, context); + } + + public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) + { + return _innerMarshaller.UsesNativeIdentifier(info, context); + } + } + + /// + /// Marshaller that enables support for a GetPinnableReference method on a native type, with a Value property fallback. + /// + internal sealed class PinnableMarshallerTypeMarshalling : ICustomNativeTypeMarshallingStrategy + { + private readonly ICustomNativeTypeMarshallingStrategy _innerMarshaller; + private readonly TypeSyntax _valuePropertyType; + + public PinnableMarshallerTypeMarshalling(ICustomNativeTypeMarshallingStrategy innerMarshaller, TypeSyntax valuePropertyType) + { + _innerMarshaller = innerMarshaller; + _valuePropertyType = valuePropertyType; + } + + private bool CanPinMarshaller(TypePositionInfo info, StubCodeContext context) + { + return context.SingleFrameSpansNativeContext && !info.IsManagedReturnPosition && !info.IsByRef || info.RefKind == RefKind.In; + } + + public ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context) + { + return _innerMarshaller.AsArgument(info, context); + } + + public TypeSyntax AsNativeType(TypePositionInfo info) + { + return _valuePropertyType; + } + + public IEnumerable GenerateCleanupStatements(TypePositionInfo info, StubCodeContext context) + { + var subContext = new CustomNativeTypeWithValuePropertyStubContext(context); + + if (!CanPinMarshaller(info, context) && !context.AdditionalTemporaryStateLivesAcrossStages) + { + // .Value = ; + yield return GenerateValuePropertyAssignment(info, context, subContext); + } + + foreach (StatementSyntax statement in _innerMarshaller.GenerateCleanupStatements(info, subContext)) + { + yield return statement; + } + } + + public IEnumerable GenerateMarshalStatements(TypePositionInfo info, StubCodeContext context, IEnumerable nativeTypeConstructorArguments) + { + var subContext = new CustomNativeTypeWithValuePropertyStubContext(context); + foreach (StatementSyntax statement in _innerMarshaller.GenerateMarshalStatements(info, subContext, nativeTypeConstructorArguments)) + { + yield return statement; + } + + if (!CanPinMarshaller(info, context)) + { + // = .Value; + yield return ExpressionStatement( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + IdentifierName(context.GetIdentifiers(info).native), + MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, + IdentifierName(subContext.GetIdentifiers(info).native), + IdentifierName(ManualTypeMarshallingHelper.ValuePropertyName)))); + } + } + + public IEnumerable GeneratePinStatements(TypePositionInfo info, StubCodeContext context) + { + // fixed (<_nativeTypeSyntax> = &) + var subContext = new CustomNativeTypeWithValuePropertyStubContext(context); + yield return FixedStatement( + VariableDeclaration( + _valuePropertyType, + SingletonSeparatedList( + VariableDeclarator(context.GetIdentifiers(info).native) + .WithInitializer(EqualsValueClause( + PrefixUnaryExpression(SyntaxKind.AddressOfExpression, + InvocationExpression( + MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, + IdentifierName(subContext.GetIdentifiers(info).native), + IdentifierName(ManualTypeMarshallingHelper.GetPinnableReferenceName)), + ArgumentList())))))), + EmptyStatement()); + } + + public IEnumerable GenerateSetupStatements(TypePositionInfo info, StubCodeContext context) + { + var subContext = new CustomNativeTypeWithValuePropertyStubContext(context); + yield return LocalDeclarationStatement( + VariableDeclaration( + _innerMarshaller.AsNativeType(info), + SingletonSeparatedList( + VariableDeclarator(subContext.GetIdentifiers(info).native) + .WithInitializer(EqualsValueClause(LiteralExpression(SyntaxKind.DefaultLiteralExpression)))))); + + foreach (StatementSyntax statement in _innerMarshaller.GenerateSetupStatements(info, subContext)) + { + yield return statement; + } + } + + private StatementSyntax GenerateValuePropertyAssignment(TypePositionInfo info, StubCodeContext context, CustomNativeTypeWithValuePropertyStubContext subContext) + { + // .Value = ; + return ExpressionStatement( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, + IdentifierName(subContext.GetIdentifiers(info).native), + IdentifierName(ManualTypeMarshallingHelper.ValuePropertyName)), + IdentifierName(context.GetIdentifiers(info).native))); + } + + public IEnumerable GenerateUnmarshalStatements(TypePositionInfo info, StubCodeContext context) + { + var subContext = new CustomNativeTypeWithValuePropertyStubContext(context); + + if (!CanPinMarshaller(info, context)) + { + // .Value = ; + yield return GenerateValuePropertyAssignment(info, context, subContext); + } + + foreach (StatementSyntax statement in _innerMarshaller.GenerateUnmarshalStatements(info, subContext)) + { + yield return statement; + } + } + + public IEnumerable GetNativeTypeConstructorArguments(TypePositionInfo info, StubCodeContext context) + { + var subContext = new CustomNativeTypeWithValuePropertyStubContext(context); + return _innerMarshaller.GetNativeTypeConstructorArguments(info, subContext); + } + + public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) + { + if (CanPinMarshaller(info, context)) + { + return false; + } + return _innerMarshaller.UsesNativeIdentifier(info, context); + } + } + + /// + /// Marshaller that enables support for native types with the constructor variants that take a sizeOfElement int parameter and that have a SetUnmarshalledCollectionLength method. + /// + internal sealed class NumElementsExpressionMarshalling : ICustomNativeTypeMarshallingStrategy + { + private readonly ICustomNativeTypeMarshallingStrategy _innerMarshaller; + private readonly ExpressionSyntax _numElementsExpression; + private readonly ExpressionSyntax _sizeOfElementExpression; + + public NumElementsExpressionMarshalling(ICustomNativeTypeMarshallingStrategy innerMarshaller, ExpressionSyntax numElementsExpression, ExpressionSyntax sizeOfElementExpression) + { + _innerMarshaller = innerMarshaller; + _numElementsExpression = numElementsExpression; + _sizeOfElementExpression = sizeOfElementExpression; + } + + public ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context) + { + return _innerMarshaller.AsArgument(info, context); + } + + public TypeSyntax AsNativeType(TypePositionInfo info) + { + return _innerMarshaller.AsNativeType(info); + } + + public IEnumerable GenerateCleanupStatements(TypePositionInfo info, StubCodeContext context) + { + // When temporary state does not live across stages, the marshaller state is uninitialized + // in any stage other than Marshal and Unmarshal. So, we need to reinitialize it here in Cleanup + // from the native data so we can safely run any cleanup functionality in the marshaller. + if (!context.AdditionalTemporaryStateLivesAcrossStages) + { + foreach (StatementSyntax statement in GenerateUnmarshallerCollectionInitialization(info, context)) + { + yield return statement; + } + } + + foreach (StatementSyntax statement in _innerMarshaller.GenerateCleanupStatements(info, context)) + { + yield return statement; + } + } + + public IEnumerable GenerateMarshalStatements(TypePositionInfo info, StubCodeContext context, IEnumerable nativeTypeConstructorArguments) + { + return _innerMarshaller.GenerateMarshalStatements(info, context, nativeTypeConstructorArguments); + } + + public IEnumerable GeneratePinStatements(TypePositionInfo info, StubCodeContext context) + { + return _innerMarshaller.GeneratePinStatements(info, context); + } + + public IEnumerable GenerateSetupStatements(TypePositionInfo info, StubCodeContext context) + { + return _innerMarshaller.GenerateSetupStatements(info, context); + } + + private IEnumerable GenerateUnmarshallerCollectionInitialization(TypePositionInfo info, StubCodeContext context) + { + string marshalerIdentifier = MarshallerHelpers.GetMarshallerIdentifier(info, context); + if (info.RefKind == RefKind.Out || info.IsManagedReturnPosition) + { + yield return ExpressionStatement(AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, + IdentifierName(marshalerIdentifier), + ImplicitObjectCreationExpression().AddArgumentListArguments(Argument(_sizeOfElementExpression)))); + } + + if (info.IsByRef || !info.ByValueContentsMarshalKind.HasFlag(ByValueContentsMarshalKind.Out)) + { + yield return ExpressionStatement( + InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + IdentifierName(marshalerIdentifier), + IdentifierName(ManualTypeMarshallingHelper.SetUnmarshalledCollectionLengthMethodName))) + .AddArgumentListArguments(Argument(_numElementsExpression))); + } + } + + public IEnumerable GenerateUnmarshalStatements(TypePositionInfo info, StubCodeContext context) + { + // To fulfill the generic contiguous collection marshaller design, + // we need to emit code to initialize the collection marshaller with the size of native elements + // and set the unmanaged collection length before we marshal back the native data. + // This ensures that the marshaller object has enough state to successfully set up the ManagedValues + // and NativeValueStorage spans when the actual collection value is unmarshalled from native to the marshaller. + foreach (StatementSyntax statement in GenerateUnmarshallerCollectionInitialization(info, context)) + { + yield return statement; + } + + foreach (StatementSyntax statement in _innerMarshaller.GenerateUnmarshalStatements(info, context)) + { + yield return statement; + } + } + + public IEnumerable GetNativeTypeConstructorArguments(TypePositionInfo info, StubCodeContext context) + { + foreach (ArgumentSyntax arg in _innerMarshaller.GetNativeTypeConstructorArguments(info, context)) + { + yield return arg; + } + yield return Argument(_sizeOfElementExpression); + } + + public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) + { + return _innerMarshaller.UsesNativeIdentifier(info, context); + } + } + + /// + /// Marshaller that enables support for marshalling blittable elements of a contiguous collection via a native type that implements the contiguous collection marshalling spec. + /// + internal sealed class ContiguousBlittableElementCollectionMarshalling : ICustomNativeTypeMarshallingStrategy + { + private readonly ICustomNativeTypeMarshallingStrategy _innerMarshaller; + private readonly TypeSyntax _elementType; + + public ContiguousBlittableElementCollectionMarshalling(ICustomNativeTypeMarshallingStrategy innerMarshaller, TypeSyntax elementType) + { + _innerMarshaller = innerMarshaller; + _elementType = elementType; + } + + public ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context) + { + return _innerMarshaller.AsArgument(info, context); + } + + public TypeSyntax AsNativeType(TypePositionInfo info) + { + return _innerMarshaller.AsNativeType(info); + } + + public IEnumerable GenerateCleanupStatements(TypePositionInfo info, StubCodeContext context) + { + return _innerMarshaller.GenerateCleanupStatements(info, context); + } + + public IEnumerable GenerateMarshalStatements(TypePositionInfo info, StubCodeContext context, IEnumerable nativeTypeConstructorArguments) + { + string nativeIdentifier = context.GetIdentifiers(info).native; + foreach (StatementSyntax statement in _innerMarshaller.GenerateMarshalStatements(info, context, nativeTypeConstructorArguments)) + { + yield return statement; + } + + if (!info.IsByRef && info.ByValueContentsMarshalKind == ByValueContentsMarshalKind.Out) + { + // If the parameter is marshalled by-value [Out], then we don't marshal the contents of the collection. + yield break; + } + + // .ManagedValues.CopyTo(MemoryMarshal.Cast>(.NativeValueStorage)); + yield return ExpressionStatement( + InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + IdentifierName(nativeIdentifier), + IdentifierName(ManualTypeMarshallingHelper.ManagedValuesPropertyName)), + IdentifierName("CopyTo"))) + .AddArgumentListArguments( + Argument( + InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + ParseTypeName(TypeNames.System_Runtime_InteropServices_MemoryMarshal), + GenericName( + Identifier("Cast")) + .WithTypeArgumentList( + TypeArgumentList( + SeparatedList( + new[] + { + PredefinedType(Token(SyntaxKind.ByteKeyword)), + _elementType + }))))) + .AddArgumentListArguments( + Argument( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + IdentifierName(nativeIdentifier), + IdentifierName(ManualTypeMarshallingHelper.NativeValueStoragePropertyName))))))); + } + + public IEnumerable GeneratePinStatements(TypePositionInfo info, StubCodeContext context) + { + return _innerMarshaller.GeneratePinStatements(info, context); + } + + public IEnumerable GenerateSetupStatements(TypePositionInfo info, StubCodeContext context) + { + return _innerMarshaller.GenerateSetupStatements(info, context); + } + + public IEnumerable GenerateUnmarshalStatements(TypePositionInfo info, StubCodeContext context) + { + string nativeIdentifier = context.GetIdentifiers(info).native; + // MemoryMarshal.Cast>(.NativeValueStorage).CopyTo(.ManagedValues); + yield return ExpressionStatement( + InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + ParseTypeName(TypeNames.System_Runtime_InteropServices_MemoryMarshal), + GenericName( + Identifier("Cast")) + .WithTypeArgumentList( + TypeArgumentList( + SeparatedList( + new[] + { + PredefinedType(Token(SyntaxKind.ByteKeyword)), + _elementType + }))))) + .AddArgumentListArguments( + Argument( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + IdentifierName(nativeIdentifier), + IdentifierName(ManualTypeMarshallingHelper.NativeValueStoragePropertyName)))), + IdentifierName("CopyTo"))) + .AddArgumentListArguments( + Argument( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + IdentifierName(nativeIdentifier), + IdentifierName(ManualTypeMarshallingHelper.ManagedValuesPropertyName))))); + + foreach (StatementSyntax statement in _innerMarshaller.GenerateUnmarshalStatements(info, context)) + { + yield return statement; + } + } + + public IEnumerable GetNativeTypeConstructorArguments(TypePositionInfo info, StubCodeContext context) + { + return _innerMarshaller.GetNativeTypeConstructorArguments(info, context); + } + + public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) + { + return _innerMarshaller.UsesNativeIdentifier(info, context); + } + } + + /// + /// Marshaller that enables support for marshalling non-blittable elements of a contiguous collection via a native type that implements the contiguous collection marshalling spec. + /// + internal sealed class ContiguousNonBlittableElementCollectionMarshalling : ICustomNativeTypeMarshallingStrategy + { + private readonly ICustomNativeTypeMarshallingStrategy _innerMarshaller; + private readonly IMarshallingGenerator _elementMarshaller; + private readonly TypePositionInfo _elementInfo; + + public ContiguousNonBlittableElementCollectionMarshalling(ICustomNativeTypeMarshallingStrategy innerMarshaller, + IMarshallingGenerator elementMarshaller, + TypePositionInfo elementInfo) + { + _innerMarshaller = innerMarshaller; + _elementMarshaller = elementMarshaller; + _elementInfo = elementInfo; + } + + private LocalDeclarationStatementSyntax GenerateNativeSpanDeclaration(TypePositionInfo info, StubCodeContext context) + { + string nativeIdentifier = context.GetIdentifiers(info).native; + string nativeSpanIdentifier = MarshallerHelpers.GetNativeSpanIdentifier(info, context); + return LocalDeclarationStatement(VariableDeclaration( + GenericName( + Identifier(TypeNames.System_Span), + TypeArgumentList( + SingletonSeparatedList(_elementMarshaller.AsNativeType(_elementInfo).GetCompatibleGenericTypeParameterSyntax())) + ), + SingletonSeparatedList( + VariableDeclarator(Identifier(nativeSpanIdentifier)) + .WithInitializer(EqualsValueClause( + InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + ParseTypeName(TypeNames.System_Runtime_InteropServices_MemoryMarshal), + GenericName( + Identifier("Cast")) + .WithTypeArgumentList( + TypeArgumentList( + SeparatedList( + new[] + { + PredefinedType(Token(SyntaxKind.ByteKeyword)), + _elementMarshaller.AsNativeType(_elementInfo).GetCompatibleGenericTypeParameterSyntax() + }))))) + .AddArgumentListArguments( + Argument(MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, + IdentifierName(nativeIdentifier), + IdentifierName(ManualTypeMarshallingHelper.NativeValueStoragePropertyName))))))))); + } + + private StatementSyntax GenerateContentsMarshallingStatement(TypePositionInfo info, StubCodeContext context, bool useManagedSpanForLength) + { + string nativeIdentifier = context.GetIdentifiers(info).native; + string nativeSpanIdentifier = MarshallerHelpers.GetNativeSpanIdentifier(info, context); + var elementSetupSubContext = new ContiguousCollectionElementMarshallingCodeContext( + StubCodeContext.Stage.Setup, + nativeSpanIdentifier, + context); + var elementSubContext = new ContiguousCollectionElementMarshallingCodeContext( + context.CurrentStage, + nativeSpanIdentifier, + context); + + string collectionIdentifierForLength = useManagedSpanForLength + ? $"{nativeIdentifier}.{ManualTypeMarshallingHelper.ManagedValuesPropertyName}" + : nativeSpanIdentifier; + + TypePositionInfo localElementInfo = _elementInfo with + { + InstanceIdentifier = info.InstanceIdentifier, + RefKind = info.IsByRef ? info.RefKind : info.ByValueContentsMarshalKind.GetRefKindForByValueContentsKind(), + ManagedIndex = info.ManagedIndex, + NativeIndex = info.NativeIndex + }; + + List elementStatements = _elementMarshaller.Generate(localElementInfo, elementSubContext).ToList(); + + if (elementStatements.Any()) + { + StatementSyntax marshallingStatement = Block( + List(_elementMarshaller.Generate(localElementInfo, elementSetupSubContext) + .Concat(elementStatements))); + + if (_elementMarshaller.AsNativeType(_elementInfo) is PointerTypeSyntax elementNativeType) + { + PointerNativeTypeAssignmentRewriter rewriter = new(elementSubContext.GetIdentifiers(localElementInfo).native, elementNativeType); + marshallingStatement = (StatementSyntax)rewriter.Visit(marshallingStatement); + } + + // Iterate through the elements of the native collection to unmarshal them + return Block( + GenerateNativeSpanDeclaration(info, context), + MarshallerHelpers.GetForLoop(collectionIdentifierForLength, elementSubContext.IndexerIdentifier) + .WithStatement(marshallingStatement)); + } + return EmptyStatement(); + } + + public ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context) + { + return _innerMarshaller.AsArgument(info, context); + } + + public TypeSyntax AsNativeType(TypePositionInfo info) + { + return _innerMarshaller.AsNativeType(info); + } + + public IEnumerable GenerateCleanupStatements(TypePositionInfo info, StubCodeContext context) + { + yield return GenerateContentsMarshallingStatement(info, context, useManagedSpanForLength: false); + foreach (StatementSyntax statement in _innerMarshaller.GenerateCleanupStatements(info, context)) + { + yield return statement; + } + } + + public IEnumerable GenerateMarshalStatements(TypePositionInfo info, StubCodeContext context, IEnumerable nativeTypeConstructorArguments) + { + foreach (StatementSyntax statement in _innerMarshaller.GenerateMarshalStatements(info, context, nativeTypeConstructorArguments)) + { + yield return statement; + } + + if (!info.IsByRef && info.ByValueContentsMarshalKind == ByValueContentsMarshalKind.Out) + { + // If the parameter is marshalled by-value [Out], then we don't marshal the contents of the collection. + yield break; + } + + yield return GenerateContentsMarshallingStatement(info, context, useManagedSpanForLength: true); + } + + public IEnumerable GeneratePinStatements(TypePositionInfo info, StubCodeContext context) + { + return _innerMarshaller.GeneratePinStatements(info, context); + } + + public IEnumerable GenerateSetupStatements(TypePositionInfo info, StubCodeContext context) + { + return _innerMarshaller.GenerateSetupStatements(info, context); + } + + public IEnumerable GenerateUnmarshalStatements(TypePositionInfo info, StubCodeContext context) + { + yield return GenerateContentsMarshallingStatement(info, context, useManagedSpanForLength: false); + foreach (StatementSyntax statement in _innerMarshaller.GenerateUnmarshalStatements(info, context)) + { + yield return statement; + } + } + + public IEnumerable GetNativeTypeConstructorArguments(TypePositionInfo info, StubCodeContext context) + { + return _innerMarshaller.GetNativeTypeConstructorArguments(info, context); + } + + public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) + { + return _innerMarshaller.UsesNativeIdentifier(info, context); + } + + /// + /// Rewrite assignment expressions to the native identifier to cast to IntPtr. + /// This handles the case where the native type of a non-blittable managed type is a pointer, + /// which are unsupported in generic type parameters. + /// + private class PointerNativeTypeAssignmentRewriter : CSharpSyntaxRewriter + { + private readonly string _nativeIdentifier; + private readonly PointerTypeSyntax _nativeType; + + public PointerNativeTypeAssignmentRewriter(string nativeIdentifier, PointerTypeSyntax nativeType) + { + _nativeIdentifier = nativeIdentifier; + _nativeType = nativeType; + } + + public override SyntaxNode VisitAssignmentExpression(AssignmentExpressionSyntax node) + { + if (node.Left.ToString() == _nativeIdentifier) + { + return node.WithRight( + CastExpression(MarshallerHelpers.SystemIntPtrType, node.Right)); + } + if (node.Right.ToString() == _nativeIdentifier) + { + return node.WithRight(CastExpression(_nativeType, node.Right)); + } + + return node; + } + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallerHelpers.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallerHelpers.cs new file mode 100644 index 0000000000000..12420cca3d078 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallerHelpers.cs @@ -0,0 +1,285 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using System; +using System.Collections.Generic; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; + +namespace Microsoft.Interop +{ + public static class MarshallerHelpers + { + public static readonly ExpressionSyntax IsWindows = InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + ParseTypeName("System.OperatingSystem"), + IdentifierName("IsWindows"))); + + public static readonly TypeSyntax InteropServicesMarshalType = ParseTypeName(TypeNames.System_Runtime_InteropServices_Marshal); + + public static readonly TypeSyntax SystemIntPtrType = ParseTypeName(TypeNames.System_IntPtr); + + public static ForStatementSyntax GetForLoop(string collectionIdentifier, string indexerIdentifier) + { + // for(int = 0; < .Length; ++) + // ; + return ForStatement(EmptyStatement()) + .WithDeclaration( + VariableDeclaration( + PredefinedType( + Token(SyntaxKind.IntKeyword))) + .WithVariables( + SingletonSeparatedList( + VariableDeclarator( + Identifier(indexerIdentifier)) + .WithInitializer( + EqualsValueClause( + LiteralExpression( + SyntaxKind.NumericLiteralExpression, + Literal(0))))))) + .WithCondition( + BinaryExpression( + SyntaxKind.LessThanExpression, + IdentifierName(indexerIdentifier), + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + IdentifierName(collectionIdentifier), + IdentifierName("Length")))) + .WithIncrementors( + SingletonSeparatedList( + PrefixUnaryExpression( + SyntaxKind.PreIncrementExpression, + IdentifierName(indexerIdentifier)))); + } + + public static LocalDeclarationStatementSyntax DeclareWithDefault(TypeSyntax typeSyntax, string identifier) + { + // = default; + return LocalDeclarationStatement( + VariableDeclaration( + typeSyntax, + SingletonSeparatedList( + VariableDeclarator(identifier) + .WithInitializer( + EqualsValueClause( + LiteralExpression(SyntaxKind.DefaultLiteralExpression)))))); + } + + public static RefKind GetRefKindForByValueContentsKind(this ByValueContentsMarshalKind byValue) + { + return byValue switch + { + ByValueContentsMarshalKind.Default => RefKind.None, + ByValueContentsMarshalKind.In => RefKind.In, + ByValueContentsMarshalKind.InOut => RefKind.Ref, + ByValueContentsMarshalKind.Out => RefKind.Out, + _ => throw new System.ArgumentOutOfRangeException(nameof(byValue)) + }; + } + + public static TypeSyntax GetCompatibleGenericTypeParameterSyntax(this TypeSyntax type) + { + TypeSyntax spanElementTypeSyntax = type; + if (spanElementTypeSyntax is PointerTypeSyntax) + { + // Pointers cannot be passed to generics, so use IntPtr for this case. + spanElementTypeSyntax = SystemIntPtrType; + } + return spanElementTypeSyntax; + } + + public static string GetMarshallerIdentifier(TypePositionInfo info, StubCodeContext context) + { + return context.GetAdditionalIdentifier(info, "marshaller"); + } + + public static string GetNativeSpanIdentifier(TypePositionInfo info, StubCodeContext context) + { + return context.GetAdditionalIdentifier(info, "nativeSpan"); + } + + /// + /// Generate a topologically sorted collection of elements. + /// + /// The type of element. + /// The initial collection of elements. + /// A function to create a key for the element. + /// A function to resolve the dependencies of a given item in the collection as index values that would be returned by . + /// A topologically sorted collection of the elemens of the collection. + /// The graph of nodes and the edges produced by has cycles. + public static IEnumerable GetTopologicallySortedElements( + ICollection elements, + Func keyFn, + Func> getDependentIndicesFn) + { + Dictionary elementIndexToEdgeMapNodeId = new(elements.Count); + List nodeIdToElement = new(elements.Count); + EdgeMap edgeMap = new(elements.Count); + + int nextEdgeMapIndex = 0; + foreach (T element in elements) + { + elementIndexToEdgeMapNodeId.Add(keyFn(element), nextEdgeMapIndex++); + nodeIdToElement.Add(element); + } + + foreach (T element in elements) + { + U elementIndex = keyFn(element); + foreach (U dependentElementIndex in getDependentIndicesFn(element)) + { + // Add an edge from the node for dependentElementIndex-> the node for elementIndex + // This way, elements that have no dependencies have no edges pointing to them. + edgeMap[elementIndexToEdgeMapNodeId[elementIndex], elementIndexToEdgeMapNodeId[dependentElementIndex]] = true; + } + } + + // Now that we have initialized our map of edges and we have our list of nodes, + // we'll use Khan's algorithm to calculate a topological sort of the elements. + // Algorithm adapted from A. B. Kahn. 1962. Topological sorting of large networks. Commun. ACM 5, 11 (Nov. 1962), 558-562. DOI:https://doi.org/10.1145/368996.369025 + + // L is the sorted list + List L = new(elements.Count); + // S is the set of elements with no incoming edges (no dependencies on it) + List S = new(elements.Count); + + // Initialize S + for (int node = 0; node < nodeIdToElement.Count; node++) + { + if (!edgeMap.AnyIncomingEdge(node)) + { + S.Add(nodeIdToElement[node]); + } + } + + while (S.Count != 0) + { + // Remove element from S + T element = S[S.Count - 1]; + S.RemoveAt(S.Count - 1); + // Add element to L + L.Add(element); + int n = elementIndexToEdgeMapNodeId[keyFn(element)]; + // For each node m that n points to + for (int m = 0; m < edgeMap.NodeCount; m++) + { + if (!edgeMap[m, n]) + { + continue; + } + // Remove the edge from n to m + edgeMap[m, n] = false; + // If m does not have any incoming edges, add to S + if (!edgeMap.AnyIncomingEdge(m)) + { + S.Add(nodeIdToElement[m]); + } + } + } + + // If we have edges left, then we have a cycle. + if (edgeMap.AnyEdges) + { + throw new InvalidOperationException(Resources.GraphHasCycles); + } + + // If we make it here, we have a topologically sorted list. + return L; + } + + private struct EdgeMap + { + private readonly bool[] _edgeMap; + + public EdgeMap(int numNodes) + { + NodeCount = numNodes; + _edgeMap = new bool[NodeCount * NodeCount]; + } + + /// + /// EdgeMap contains a map of boolean values denoting if an edge exists + /// If edgeMap[X][Y] is true, that means that there exists an edge Y -> X + /// + /// The node the edge points to. + /// The node the edge start at. + /// If there exists an edge that starts at and ends at + public bool this[int to, int from] + { + get => _edgeMap[to * NodeCount + from]; + set => _edgeMap[to * NodeCount + from] = value; + } + + public bool AnyEdges => Array.IndexOf(_edgeMap, true) != -1; + + public int NodeCount { get; } + + public bool AnyIncomingEdge(int to) + { + return Array.IndexOf(_edgeMap, true, to * NodeCount, NodeCount) != -1; + } + } + + public static IEnumerable GetDependentElementsOfMarshallingInfo( + MarshallingInfo elementMarshallingInfo) + { + if (elementMarshallingInfo is NativeContiguousCollectionMarshallingInfo nestedCollection) + { + if (nestedCollection.ElementCountInfo is CountElementCountInfo { ElementInfo: TypePositionInfo nestedCountElement }) + { + yield return nestedCountElement; + } + foreach (TypePositionInfo nestedElements in GetDependentElementsOfMarshallingInfo(nestedCollection.ElementMarshallingInfo)) + { + yield return nestedElements; + } + } + } + + public static class StringMarshaller + { + public static ExpressionSyntax AllocationExpression(CharEncoding encoding, string managedIdentifier) + { + string methodName = encoding switch + { + CharEncoding.Utf8 => "StringToCoTaskMemUTF8", // Not in .NET Standard 2.0, so we use the hard-coded name + CharEncoding.Utf16 => nameof(System.Runtime.InteropServices.Marshal.StringToCoTaskMemUni), + CharEncoding.Ansi => nameof(System.Runtime.InteropServices.Marshal.StringToCoTaskMemAnsi), + _ => throw new System.ArgumentOutOfRangeException(nameof(encoding)) + }; + + // Marshal.StringToCoTaskMemUTF8() + // or + // Marshal.StringToCoTaskMemUni() + // or + // Marshal.StringToCoTaskMemAnsi() + return InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + InteropServicesMarshalType, + IdentifierName(methodName)), + ArgumentList( + SingletonSeparatedList( + Argument(IdentifierName(managedIdentifier))))); + } + + public static ExpressionSyntax FreeExpression(string nativeIdentifier) + { + // Marshal.FreeCoTaskMem((IntPtr)) + return InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + InteropServicesMarshalType, + IdentifierName(nameof(System.Runtime.InteropServices.Marshal.FreeCoTaskMem))), + ArgumentList(SingletonSeparatedList( + Argument( + CastExpression( + SystemIntPtrType, + IdentifierName(nativeIdentifier)))))); + } + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGenerator.cs new file mode 100644 index 0000000000000..74e7a517a4707 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGenerator.cs @@ -0,0 +1,119 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Diagnostics; + +namespace Microsoft.Interop +{ + /// + /// Interface for generation of marshalling code for P/Invoke stubs + /// + public interface IMarshallingGenerator + { + /// + /// Get the native type syntax for + /// + /// Object to marshal + /// Type syntax for the native type representing + TypeSyntax AsNativeType(TypePositionInfo info); + + /// + /// Get the as a parameter of the P/Invoke declaration + /// + /// Object to marshal + /// Parameter syntax for + ParameterSyntax AsParameter(TypePositionInfo info); + + /// + /// Get the as an argument to be passed to the P/Invoke + /// + /// Object to marshal + /// Code generation context + /// Argument syntax for + ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context); + + /// + /// Generate code for marshalling + /// + /// Object to marshal + /// Code generation context + /// List of statements to be added to the P/Invoke stub + /// + /// The generator should return the appropriate statements based on the + /// of . + /// For , any statements not of type + /// will be ignored. + /// + IEnumerable Generate(TypePositionInfo info, StubCodeContext context); + + /// + /// Returns whether or not this marshaller uses an identifier for the native value in addition + /// to an identifer for the managed value. + /// + /// Object to marshal + /// Code generation context + /// If the marshaller uses an identifier for the native value, true; otherwise, false. + /// + /// of may not be valid. + /// + bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context); + + /// + /// Returns if the given ByValueContentsMarshalKind is supported in the current marshalling context. + /// A supported marshal kind has a different behavior than the default behavior. + /// + /// The marshal kind. + /// The marshalling context. + /// + bool SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, StubCodeContext context); + } + + /// + /// Interface for generating attributes for native return types. + /// + public interface IAttributedReturnTypeMarshallingGenerator : IMarshallingGenerator + { + /// + /// Gets any attributes that should be applied to the return type for this . + /// + /// Object to marshal + /// Attributes for the return type for this , or null if no attributes should be added. + AttributeListSyntax? GenerateAttributesForReturnType(TypePositionInfo info); + } + + + /// + /// Exception used to indicate marshalling isn't supported. + /// + public sealed class MarshallingNotSupportedException : Exception + { + /// + /// Construct a new instance. + /// + /// instance + /// instance + public MarshallingNotSupportedException(TypePositionInfo info, StubCodeContext context) + { + TypePositionInfo = info; + StubCodeContext = context; + } + + /// + /// Type that is being marshalled. + /// + public TypePositionInfo TypePositionInfo { get; private init; } + + /// + /// Context in which the marshalling is taking place. + /// + public StubCodeContext StubCodeContext { get; private init; } + + /// + /// [Optional] Specific reason marshalling of the supplied type isn't supported. + /// + public string? NotSupportedDetails { get; init; } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGeneratorFactory.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGeneratorFactory.cs new file mode 100644 index 0000000000000..2170b4978b9d1 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/MarshallingGeneratorFactory.cs @@ -0,0 +1,218 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.InteropServices; +using Microsoft.CodeAnalysis; + +namespace Microsoft.Interop +{ + public interface IMarshallingGeneratorFactory + { + /// + /// Create an instance for marshalling the supplied type in the given position. + /// + /// Type details + /// Metadata about the stub the type is associated with + /// A instance. + public IMarshallingGenerator Create( + TypePositionInfo info, + StubCodeContext context); + } + + public sealed class DefaultMarshallingGeneratorFactory : IMarshallingGeneratorFactory + { + private static readonly ByteBoolMarshaller s_byteBool = new(); + private static readonly WinBoolMarshaller s_winBool = new(); + private static readonly VariantBoolMarshaller s_variantBool = new(); + + private static readonly Utf16CharMarshaller s_utf16Char = new(); + private static readonly Utf16StringMarshaller s_utf16String = new(); + private static readonly Utf8StringMarshaller s_utf8String = new(); + private static readonly AnsiStringMarshaller s_ansiString = new AnsiStringMarshaller(s_utf8String); + private static readonly PlatformDefinedStringMarshaller s_platformDefinedString = new PlatformDefinedStringMarshaller(s_utf16String, s_utf8String); + + private static readonly Forwarder s_forwarder = new(); + private static readonly BlittableMarshaller s_blittable = new(); + private static readonly DelegateMarshaller s_delegate = new(); + private static readonly SafeHandleMarshaller s_safeHandle = new(); + private InteropGenerationOptions Options { get; } + + public DefaultMarshallingGeneratorFactory(InteropGenerationOptions options) + { + Options = options; + } + + /// + /// Create an instance for marshalling the supplied type in the given position. + /// + /// Type details + /// Metadata about the stub the type is associated with + /// A instance. + public IMarshallingGenerator Create( + TypePositionInfo info, + StubCodeContext context) + { + switch (info) + { + // Blittable primitives with no marshalling info or with a compatible [MarshalAs] attribute. + case { ManagedType: SpecialTypeInfo { SpecialType: SpecialType.System_SByte }, MarshallingAttributeInfo: NoMarshallingInfo or MarshalAsInfo(UnmanagedType.I1, _) } + or { ManagedType: SpecialTypeInfo { SpecialType: SpecialType.System_Byte }, MarshallingAttributeInfo: NoMarshallingInfo or MarshalAsInfo(UnmanagedType.U1, _) } + or { ManagedType: SpecialTypeInfo { SpecialType: SpecialType.System_Int16 }, MarshallingAttributeInfo: NoMarshallingInfo or MarshalAsInfo(UnmanagedType.I2, _) } + or { ManagedType: SpecialTypeInfo { SpecialType: SpecialType.System_UInt16 }, MarshallingAttributeInfo: NoMarshallingInfo or MarshalAsInfo(UnmanagedType.U2, _) } + or { ManagedType: SpecialTypeInfo { SpecialType: SpecialType.System_Int32 }, MarshallingAttributeInfo: NoMarshallingInfo or MarshalAsInfo(UnmanagedType.I4, _) } + or { ManagedType: SpecialTypeInfo { SpecialType: SpecialType.System_UInt32 }, MarshallingAttributeInfo: NoMarshallingInfo or MarshalAsInfo(UnmanagedType.U4, _) } + or { ManagedType: SpecialTypeInfo { SpecialType: SpecialType.System_Int64 }, MarshallingAttributeInfo: NoMarshallingInfo or MarshalAsInfo(UnmanagedType.I8, _) } + or { ManagedType: SpecialTypeInfo { SpecialType: SpecialType.System_UInt64 }, MarshallingAttributeInfo: NoMarshallingInfo or MarshalAsInfo(UnmanagedType.U8, _) } + or { ManagedType: SpecialTypeInfo { SpecialType: SpecialType.System_IntPtr }, MarshallingAttributeInfo: NoMarshallingInfo or MarshalAsInfo(UnmanagedType.SysInt, _) } + or { ManagedType: SpecialTypeInfo { SpecialType: SpecialType.System_UIntPtr }, MarshallingAttributeInfo: NoMarshallingInfo or MarshalAsInfo(UnmanagedType.SysUInt, _) } + or { ManagedType: SpecialTypeInfo { SpecialType: SpecialType.System_Single }, MarshallingAttributeInfo: NoMarshallingInfo or MarshalAsInfo(UnmanagedType.R4, _) } + or { ManagedType: SpecialTypeInfo { SpecialType: SpecialType.System_Double }, MarshallingAttributeInfo: NoMarshallingInfo or MarshalAsInfo(UnmanagedType.R8, _) }: + return s_blittable; + + // Enum with no marshalling info + case { ManagedType: EnumTypeInfo enumType, MarshallingAttributeInfo: NoMarshallingInfo }: + // Check that the underlying type is not bool or char. C# does not allow this, but ECMA-335 does. + SpecialType underlyingSpecialType = enumType.UnderlyingType; + if (underlyingSpecialType == SpecialType.System_Boolean || underlyingSpecialType == SpecialType.System_Char) + { + throw new MarshallingNotSupportedException(info, context); + } + return s_blittable; + + // Pointer with no marshalling info + case { ManagedType: PointerTypeInfo(_, _, IsFunctionPointer: false), MarshallingAttributeInfo: NoMarshallingInfo }: + return s_blittable; + + // Function pointer with no marshalling info + case { ManagedType: PointerTypeInfo(_, _, IsFunctionPointer: true), MarshallingAttributeInfo: NoMarshallingInfo or MarshalAsInfo(UnmanagedType.FunctionPtr, _) }: + return s_blittable; + + case { ManagedType: SpecialTypeInfo { SpecialType: SpecialType.System_Boolean }, MarshallingAttributeInfo: NoMarshallingInfo }: + return s_winBool; // [Compat] Matching the default for the built-in runtime marshallers. + case { ManagedType: SpecialTypeInfo { SpecialType: SpecialType.System_Boolean }, MarshallingAttributeInfo: MarshalAsInfo(UnmanagedType.I1 or UnmanagedType.U1, _) }: + return s_byteBool; + case { ManagedType: SpecialTypeInfo { SpecialType: SpecialType.System_Boolean }, MarshallingAttributeInfo: MarshalAsInfo(UnmanagedType.I4 or UnmanagedType.U4 or UnmanagedType.Bool, _) }: + return s_winBool; + case { ManagedType: SpecialTypeInfo { SpecialType: SpecialType.System_Boolean }, MarshallingAttributeInfo: MarshalAsInfo(UnmanagedType.VariantBool, _) }: + return s_variantBool; + + case { ManagedType: DelegateTypeInfo, MarshallingAttributeInfo: NoMarshallingInfo or MarshalAsInfo(UnmanagedType.FunctionPtr, _) }: + return s_delegate; + + case { MarshallingAttributeInfo: SafeHandleMarshallingInfo(_, bool isAbstract) }: + if (!context.AdditionalTemporaryStateLivesAcrossStages) + { + throw new MarshallingNotSupportedException(info, context); + } + if (info.IsByRef && isAbstract) + { + throw new MarshallingNotSupportedException(info, context) + { + NotSupportedDetails = Resources.SafeHandleByRefMustBeConcrete + }; + } + return s_safeHandle; + + case { ManagedType: SpecialTypeInfo { SpecialType: SpecialType.System_Char } }: + return CreateCharMarshaller(info, context); + + case { ManagedType: SpecialTypeInfo { SpecialType: SpecialType.System_String } }: + return CreateStringMarshaller(info, context); + + case { ManagedType: SpecialTypeInfo { SpecialType: SpecialType.System_Void } }: + return s_forwarder; + + default: + throw new MarshallingNotSupportedException(info, context); + } + } + + private IMarshallingGenerator CreateCharMarshaller(TypePositionInfo info, StubCodeContext context) + { + MarshallingInfo marshalInfo = info.MarshallingAttributeInfo; + if (marshalInfo is NoMarshallingInfo) + { + // [Compat] Require explicit marshalling information. + throw new MarshallingNotSupportedException(info, context) + { + NotSupportedDetails = Resources.MarshallingStringOrCharAsUndefinedNotSupported + }; + } + + // Explicit MarshalAs takes precedence over string encoding info + if (marshalInfo is MarshalAsInfo marshalAsInfo) + { + switch (marshalAsInfo.UnmanagedType) + { + case UnmanagedType.I2: + case UnmanagedType.U2: + return s_utf16Char; + } + } + else if (marshalInfo is MarshallingInfoStringSupport marshalStringInfo) + { + switch (marshalStringInfo.CharEncoding) + { + case CharEncoding.Utf16: + return s_utf16Char; + case CharEncoding.Ansi: + throw new MarshallingNotSupportedException(info, context) // [Compat] ANSI is not supported for char + { + NotSupportedDetails = string.Format(Resources.MarshallingCharAsSpecifiedCharSetNotSupported, CharSet.Ansi) + }; + case CharEncoding.PlatformDefined: + throw new MarshallingNotSupportedException(info, context) // [Compat] See conversion of CharSet.Auto. + { + NotSupportedDetails = string.Format(Resources.MarshallingCharAsSpecifiedCharSetNotSupported, CharSet.Auto) + }; + } + } + + throw new MarshallingNotSupportedException(info, context); + } + + private IMarshallingGenerator CreateStringMarshaller(TypePositionInfo info, StubCodeContext context) + { + MarshallingInfo marshalInfo = info.MarshallingAttributeInfo; + if (marshalInfo is NoMarshallingInfo) + { + // [Compat] Require explicit marshalling information. + throw new MarshallingNotSupportedException(info, context) + { + NotSupportedDetails = Resources.MarshallingStringOrCharAsUndefinedNotSupported + }; + } + + // Explicit MarshalAs takes precedence over string encoding info + if (marshalInfo is MarshalAsInfo marshalAsInfo) + { + switch (marshalAsInfo.UnmanagedType) + { + case UnmanagedType.LPStr: + return s_ansiString; + case UnmanagedType.LPTStr: + case UnmanagedType.LPWStr: + return s_utf16String; + case (UnmanagedType)0x30:// UnmanagedType.LPUTF8Str + return s_utf8String; + } + } + else if (marshalInfo is MarshallingInfoStringSupport marshalStringInfo) + { + switch (marshalStringInfo.CharEncoding) + { + case CharEncoding.Ansi: + return s_ansiString; + case CharEncoding.Utf16: + return s_utf16String; + case CharEncoding.Utf8: + return s_utf8String; + case CharEncoding.PlatformDefined: + return s_platformDefinedString; + } + } + + throw new MarshallingNotSupportedException(info, context); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/PinnableManagedValueMarshaller.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/PinnableManagedValueMarshaller.cs new file mode 100644 index 0000000000000..aa47a55409cd2 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/PinnableManagedValueMarshaller.cs @@ -0,0 +1,87 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; + +namespace Microsoft.Interop +{ + public sealed class PinnableManagedValueMarshaller : IMarshallingGenerator + { + private readonly IMarshallingGenerator _manualMarshallingGenerator; + + public PinnableManagedValueMarshaller(IMarshallingGenerator manualMarshallingGenerator) + { + _manualMarshallingGenerator = manualMarshallingGenerator; + } + + public ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context) + { + if (IsPinningPathSupported(info, context)) + { + string identifier = context.GetIdentifiers(info).native; + return Argument(CastExpression(AsNativeType(info), IdentifierName(identifier))); + } + return _manualMarshallingGenerator.AsArgument(info, context); + } + + public TypeSyntax AsNativeType(TypePositionInfo info) + { + return _manualMarshallingGenerator.AsNativeType(info); + } + + public ParameterSyntax AsParameter(TypePositionInfo info) + { + return _manualMarshallingGenerator.AsParameter(info); + } + + public IEnumerable Generate(TypePositionInfo info, StubCodeContext context) + { + if (IsPinningPathSupported(info, context)) + { + return GeneratePinningPath(info, context); + } + return _manualMarshallingGenerator.Generate(info, context); + } + + public bool SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, StubCodeContext context) + { + return _manualMarshallingGenerator.SupportsByValueMarshalKind(marshalKind, context); + } + + public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) + { + if (IsPinningPathSupported(info, context)) + { + return false; + } + return _manualMarshallingGenerator.UsesNativeIdentifier(info, context); + } + private static bool IsPinningPathSupported(TypePositionInfo info, StubCodeContext context) + { + return context.SingleFrameSpansNativeContext && !info.IsByRef && !info.IsManagedReturnPosition; + } + + private IEnumerable GeneratePinningPath(TypePositionInfo info, StubCodeContext context) + { + if (context.CurrentStage == StubCodeContext.Stage.Pin) + { + (string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(info); + yield return FixedStatement( + VariableDeclaration( + PointerType(PredefinedType(Token(SyntaxKind.VoidKeyword))), + SingletonSeparatedList( + VariableDeclarator(Identifier(nativeIdentifier)) + .WithInitializer(EqualsValueClause( + IdentifierName(managedIdentifier) + )) + ) + ), + EmptyStatement() + ); + } + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/SafeHandleMarshaller.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/SafeHandleMarshaller.cs new file mode 100644 index 0000000000000..4a663542f52c1 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/SafeHandleMarshaller.cs @@ -0,0 +1,246 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Runtime.InteropServices; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; + +namespace Microsoft.Interop +{ + public sealed class SafeHandleMarshaller : IMarshallingGenerator + { + public TypeSyntax AsNativeType(TypePositionInfo info) + { + return MarshallerHelpers.SystemIntPtrType; + } + + public ParameterSyntax AsParameter(TypePositionInfo info) + { + TypeSyntax type = info.IsByRef + ? PointerType(AsNativeType(info)) + : AsNativeType(info); + return Parameter(Identifier(info.InstanceIdentifier)) + .WithType(type); + } + + public ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context) + { + string identifier = context.GetIdentifiers(info).native; + if (info.IsByRef) + { + return Argument( + PrefixUnaryExpression( + SyntaxKind.AddressOfExpression, + IdentifierName(identifier))); + } + + return Argument(IdentifierName(identifier)); + } + + public IEnumerable Generate(TypePositionInfo info, StubCodeContext context) + { + // The high level logic (note that the parameter may be in, out or both): + // 1) If this is an input parameter we need to AddRef the SafeHandle. + // 2) If this is an output parameter we need to preallocate a SafeHandle to wrap the new native handle value. We + // must allocate this before the native call to avoid a failure point when we already have a native resource + // allocated. We must allocate a new SafeHandle even if we have one on input since both input and output native + // handles need to be tracked and released by a SafeHandle. + // 3) Initialize a local IntPtr that will be passed to the native call. If we have an input SafeHandle the value + // comes from there otherwise we get it from the new SafeHandle (which is guaranteed to be initialized to an + // invalid handle value). + // 4) If this is a out parameter we also store the original handle value (that we just computed above) in a local + // variable. + // 5) If we successfully AddRef'd the incoming SafeHandle, we need to Release it before we return. + // 6) After the native call, if this is an output parameter and the handle value we passed to native differs from + // the local copy we made then the new handle value is written into the output SafeHandle and that SafeHandle + // is propagated back to the caller. + + (string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(info); + string addRefdIdentifier = $"{managedIdentifier}__addRefd"; + string newHandleObjectIdentifier = info.IsManagedReturnPosition + ? managedIdentifier + : $"{managedIdentifier}__newHandle"; + string handleValueBackupIdentifier = $"{nativeIdentifier}__original"; + switch (context.CurrentStage) + { + case StubCodeContext.Stage.Setup: + if (!info.IsManagedReturnPosition && info.RefKind != RefKind.Out) + { + yield return LocalDeclarationStatement( + VariableDeclaration( + PredefinedType(Token(SyntaxKind.BoolKeyword)), + SingletonSeparatedList( + VariableDeclarator(addRefdIdentifier) + .WithInitializer(EqualsValueClause(LiteralExpression(SyntaxKind.FalseLiteralExpression)))))); + } + + ExpressionSyntax safeHandleCreationExpression = ((SafeHandleMarshallingInfo)info.MarshallingAttributeInfo).AccessibleDefaultConstructor + ? ObjectCreationExpression(info.ManagedType.Syntax, ArgumentList(), initializer: null) + : CastExpression( + info.ManagedType.Syntax, + InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + ParseTypeName(TypeNames.System_Activator), + IdentifierName("CreateInstance"))) + .WithArgumentList( + ArgumentList( + SeparatedList( + new[]{ + Argument( + TypeOfExpression( + info.ManagedType.Syntax)), + Argument( + LiteralExpression( + SyntaxKind.TrueLiteralExpression)) + .WithNameColon( + NameColon( + IdentifierName("nonPublic"))) + })))); + + if (info.IsManagedReturnPosition) + { + yield return ExpressionStatement( + AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, + IdentifierName(managedIdentifier), + safeHandleCreationExpression + )); + } + else if (info.IsByRef && info.RefKind != RefKind.In) + { + // We create the new handle in the Setup phase + // so we eliminate the possible failure points during unmarshalling, where we would + // leak the handle if we failed to create the handle. + yield return LocalDeclarationStatement( + VariableDeclaration( + info.ManagedType.Syntax, + SingletonSeparatedList( + VariableDeclarator(newHandleObjectIdentifier) + .WithInitializer(EqualsValueClause(safeHandleCreationExpression))))); + if (info.RefKind != RefKind.Out) + { + yield return LocalDeclarationStatement( + VariableDeclaration( + AsNativeType(info), + SingletonSeparatedList( + VariableDeclarator(handleValueBackupIdentifier) + .WithInitializer(EqualsValueClause( + InvocationExpression( + MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, + IdentifierName(newHandleObjectIdentifier), + IdentifierName(nameof(SafeHandle.DangerousGetHandle))), + ArgumentList())))))); + } + } + break; + case StubCodeContext.Stage.Marshal: + if (info.RefKind != RefKind.Out) + { + // .DangerousAddRef(ref ); + yield return ExpressionStatement( + InvocationExpression( + MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, + IdentifierName(managedIdentifier), + IdentifierName(nameof(SafeHandle.DangerousAddRef))), + ArgumentList(SingletonSeparatedList( + Argument(IdentifierName(addRefdIdentifier)) + .WithRefKindKeyword(Token(SyntaxKind.RefKeyword)))))); + + + ExpressionSyntax assignHandleToNativeExpression = + AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, + IdentifierName(nativeIdentifier), + InvocationExpression( + MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, + IdentifierName(managedIdentifier), + IdentifierName(nameof(SafeHandle.DangerousGetHandle))), + ArgumentList())); + if (info.IsByRef && info.RefKind != RefKind.In) + { + yield return ExpressionStatement( + AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, + IdentifierName(handleValueBackupIdentifier), + assignHandleToNativeExpression)); + } + else + { + yield return ExpressionStatement(assignHandleToNativeExpression); + } + } + break; + case StubCodeContext.Stage.GuaranteedUnmarshal: + StatementSyntax unmarshalStatement = ExpressionStatement( + InvocationExpression( + MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, + ParseTypeName(TypeNames.System_Runtime_InteropServices_Marshal), + IdentifierName("InitHandle")), + ArgumentList(SeparatedList( + new[] + { + Argument(IdentifierName(newHandleObjectIdentifier)), + Argument(IdentifierName(nativeIdentifier)) + })))); + + if (info.IsManagedReturnPosition) + { + yield return unmarshalStatement; + } + else if (info.RefKind == RefKind.Out) + { + yield return unmarshalStatement; + yield return ExpressionStatement( + AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, + IdentifierName(managedIdentifier), + IdentifierName(newHandleObjectIdentifier))); + } + else if (info.RefKind == RefKind.Ref) + { + // Decrement refcount on original SafeHandle if we addrefd + yield return IfStatement( + IdentifierName(addRefdIdentifier), + ExpressionStatement( + InvocationExpression( + MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, + IdentifierName(managedIdentifier), + IdentifierName(nameof(SafeHandle.DangerousRelease))), + ArgumentList()))); + + // Do not unmarshal the handle if the value didn't change. + yield return IfStatement( + BinaryExpression(SyntaxKind.NotEqualsExpression, + IdentifierName(handleValueBackupIdentifier), + IdentifierName(nativeIdentifier)), + Block( + unmarshalStatement, + ExpressionStatement( + AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, + IdentifierName(managedIdentifier), + IdentifierName(newHandleObjectIdentifier))))); + } + break; + case StubCodeContext.Stage.Cleanup: + if (!info.IsManagedReturnPosition && (!info.IsByRef || info.RefKind == RefKind.In)) + { + yield return IfStatement( + IdentifierName(addRefdIdentifier), + ExpressionStatement( + InvocationExpression( + MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, + IdentifierName(managedIdentifier), + IdentifierName(nameof(SafeHandle.DangerousRelease))), + ArgumentList()))); + } + break; + default: + break; + } + } + + public bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) => true; + + public bool SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, StubCodeContext context) => false; + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Ansi.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Ansi.cs new file mode 100644 index 0000000000000..40c09b0ed1890 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Ansi.cs @@ -0,0 +1,167 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; + +using static Microsoft.Interop.MarshallerHelpers; + +namespace Microsoft.Interop +{ + public sealed class AnsiStringMarshaller : ConditionalStackallocMarshallingGenerator + { + private static readonly TypeSyntax s_nativeType = PointerType(PredefinedType(Token(SyntaxKind.ByteKeyword))); + + private readonly Utf8StringMarshaller _utf8StringMarshaller; + + public AnsiStringMarshaller(Utf8StringMarshaller utf8StringMarshaller) + { + _utf8StringMarshaller = utf8StringMarshaller; + } + + public override ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context) + { + string identifier = context.GetIdentifiers(info).native; + if (info.IsByRef) + { + // & + return Argument( + PrefixUnaryExpression( + SyntaxKind.AddressOfExpression, + IdentifierName(identifier))); + } + + // + return Argument(IdentifierName(identifier)); + } + + public override TypeSyntax AsNativeType(TypePositionInfo info) + { + // byte* + return s_nativeType; + } + + public override ParameterSyntax AsParameter(TypePositionInfo info) + { + // byte** + // or + // byte* + TypeSyntax type = info.IsByRef + ? PointerType(AsNativeType(info)) + : AsNativeType(info); + return Parameter(Identifier(info.InstanceIdentifier)) + .WithType(type); + } + + public override IEnumerable Generate(TypePositionInfo info, StubCodeContext context) + { + (string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(info); + switch (context.CurrentStage) + { + case StubCodeContext.Stage.Setup: + if (TryGenerateSetupSyntax(info, context, out StatementSyntax conditionalAllocSetup)) + yield return conditionalAllocSetup; + + break; + case StubCodeContext.Stage.Marshal: + if (info.RefKind != RefKind.Out) + { + // = (byte*)Marshal.StringToCoTaskMemAnsi(); + BlockSyntax windowsBlock = Block( + ExpressionStatement( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + IdentifierName(nativeIdentifier), + CastExpression( + AsNativeType(info), + StringMarshaller.AllocationExpression(CharEncoding.Ansi, managedIdentifier))))); + + // Set the allocation marker to true if it is being used + if (UsesConditionalStackAlloc(info, context)) + { + // = true + windowsBlock = windowsBlock.AddStatements( + ExpressionStatement( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + IdentifierName(GetAllocationMarkerIdentifier(info, context)), + LiteralExpression(SyntaxKind.TrueLiteralExpression)))); + } + + // [Compat] The generated source for ANSI string marshalling does not optimize for + // allocating on the stack based on the string length. It always uses AllocCoTaskMem. + // if (OperatingSystem.IsWindows()) + // { + // = (byte*)Marshal.StringToCoTaskMemAnsi(); + // } + // else + // { + // << marshal as UTF-8 >> + // } + yield return IfStatement(IsWindows, + windowsBlock, + ElseClause( + Block(_utf8StringMarshaller.Generate(info, context)))); + } + break; + case StubCodeContext.Stage.Unmarshal: + if (info.IsManagedReturnPosition || (info.IsByRef && info.RefKind != RefKind.In)) + { + // if (OperatingSystem.IsWindows()) + // { + // = == null ? null : new string((sbyte*)); + // } + // else + // { + // << unmarshal as UTF-8 >> + // } + yield return IfStatement(IsWindows, + Block( + ExpressionStatement( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + IdentifierName(managedIdentifier), + ConditionalExpression( + BinaryExpression( + SyntaxKind.EqualsExpression, + IdentifierName(nativeIdentifier), + LiteralExpression(SyntaxKind.DefaultLiteralExpression)), + LiteralExpression(SyntaxKind.NullLiteralExpression), + ObjectCreationExpression( + PredefinedType(Token(SyntaxKind.StringKeyword)), + ArgumentList(SingletonSeparatedList( + Argument( + CastExpression( + PointerType(PredefinedType(Token(SyntaxKind.SByteKeyword))), + IdentifierName(nativeIdentifier))))), + initializer: null))))), + ElseClause( + Block(_utf8StringMarshaller.Generate(info, context)))); + } + break; + case StubCodeContext.Stage.Cleanup: + yield return GenerateConditionalAllocationFreeSyntax(info, context); + break; + } + } + + public override bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) => true; + + public override bool SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, StubCodeContext context) => false; + + // This marshaller only uses the conditional allocaction base for setup and cleanup. + // It always allocates for ANSI (Windows) and relies on the UTF-8 (non-Windows) string marshaller for allocation/marshalling. + protected override ExpressionSyntax GenerateAllocationExpression(TypePositionInfo info, StubCodeContext context, SyntaxToken byteLengthIdentifier, out bool allocationRequiresByteLength) => throw new NotImplementedException(); + protected override ExpressionSyntax GenerateByteLengthCalculationExpression(TypePositionInfo info, StubCodeContext context) => throw new NotImplementedException(); + protected override StatementSyntax GenerateStackallocOnlyValueMarshalling(TypePositionInfo info, StubCodeContext context, SyntaxToken byteLengthIdentifier, SyntaxToken stackAllocPtrIdentifier) => throw new NotImplementedException(); + + protected override ExpressionSyntax GenerateFreeExpression(TypePositionInfo info, StubCodeContext context) + { + return StringMarshaller.FreeExpression(context.GetIdentifiers(info).native); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.PlatformDefined.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.PlatformDefined.cs new file mode 100644 index 0000000000000..655e2fe1b218a --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.PlatformDefined.cs @@ -0,0 +1,179 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; + +using static Microsoft.Interop.MarshallerHelpers; + +namespace Microsoft.Interop +{ + public sealed class PlatformDefinedStringMarshaller : ConditionalStackallocMarshallingGenerator + { + private static readonly TypeSyntax s_nativeType = PointerType(PredefinedType(Token(SyntaxKind.VoidKeyword))); + + private readonly IMarshallingGenerator _windowsMarshaller; + private readonly IMarshallingGenerator _nonWindowsMarshaller; + + public PlatformDefinedStringMarshaller(IMarshallingGenerator windowsMarshaller, IMarshallingGenerator nonWindowsMarshaller) + { + _windowsMarshaller = windowsMarshaller; + _nonWindowsMarshaller = nonWindowsMarshaller; + } + + public override ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context) + { + ExpressionSyntax windowsExpr = _windowsMarshaller.AsArgument(info, context).Expression; + ExpressionSyntax nonWindowsExpr = _nonWindowsMarshaller.AsArgument(info, context).Expression; + + // If the Windows and non-Windows syntax are equivalent, just return one of them. + if (windowsExpr.IsEquivalentTo(nonWindowsExpr)) + return Argument(windowsExpr); + + // OperatingSystem.IsWindows() ? << Windows code >> : << non-Windows code >> + return Argument( + ConditionalExpression( + IsWindows, + windowsExpr, + nonWindowsExpr)); + } + + public override TypeSyntax AsNativeType(TypePositionInfo info) + { + // void* + return s_nativeType; + } + + public override ParameterSyntax AsParameter(TypePositionInfo info) + { + // void** + // or + // void* + TypeSyntax type = info.IsByRef + ? PointerType(AsNativeType(info)) + : AsNativeType(info); + return Parameter(Identifier(info.InstanceIdentifier)) + .WithType(type); + } + + public override IEnumerable Generate(TypePositionInfo info, StubCodeContext context) + { + switch (context.CurrentStage) + { + case StubCodeContext.Stage.Setup: + if (TryGenerateSetupSyntax(info, context, out StatementSyntax conditionalAllocSetup)) + yield return conditionalAllocSetup; + + break; + case StubCodeContext.Stage.Marshal: + if (info.RefKind != RefKind.Out) + { + if (TryGetConditionalBlockForStatements( + _windowsMarshaller.Generate(info, context), + _nonWindowsMarshaller.Generate(info, context), + out StatementSyntax marshal)) + { + yield return marshal; + } + } + break; + case StubCodeContext.Stage.Pin: + // [Compat] The built-in system could determine the platform at runtime and pin only on + // the platform on which is is needed. In the generated source, if pinning is needed for + // any platform, it is done on every platform. + foreach (StatementSyntax s in _windowsMarshaller.Generate(info, context)) + yield return s; + + foreach (StatementSyntax s in _nonWindowsMarshaller.Generate(info, context)) + yield return s; + + break; + case StubCodeContext.Stage.Unmarshal: + if (info.IsManagedReturnPosition || (info.IsByRef && info.RefKind != RefKind.In)) + { + if (TryGetConditionalBlockForStatements( + _windowsMarshaller.Generate(info, context), + _nonWindowsMarshaller.Generate(info, context), + out StatementSyntax unmarshal)) + { + yield return unmarshal; + } + } + break; + case StubCodeContext.Stage.Cleanup: + yield return GenerateConditionalAllocationFreeSyntax(info, context); + break; + } + } + + public override bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) => true; + + public override bool SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, StubCodeContext context) => false; + + // This marshaller only uses the conditional allocaction base for setup and cleanup. + // It relies on the UTF-16 (Windows) and UTF-8 (non-Windows) string marshallers for allocation/marshalling. + protected override ExpressionSyntax GenerateAllocationExpression(TypePositionInfo info, StubCodeContext context, SyntaxToken byteLengthIdentifier, out bool allocationRequiresByteLength) => throw new NotImplementedException(); + protected override ExpressionSyntax GenerateByteLengthCalculationExpression(TypePositionInfo info, StubCodeContext context) => throw new NotImplementedException(); + protected override StatementSyntax GenerateStackallocOnlyValueMarshalling(TypePositionInfo info, StubCodeContext context, SyntaxToken byteLengthIdentifier, SyntaxToken stackAllocPtrIdentifier) => throw new NotImplementedException(); + + protected override ExpressionSyntax GenerateFreeExpression(TypePositionInfo info, StubCodeContext context) + { + return StringMarshaller.FreeExpression(context.GetIdentifiers(info).native); + } + + private bool TryGetConditionalBlockForStatements( + IEnumerable windowsStatements, + IEnumerable nonWindowsStatements, + out StatementSyntax conditionalBlock) + { + conditionalBlock = EmptyStatement(); + + bool hasWindowsStatements = windowsStatements.Any(); + bool hasNonWindowsStatements = nonWindowsStatements.Any(); + if (hasWindowsStatements) + { + IfStatementSyntax windowsIfBlock = IfStatement(IsWindows, Block(windowsStatements)); + if (hasNonWindowsStatements) + { + // if (OperatingSystem.IsWindows()) + // { + // << Windows code >> + // } + // else + // { + // << non-Windows code >> + // } + conditionalBlock = windowsIfBlock.WithElse( + ElseClause(Block(nonWindowsStatements))); + } + else + { + // if (OperatingSystem.IsWindows()) + // { + // << Windows code >> + // } + conditionalBlock = windowsIfBlock; + } + + return true; + } + else if (hasNonWindowsStatements) + { + // if (!OperatingSystem.IsWindows()) + // { + // << non-Windows code >> + // } + conditionalBlock = IfStatement(PrefixUnaryExpression(SyntaxKind.LogicalNotExpression, IsWindows), + Block(nonWindowsStatements)); + + } + + return hasWindowsStatements || hasNonWindowsStatements; + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Utf16.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Utf16.cs new file mode 100644 index 0000000000000..aca7252e6f39d --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Utf16.cs @@ -0,0 +1,236 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; + +using static Microsoft.Interop.MarshallerHelpers; + +namespace Microsoft.Interop +{ + public sealed class Utf16StringMarshaller : ConditionalStackallocMarshallingGenerator + { + // [Compat] Equivalent of MAX_PATH on Windows to match built-in system + // The assumption is file paths are the most common case for marshalling strings, + // so the threshold for optimized allocation is based on that length. + private const int StackAllocBytesThreshold = 260 * sizeof(ushort); + + private static readonly TypeSyntax s_nativeType = PointerType(PredefinedType(Token(SyntaxKind.UShortKeyword))); + + private static string PinnedIdentifier(string nativeIdentifier) => $"{nativeIdentifier}__pinned"; + + public override ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context) + { + string identifier = context.GetIdentifiers(info).native; + if (info.IsByRef) + { + // & + return Argument( + PrefixUnaryExpression( + SyntaxKind.AddressOfExpression, + IdentifierName(identifier))); + } + else if (context.SingleFrameSpansNativeContext) + { + // (ushort*) + return Argument( + CastExpression( + AsNativeType(info), + IdentifierName(PinnedIdentifier(identifier)))); + } + + // + return Argument(IdentifierName(identifier)); + } + + public override TypeSyntax AsNativeType(TypePositionInfo info) + { + // ushort* + return s_nativeType; + } + + public override ParameterSyntax AsParameter(TypePositionInfo info) + { + // ushort** + // or + // ushort* + TypeSyntax type = info.IsByRef + ? PointerType(AsNativeType(info)) + : AsNativeType(info); + return Parameter(Identifier(info.InstanceIdentifier)) + .WithType(type); + } + + public override IEnumerable Generate(TypePositionInfo info, StubCodeContext context) + { + (string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(info); + if (context.SingleFrameSpansNativeContext && !info.IsByRef && !info.IsManagedReturnPosition) + { + if (context.CurrentStage == StubCodeContext.Stage.Pin) + { + // fixed (char* = ) + yield return FixedStatement( + VariableDeclaration( + PointerType(PredefinedType(Token(SyntaxKind.CharKeyword))), + SingletonSeparatedList( + VariableDeclarator(Identifier(PinnedIdentifier(nativeIdentifier))) + .WithInitializer(EqualsValueClause(IdentifierName(managedIdentifier))))), + EmptyStatement()); + } + + yield break; + } + + switch (context.CurrentStage) + { + case StubCodeContext.Stage.Setup: + if (TryGenerateSetupSyntax(info, context, out StatementSyntax conditionalAllocSetup)) + yield return conditionalAllocSetup; + + break; + case StubCodeContext.Stage.Marshal: + if (info.RefKind != RefKind.Out) + { + foreach (StatementSyntax statement in GenerateConditionalAllocationSyntax( + info, + context, + StackAllocBytesThreshold)) + { + yield return statement; + } + } + break; + case StubCodeContext.Stage.Unmarshal: + if (info.IsManagedReturnPosition || (info.IsByRef && info.RefKind != RefKind.In)) + { + // = == null ? null : new string((char*)); + yield return ExpressionStatement( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + IdentifierName(managedIdentifier), + ConditionalExpression( + BinaryExpression( + SyntaxKind.EqualsExpression, + IdentifierName(nativeIdentifier), + LiteralExpression(SyntaxKind.DefaultLiteralExpression)), + LiteralExpression(SyntaxKind.NullLiteralExpression), + ObjectCreationExpression( + PredefinedType(Token(SyntaxKind.StringKeyword)), + ArgumentList(SingletonSeparatedList( + Argument( + CastExpression( + PointerType(PredefinedType(Token(SyntaxKind.CharKeyword))), + IdentifierName(nativeIdentifier))))), + initializer: null)))); + } + break; + case StubCodeContext.Stage.Cleanup: + yield return GenerateConditionalAllocationFreeSyntax(info, context); + + break; + } + } + + public override bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) => true; + + public override bool SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, StubCodeContext context) => false; + + protected override ExpressionSyntax GenerateAllocationExpression( + TypePositionInfo info, + StubCodeContext context, + SyntaxToken byteLengthIdentifier, + out bool allocationRequiresByteLength) + { + allocationRequiresByteLength = false; + return CastExpression( + AsNativeType(info), + StringMarshaller.AllocationExpression(CharEncoding.Utf16, context.GetIdentifiers(info).managed)); + } + + protected override ExpressionSyntax GenerateByteLengthCalculationExpression(TypePositionInfo info, StubCodeContext context) + { + // +1 for null terminator + // *2 for number of bytes per char + // int = (.Length + 1) * 2; + return + BinaryExpression( + SyntaxKind.MultiplyExpression, + ParenthesizedExpression( + BinaryExpression( + SyntaxKind.AddExpression, + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + IdentifierName(context.GetIdentifiers(info).managed), + IdentifierName("Length")), + LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(1)))), + LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(2))); + } + + protected override StatementSyntax GenerateStackallocOnlyValueMarshalling( + TypePositionInfo info, + StubCodeContext context, + SyntaxToken byteLengthIdentifier, + SyntaxToken stackAllocPtrIdentifier) + { + string managedIdentifier = context.GetIdentifiers(info).managed; + return Block( + // ((ReadOnlySpan)).CopyTo(new Span(, .Length)); + ExpressionStatement( + InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + ParenthesizedExpression( + CastExpression( + GenericName(Identifier("System.ReadOnlySpan"), + TypeArgumentList(SingletonSeparatedList( + PredefinedType(Token(SyntaxKind.CharKeyword))))), + IdentifierName(managedIdentifier))), + IdentifierName("CopyTo")), + ArgumentList( + SeparatedList(new[] { + Argument( + ObjectCreationExpression( + GenericName(Identifier(TypeNames.System_Span), + TypeArgumentList(SingletonSeparatedList( + PredefinedType(Token(SyntaxKind.CharKeyword))))), + ArgumentList( + SeparatedList(new[]{ + Argument(IdentifierName(stackAllocPtrIdentifier)), + Argument( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + IdentifierName(managedIdentifier), + IdentifierName("Length")))})), + initializer: null))})))), + // ((char*))[.Length] = '\0'; + ExpressionStatement( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + ElementAccessExpression( + ParenthesizedExpression( + CastExpression( + PointerType(PredefinedType(Token(SyntaxKind.CharKeyword))), + IdentifierName(stackAllocPtrIdentifier))), + BracketedArgumentList( + SingletonSeparatedList( + Argument( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + IdentifierName(managedIdentifier), + IdentifierName("Length")))))), + LiteralExpression( + SyntaxKind.CharacterLiteralExpression, + Literal('\0'))))); + } + + protected override ExpressionSyntax GenerateFreeExpression( + TypePositionInfo info, + StubCodeContext context) + { + return StringMarshaller.FreeExpression(context.GetIdentifiers(info).native); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Utf8.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Utf8.cs new file mode 100644 index 0000000000000..8414b271b0ef6 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Marshalling/StringMarshaller.Utf8.cs @@ -0,0 +1,192 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; + +using static Microsoft.Interop.MarshallerHelpers; + +namespace Microsoft.Interop +{ + public sealed class Utf8StringMarshaller : ConditionalStackallocMarshallingGenerator + { + // [Compat] Equivalent of MAX_PATH on Windows to match built-in system + // The assumption is file paths are the most common case for marshalling strings, + // so the threshold for optimized allocation is based on that length. + private const int StackAllocBytesThreshold = 260; + + // Conversion from a 2-byte 'char' in UTF-16 to bytes in UTF-8 has a maximum of 3 bytes per 'char' + // Two bytes ('char') in UTF-16 can be either: + // - Code point in the Basic Multilingual Plane: all 16 bits are that of the code point + // - Part of a pair for a code point in the Supplementary Planes: 10 bits are that of the code point + // In UTF-8, 3 bytes are need to represent the code point in first and 4 bytes in the second. Thus, the + // maximum number of bytes per 'char' is 3. + private const int MaxByteCountPerChar = 3; + + private static readonly TypeSyntax s_nativeType = PointerType(PredefinedType(Token(SyntaxKind.ByteKeyword))); + private static readonly TypeSyntax s_utf8EncodingType = ParseTypeName("System.Text.Encoding.UTF8"); + + public override ArgumentSyntax AsArgument(TypePositionInfo info, StubCodeContext context) + { + string identifier = context.GetIdentifiers(info).native; + if (info.IsByRef) + { + return Argument( + PrefixUnaryExpression( + SyntaxKind.AddressOfExpression, + IdentifierName(identifier))); + } + + return Argument(IdentifierName(identifier)); + } + + public override TypeSyntax AsNativeType(TypePositionInfo info) => s_nativeType; + + public override ParameterSyntax AsParameter(TypePositionInfo info) + { + TypeSyntax type = info.IsByRef + ? PointerType(AsNativeType(info)) + : AsNativeType(info); + return Parameter(Identifier(info.InstanceIdentifier)) + .WithType(type); + } + + public override IEnumerable Generate(TypePositionInfo info, StubCodeContext context) + { + (string managedIdentifier, string nativeIdentifier) = context.GetIdentifiers(info); + switch (context.CurrentStage) + { + case StubCodeContext.Stage.Setup: + if (TryGenerateSetupSyntax(info, context, out StatementSyntax conditionalAllocSetup)) + yield return conditionalAllocSetup; + + break; + case StubCodeContext.Stage.Marshal: + if (info.RefKind != RefKind.Out) + { + foreach (StatementSyntax statement in GenerateConditionalAllocationSyntax( + info, + context, + StackAllocBytesThreshold)) + { + yield return statement; + } + } + break; + case StubCodeContext.Stage.Unmarshal: + if (info.IsManagedReturnPosition || (info.IsByRef && info.RefKind != RefKind.In)) + { + // = Marshal.PtrToStringUTF8((IntPtr)); + yield return ExpressionStatement( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + IdentifierName(managedIdentifier), + InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + InteropServicesMarshalType, + IdentifierName("PtrToStringUTF8")), + ArgumentList(SingletonSeparatedList( + Argument( + CastExpression( + SystemIntPtrType, + IdentifierName(nativeIdentifier)))))))); + } + break; + case StubCodeContext.Stage.Cleanup: + yield return GenerateConditionalAllocationFreeSyntax(info, context); + break; + } + } + + public override bool UsesNativeIdentifier(TypePositionInfo info, StubCodeContext context) => true; + + public override bool SupportsByValueMarshalKind(ByValueContentsMarshalKind marshalKind, StubCodeContext context) => false; + + protected override ExpressionSyntax GenerateAllocationExpression( + TypePositionInfo info, + StubCodeContext context, + SyntaxToken byteLengthIdentifier, + out bool allocationRequiresByteLength) + { + allocationRequiresByteLength = false; + return CastExpression( + AsNativeType(info), + StringMarshaller.AllocationExpression(CharEncoding.Utf8, context.GetIdentifiers(info).managed)); + } + + protected override ExpressionSyntax GenerateByteLengthCalculationExpression(TypePositionInfo info, StubCodeContext context) + { + // + 1 for number of characters in case left over high surrogate is ? + // * (3 for UTF-8) + // +1 for null terminator + // int = (.Length + 1) * 3 + 1; + return BinaryExpression( + SyntaxKind.AddExpression, + BinaryExpression( + SyntaxKind.MultiplyExpression, + ParenthesizedExpression( + BinaryExpression( + SyntaxKind.AddExpression, + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + IdentifierName(context.GetIdentifiers(info).managed), + IdentifierName("Length")), + LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(1)))), + LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(MaxByteCountPerChar))), + LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(1))); + } + + protected override StatementSyntax GenerateStackallocOnlyValueMarshalling( + TypePositionInfo info, + StubCodeContext context, + SyntaxToken byteLengthIdentifier, + SyntaxToken stackAllocPtrIdentifier) + { + return Block( + // = Encoding.UTF8.GetBytes(, new Span(, )); + ExpressionStatement( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + IdentifierName(byteLengthIdentifier), + InvocationExpression( + MemberAccessExpression( + SyntaxKind.SimpleMemberAccessExpression, + s_utf8EncodingType, + IdentifierName("GetBytes")), + ArgumentList( + SeparatedList(new ArgumentSyntax[] { + Argument(IdentifierName(context.GetIdentifiers(info).managed)), + Argument( + ObjectCreationExpression( + GenericName(Identifier(TypeNames.System_Span), + TypeArgumentList(SingletonSeparatedList( + PredefinedType(Token(SyntaxKind.ByteKeyword))))), + ArgumentList( + SeparatedList(new ArgumentSyntax[]{ + Argument(IdentifierName(stackAllocPtrIdentifier)), + Argument(IdentifierName(byteLengthIdentifier))})), + initializer: null))}))))), + // [] = 0; + ExpressionStatement( + AssignmentExpression( + SyntaxKind.SimpleAssignmentExpression, + ElementAccessExpression( + IdentifierName(stackAllocPtrIdentifier), + BracketedArgumentList( + SingletonSeparatedList( + Argument(IdentifierName(byteLengthIdentifier))))), + LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(0))))); + } + + protected override ExpressionSyntax GenerateFreeExpression( + TypePositionInfo info, + StubCodeContext context) + { + return StringMarshaller.FreeExpression(context.GetIdentifiers(info).native); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/MarshallingAttributeInfo.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/MarshallingAttributeInfo.cs new file mode 100644 index 0000000000000..6924088f311fd --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/MarshallingAttributeInfo.cs @@ -0,0 +1,814 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.CodeAnalysis; +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Diagnostics; +using System.Linq; +using System.Runtime.InteropServices; + +namespace Microsoft.Interop +{ + + /// + /// Type used to pass on default marshalling details. + /// + public sealed record DefaultMarshallingInfo( + CharEncoding CharEncoding + ); + + // The following types are modeled to fit with the current prospective spec + // for C# vNext discriminated unions. Once discriminated unions are released, + // these should be updated to be implemented as a discriminated union. + + public abstract record MarshallingInfo + { + // Add a constructor that can only be called by derived types in the same assembly + // to enforce that this type cannot be extended by users of this library. + private protected MarshallingInfo() + { } + } + + public sealed record NoMarshallingInfo : MarshallingInfo + { + public static readonly MarshallingInfo Instance = new NoMarshallingInfo(); + + private NoMarshallingInfo() { } + } + + /// + /// Character encoding enumeration. + /// + public enum CharEncoding + { + Undefined, + Utf8, + Utf16, + Ansi, + PlatformDefined + } + + /// + /// Details that are required when scenario supports strings. + /// + public record MarshallingInfoStringSupport( + CharEncoding CharEncoding + ) : MarshallingInfo; + + /// + /// Simple User-application of System.Runtime.InteropServices.MarshalAsAttribute + /// + public sealed record MarshalAsInfo( + UnmanagedType UnmanagedType, + CharEncoding CharEncoding) : MarshallingInfoStringSupport(CharEncoding) + { + } + + /// + /// User-applied System.Runtime.InteropServices.BlittableTypeAttribute + /// or System.Runtime.InteropServices.GeneratedMarshallingAttribute on a blittable type + /// in source in this compilation. + /// + public sealed record BlittableTypeAttributeInfo : MarshallingInfo; + + [Flags] + public enum CustomMarshallingFeatures + { + None = 0, + ManagedToNative = 0x1, + NativeToManaged = 0x2, + ManagedToNativeStackalloc = 0x4, + ManagedTypePinning = 0x8, + NativeTypePinning = 0x10, + FreeNativeResources = 0x20, + } + + public abstract record CountInfo + { + private protected CountInfo() { } + } + + public sealed record NoCountInfo : CountInfo + { + public static readonly NoCountInfo Instance = new NoCountInfo(); + + private NoCountInfo() { } + } + + public sealed record ConstSizeCountInfo(int Size) : CountInfo; + + public sealed record CountElementCountInfo(TypePositionInfo ElementInfo) : CountInfo + { + public const string ReturnValueElementName = "return-value"; + } + + public sealed record SizeAndParamIndexInfo(int ConstSize, TypePositionInfo? ParamAtIndex) : CountInfo + { + public const int UnspecifiedConstSize = -1; + + public const TypePositionInfo UnspecifiedParam = null; + + public static readonly SizeAndParamIndexInfo Unspecified = new(UnspecifiedConstSize, UnspecifiedParam); + } + + /// + /// User-applied System.Runtime.InteropServices.NativeMarshallingAttribute + /// + public record NativeMarshallingAttributeInfo( + ManagedTypeInfo NativeMarshallingType, + ManagedTypeInfo? ValuePropertyType, + CustomMarshallingFeatures MarshallingFeatures, + bool UseDefaultMarshalling) : MarshallingInfo; + + /// + /// User-applied System.Runtime.InteropServices.GeneratedMarshallingAttribute + /// on a non-blittable type in source in this compilation. + /// + public sealed record GeneratedNativeMarshallingAttributeInfo( + string NativeMarshallingFullyQualifiedTypeName) : MarshallingInfo; + + /// + /// The type of the element is a SafeHandle-derived type with no marshalling attributes. + /// + public sealed record SafeHandleMarshallingInfo(bool AccessibleDefaultConstructor, bool IsAbstract) : MarshallingInfo; + + /// + /// User-applied System.Runtime.InteropServices.NativeMarshallingAttribute + /// with a contiguous collection marshaller + public sealed record NativeContiguousCollectionMarshallingInfo( + ManagedTypeInfo NativeMarshallingType, + ManagedTypeInfo? ValuePropertyType, + CustomMarshallingFeatures MarshallingFeatures, + bool UseDefaultMarshalling, + CountInfo ElementCountInfo, + ManagedTypeInfo ElementType, + MarshallingInfo ElementMarshallingInfo) : NativeMarshallingAttributeInfo( + NativeMarshallingType, + ValuePropertyType, + MarshallingFeatures, + UseDefaultMarshalling + ); + + public sealed class MarshallingAttributeInfoParser + { + private readonly Compilation _compilation; + private readonly IGeneratorDiagnostics _diagnostics; + private readonly DefaultMarshallingInfo _defaultInfo; + private readonly ISymbol _contextSymbol; + private readonly ITypeSymbol _marshalAsAttribute; + private readonly ITypeSymbol _marshalUsingAttribute; + + public MarshallingAttributeInfoParser( + Compilation compilation, + IGeneratorDiagnostics diagnostics, + DefaultMarshallingInfo defaultInfo, + ISymbol contextSymbol) + { + _compilation = compilation; + _diagnostics = diagnostics; + _defaultInfo = defaultInfo; + _contextSymbol = contextSymbol; + _marshalAsAttribute = compilation.GetTypeByMetadataName(TypeNames.System_Runtime_InteropServices_MarshalAsAttribute)!; + _marshalUsingAttribute = compilation.GetTypeByMetadataName(TypeNames.MarshalUsingAttribute)!; + } + + public MarshallingInfo ParseMarshallingInfo( + ITypeSymbol managedType, + IEnumerable useSiteAttributes) + { + return ParseMarshallingInfo(managedType, useSiteAttributes, ImmutableHashSet.Empty); + } + + private MarshallingInfo ParseMarshallingInfo( + ITypeSymbol managedType, + IEnumerable useSiteAttributes, + ImmutableHashSet inspectedElements) + { + Dictionary marshallingAttributesByIndirectionLevel = new(); + int maxIndirectionLevelDataProvided = 0; + foreach (AttributeData attribute in useSiteAttributes) + { + if (TryGetAttributeIndirectionLevel(attribute, out int indirectionLevel)) + { + if (marshallingAttributesByIndirectionLevel.ContainsKey(indirectionLevel)) + { + _diagnostics.ReportInvalidMarshallingAttributeInfo(attribute, nameof(Resources.DuplicateMarshallingInfo), indirectionLevel.ToString()); + return NoMarshallingInfo.Instance; + } + marshallingAttributesByIndirectionLevel.Add(indirectionLevel, attribute); + maxIndirectionLevelDataProvided = Math.Max(maxIndirectionLevelDataProvided, indirectionLevel); + } + } + + int maxIndirectionLevelUsed = 0; + MarshallingInfo info = GetMarshallingInfo( + managedType, + marshallingAttributesByIndirectionLevel, + indirectionLevel: 0, + inspectedElements, + ref maxIndirectionLevelUsed); + if (maxIndirectionLevelUsed < maxIndirectionLevelDataProvided) + { + _diagnostics.ReportInvalidMarshallingAttributeInfo( + marshallingAttributesByIndirectionLevel[maxIndirectionLevelDataProvided], + nameof(Resources.ExtraneousMarshallingInfo), + maxIndirectionLevelDataProvided.ToString(), + maxIndirectionLevelUsed.ToString()); + } + return info; + } + + private MarshallingInfo GetMarshallingInfo( + ITypeSymbol type, + Dictionary useSiteAttributes, + int indirectionLevel, + ImmutableHashSet inspectedElements, + ref int maxIndirectionLevelUsed) + { + maxIndirectionLevelUsed = Math.Max(indirectionLevel, maxIndirectionLevelUsed); + CountInfo parsedCountInfo = NoCountInfo.Instance; + + if (useSiteAttributes.TryGetValue(indirectionLevel, out AttributeData useSiteAttribute)) + { + INamedTypeSymbol attributeClass = useSiteAttribute.AttributeClass!; + + if (indirectionLevel == 0 + && SymbolEqualityComparer.Default.Equals(_compilation.GetTypeByMetadataName(TypeNames.System_Runtime_InteropServices_MarshalAsAttribute), attributeClass)) + { + // https://docs.microsoft.com/dotnet/api/system.runtime.interopservices.marshalasattribute + return CreateInfoFromMarshalAs(type, useSiteAttribute, inspectedElements, ref maxIndirectionLevelUsed); + } + else if (SymbolEqualityComparer.Default.Equals(_compilation.GetTypeByMetadataName(TypeNames.MarshalUsingAttribute), attributeClass)) + { + if (parsedCountInfo != NoCountInfo.Instance) + { + _diagnostics.ReportInvalidMarshallingAttributeInfo(useSiteAttribute, nameof(Resources.DuplicateCountInfo)); + return NoMarshallingInfo.Instance; + } + parsedCountInfo = CreateCountInfo(useSiteAttribute, inspectedElements); + if (useSiteAttribute.ConstructorArguments.Length != 0) + { + return CreateNativeMarshallingInfo( + type, + useSiteAttribute, + isMarshalUsingAttribute: true, + indirectionLevel, + parsedCountInfo, + useSiteAttributes, + inspectedElements, + ref maxIndirectionLevelUsed); + } + } + } + + // If we aren't overriding the marshalling at usage time, + // then fall back to the information on the element type itself. + foreach (AttributeData typeAttribute in type.GetAttributes()) + { + INamedTypeSymbol attributeClass = typeAttribute.AttributeClass!; + + if (SymbolEqualityComparer.Default.Equals(_compilation.GetTypeByMetadataName(TypeNames.BlittableTypeAttribute), attributeClass)) + { + // If type is generic, then we need to re-evaluate that it is blittable at usage time. + if (type is INamedTypeSymbol { IsGenericType: false } || type.HasOnlyBlittableFields()) + { + return new BlittableTypeAttributeInfo(); + } + break; + } + else if (SymbolEqualityComparer.Default.Equals(_compilation.GetTypeByMetadataName(TypeNames.NativeMarshallingAttribute), attributeClass)) + { + return CreateNativeMarshallingInfo( + type, + typeAttribute, + isMarshalUsingAttribute: false, + indirectionLevel, + parsedCountInfo, + useSiteAttributes, + inspectedElements, + ref maxIndirectionLevelUsed); + } + else if (SymbolEqualityComparer.Default.Equals(_compilation.GetTypeByMetadataName(TypeNames.GeneratedMarshallingAttribute), attributeClass)) + { + return type.IsConsideredBlittable() ? new BlittableTypeAttributeInfo() : new GeneratedNativeMarshallingAttributeInfo(null! /* TODO: determine naming convention */); + } + } + + // If the type doesn't have custom attributes that dictate marshalling, + // then consider the type itself. + if (TryCreateTypeBasedMarshallingInfo( + type, + parsedCountInfo, + indirectionLevel, + useSiteAttributes, + inspectedElements, + ref maxIndirectionLevelUsed, + out MarshallingInfo infoMaybe)) + { + return infoMaybe; + } + + // No marshalling info was computed, but a character encoding was provided. + // If the type is a character or string then pass on these details. + if (_defaultInfo.CharEncoding != CharEncoding.Undefined + && (type.SpecialType == SpecialType.System_Char + || type.SpecialType == SpecialType.System_String)) + { + return new MarshallingInfoStringSupport(_defaultInfo.CharEncoding); + } + + return NoMarshallingInfo.Instance; + } + + private CountInfo CreateCountInfo(AttributeData marshalUsingData, ImmutableHashSet inspectedElements) + { + int? constSize = null; + string? elementName = null; + foreach (KeyValuePair arg in marshalUsingData.NamedArguments) + { + if (arg.Key == ManualTypeMarshallingHelper.MarshalUsingProperties.ConstantElementCount) + { + constSize = (int)arg.Value.Value!; + } + else if (arg.Key == ManualTypeMarshallingHelper.MarshalUsingProperties.CountElementName) + { + if (arg.Value.Value is null) + { + _diagnostics.ReportConfigurationNotSupported(marshalUsingData, ManualTypeMarshallingHelper.MarshalUsingProperties.CountElementName, "null"); + return NoCountInfo.Instance; + } + elementName = (string)arg.Value.Value!; + } + } + + if (constSize is not null && elementName is not null) + { + _diagnostics.ReportInvalidMarshallingAttributeInfo(marshalUsingData, nameof(Resources.ConstantAndElementCountInfoDisallowed)); + } + else if (constSize is not null) + { + return new ConstSizeCountInfo(constSize.Value); + } + else if (elementName is not null) + { + if (inspectedElements.Contains(elementName)) + { + throw new CyclicalCountElementInfoException(inspectedElements, elementName); + } + + try + { + TypePositionInfo? elementInfo = CreateForElementName(elementName, inspectedElements.Add(elementName)); + if (elementInfo is null) + { + _diagnostics.ReportConfigurationNotSupported(marshalUsingData, ManualTypeMarshallingHelper.MarshalUsingProperties.CountElementName, elementName); + return NoCountInfo.Instance; + } + return new CountElementCountInfo(elementInfo); + } + // Specifically catch the exception when we're trying to inspect the element that started the cycle. + // This ensures that we've unwound the whole cycle so when we return NoCountInfo.Instance, there will be no cycles in the count info. + catch (CyclicalCountElementInfoException ex) when (ex.StartOfCycle == elementName) + { + _diagnostics.ReportInvalidMarshallingAttributeInfo(marshalUsingData, nameof(Resources.CyclicalCountInfo), elementName); + return NoCountInfo.Instance; + } + } + + return NoCountInfo.Instance; + } + + private TypePositionInfo? CreateForParamIndex(AttributeData attrData, int paramIndex, ImmutableHashSet inspectedElements) + { + if (!(_contextSymbol is IMethodSymbol method && 0 <= paramIndex && paramIndex < method.Parameters.Length)) + { + return null; + } + IParameterSymbol param = method.Parameters[paramIndex]; + + if (inspectedElements.Contains(param.Name)) + { + throw new CyclicalCountElementInfoException(inspectedElements, param.Name); + } + + try + { + return TypePositionInfo.CreateForParameter( + param, + ParseMarshallingInfo(param.Type, param.GetAttributes(), inspectedElements.Add(param.Name)), _compilation) with + { ManagedIndex = paramIndex }; + } + // Specifically catch the exception when we're trying to inspect the element that started the cycle. + // This ensures that we've unwound the whole cycle so when we return, there will be no cycles in the count info. + catch (CyclicalCountElementInfoException ex) when (ex.StartOfCycle == param.Name) + { + _diagnostics.ReportInvalidMarshallingAttributeInfo(attrData, nameof(Resources.CyclicalCountInfo), param.Name); + return SizeAndParamIndexInfo.UnspecifiedParam; + } + } + + private TypePositionInfo? CreateForElementName(string elementName, ImmutableHashSet inspectedElements) + { + if (_contextSymbol is IMethodSymbol method) + { + if (elementName == CountElementCountInfo.ReturnValueElementName) + { + return new TypePositionInfo( + ManagedTypeInfo.CreateTypeInfoForTypeSymbol(method.ReturnType), + ParseMarshallingInfo(method.ReturnType, method.GetReturnTypeAttributes(), inspectedElements)) with + { + ManagedIndex = TypePositionInfo.ReturnIndex + }; + } + + for (int i = 0; i < method.Parameters.Length; i++) + { + IParameterSymbol param = method.Parameters[i]; + if (param.Name == elementName) + { + return TypePositionInfo.CreateForParameter(param, ParseMarshallingInfo(param.Type, param.GetAttributes(), inspectedElements), _compilation) with { ManagedIndex = i }; + } + } + } + else if (_contextSymbol is INamedTypeSymbol _) + { + // TODO: Handle when we create a struct marshalling generator + // Do we want to support CountElementName pointing to only fields, or properties as well? + // If only fields, how do we handle properties with generated backing fields? + } + + return null; + } + + private MarshallingInfo CreateInfoFromMarshalAs( + ITypeSymbol type, + AttributeData attrData, + ImmutableHashSet inspectedElements, + ref int maxIndirectionLevelUsed) + { + object unmanagedTypeObj = attrData.ConstructorArguments[0].Value!; + UnmanagedType unmanagedType = unmanagedTypeObj is short unmanagedTypeAsShort + ? (UnmanagedType)unmanagedTypeAsShort + : (UnmanagedType)unmanagedTypeObj; + if (!Enum.IsDefined(typeof(UnmanagedType), unmanagedType) + || unmanagedType == UnmanagedType.CustomMarshaler + || unmanagedType == UnmanagedType.SafeArray) + { + _diagnostics.ReportConfigurationNotSupported(attrData, nameof(UnmanagedType), unmanagedType.ToString()); + } + bool isArrayType = unmanagedType == UnmanagedType.LPArray || unmanagedType == UnmanagedType.ByValArray; + UnmanagedType elementUnmanagedType = (UnmanagedType)SizeAndParamIndexInfo.UnspecifiedConstSize; + SizeAndParamIndexInfo arraySizeInfo = SizeAndParamIndexInfo.Unspecified; + + // All other data on attribute is defined as NamedArguments. + foreach (KeyValuePair namedArg in attrData.NamedArguments) + { + switch (namedArg.Key) + { + default: + Debug.Fail($"An unknown member was found on {nameof(MarshalAsAttribute)}"); + continue; + case nameof(MarshalAsAttribute.SafeArraySubType): + case nameof(MarshalAsAttribute.SafeArrayUserDefinedSubType): + case nameof(MarshalAsAttribute.IidParameterIndex): + case nameof(MarshalAsAttribute.MarshalTypeRef): + case nameof(MarshalAsAttribute.MarshalType): + case nameof(MarshalAsAttribute.MarshalCookie): + _diagnostics.ReportConfigurationNotSupported(attrData, $"{attrData.AttributeClass!.Name}{Type.Delimiter}{namedArg.Key}"); + break; + case nameof(MarshalAsAttribute.ArraySubType): + if (!isArrayType) + { + _diagnostics.ReportConfigurationNotSupported(attrData, $"{attrData.AttributeClass!.Name}{Type.Delimiter}{namedArg.Key}"); + } + elementUnmanagedType = (UnmanagedType)namedArg.Value.Value!; + break; + case nameof(MarshalAsAttribute.SizeConst): + if (!isArrayType) + { + _diagnostics.ReportConfigurationNotSupported(attrData, $"{attrData.AttributeClass!.Name}{Type.Delimiter}{namedArg.Key}"); + } + arraySizeInfo = arraySizeInfo with { ConstSize = (int)namedArg.Value.Value! }; + break; + case nameof(MarshalAsAttribute.SizeParamIndex): + if (!isArrayType) + { + _diagnostics.ReportConfigurationNotSupported(attrData, $"{attrData.AttributeClass!.Name}{Type.Delimiter}{namedArg.Key}"); + } + TypePositionInfo? paramIndexInfo = CreateForParamIndex(attrData, (short)namedArg.Value.Value!, inspectedElements); + + if (paramIndexInfo is null) + { + _diagnostics.ReportConfigurationNotSupported(attrData, nameof(MarshalAsAttribute.SizeParamIndex), namedArg.Value.Value.ToString()); + } + arraySizeInfo = arraySizeInfo with { ParamAtIndex = paramIndexInfo }; + break; + } + } + + if (!isArrayType) + { + return new MarshalAsInfo(unmanagedType, _defaultInfo.CharEncoding); + } + + if (type is not IArrayTypeSymbol { ElementType: ITypeSymbol elementType }) + { + _diagnostics.ReportConfigurationNotSupported(attrData, nameof(UnmanagedType), unmanagedType.ToString()); + return NoMarshallingInfo.Instance; + } + + MarshallingInfo elementMarshallingInfo = NoMarshallingInfo.Instance; + if (elementUnmanagedType != (UnmanagedType)SizeAndParamIndexInfo.UnspecifiedConstSize) + { + elementMarshallingInfo = new MarshalAsInfo(elementUnmanagedType, _defaultInfo.CharEncoding); + } + else + { + maxIndirectionLevelUsed = 1; + elementMarshallingInfo = GetMarshallingInfo(elementType, new Dictionary(), 1, ImmutableHashSet.Empty, ref maxIndirectionLevelUsed); + } + + INamedTypeSymbol? arrayMarshaller; + + if (elementType is IPointerTypeSymbol { PointedAtType: ITypeSymbol pointedAt }) + { + arrayMarshaller = _compilation.GetTypeByMetadataName(TypeNames.System_Runtime_InteropServices_GeneratedMarshalling_PtrArrayMarshaller_Metadata)?.Construct(pointedAt); + } + else + { + arrayMarshaller = _compilation.GetTypeByMetadataName(TypeNames.System_Runtime_InteropServices_GeneratedMarshalling_ArrayMarshaller_Metadata)?.Construct(elementType); + } + + if (arrayMarshaller is null) + { + // If the array marshaler type is not available, then we cannot marshal arrays. + return NoMarshallingInfo.Instance; + } + + ITypeSymbol? valuePropertyType = ManualTypeMarshallingHelper.FindValueProperty(arrayMarshaller)?.Type; + + return new NativeContiguousCollectionMarshallingInfo( + NativeMarshallingType: ManagedTypeInfo.CreateTypeInfoForTypeSymbol(arrayMarshaller), + ValuePropertyType: valuePropertyType is not null ? ManagedTypeInfo.CreateTypeInfoForTypeSymbol(valuePropertyType) : null, + MarshallingFeatures: ~CustomMarshallingFeatures.ManagedTypePinning, + UseDefaultMarshalling: true, + ElementCountInfo: arraySizeInfo, + ElementType: ManagedTypeInfo.CreateTypeInfoForTypeSymbol(elementType), + ElementMarshallingInfo: elementMarshallingInfo); + } + + private MarshallingInfo CreateNativeMarshallingInfo( + ITypeSymbol type, + AttributeData attrData, + bool isMarshalUsingAttribute, + int indirectionLevel, + CountInfo parsedCountInfo, + Dictionary useSiteAttributes, + ImmutableHashSet inspectedElements, + ref int maxIndirectionLevelUsed) + { + CustomMarshallingFeatures features = CustomMarshallingFeatures.None; + + if (!isMarshalUsingAttribute && ManualTypeMarshallingHelper.FindGetPinnableReference(type) is not null) + { + features |= CustomMarshallingFeatures.ManagedTypePinning; + } + + ITypeSymbol spanOfByte = _compilation.GetTypeByMetadataName(TypeNames.System_Span_Metadata)!.Construct(_compilation.GetSpecialType(SpecialType.System_Byte)); + + INamedTypeSymbol nativeType = (INamedTypeSymbol)attrData.ConstructorArguments[0].Value!; + + if (nativeType.IsUnboundGenericType) + { + if (isMarshalUsingAttribute) + { + _diagnostics.ReportInvalidMarshallingAttributeInfo(attrData, nameof(Resources.NativeGenericTypeMustBeClosedOrMatchArityMessage), nativeType.ToDisplayString()); + return NoMarshallingInfo.Instance; + } + else if (type is INamedTypeSymbol namedType) + { + if (namedType.Arity != nativeType.Arity) + { + _diagnostics.ReportInvalidMarshallingAttributeInfo(attrData, nameof(Resources.NativeGenericTypeMustBeClosedOrMatchArityMessage), nativeType.ToDisplayString()); + return NoMarshallingInfo.Instance; + } + else + { + nativeType = nativeType.ConstructedFrom.Construct(namedType.TypeArguments.ToArray()); + } + } + else + { + _diagnostics.ReportInvalidMarshallingAttributeInfo(attrData, nameof(Resources.NativeGenericTypeMustBeClosedOrMatchArityMessage), nativeType.ToDisplayString()); + return NoMarshallingInfo.Instance; + } + } + + ITypeSymbol contiguousCollectionMarshalerAttribute = _compilation.GetTypeByMetadataName(TypeNames.GenericContiguousCollectionMarshallerAttribute)!; + + bool isContiguousCollectionMarshaller = nativeType.GetAttributes().Any(attr => SymbolEqualityComparer.Default.Equals(attr.AttributeClass, contiguousCollectionMarshalerAttribute)); + IPropertySymbol? valueProperty = ManualTypeMarshallingHelper.FindValueProperty(nativeType); + + ManualTypeMarshallingHelper.NativeTypeMarshallingVariant marshallingVariant = isContiguousCollectionMarshaller + ? ManualTypeMarshallingHelper.NativeTypeMarshallingVariant.ContiguousCollection + : ManualTypeMarshallingHelper.NativeTypeMarshallingVariant.Standard; + + bool hasInt32Constructor = false; + foreach (IMethodSymbol ctor in nativeType.Constructors) + { + if (ManualTypeMarshallingHelper.IsManagedToNativeConstructor(ctor, type, marshallingVariant) && (valueProperty is null or { GetMethod: not null })) + { + features |= CustomMarshallingFeatures.ManagedToNative; + } + else if (ManualTypeMarshallingHelper.IsStackallocConstructor(ctor, type, spanOfByte, marshallingVariant) + && (valueProperty is null or { GetMethod: not null })) + { + features |= CustomMarshallingFeatures.ManagedToNativeStackalloc; + } + else if (ctor.Parameters.Length == 1 && ctor.Parameters[0].Type.SpecialType == SpecialType.System_Int32) + { + hasInt32Constructor = true; + } + } + + // The constructor that takes only the native element size is required for collection marshallers + // in the native-to-managed scenario. + if ((!isContiguousCollectionMarshaller + || (hasInt32Constructor && ManualTypeMarshallingHelper.HasSetUnmarshalledCollectionLengthMethod(nativeType))) + && ManualTypeMarshallingHelper.HasToManagedMethod(nativeType, type) + && (valueProperty is null or { SetMethod: not null })) + { + features |= CustomMarshallingFeatures.NativeToManaged; + } + + if (features == CustomMarshallingFeatures.None) + { + _diagnostics.ReportInvalidMarshallingAttributeInfo( + attrData, + isContiguousCollectionMarshaller + ? nameof(Resources.CollectionNativeTypeMustHaveRequiredShapeMessage) + : nameof(Resources.NativeTypeMustHaveRequiredShapeMessage), + nativeType.ToDisplayString()); + return NoMarshallingInfo.Instance; + } + + if (ManualTypeMarshallingHelper.HasFreeNativeMethod(nativeType)) + { + features |= CustomMarshallingFeatures.FreeNativeResources; + } + + if (ManualTypeMarshallingHelper.FindGetPinnableReference(nativeType) is not null) + { + features |= CustomMarshallingFeatures.NativeTypePinning; + } + + if (isContiguousCollectionMarshaller) + { + if (!ManualTypeMarshallingHelper.HasNativeValueStorageProperty(nativeType, spanOfByte)) + { + _diagnostics.ReportInvalidMarshallingAttributeInfo(attrData, nameof(Resources.CollectionNativeTypeMustHaveRequiredShapeMessage), nativeType.ToDisplayString()); + return NoMarshallingInfo.Instance; + } + + if (!ManualTypeMarshallingHelper.TryGetElementTypeFromContiguousCollectionMarshaller(nativeType, out ITypeSymbol elementType)) + { + _diagnostics.ReportInvalidMarshallingAttributeInfo(attrData, nameof(Resources.CollectionNativeTypeMustHaveRequiredShapeMessage), nativeType.ToDisplayString()); + return NoMarshallingInfo.Instance; + } + + return new NativeContiguousCollectionMarshallingInfo( + ManagedTypeInfo.CreateTypeInfoForTypeSymbol(nativeType), + valueProperty is not null ? ManagedTypeInfo.CreateTypeInfoForTypeSymbol(valueProperty.Type) : null, + features, + UseDefaultMarshalling: !isMarshalUsingAttribute, + parsedCountInfo, + ManagedTypeInfo.CreateTypeInfoForTypeSymbol(elementType), + GetMarshallingInfo(elementType, useSiteAttributes, indirectionLevel + 1, inspectedElements, ref maxIndirectionLevelUsed)); + } + + return new NativeMarshallingAttributeInfo( + ManagedTypeInfo.CreateTypeInfoForTypeSymbol(nativeType), + valueProperty is not null ? ManagedTypeInfo.CreateTypeInfoForTypeSymbol(valueProperty.Type) : null, + features, + UseDefaultMarshalling: !isMarshalUsingAttribute); + } + + private bool TryCreateTypeBasedMarshallingInfo( + ITypeSymbol type, + CountInfo parsedCountInfo, + int indirectionLevel, + Dictionary useSiteAttributes, + ImmutableHashSet inspectedElements, + ref int maxIndirectionLevelUsed, + out MarshallingInfo marshallingInfo) + { + // Check for an implicit SafeHandle conversion. + CodeAnalysis.Operations.CommonConversion conversion = _compilation.ClassifyCommonConversion(type, _compilation.GetTypeByMetadataName(TypeNames.System_Runtime_InteropServices_SafeHandle)!); + if (conversion.Exists + && conversion.IsImplicit + && (conversion.IsReference || conversion.IsIdentity)) + { + bool hasAccessibleDefaultConstructor = false; + if (type is INamedTypeSymbol named && !named.IsAbstract && named.InstanceConstructors.Length > 0) + { + foreach (IMethodSymbol ctor in named.InstanceConstructors) + { + if (ctor.Parameters.Length == 0) + { + hasAccessibleDefaultConstructor = _compilation.IsSymbolAccessibleWithin(ctor, _contextSymbol.ContainingType); + break; + } + } + } + marshallingInfo = new SafeHandleMarshallingInfo(hasAccessibleDefaultConstructor, type.IsAbstract); + return true; + } + + if (type is IArrayTypeSymbol { ElementType: ITypeSymbol elementType }) + { + INamedTypeSymbol? arrayMarshaller; + + if (elementType is IPointerTypeSymbol { PointedAtType: ITypeSymbol pointedAt }) + { + arrayMarshaller = _compilation.GetTypeByMetadataName(TypeNames.System_Runtime_InteropServices_GeneratedMarshalling_PtrArrayMarshaller_Metadata)?.Construct(pointedAt); + } + else + { + arrayMarshaller = _compilation.GetTypeByMetadataName(TypeNames.System_Runtime_InteropServices_GeneratedMarshalling_ArrayMarshaller_Metadata)?.Construct(elementType); + } + + if (arrayMarshaller is null) + { + // If the array marshaler type is not available, then we cannot marshal arrays. + marshallingInfo = NoMarshallingInfo.Instance; + return false; + } + + ITypeSymbol? valuePropertyType = ManualTypeMarshallingHelper.FindValueProperty(arrayMarshaller)?.Type; + + marshallingInfo = new NativeContiguousCollectionMarshallingInfo( + NativeMarshallingType: ManagedTypeInfo.CreateTypeInfoForTypeSymbol(arrayMarshaller), + ValuePropertyType: valuePropertyType is not null ? ManagedTypeInfo.CreateTypeInfoForTypeSymbol(valuePropertyType) : null, + MarshallingFeatures: ~CustomMarshallingFeatures.ManagedTypePinning, + UseDefaultMarshalling: true, + ElementCountInfo: parsedCountInfo, + ElementType: ManagedTypeInfo.CreateTypeInfoForTypeSymbol(elementType), + ElementMarshallingInfo: GetMarshallingInfo(elementType, useSiteAttributes, indirectionLevel + 1, inspectedElements, ref maxIndirectionLevelUsed)); + return true; + } + + if (type is INamedTypeSymbol { IsValueType: true } valueType + && !valueType.IsExposedOutsideOfCurrentCompilation() + && valueType.IsConsideredBlittable()) + { + // Allow implicit [BlittableType] on internal value types. + marshallingInfo = new BlittableTypeAttributeInfo(); + return true; + } + + marshallingInfo = NoMarshallingInfo.Instance; + return false; + } + + private bool TryGetAttributeIndirectionLevel(AttributeData attrData, out int indirectionLevel) + { + if (SymbolEqualityComparer.Default.Equals(attrData.AttributeClass, _marshalAsAttribute)) + { + indirectionLevel = 0; + return true; + } + + if (!SymbolEqualityComparer.Default.Equals(attrData.AttributeClass, _marshalUsingAttribute)) + { + indirectionLevel = 0; + return false; + } + + foreach (KeyValuePair arg in attrData.NamedArguments) + { + if (arg.Key == ManualTypeMarshallingHelper.MarshalUsingProperties.ElementIndirectionLevel) + { + indirectionLevel = (int)arg.Value.Value!; + return true; + } + } + indirectionLevel = 0; + return true; + } + + private class CyclicalCountElementInfoException : Exception + { + public CyclicalCountElementInfoException(ImmutableHashSet elementsInCycle, string startOfCycle) + { + ElementsInCycle = elementsInCycle; + StartOfCycle = startOfCycle; + } + + public ImmutableHashSet ElementsInCycle { get; } + + public string StartOfCycle { get; } + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj new file mode 100644 index 0000000000000..e8f403d2f8329 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj @@ -0,0 +1,31 @@ + + + + netstandard2.0 + false + enable + Microsoft.Interop + true + + + + + + + + + + Resources.resx + True + True + + + + + + Designer + Resources.Designer.cs + ResXFileCodeGenerator + + + diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Properties/AssemblyInfo.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000000..dcac8d25f61d5 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Properties/AssemblyInfo.cs @@ -0,0 +1,4 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +[assembly: System.Resources.NeutralResourcesLanguage("en-US")] diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources.Designer.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources.Designer.cs new file mode 100644 index 0000000000000..1d254e29a5c23 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources.Designer.cs @@ -0,0 +1,369 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Microsoft.Interop { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.Interop.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Marshalling an array from unmanaged to managed requires either the 'SizeParamIndex' or 'SizeConst' fields to be set on a 'MarshalAsAttribute' or the 'ConstantElementCount' or 'CountElementName' properties to be set on a 'MarshalUsingAttribute'.. + /// + internal static string ArraySizeMustBeSpecified { + get { + return ResourceManager.GetString("ArraySizeMustBeSpecified", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The 'SizeParamIndex' value in the 'MarshalAsAttribute' is out of range.. + /// + internal static string ArraySizeParamIndexOutOfRange { + get { + return ResourceManager.GetString("ArraySizeParamIndexOutOfRange", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The 'BlittableTypeAttribute' and 'NativeMarshallingAttribute' attributes are mutually exclusive.. + /// + internal static string CannotHaveMultipleMarshallingAttributesDescription { + get { + return ResourceManager.GetString("CannotHaveMultipleMarshallingAttributesDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Type '{0}' is marked with 'BlittableTypeAttribute' and 'NativeMarshallingAttribute'. A type can only have one of these two attributes.. + /// + internal static string CannotHaveMultipleMarshallingAttributesMessage { + get { + return ResourceManager.GetString("CannotHaveMultipleMarshallingAttributesMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to A native type with the 'GenericContiguousCollectionMarshallerAttribute' must have at least one of the two marshalling methods as well as a 'ManagedValues' property of type 'Span<T>' for some 'T' and a 'NativeValueStorage' property of type 'Span<byte>' to enable marshalling the managed type.. + /// + internal static string CollectionNativeTypeMustHaveRequiredShapeDescription { + get { + return ResourceManager.GetString("CollectionNativeTypeMustHaveRequiredShapeDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The native type '{0}' must be a value type and have a constructor that takes two parameters, one of type '{1}' and an 'int', or have a parameterless instance method named 'ToManaged' that returns '{1}' as well as a 'ManagedValues' property of type 'Span<T>' for some 'T' and a 'NativeValueStorage' property of type 'Span<byte>'. + /// + internal static string CollectionNativeTypeMustHaveRequiredShapeMessage { + get { + return ResourceManager.GetString("CollectionNativeTypeMustHaveRequiredShapeMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The specified collection size parameter for an collection must be an integer type. If the size information is applied to a nested collection, the size parameter must be a collection of one less level of nesting with an integral element.. + /// + internal static string CollectionSizeParamTypeMustBeIntegral { + get { + return ResourceManager.GetString("CollectionSizeParamTypeMustBeIntegral", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Only one of 'ConstantElementCount' or 'ElementCountInfo' may be used in a 'MarshalUsingAttribute' for a given 'ElementIndirectionLevel'. + /// + internal static string ConstantAndElementCountInfoDisallowed { + get { + return ResourceManager.GetString("ConstantAndElementCountInfoDisallowed", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The specified parameter needs to be marshalled from managed to native, but the native type '{0}' does not support it.. + /// + internal static string CustomTypeMarshallingManagedToNativeUnsupported { + get { + return ResourceManager.GetString("CustomTypeMarshallingManagedToNativeUnsupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The specified parameter needs to be marshalled from native to managed, but the native type '{0}' does not support it.. + /// + internal static string CustomTypeMarshallingNativeToManagedUnsupported { + get { + return ResourceManager.GetString("CustomTypeMarshallingNativeToManagedUnsupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to This element cannot depend on '{0}' for collection size information without creating a dependency cycle. + /// + internal static string CyclicalCountInfo { + get { + return ResourceManager.GetString("CyclicalCountInfo", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Count information for a given element at a given indirection level can only be specified once. + /// + internal static string DuplicateCountInfo { + get { + return ResourceManager.GetString("DuplicateCountInfo", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Multiple marshalling attributes per element per indirection level is unsupported, but duplicate information was provided for indirection level {0}. + /// + internal static string DuplicateMarshallingInfo { + get { + return ResourceManager.GetString("DuplicateMarshallingInfo", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Marshalling info was specified for 'ElementIndirectionLevel' {0}, but marshalling info was only needed for {1} level(s) of indirection. + /// + internal static string ExtraneousMarshallingInfo { + get { + return ResourceManager.GetString("ExtraneousMarshallingInfo", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The provided graph has cycles and cannot be topologically sorted.. + /// + internal static string GraphHasCycles { + get { + return ResourceManager.GetString("GraphHasCycles", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The '[In]' attribute is not supported unless the '[Out]' attribute is also used. The behavior of the '[In]' attribute without the '[Out]' attribute is the same as the default behavior.. + /// + internal static string InAttributeNotSupportedWithoutOut { + get { + return ResourceManager.GetString("InAttributeNotSupportedWithoutOut", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The '[In]' and '[Out]' attributes are unsupported on parameters passed by reference. Use the 'in', 'ref', or 'out' keywords instead.. + /// + internal static string InOutAttributeByRefNotSupported { + get { + return ResourceManager.GetString("InOutAttributeByRefNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The provided '[In]' and '[Out]' attributes on this parameter are unsupported on this parameter.. + /// + internal static string InOutAttributeMarshalerNotSupported { + get { + return ResourceManager.GetString("InOutAttributeMarshalerNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Marshalling char with 'CharSet.{0}' is not supported. Instead, manually convert the char type to the desired byte representation and pass to the source-generated P/Invoke.. + /// + internal static string MarshallingCharAsSpecifiedCharSetNotSupported { + get { + return ResourceManager.GetString("MarshallingCharAsSpecifiedCharSetNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Marshalling string or char without explicit marshalling information is not supported. Specify either 'GeneratedDllImportAttribute.CharSet' or 'MarshalAsAttribute'.. + /// + internal static string MarshallingStringOrCharAsUndefinedNotSupported { + get { + return ResourceManager.GetString("MarshallingStringOrCharAsUndefinedNotSupported", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The native type '{0}' for managed type '{1}' must be a closed generic type or have the same arity as the managed type.. + /// + internal static string NativeGenericTypeMustBeClosedOrMatchArityMessage { + get { + return ResourceManager.GetString("NativeGenericTypeMustBeClosedOrMatchArityMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The native type must have at least one of the two marshalling methods to enable marshalling the managed type.. + /// + internal static string NativeTypeMustHaveRequiredShapeDescription { + get { + return ResourceManager.GetString("NativeTypeMustHaveRequiredShapeDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The native type '{0}' must be a value type and have a constructor that takes one parameter of type '{1}' or a parameterless instance method named 'ToManaged' that returns '{1}'. + /// + internal static string NativeTypeMustHaveRequiredShapeMessage { + get { + return ResourceManager.GetString("NativeTypeMustHaveRequiredShapeMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The '[Out]' attribute is only supported on array parameters.. + /// + internal static string OutByValueNotSupportedDescription { + get { + return ResourceManager.GetString("OutByValueNotSupportedDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The '[Out]' attribute is not supported on the '{0}' parameter.. + /// + internal static string OutByValueNotSupportedMessage { + get { + return ResourceManager.GetString("OutByValueNotSupportedMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The 'Value' property must not be a 'ref' or 'readonly ref' property.. + /// + internal static string RefValuePropertyUnsupportedDescription { + get { + return ResourceManager.GetString("RefValuePropertyUnsupportedDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The 'Value' property on the native type '{0}' must not be a 'ref' or 'readonly ref' property.. + /// + internal static string RefValuePropertyUnsupportedMessage { + get { + return ResourceManager.GetString("RefValuePropertyUnsupportedMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to An abstract type derived from 'SafeHandle' cannot be marshalled by reference. The provided type must be concrete.. + /// + internal static string SafeHandleByRefMustBeConcrete { + get { + return ResourceManager.GetString("SafeHandleByRefMustBeConcrete", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Specified type is not supported by source-generated P/Invokes. + /// + internal static string TypeNotSupportedTitle { + get { + return ResourceManager.GetString("TypeNotSupportedTitle", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Marshalling a value between managed and native with a native type with a 'Value' property requires extra state, which is not supported in this context.. + /// + internal static string ValuePropertyMarshallingRequiresAdditionalState { + get { + return ResourceManager.GetString("ValuePropertyMarshallingRequiresAdditionalState", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The native type's 'Value' property must have a getter to support marshalling from managed to native.. + /// + internal static string ValuePropertyMustHaveGetterDescription { + get { + return ResourceManager.GetString("ValuePropertyMustHaveGetterDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The 'Value' property on the native type '{0}' must have a getter. + /// + internal static string ValuePropertyMustHaveGetterMessage { + get { + return ResourceManager.GetString("ValuePropertyMustHaveGetterMessage", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The native type's 'Value' property must have a setter to support marshalling from native to managed.. + /// + internal static string ValuePropertyMustHaveSetterDescription { + get { + return ResourceManager.GetString("ValuePropertyMustHaveSetterDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The 'Value' property on the native type '{0}' must have a setter. + /// + internal static string ValuePropertyMustHaveSetterMessage { + get { + return ResourceManager.GetString("ValuePropertyMustHaveSetterMessage", resourceCulture); + } + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources.resx b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources.resx new file mode 100644 index 0000000000000..544a1ea46a212 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources.resx @@ -0,0 +1,222 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Marshalling an array from unmanaged to managed requires either the 'SizeParamIndex' or 'SizeConst' fields to be set on a 'MarshalAsAttribute' or the 'ConstantElementCount' or 'CountElementName' properties to be set on a 'MarshalUsingAttribute'. + + + The 'SizeParamIndex' value in the 'MarshalAsAttribute' is out of range. + + + The 'BlittableTypeAttribute' and 'NativeMarshallingAttribute' attributes are mutually exclusive. + + + Type '{0}' is marked with 'BlittableTypeAttribute' and 'NativeMarshallingAttribute'. A type can only have one of these two attributes. + + + The specified collection size parameter for an collection must be an integer type. If the size information is applied to a nested collection, the size parameter must be a collection of one less level of nesting with an integral element. + + + The specified parameter needs to be marshalled from managed to native, but the native type '{0}' does not support it. + + + The specified parameter needs to be marshalled from native to managed, but the native type '{0}' does not support it. + + + The provided graph has cycles and cannot be topologically sorted. + + + The '[In]' attribute is not supported unless the '[Out]' attribute is also used. The behavior of the '[In]' attribute without the '[Out]' attribute is the same as the default behavior. + + + The '[In]' and '[Out]' attributes are unsupported on parameters passed by reference. Use the 'in', 'ref', or 'out' keywords instead. + + + The provided '[In]' and '[Out]' attributes on this parameter are unsupported on this parameter. + + + Marshalling char with 'CharSet.{0}' is not supported. Instead, manually convert the char type to the desired byte representation and pass to the source-generated P/Invoke. + + + Marshalling string or char without explicit marshalling information is not supported. Specify either 'GeneratedDllImportAttribute.CharSet' or 'MarshalAsAttribute'. + + + The '[Out]' attribute is only supported on array parameters. + + + The '[Out]' attribute is not supported on the '{0}' parameter. + + + The 'Value' property must not be a 'ref' or 'readonly ref' property. + + + The 'Value' property on the native type '{0}' must not be a 'ref' or 'readonly ref' property. + + + An abstract type derived from 'SafeHandle' cannot be marshalled by reference. The provided type must be concrete. + + + Specified type is not supported by source-generated P/Invokes + + + Marshalling a value between managed and native with a native type with a 'Value' property requires extra state, which is not supported in this context. + + + The native type's 'Value' property must have a getter to support marshalling from managed to native. + + + The 'Value' property on the native type '{0}' must have a getter + + + The native type's 'Value' property must have a setter to support marshalling from native to managed. + + + The 'Value' property on the native type '{0}' must have a setter + + + This element cannot depend on '{0}' for collection size information without creating a dependency cycle + + + Count information for a given element at a given indirection level can only be specified once + + + Multiple marshalling attributes per element per indirection level is unsupported, but duplicate information was provided for indirection level {0} + + + Marshalling info was specified for 'ElementIndirectionLevel' {0}, but marshalling info was only needed for {1} level(s) of indirection + + + The native type '{0}' for managed type '{1}' must be a closed generic type or have the same arity as the managed type. + + + The native type must have at least one of the two marshalling methods to enable marshalling the managed type. + + + The native type '{0}' must be a value type and have a constructor that takes one parameter of type '{1}' or a parameterless instance method named 'ToManaged' that returns '{1}' + + + A native type with the 'GenericContiguousCollectionMarshallerAttribute' must have at least one of the two marshalling methods as well as a 'ManagedValues' property of type 'Span<T>' for some 'T' and a 'NativeValueStorage' property of type 'Span<byte>' to enable marshalling the managed type. + + + The native type '{0}' must be a value type and have a constructor that takes two parameters, one of type '{1}' and an 'int', or have a parameterless instance method named 'ToManaged' that returns '{1}' as well as a 'ManagedValues' property of type 'Span<T>' for some 'T' and a 'NativeValueStorage' property of type 'Span<byte>' + + + Only one of 'ConstantElementCount' or 'ElementCountInfo' may be used in a 'MarshalUsingAttribute' for a given 'ElementIndirectionLevel' + + \ No newline at end of file diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/StubCodeContext.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/StubCodeContext.cs new file mode 100644 index 0000000000000..4f3229265eebe --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/StubCodeContext.cs @@ -0,0 +1,111 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; + +namespace Microsoft.Interop +{ + public abstract class StubCodeContext + { + /// + /// Code generation stage + /// + public enum Stage + { + /// + /// Invalid stage + /// + Invalid, + + /// + /// Perform any setup required + /// + Setup, + + /// + /// Convert managed data to native data + /// + Marshal, + + /// + /// Pin data in preparation for calling the generated P/Invoke + /// + Pin, + + /// + /// Call the generated P/Invoke + /// + /// + /// should provide the + /// argument to pass to the P/Invoke + /// + Invoke, + + /// + /// Convert native data to managed data + /// + Unmarshal, + + /// + /// Perform any cleanup required + /// + Cleanup, + + /// + /// Keep alive any managed objects that need to stay alive across the call. + /// + KeepAlive, + + /// + /// Convert native data to managed data even in the case of an exception during + /// the non-cleanup phases. + /// + GuaranteedUnmarshal + } + + public Stage CurrentStage { get; set; } = Stage.Invalid; + + /// + /// The stub emits code that runs in a single stack frame and the frame spans over the native context. + /// + /// + /// Stubs that emit code into a single frame that spans the native context can do two things: + /// + /// A fixed statement can be used on an individual value in the stage and the pointer can be passed to native code. + /// Memory can be allocated via the stackalloc keyword and will live through the full native context of the call. + /// + /// + public abstract bool SingleFrameSpansNativeContext { get; } + + /// + /// Additional variables other than the {managedIdentifier} and {nativeIdentifier} variables can be added to the stub to track additional state for the marshaller in the stub in the Setup phase, and they will live across all phases of the stub. + /// + /// + /// When this property is false, any additional variables can only be considered to have the state they had immediately after the Setup phase. + /// + public abstract bool AdditionalTemporaryStateLivesAcrossStages { get; } + + /// + /// If this context is a nested context, return the parent context. Otherwise, return null. + /// + public StubCodeContext? ParentContext { get; protected set; } + + public const string GeneratedNativeIdentifierSuffix = "_gen_native"; + + /// + /// Get managed and native instance identifiers for the + /// + /// Object for which to get identifiers + /// Managed and native identifiers + public virtual (string managed, string native) GetIdentifiers(TypePositionInfo info) + { + return (info.InstanceIdentifier, $"__{info.InstanceIdentifier.TrimStart('@')}{GeneratedNativeIdentifierSuffix}"); + } + + public virtual string GetAdditionalIdentifier(TypePositionInfo info, string name) + { + return $"{GetIdentifiers(info).native}__{name}"; + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypeNames.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypeNames.cs new file mode 100644 index 0000000000000..1925d2ece51bb --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypeNames.cs @@ -0,0 +1,79 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Text; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.Interop; + +namespace Microsoft.Interop +{ + public static class TypeNames + { + public const string DllImportAttribute = "System.Runtime.InteropServices.DllImportAttribute"; + public const string GeneratedDllImportAttribute = "System.Runtime.InteropServices.GeneratedDllImportAttribute"; + + public const string GeneratedMarshallingAttribute = "System.Runtime.InteropServices.GeneratedMarshallingAttribute"; + + public const string BlittableTypeAttribute = "System.Runtime.InteropServices.BlittableTypeAttribute"; + + public const string NativeMarshallingAttribute = "System.Runtime.InteropServices.NativeMarshallingAttribute"; + + public const string MarshalUsingAttribute = "System.Runtime.InteropServices.MarshalUsingAttribute"; + + public const string GenericContiguousCollectionMarshallerAttribute = "System.Runtime.InteropServices.GenericContiguousCollectionMarshallerAttribute"; + + public const string LCIDConversionAttribute = "System.Runtime.InteropServices.LCIDConversionAttribute"; + + public const string SuppressGCTransitionAttribute = "System.Runtime.InteropServices.SuppressGCTransitionAttribute"; + + public const string UnmanagedCallConvAttribute = "System.Runtime.InteropServices.UnmanagedCallConvAttribute"; + public const string System_Span_Metadata = "System.Span`1"; + public const string System_Span = "System.Span"; + + public const string System_IntPtr = "System.IntPtr"; + + public const string System_Activator = "System.Activator"; + + public const string System_Type = "System.Type"; + + public const string System_Runtime_InteropServices_StructLayoutAttribute = "System.Runtime.InteropServices.StructLayoutAttribute"; + + public const string System_Runtime_InteropServices_MarshalAsAttribute = "System.Runtime.InteropServices.MarshalAsAttribute"; + + public const string System_Runtime_InteropServices_Marshal = "System.Runtime.InteropServices.Marshal"; + + private const string System_Runtime_InteropServices_MarshalEx = "System.Runtime.InteropServices.MarshalEx"; + + public static string MarshalEx(InteropGenerationOptions options) + { + return options.UseMarshalType ? System_Runtime_InteropServices_Marshal : System_Runtime_InteropServices_MarshalEx; + } + + public const string System_Runtime_InteropServices_UnmanagedType = "System.Runtime.InteropServices.UnmanagedType"; + + public const string System_Runtime_InteropServices_MemoryMarshal = "System.Runtime.InteropServices.MemoryMarshal"; + + public const string System_Runtime_InteropServices_GeneratedMarshalling_ArrayMarshaller_Metadata = "System.Runtime.InteropServices.GeneratedMarshalling.ArrayMarshaller`1"; + + public const string System_Runtime_InteropServices_GeneratedMarshalling_PtrArrayMarshaller_Metadata = "System.Runtime.InteropServices.GeneratedMarshalling.PtrArrayMarshaller`1"; + + public const string System_Runtime_InteropServices_SafeHandle = "System.Runtime.InteropServices.SafeHandle"; + + public const string System_Runtime_InteropServices_OutAttribute = "System.Runtime.InteropServices.OutAttribute"; + + public const string System_Runtime_InteropServices_InAttribute = "System.Runtime.InteropServices.InAttribute"; + + public const string System_Runtime_CompilerServices_SkipLocalsInitAttribute = "System.Runtime.CompilerServices.SkipLocalsInitAttribute"; + + private const string System_Runtime_CompilerServices_Unsafe = "System.Runtime.CompilerServices.Unsafe"; + + private const string Internal_Runtime_CompilerServices_Unsafe = "Internal.Runtime.CompilerServices.Unsafe"; + + public static string Unsafe(InteropGenerationOptions options) + { + return options.UseInternalUnsafeType ? Internal_Runtime_CompilerServices_Unsafe : System_Runtime_CompilerServices_Unsafe; + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypePositionInfo.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypePositionInfo.cs new file mode 100644 index 0000000000000..5c5b6b48948d7 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypePositionInfo.cs @@ -0,0 +1,113 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; + +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory; + +namespace Microsoft.Interop +{ + + /// + /// Describes how to marshal the contents of a value in comparison to the value itself. + /// Only makes sense for array-like types. For example, an "out" array doesn't change the + /// pointer to the array value, but it marshals the contents of the native array back to the + /// contents of the managed array. + /// + [Flags] + public enum ByValueContentsMarshalKind + { + /// + /// Marshal contents from managed to native only. + /// This is the default behavior. + /// + Default = 0x0, + /// + /// Marshal contents from managed to native only. + /// This is the default behavior. + /// + In = 0x1, + /// + /// Marshal contents from native to managed only. + /// + Out = 0x2, + /// + /// Marshal contents both to and from native. + /// + InOut = In | Out + } + + /// + /// Positional type information involved in unmanaged/managed scenarios. + /// + public sealed record TypePositionInfo(ManagedTypeInfo ManagedType, MarshallingInfo MarshallingAttributeInfo) + { + public const int UnsetIndex = int.MinValue; + public const int ReturnIndex = UnsetIndex + 1; + + public string InstanceIdentifier { get; init; } = string.Empty; + + public RefKind RefKind { get; init; } = RefKind.None; + public SyntaxKind RefKindSyntax { get; init; } = SyntaxKind.None; + + public bool IsByRef => RefKind != RefKind.None; + + public ByValueContentsMarshalKind ByValueContentsMarshalKind { get; init; } + + public bool IsManagedReturnPosition { get => ManagedIndex == ReturnIndex; } + public bool IsNativeReturnPosition { get => NativeIndex == ReturnIndex; } + + public int ManagedIndex { get; init; } = UnsetIndex; + public int NativeIndex { get; init; } = UnsetIndex; + + public static TypePositionInfo CreateForParameter(IParameterSymbol paramSymbol, MarshallingInfo marshallingInfo, Compilation compilation) + { + var typeInfo = new TypePositionInfo(ManagedTypeInfo.CreateTypeInfoForTypeSymbol(paramSymbol.Type), marshallingInfo) + { + InstanceIdentifier = ParseToken(paramSymbol.Name).IsReservedKeyword() ? $"@{paramSymbol.Name}" : paramSymbol.Name, + RefKind = paramSymbol.RefKind, + RefKindSyntax = RefKindToSyntax(paramSymbol.RefKind), + ByValueContentsMarshalKind = GetByValueContentsMarshalKind(paramSymbol.GetAttributes(), compilation) + }; + + return typeInfo; + } + + private static ByValueContentsMarshalKind GetByValueContentsMarshalKind(IEnumerable attributes, Compilation compilation) + { + INamedTypeSymbol outAttributeType = compilation.GetTypeByMetadataName(TypeNames.System_Runtime_InteropServices_OutAttribute)!; + INamedTypeSymbol inAttributeType = compilation.GetTypeByMetadataName(TypeNames.System_Runtime_InteropServices_InAttribute)!; + + ByValueContentsMarshalKind marshalKind = ByValueContentsMarshalKind.Default; + + foreach (AttributeData attr in attributes) + { + if (SymbolEqualityComparer.Default.Equals(attr.AttributeClass, outAttributeType)) + { + marshalKind |= ByValueContentsMarshalKind.Out; + } + else if (SymbolEqualityComparer.Default.Equals(attr.AttributeClass, inAttributeType)) + { + marshalKind |= ByValueContentsMarshalKind.In; + } + } + + return marshalKind; + } + + private static SyntaxKind RefKindToSyntax(RefKind refKind) + { + return refKind switch + { + RefKind.In => SyntaxKind.InKeyword, + RefKind.Ref => SyntaxKind.RefKeyword, + RefKind.Out => SyntaxKind.OutKeyword, + RefKind.None => SyntaxKind.None, + _ => throw new NotImplementedException("Support for some RefKind"), + }; + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypeSymbolExtensions.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypeSymbolExtensions.cs new file mode 100644 index 0000000000000..9768e2d03ce69 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/TypeSymbolExtensions.cs @@ -0,0 +1,197 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Immutable; +using System.Runtime.InteropServices; + +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace Microsoft.Interop +{ + public static class TypeSymbolExtensions + { + public static bool HasOnlyBlittableFields(this ITypeSymbol type) => HasOnlyBlittableFields(type, ImmutableHashSet.Create(SymbolEqualityComparer.Default)); + + private static bool HasOnlyBlittableFields(this ITypeSymbol type, ImmutableHashSet seenTypes) + { + if (seenTypes.Contains(type)) + { + // A recursive struct type isn't blittable. + // It's also illegal in C#, but I believe that source generators run + // before that is detected, so we check here to avoid a stack overflow. + return false; + } + + foreach (IFieldSymbol field in type.GetMembers().OfType()) + { + if (!field.IsStatic) + { + bool fieldBlittable = field switch + { + { Type: { IsReferenceType: true } } => false, + { Type: IPointerTypeSymbol ptr } => IsConsideredBlittable(ptr.PointedAtType), + { Type: IFunctionPointerTypeSymbol } => true, + not { Type: { SpecialType: SpecialType.None } } => IsSpecialTypeBlittable(field.Type.SpecialType), + // Assume that type parameters that can be blittable are blittable. + // We'll re-evaluate blittability for generic fields of generic types at instantation time. + { Type: ITypeParameterSymbol } => true, + { Type: { IsValueType: false } } => false, + _ => IsConsideredBlittable(field.Type, seenTypes.Add(type)) + }; + + if (!fieldBlittable) + { + return false; + } + } + } + + return true; + } + + private static bool IsSpecialTypeBlittable(SpecialType specialType) + => specialType switch + { + SpecialType.System_Void + or SpecialType.System_SByte + or SpecialType.System_Byte + or SpecialType.System_Int16 + or SpecialType.System_UInt16 + or SpecialType.System_Int32 + or SpecialType.System_UInt32 + or SpecialType.System_Int64 + or SpecialType.System_UInt64 + or SpecialType.System_Single + or SpecialType.System_Double + or SpecialType.System_IntPtr + or SpecialType.System_UIntPtr => true, + _ => false + }; + + public static bool IsConsideredBlittable(this ITypeSymbol type) => IsConsideredBlittable(type, ImmutableHashSet.Create(SymbolEqualityComparer.Default)); + + private static bool IsConsideredBlittable(this ITypeSymbol type, ImmutableHashSet seenTypes) + { + if (type.SpecialType != SpecialType.None) + { + return IsSpecialTypeBlittable(type.SpecialType); + } + + if (type.TypeKind is TypeKind.FunctionPointer or TypeKind.Pointer) + { + return true; + } + + if (type.IsReferenceType) + { + return false; + } + + if (type is INamedTypeSymbol { TypeKind: TypeKind.Enum, EnumUnderlyingType: ITypeSymbol underlyingType }) + { + return underlyingType.IsConsideredBlittable(seenTypes); + } + + bool hasNativeMarshallingAttribute = false; + bool hasGeneratedMarshallingAttribute = false; + // [TODO]: Match attributes on full name or symbol, not just on type name. + foreach (AttributeData attr in type.GetAttributes()) + { + if (attr.AttributeClass is null) + { + continue; + } + if (attr.AttributeClass.Name == "BlittableTypeAttribute") + { + if (type is INamedTypeSymbol { IsGenericType: true } generic) + { + // If the type is generic, we inspect the fields again + // to determine blittability of this instantiation + // since we are guaranteed that if a type has generic fields, + // they will be present in the contract assembly to ensure + // that recursive structs can be identified at build time. + return generic.HasOnlyBlittableFields(seenTypes); + } + return true; + } + else if (attr.AttributeClass.Name == "GeneratedMarshallingAttribute") + { + hasGeneratedMarshallingAttribute = true; + } + else if (attr.AttributeClass.Name == "NativeMarshallingAttribute") + { + hasNativeMarshallingAttribute = true; + } + } + + if (hasGeneratedMarshallingAttribute && !hasNativeMarshallingAttribute) + { + // The struct type has generated marshalling via a source generator. + // We can't guarantee that we can see the results of the struct source generator, + // so we re-calculate if the type is blittable here. + return type.HasOnlyBlittableFields(seenTypes); + } + + if (type is INamedTypeSymbol namedType + && namedType.DeclaringSyntaxReferences.Length != 0 + && !namedType.IsExposedOutsideOfCurrentCompilation()) + { + // If a type is declared in the current compilation and not exposed outside of it, + // we will allow it to be considered blittable if its fields are considered blittable. + return type.HasOnlyBlittableFields(seenTypes); + } + return false; + } + + public static bool IsAutoLayout(this INamedTypeSymbol type, ITypeSymbol structLayoutAttributeType) + { + foreach (AttributeData attr in type.GetAttributes()) + { + if (SymbolEqualityComparer.Default.Equals(structLayoutAttributeType, attr.AttributeClass)) + { + return (LayoutKind)(int)attr.ConstructorArguments[0].Value! == LayoutKind.Auto; + } + } + return type.IsReferenceType; + } + + public static TypeSyntax AsTypeSyntax(this ITypeSymbol type) + { + return SyntaxFactory.ParseTypeName(type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)); + } + + public static bool IsIntegralType(this SpecialType type) + { + return type switch + { + SpecialType.System_SByte + or SpecialType.System_Byte + or SpecialType.System_Int16 + or SpecialType.System_UInt16 + or SpecialType.System_Int32 + or SpecialType.System_UInt32 + or SpecialType.System_Int64 + or SpecialType.System_UInt64 + or SpecialType.System_IntPtr + or SpecialType.System_UIntPtr => true, + _ => false + }; + } + + public static bool IsExposedOutsideOfCurrentCompilation(this INamedTypeSymbol type) + { + for (; type is not null; type = type.ContainingType) + { + Accessibility accessibility = type.DeclaredAccessibility; + + if (accessibility is Accessibility.Internal or Accessibility.ProtectedAndInternal or Accessibility.Private or Accessibility.Friend or Accessibility.ProtectedAndFriend) + { + return false; + } + } + return true; + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/Ancillary.Interop.csproj b/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/Ancillary.Interop.csproj new file mode 100644 index 0000000000000..9b389dddc8dc1 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/Ancillary.Interop.csproj @@ -0,0 +1,18 @@ + + + + Microsoft.Interop.Ancillary + $(NetCoreAppCurrent) + System.Runtime.InteropServices + enable + true + APIs required for usage of the DllImportGenerator and related tools. + $(DefineConstants);DLLIMPORT_GENERATOR_TEST + + + + + + + + diff --git a/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/Directory.Build.props b/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/Directory.Build.props new file mode 100644 index 0000000000000..fa9c3a4001db5 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/Directory.Build.props @@ -0,0 +1,7 @@ + + + + + true + + diff --git a/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/MarshalEx.cs b/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/MarshalEx.cs new file mode 100644 index 0000000000000..8bd0b2fd56488 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/MarshalEx.cs @@ -0,0 +1,18 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics.CodeAnalysis; +using System.Reflection; + +namespace System.Runtime.InteropServices +{ + /// + /// Marshalling helper methods that will likely live in S.R.IS.Marshal + /// when we integrate our APIs with dotnet/runtime. + /// When referencing this type in a source-generator, make sure to use + /// the TypeNames.MarshalEx method to enable configuration when dogfooding. + /// + public static class MarshalEx + { + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/SpanMarshallers.cs b/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/SpanMarshallers.cs new file mode 100644 index 0000000000000..453259feeda1b --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/Ancillary.Interop/SpanMarshallers.cs @@ -0,0 +1,395 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System.Runtime.CompilerServices; + +namespace System.Runtime.InteropServices.GeneratedMarshalling +{ + [GenericContiguousCollectionMarshaller] + public unsafe ref struct ReadOnlySpanMarshaller + { + private ReadOnlySpan _managedSpan; + private readonly int _sizeOfNativeElement; + private IntPtr _allocatedMemory; + + public ReadOnlySpanMarshaller(int sizeOfNativeElement) + : this() + { + _sizeOfNativeElement = sizeOfNativeElement; + } + + public ReadOnlySpanMarshaller(ReadOnlySpan managed, int sizeOfNativeElement) + { + _allocatedMemory = default; + _sizeOfNativeElement = sizeOfNativeElement; + if (managed.Length == 0) + { + _managedSpan = default; + NativeValueStorage = default; + return; + } + _managedSpan = managed; + _sizeOfNativeElement = sizeOfNativeElement; + int spaceToAllocate = managed.Length * sizeOfNativeElement; + _allocatedMemory = Marshal.AllocCoTaskMem(spaceToAllocate); + NativeValueStorage = new Span((void*)_allocatedMemory, spaceToAllocate); + } + + public ReadOnlySpanMarshaller(ReadOnlySpan managed, Span stackSpace, int sizeOfNativeElement) + { + _allocatedMemory = default; + _sizeOfNativeElement = sizeOfNativeElement; + if (managed.Length == 0) + { + _managedSpan = default; + NativeValueStorage = default; + return; + } + _managedSpan = managed; + int spaceToAllocate = managed.Length * sizeOfNativeElement; + if (spaceToAllocate <= stackSpace.Length) + { + NativeValueStorage = stackSpace[0..spaceToAllocate]; + } + else + { + _allocatedMemory = Marshal.AllocCoTaskMem(spaceToAllocate); + NativeValueStorage = new Span((void*)_allocatedMemory, spaceToAllocate); + } + } + + /// + /// Stack-alloc threshold set to 256 bytes to enable small arrays to be passed on the stack. + /// Number kept small to ensure that P/Invokes with a lot of array parameters doesn't + /// blow the stack since this is a new optimization in the code-generated interop. + /// + public const int StackBufferSize = 0x200; + + public Span ManagedValues => MemoryMarshal.CreateSpan(ref MemoryMarshal.GetReference(_managedSpan), _managedSpan.Length); + + public Span NativeValueStorage { get; private set; } + + public ref byte GetPinnableReference() => ref MemoryMarshal.GetReference(NativeValueStorage); + + public void SetUnmarshalledCollectionLength(int length) + { + _managedSpan = new T[length]; + } + + public byte* Value + { + get + { + Debug.Assert(_managedSpan.IsEmpty || _allocatedMemory != IntPtr.Zero); + return (byte*)_allocatedMemory; + } + set + { + if (value == null) + { + _managedSpan = null; + NativeValueStorage = default; + } + else + { + _allocatedMemory = (IntPtr)value; + NativeValueStorage = new Span(value, _managedSpan.Length * _sizeOfNativeElement); + } + } + } + + public ReadOnlySpan ToManaged() => _managedSpan; + + public void FreeNative() + { + Marshal.FreeCoTaskMem(_allocatedMemory); + } + } + + [GenericContiguousCollectionMarshaller] + public unsafe ref struct SpanMarshaller + { + private ReadOnlySpanMarshaller _inner; + + public SpanMarshaller(int sizeOfNativeElement) + : this() + { + _inner = new ReadOnlySpanMarshaller(sizeOfNativeElement); + } + + public SpanMarshaller(Span managed, int sizeOfNativeElement) + { + _inner = new ReadOnlySpanMarshaller(managed, sizeOfNativeElement); + } + + public SpanMarshaller(Span managed, Span stackSpace, int sizeOfNativeElement) + { + _inner = new ReadOnlySpanMarshaller(managed, stackSpace, sizeOfNativeElement); + } + + /// + /// Stack-alloc threshold set to 256 bytes to enable small arrays to be passed on the stack. + /// Number kept small to ensure that P/Invokes with a lot of array parameters doesn't + /// blow the stack since this is a new optimization in the code-generated interop. + /// + public const int StackBufferSize = ReadOnlySpanMarshaller.StackBufferSize; + + public Span ManagedValues => _inner.ManagedValues; + + public Span NativeValueStorage + { + get => _inner.NativeValueStorage; + } + + public ref byte GetPinnableReference() => ref _inner.GetPinnableReference(); + + public void SetUnmarshalledCollectionLength(int length) + { + _inner.SetUnmarshalledCollectionLength(length); + } + + public byte* Value + { + get => _inner.Value; + set => _inner.Value = value; + } + + public Span ToManaged() + { + ReadOnlySpan managedInner = _inner.ToManaged(); + return MemoryMarshal.CreateSpan(ref MemoryMarshal.GetReference(managedInner), managedInner.Length); + } + + public void FreeNative() + { + _inner.FreeNative(); + } + } + + [GenericContiguousCollectionMarshaller] + public unsafe ref struct NeverNullSpanMarshaller + { + private SpanMarshaller _inner; + + public NeverNullSpanMarshaller(int sizeOfNativeElement) + : this() + { + _inner = new SpanMarshaller(sizeOfNativeElement); + } + + public NeverNullSpanMarshaller(Span managed, int sizeOfNativeElement) + { + _inner = new SpanMarshaller(managed, sizeOfNativeElement); + } + + public NeverNullSpanMarshaller(Span managed, Span stackSpace, int sizeOfNativeElement) + { + _inner = new SpanMarshaller(managed, stackSpace, sizeOfNativeElement); + } + + /// + /// Stack-alloc threshold set to 256 bytes to enable small spans to be passed on the stack. + /// Number kept small to ensure that P/Invokes with a lot of span parameters doesn't + /// blow the stack. + /// + public const int StackBufferSize = SpanMarshaller.StackBufferSize; + + public Span ManagedValues => _inner.ManagedValues; + + public Span NativeValueStorage + { + get => _inner.NativeValueStorage; + } + + public ref byte GetPinnableReference() + { + if (_inner.ManagedValues.Length == 0) + { + return ref *(byte*)0xa5a5a5a5; + } + return ref _inner.GetPinnableReference(); + } + + public void SetUnmarshalledCollectionLength(int length) + { + _inner.SetUnmarshalledCollectionLength(length); + } + + public byte* Value + { + get + { + if (_inner.ManagedValues.Length == 0) + { + return (byte*)0x1; + } + return _inner.Value; + } + + set => _inner.Value = value; + } + + public Span ToManaged() => _inner.ToManaged(); + + public void FreeNative() + { + _inner.FreeNative(); + } + } + + [GenericContiguousCollectionMarshaller] + public unsafe ref struct NeverNullReadOnlySpanMarshaller + { + private ReadOnlySpanMarshaller _inner; + + public NeverNullReadOnlySpanMarshaller(int sizeOfNativeElement) + : this() + { + _inner = new ReadOnlySpanMarshaller(sizeOfNativeElement); + } + + public NeverNullReadOnlySpanMarshaller(ReadOnlySpan managed, int sizeOfNativeElement) + { + _inner = new ReadOnlySpanMarshaller(managed, sizeOfNativeElement); + } + + public NeverNullReadOnlySpanMarshaller(ReadOnlySpan managed, Span stackSpace, int sizeOfNativeElement) + { + _inner = new ReadOnlySpanMarshaller(managed, stackSpace, sizeOfNativeElement); + } + + /// + /// Stack-alloc threshold set to 256 bytes to enable small spans to be passed on the stack. + /// Number kept small to ensure that P/Invokes with a lot of span parameters doesn't + /// blow the stack. + /// + public const int StackBufferSize = SpanMarshaller.StackBufferSize; + + public Span ManagedValues => _inner.ManagedValues; + + public Span NativeValueStorage + { + get => _inner.NativeValueStorage; + } + + public ref byte GetPinnableReference() + { + if (_inner.ManagedValues.Length == 0) + { + return ref *(byte*)0xa5a5a5a5; + } + return ref _inner.GetPinnableReference(); + } + + public void SetUnmarshalledCollectionLength(int length) + { + _inner.SetUnmarshalledCollectionLength(length); + } + + public byte* Value + { + get + { + if (_inner.ManagedValues.Length == 0) + { + return (byte*)0x1; + } + return _inner.Value; + } + + set => _inner.Value = value; + } + + public ReadOnlySpan ToManaged() => _inner.ToManaged(); + + public void FreeNative() + { + _inner.FreeNative(); + } + } + + [GenericContiguousCollectionMarshaller] + public unsafe ref struct DirectSpanMarshaller + where T : unmanaged + { + private int _unmarshalledLength; + private T* _allocatedMemory; + private Span _data; + + public DirectSpanMarshaller(int sizeOfNativeElement) + :this() + { + // This check is not exhaustive, but it will catch the majority of cases. + if (typeof(T) == typeof(bool) || typeof(T) == typeof(char) || Unsafe.SizeOf() != sizeOfNativeElement) + { + throw new ArgumentException("This marshaller only supports blittable element types. The provided type parameter must be blittable", nameof(T)); + } + } + + public DirectSpanMarshaller(Span managed, int sizeOfNativeElement) + :this(sizeOfNativeElement) + { + if (managed.Length == 0) + { + return; + } + + int spaceToAllocate = managed.Length * Unsafe.SizeOf(); + _allocatedMemory = (T*)Marshal.AllocCoTaskMem(spaceToAllocate); + _data = managed; + } + + public DirectSpanMarshaller(Span managed, Span stackSpace, int sizeOfNativeElement) + :this(sizeOfNativeElement) + { + Debug.Assert(stackSpace.IsEmpty); + _data = managed; + } + + /// + /// Stack-alloc threshold set to 0 so that the generator can use the constructor that takes a stackSpace to let the marshaller know that the original data span can be used and safely pinned. + /// + public const int StackBufferSize = 0; + + public Span ManagedValues => _data; + + public Span NativeValueStorage => _allocatedMemory != null + ? new Span(_allocatedMemory, _data.Length * Unsafe.SizeOf()) + : MemoryMarshal.Cast(_data); + + public ref T GetPinnableReference() => ref _data.GetPinnableReference(); + + public void SetUnmarshalledCollectionLength(int length) + { + _unmarshalledLength = length; + } + + public T* Value + { + get + { + Debug.Assert(_data.IsEmpty || _allocatedMemory != null); + return _allocatedMemory; + } + set + { + // We don't save the pointer assigned here to be freed + // since this marshaller passes back the actual memory span from native code + // back to managed code. + _allocatedMemory = null; + _data = new Span(value, _unmarshalledLength); + } + } + + public Span ToManaged() + { + return _data; + } + + public void FreeNative() + { + Marshal.FreeCoTaskMem((IntPtr)_allocatedMemory); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/ArrayTests.cs b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/ArrayTests.cs new file mode 100644 index 0000000000000..fcdedc6ba004c --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/ArrayTests.cs @@ -0,0 +1,324 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using SharedTypes; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; + +using Xunit; + +namespace DllImportGenerator.IntegrationTests +{ + partial class NativeExportsNE + { + public partial class Arrays + { + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "sum_int_array")] + public static partial int Sum(int[] values, int numValues); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "sum_int_array")] + public static partial int Sum(ref int values, int numValues); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "sum_int_array_ref")] + public static partial int SumInArray(in int[] values, int numValues); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "duplicate_int_array")] + public static partial void Duplicate([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] ref int[] values, int numValues); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "create_range_array")] + [return:MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] + public static partial int[] CreateRange(int start, int end, out int numValues); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "create_range_array_out")] + public static partial void CreateRange_Out(int start, int end, out int numValues, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] out int[] res); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "sum_string_lengths")] + public static partial int SumStringLengths([MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr)] string[] strArray); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "reverse_strings_replace")] + public static partial void ReverseStrings_Ref([MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 1)] ref string[] strArray, out int numElements); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "reverse_strings_return")] + [return: MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 1)] + public static partial string[] ReverseStrings_Return([MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr)] string[] strArray, out int numElements); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "reverse_strings_out")] + public static partial void ReverseStrings_Out([MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr)] string[] strArray, out int numElements, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeParamIndex = 1)] out string[] res); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "get_long_bytes")] + [return:MarshalAs(UnmanagedType.LPArray, SizeConst = sizeof(long))] + public static partial byte[] GetLongBytes(long l); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "append_int_to_array")] + public static partial void Append([MarshalAs(UnmanagedType.LPArray, SizeConst = 1, SizeParamIndex = 1)] ref int[] values, int numOriginalValues, int newValue); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "fill_range_array")] + [return: MarshalAs(UnmanagedType.U1)] + public static partial bool FillRangeArray([Out] IntStructWrapper[] array, int length, int start); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "double_values")] + public static partial bool DoubleValues([In, Out] IntStructWrapper[] array, int length); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "and_all_members")] + [return:MarshalAs(UnmanagedType.U1)] + public static partial bool AndAllMembers(BoolStruct[] pArray, int length); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "transpose_matrix")] + [return: MarshalUsing(CountElementName = "numColumns")] + [return: MarshalUsing(CountElementName = "numRows", ElementIndirectionLevel = 1)] + public static partial int[][] TransposeMatrix(int[][] matrix, int[] numRows, int numColumns); + } + } + + public class ArrayTests + { + [Fact] + public void IntArrayMarshalledToNativeAsExpected() + { + var array = new[] { 1, 5, 79, 165, 32, 3 }; + Assert.Equal(array.Sum(), NativeExportsNE.Arrays.Sum(array, array.Length)); + } + + [Fact] + public void IntArrayRefToFirstElementMarshalledToNativeAsExpected() + { + var array = new[] { 1, 5, 79, 165, 32, 3 }; + Assert.Equal(array.Sum(), NativeExportsNE.Arrays.Sum(ref array[0], array.Length)); + } + + [Fact] + public void NullIntArrayMarshalledToNativeAsExpected() + { + Assert.Equal(-1, NativeExportsNE.Arrays.Sum(null, 0)); + } + + [Fact] + public void ZeroLengthArrayMarshalledAsNonNull() + { + var array = new int[0]; + Assert.Equal(0, NativeExportsNE.Arrays.Sum(array, array.Length)); + } + + [Fact] + public void IntArrayInParameter() + { + var array = new[] { 1, 5, 79, 165, 32, 3 }; + Assert.Equal(array.Sum(), NativeExportsNE.Arrays.SumInArray(array, array.Length)); + } + + [Fact] + public void IntArrayRefParameter() + { + var array = new [] { 1, 5, 79, 165, 32, 3 }; + var newArray = array; + NativeExportsNE.Arrays.Duplicate(ref newArray, array.Length); + Assert.Equal((IEnumerable)array, newArray); + } + + [Fact] + public void ArraysReturnedFromNative() + { + int start = 5; + int end = 20; + + IEnumerable expected = Enumerable.Range(start, end - start); + Assert.Equal(expected, NativeExportsNE.Arrays.CreateRange(start, end, out _)); + + int[] res; + NativeExportsNE.Arrays.CreateRange_Out(start, end, out _, out res); + Assert.Equal(expected, res); + } + + [Fact] + public void NullArrayReturnedFromNative() + { + Assert.Null(NativeExportsNE.Arrays.CreateRange(1, 0, out _)); + + int[] res; + NativeExportsNE.Arrays.CreateRange_Out(1, 0, out _, out res); + Assert.Null(res); + } + + private static string[] GetStringArray() + { + return new [] + { + "ABCdef 123$%^", + "🍜 !! 🍜 !!", + "🌲 木 🔥 火 🌾 土 🛡 金 🌊 水" , + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vitae posuere mauris, sed ultrices leo. Suspendisse potenti. Mauris enim enim, blandit tincidunt consequat in, varius sit amet neque. Morbi eget porttitor ex. Duis mattis aliquet ante quis imperdiet. Duis sit.", + string.Empty, + null + }; + } + + [Fact] + public void ByValueArrayWithElementMarshalling() + { + var strings = GetStringArray(); + Assert.Equal(strings.Sum(str => str?.Length ?? 0), NativeExportsNE.Arrays.SumStringLengths(strings)); + } + + [Fact] + public void ByValueNullArrayWithElementMarshalling() + { + Assert.Equal(0, NativeExportsNE.Arrays.SumStringLengths(null)); + } + + [Fact] + public void ByRefArrayWithElementMarshalling() + { + var strings = GetStringArray(); + var expectedStrings = strings.Select(s => ReverseChars(s)).ToArray(); + NativeExportsNE.Arrays.ReverseStrings_Ref(ref strings, out _); + + Assert.Equal((IEnumerable)expectedStrings, strings); + } + + [Fact] + public void ReturnArrayWithElementMarshalling() + { + var strings = GetStringArray(); + var expectedStrings = strings.Select(s => ReverseChars(s)).ToArray(); + Assert.Equal(expectedStrings, NativeExportsNE.Arrays.ReverseStrings_Return(strings, out _)); + + string[] res; + NativeExportsNE.Arrays.ReverseStrings_Out(strings, out _, out res); + Assert.Equal(expectedStrings, res); + } + + [Fact] + public void ByRefNullArrayWithElementMarshalling() + { + string[] strings = null; + NativeExportsNE.Arrays.ReverseStrings_Ref(ref strings, out _); + + Assert.Null(strings); + } + + [Fact] + public void ReturnNullArrayWithElementMarshalling() + { + string[] strings = null; + Assert.Null(NativeExportsNE.Arrays.ReverseStrings_Return(strings, out _)); + + string[] res; + NativeExportsNE.Arrays.ReverseStrings_Out(strings, out _, out res); + Assert.Null(res); + } + + [Fact] + public void ConstantSizeArray() + { + var longVal = 0x12345678ABCDEF10L; + + Assert.Equal(longVal, MemoryMarshal.Read(NativeExportsNE.Arrays.GetLongBytes(longVal))); + } + + [Fact] + public void DynamicSizedArrayWithConstantComponent() + { + var array = new [] { 1, 5, 79, 165, 32, 3 }; + int newValue = 42; + var newArray = array; + NativeExportsNE.Arrays.Append(ref newArray, array.Length, newValue); + Assert.Equal(array.Concat(new [] { newValue }), newArray); + } + + [Fact] + public void ArrayByValueOutParameter() + { + var testArray = new IntStructWrapper[10]; + int start = 5; + + NativeExportsNE.Arrays.FillRangeArray(testArray, testArray.Length, start); + + Assert.Equal(Enumerable.Range(start, 10), testArray.Select(wrapper => wrapper.Value)); + } + + [Fact] + public void ArrayByValueInOutParameter() + { + var testValues = Enumerable.Range(42, 15).Select(i => new IntStructWrapper { Value = i }); + + var testArray = testValues.ToArray(); + + NativeExportsNE.Arrays.DoubleValues(testArray, testArray.Length); + + Assert.Equal(testValues.Select(wrapper => wrapper.Value * 2), testArray.Select(wrapper => wrapper.Value)); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void ArrayWithSimpleNonBlittableTypeMarshalling(bool result) + { + var boolValues = new[] + { + new BoolStruct + { + b1 = true, + b2 = true, + b3 = true, + }, + new BoolStruct + { + b1 = true, + b2 = true, + b3 = true, + }, + new BoolStruct + { + b1 = true, + b2 = true, + b3 = result, + }, + }; + + Assert.Equal(result, NativeExportsNE.Arrays.AndAllMembers(boolValues, boolValues.Length)); + } + + [Fact] + public void ArraysOfArrays() + { + var random = new Random(42); + int numRows = random.Next(1, 5); + int numColumns = random.Next(1, 5); + int[][] matrix = new int[numRows][]; + for (int i = 0; i < numRows; i++) + { + matrix[i] = new int[numColumns]; + for (int j = 0; j < numColumns; j++) + { + matrix[i][j] = random.Next(); + } + } + + int[] numRowsArray = new int[numColumns]; + numRowsArray.AsSpan().Fill(numRows); + + int[][] transposed = NativeExportsNE.Arrays.TransposeMatrix(matrix, numRowsArray, numColumns); + + for (int i = 0; i < numRows; i++) + { + for (int j = 0; j < numColumns; j++) + { + Assert.Equal(matrix[i][j], transposed[j][i]); + } + } + } + + private static string ReverseChars(string value) + { + if (value == null) + return null; + + var chars = value.ToCharArray(); + Array.Reverse(chars); + return new string(chars); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/BlittableStructTests.cs b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/BlittableStructTests.cs new file mode 100644 index 0000000000000..5aa24bf1af91a --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/BlittableStructTests.cs @@ -0,0 +1,86 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.InteropServices; + +using SharedTypes; + +using Xunit; + +namespace DllImportGenerator.IntegrationTests +{ + partial class NativeExportsNE + { + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "blittablestructs_return_instance")] + public static partial IntFields DoubleIntFields(IntFields result); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "blittablestructs_double_intfields_byref")] + public static partial void DoubleIntFieldsByRef(ref IntFields result); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "blittablestructs_double_intfields_byref")] + public static partial void DoubleIntFieldsByRefIn(in IntFields result); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "blittablestructs_double_intfields_refreturn")] + public static partial void DoubleIntFieldsRefReturn( + IntFields input, + ref IntFields result); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "blittablestructs_double_intfields_refreturn")] + public static partial void DoubleIntFieldsOutReturn( + IntFields input, + out IntFields result); + } + + public class BlittableStructTests + { + [Fact] + public void ValidateBlittableStruct() + { + const int A = 24, B = 37, C = 59; + var initial = new IntFields() + { + a = A, + b = B, + c = C, + }; + var expected = new IntFields() + { + a = initial.a * 2, + b = initial.b * 2, + c = initial.c * 2, + }; + + var input = initial; + { + var result = NativeExportsNE.DoubleIntFields(input); + Assert.Equal(initial, input); + Assert.Equal(expected, result); + } + { + var result = new IntFields(); + NativeExportsNE.DoubleIntFieldsRefReturn(input, ref result); + Assert.Equal(initial, input); + Assert.Equal(expected, result); + } + + { + IntFields result; + NativeExportsNE.DoubleIntFieldsOutReturn(input, out result); + Assert.Equal(initial, input); + Assert.Equal(expected, result); + } + + { + input = initial; + NativeExportsNE.DoubleIntFieldsByRef(ref input); + Assert.Equal(expected, input); + } + + { + input = initial; + NativeExportsNE.DoubleIntFieldsByRefIn(in input); + Assert.Equal(expected, input); // Updated even when passed with in keyword (matches built-in system) + } + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/BooleanTests.cs b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/BooleanTests.cs new file mode 100644 index 0000000000000..063174d3e3577 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/BooleanTests.cs @@ -0,0 +1,204 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Runtime.InteropServices; + +using Xunit; + +namespace DllImportGenerator.IntegrationTests +{ + partial class NativeExportsNE + { + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "bytebool_return_as_uint")] + public static partial uint ReturnByteBoolAsUInt([MarshalAs(UnmanagedType.U1)] bool input); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "bytebool_return_as_uint")] + public static partial uint ReturnSByteBoolAsUInt([MarshalAs(UnmanagedType.I1)] bool input); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "variantbool_return_as_uint")] + public static partial uint ReturnVariantBoolAsUInt([MarshalAs(UnmanagedType.VariantBool)] bool input); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "bool_return_as_uint")] + public static partial uint ReturnIntBoolAsUInt([MarshalAs(UnmanagedType.I4)] bool input); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "bool_return_as_uint")] + public static partial uint ReturnUIntBoolAsUInt([MarshalAs(UnmanagedType.U4)] bool input); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "bool_return_as_uint")] + public static partial uint ReturnWinBoolAsUInt([MarshalAs(UnmanagedType.Bool)] bool input); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "bool_return_as_uint")] + public static partial uint ReturnDefaultBoolAsUInt(bool input); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "bool_return_as_uint")] + [return: MarshalAs(UnmanagedType.U1)] + public static partial bool ReturnUIntAsByteBool(uint input); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "bool_return_as_uint")] + [return: MarshalAs(UnmanagedType.VariantBool)] + public static partial bool ReturnUIntAsVariantBool(uint input); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "bool_return_as_uint")] + [return: MarshalAs(UnmanagedType.Bool)] + public static partial bool ReturnUIntAsWinBool(uint input); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "bool_return_as_uint")] + public static partial bool ReturnUIntAsDefaultBool(uint input); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "bool_return_as_refuint")] + public static partial void ReturnUIntAsByteBool_Ref(uint input, [MarshalAs(UnmanagedType.U1)] ref bool res); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "bool_return_as_refuint")] + public static partial void ReturnUIntAsByteBool_Out(uint input, [MarshalAs(UnmanagedType.U1)] out bool res); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "bool_return_as_refuint")] + public static partial void ReturnUIntAsByteBool_In(uint input, [MarshalAs(UnmanagedType.U1)] in bool res); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "bool_return_as_refuint")] + public static partial void ReturnUIntAsVariantBool_Ref(uint input, [MarshalAs(UnmanagedType.VariantBool)] ref bool res); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "bool_return_as_refuint")] + public static partial void ReturnUIntAsVariantBool_Out(uint input, [MarshalAs(UnmanagedType.VariantBool)] out bool res); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "bool_return_as_refuint")] + public static partial void ReturnUIntAsVariantBool_In(uint input, [MarshalAs(UnmanagedType.VariantBool)] in bool res); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "bool_return_as_refuint")] + public static partial void ReturnUIntAsWinBool_Ref(uint input, [MarshalAs(UnmanagedType.Bool)] ref bool res); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "bool_return_as_refuint")] + public static partial void ReturnUIntAsWinBool_Out(uint input, [MarshalAs(UnmanagedType.Bool)] out bool res); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "bool_return_as_refuint")] + public static partial void ReturnUIntAsWinBool_In(uint input, [MarshalAs(UnmanagedType.Bool)] in bool res); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "bool_return_as_refuint")] + public static partial void ReturnUIntAsDefaultBool_Ref(uint input, ref bool res); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "bool_return_as_refuint")] + public static partial void ReturnUIntAsDefaultBool_Out(uint input, out bool res); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "bool_return_as_refuint")] + public static partial void ReturnUIntAsDefaultBool_In(uint input, in bool res); + } + + public class BooleanTests + { + // See definition of Windows' VARIANT_BOOL + const ushort VARIANT_TRUE = unchecked((ushort)-1); + const ushort VARIANT_FALSE = 0; + + [Fact] + public void ValidateBoolIsMarshalledAsExpected() + { + Assert.Equal((uint)1, NativeExportsNE.ReturnByteBoolAsUInt(true)); + Assert.Equal((uint)0, NativeExportsNE.ReturnByteBoolAsUInt(false)); + Assert.Equal((uint)1, NativeExportsNE.ReturnSByteBoolAsUInt(true)); + Assert.Equal((uint)0, NativeExportsNE.ReturnSByteBoolAsUInt(false)); + Assert.Equal(VARIANT_TRUE, NativeExportsNE.ReturnVariantBoolAsUInt(true)); + Assert.Equal(VARIANT_FALSE, NativeExportsNE.ReturnVariantBoolAsUInt(false)); + Assert.Equal((uint)1, NativeExportsNE.ReturnIntBoolAsUInt(true)); + Assert.Equal((uint)0, NativeExportsNE.ReturnIntBoolAsUInt(false)); + Assert.Equal((uint)1, NativeExportsNE.ReturnUIntBoolAsUInt(true)); + Assert.Equal((uint)0, NativeExportsNE.ReturnUIntBoolAsUInt(false)); + Assert.Equal((uint)1, NativeExportsNE.ReturnWinBoolAsUInt(true)); + Assert.Equal((uint)0, NativeExportsNE.ReturnWinBoolAsUInt(false)); + Assert.Equal((uint)1, NativeExportsNE.ReturnDefaultBoolAsUInt(true)); + Assert.Equal((uint)0, NativeExportsNE.ReturnDefaultBoolAsUInt(false)); + } + + [Theory] + [InlineData(new object[] { 0, false })] + [InlineData(new object[] { 1, true })] + [InlineData(new object[] { 37, true })] + [InlineData(new object[] { 0xff, true })] + [InlineData(new object[] { 0xffffff00, false })] + public void ValidateByteBoolReturns(uint value, bool expected) + { + Assert.Equal(expected, NativeExportsNE.ReturnUIntAsByteBool(value)); + + bool result = !expected; + NativeExportsNE.ReturnUIntAsByteBool_Ref(value, ref result); + Assert.Equal(expected, result); + + result = !expected; + NativeExportsNE.ReturnUIntAsByteBool_Out(value, out result); + Assert.Equal(expected, result); + + result = !expected; + NativeExportsNE.ReturnUIntAsByteBool_In(value, in result); + Assert.Equal(!expected, result); // Should not be updated when using 'in' + } + + [Theory] + [InlineData(new object[] { 0, false })] + [InlineData(new object[] { 1, false })] + [InlineData(new object[] { 0xff, false })] + [InlineData(new object[] { VARIANT_TRUE, true })] + [InlineData(new object[] { 0xffffffff, true })] + [InlineData(new object[] { 0xffff0000, false })] + public void ValidateVariantBoolReturns(uint value, bool expected) + { + Assert.Equal(expected, NativeExportsNE.ReturnUIntAsVariantBool(value)); + + bool result = !expected; + NativeExportsNE.ReturnUIntAsVariantBool_Ref(value, ref result); + Assert.Equal(expected, result); + + result = !expected; + NativeExportsNE.ReturnUIntAsVariantBool_Out(value, out result); + Assert.Equal(expected, result); + + result = !expected; + NativeExportsNE.ReturnUIntAsVariantBool_In(value, in result); + Assert.Equal(!expected, result); // Should not be updated when using 'in' + } + + [Theory] + [InlineData(new object[] { 0, false })] + [InlineData(new object[] { 1, true})] + [InlineData(new object[] { 37, true })] + [InlineData(new object[] { 0xffffffff, true })] + [InlineData(new object[] { 0x80000000, true })] + public void ValidateWinBoolReturns(uint value, bool expected) + { + Assert.Equal(expected, NativeExportsNE.ReturnUIntAsWinBool(value)); + + bool result = !expected; + NativeExportsNE.ReturnUIntAsWinBool_Ref(value, ref result); + Assert.Equal(expected, result); + + result = !expected; + NativeExportsNE.ReturnUIntAsWinBool_Out(value, out result); + Assert.Equal(expected, result); + + result = !expected; + NativeExportsNE.ReturnUIntAsWinBool_In(value, in result); + Assert.Equal(!expected, result); // Should not be updated when using 'in' + } + + [Theory] + [InlineData(new object[] { 0, false })] + [InlineData(new object[] { 1, true })] + [InlineData(new object[] { 37, true })] + [InlineData(new object[] { 0xffffffff, true })] + [InlineData(new object[] { 0x80000000, true })] + public void ValidateDefaultBoolReturns(uint value, bool expected) + { + Assert.Equal(expected, NativeExportsNE.ReturnUIntAsDefaultBool(value)); + + bool result = !expected; + NativeExportsNE.ReturnUIntAsDefaultBool_Ref(value, ref result); + Assert.Equal(expected, result); + + result = !expected; + NativeExportsNE.ReturnUIntAsDefaultBool_Out(value, out result); + Assert.Equal(expected, result); + + result = !expected; + NativeExportsNE.ReturnUIntAsDefaultBool_In(value, in result); + Assert.Equal(!expected, result); // Should not be updated when using 'in' + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/CallingConventionTests.cs b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/CallingConventionTests.cs new file mode 100644 index 0000000000000..161b94f8c39e9 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/CallingConventionTests.cs @@ -0,0 +1,48 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; +using Xunit; + +namespace DllImportGenerator.IntegrationTests +{ + internal partial class NativeExportsNE + { + internal partial class CallingConventions + { + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "add_integers_cdecl")] + [UnmanagedCallConv(CallConvs = new[] { typeof(CallConvCdecl) })] + public static partial long AddLongsCdecl(long i, long j, long k, long l, long m, long n, long o, long p, long q); + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "add_integers_stdcall")] + [UnmanagedCallConv(CallConvs = new[] { typeof(CallConvStdcall) })] + public static partial long AddLongsStdcall(long i, long j, long k, long l, long m, long n, long o, long p, long q); + } + } + + public class CallingConventionTests + { + [Fact] + public void UnmanagedCallConvPropagated() + { + Random rng = new Random(1234); + long i = rng.Next(); + long j = rng.Next(); + long k = rng.Next(); + long l = rng.Next(); + long m = rng.Next(); + long n = rng.Next(); + long o = rng.Next(); + long p = rng.Next(); + long q = rng.Next(); + long expected = i + j + k + l + m + n + o + p + q; + Assert.Equal(expected, NativeExportsNE.CallingConventions.AddLongsCdecl(i, j, k, l, m, n, o, p, q)); + Assert.Equal(expected, NativeExportsNE.CallingConventions.AddLongsStdcall(i, j, k, l, m, n, o, p, q)); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/CharacterTests.cs b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/CharacterTests.cs new file mode 100644 index 0000000000000..d68aef5f91b88 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/CharacterTests.cs @@ -0,0 +1,102 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; + +using Xunit; + +namespace DllImportGenerator.IntegrationTests +{ + partial class NativeExportsNE + { + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "unicode_return_as_uint", CharSet = CharSet.Unicode)] + public static partial uint ReturnUnicodeAsUInt(char input); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "char_return_as_uint", CharSet = CharSet.Unicode)] + public static partial char ReturnUIntAsUnicode(uint input); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "char_return_as_refuint", CharSet = CharSet.Unicode)] + public static partial void ReturnUIntAsUnicode_Ref(uint input, ref char res); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "char_return_as_refuint", CharSet = CharSet.Unicode)] + public static partial void ReturnUIntAsUnicode_Out(uint input, out char res); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "char_return_as_refuint", CharSet = CharSet.Unicode)] + public static partial void ReturnUIntAsUnicode_In(uint input, in char res); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "char_return_as_uint", CharSet = CharSet.None)] + [return: MarshalAs(UnmanagedType.U2)] + public static partial char ReturnU2AsU2IgnoreCharSet([MarshalAs(UnmanagedType.U2)] char input); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "char_return_as_uint", CharSet = CharSet.Ansi)] + [return: MarshalAs(UnmanagedType.I2)] + public static partial char ReturnI2AsI2IgnoreCharSet([MarshalAs(UnmanagedType.I2)] char input); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "char_reverse_buffer_ref", CharSet = CharSet.Unicode)] + public static partial void ReverseBuffer(ref char buffer, int len); + } + + public class CharacterTests + { + public static IEnumerable CharacterMappings() + { + yield return new object[] { 'A', 0x41 }; + yield return new object[] { 'E', 0x45 }; + yield return new object[] { 'J', 0x4a }; + yield return new object[] { 'ß', 0xdf }; + yield return new object[] { '✅', 0x2705 }; + yield return new object[] { '鸟', 0x9e1f }; + } + + [Theory] + [MemberData(nameof(CharacterMappings))] + public void ValidateUnicodeCharIsMarshalledAsExpected(char value, uint expected) + { + Assert.Equal(expected, NativeExportsNE.ReturnUnicodeAsUInt(value)); + } + + [Theory] + [MemberData(nameof(CharacterMappings))] + public void ValidateUnicodeReturns(char expected, uint value) + { + Assert.Equal(expected, NativeExportsNE.ReturnUIntAsUnicode(value)); + + char initial = '\u0000'; + char result = initial; + NativeExportsNE.ReturnUIntAsUnicode_Ref(value, ref result); + Assert.Equal(expected, result); + + result = initial; + NativeExportsNE.ReturnUIntAsUnicode_Out(value, out result); + Assert.Equal(expected, result); + + result = initial; + NativeExportsNE.ReturnUIntAsUnicode_In(value, in result); + Assert.Equal(expected, result); // Value is updated even when passed with 'in' keyword (matches built-in system) + } + + [Theory] + [MemberData(nameof(CharacterMappings))] + public void ValidateIgnoreCharSet(char value, uint expectedUInt) + { + char expected = (char)expectedUInt; + Assert.Equal(expected, NativeExportsNE.ReturnU2AsU2IgnoreCharSet(value)); + Assert.Equal(expected, NativeExportsNE.ReturnI2AsI2IgnoreCharSet(value)); + } + + [Fact] + public void ValidateRefCharAsBuffer() + { + char[] chars = CharacterMappings().Select(o => (char)o[0]).ToArray(); + char[] expected = new char[chars.Length]; + Array.Copy(chars, expected, chars.Length); + Array.Reverse(expected); + + NativeExportsNE.ReverseBuffer(ref MemoryMarshal.GetArrayDataReference(chars), chars.Length); + Assert.Equal(expected, chars); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/CollectionTests.cs b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/CollectionTests.cs new file mode 100644 index 0000000000000..4a08b3f79d213 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/CollectionTests.cs @@ -0,0 +1,235 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using SharedTypes; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; + +using Xunit; + +namespace DllImportGenerator.IntegrationTests +{ + partial class NativeExportsNE + { + public partial class Collections + { + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "sum_int_array")] + public static partial int Sum([MarshalUsing(typeof(ListMarshaller))] List values, int numValues); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "sum_int_array")] + public static partial int Sum(ref int values, int numValues); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "sum_int_array_ref")] + public static partial int SumInArray([MarshalUsing(typeof(ListMarshaller))] in List values, int numValues); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "duplicate_int_array")] + public static partial void Duplicate([MarshalUsing(typeof(ListMarshaller), CountElementName = "numValues")] ref List values, int numValues); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "create_range_array")] + [return:MarshalUsing(typeof(ListMarshaller), CountElementName = "numValues")] + public static partial List CreateRange(int start, int end, out int numValues); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "create_range_array_out")] + public static partial void CreateRange_Out(int start, int end, out int numValues, [MarshalUsing(typeof(ListMarshaller), CountElementName = "numValues")] out List res); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "sum_string_lengths")] + public static partial int SumStringLengths([MarshalUsing(typeof(ListMarshaller)), MarshalUsing(typeof(Utf16StringMarshaler), ElementIndirectionLevel = 1)] List strArray); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "reverse_strings_replace")] + public static partial void ReverseStrings_Ref([MarshalUsing(typeof(ListMarshaller), CountElementName = "numElements"), MarshalUsing(typeof(Utf16StringMarshaler), ElementIndirectionLevel = 1)] ref List strArray, out int numElements); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "reverse_strings_return")] + [return: MarshalUsing(typeof(ListMarshaller), CountElementName = "numElements"), MarshalUsing(typeof(Utf16StringMarshaler), ElementIndirectionLevel = 1)] + public static partial List ReverseStrings_Return([MarshalUsing(typeof(ListMarshaller), CountElementName = "numElements"), MarshalUsing(typeof(Utf16StringMarshaler), ElementIndirectionLevel = 1)] List strArray, out int numElements); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "reverse_strings_out")] + public static partial void ReverseStrings_Out( + [MarshalUsing(typeof(ListMarshaller)), MarshalUsing(typeof(Utf16StringMarshaler), ElementIndirectionLevel = 1)] List strArray, + out int numElements, + [MarshalUsing(typeof(ListMarshaller), CountElementName = "numElements"), MarshalUsing(typeof(Utf16StringMarshaler), ElementIndirectionLevel = 1)] out List res); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "get_long_bytes")] + [return:MarshalUsing(typeof(ListMarshaller), ConstantElementCount = sizeof(long))] + public static partial List GetLongBytes(long l); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "and_all_members")] + [return:MarshalAs(UnmanagedType.U1)] + public static partial bool AndAllMembers([MarshalUsing(typeof(ListMarshaller))] List pArray, int length); + } + } + + public class CollectionTests + { + [Fact] + public void BlittableElementColllectionMarshalledToNativeAsExpected() + { + var list = new List { 1, 5, 79, 165, 32, 3 }; + Assert.Equal(list.Sum(), NativeExportsNE.Collections.Sum(list, list.Count)); + } + + [Fact] + public void NullBlittableElementColllectionMarshalledToNativeAsExpected() + { + Assert.Equal(-1, NativeExportsNE.Collections.Sum(null, 0)); + } + + [Fact] + public void BlittableElementColllectionInParameter() + { + var list = new List { 1, 5, 79, 165, 32, 3 }; + Assert.Equal(list.Sum(), NativeExportsNE.Collections.SumInArray(list, list.Count)); + } + + [Fact] + public void BlittableElementCollectionRefParameter() + { + var list = new List { 1, 5, 79, 165, 32, 3 }; + var newList = list; + NativeExportsNE.Collections.Duplicate(ref newList, list.Count); + Assert.Equal((IEnumerable)list, newList); + } + + [Fact] + public void BlittableElementCollectionReturnedFromNative() + { + int start = 5; + int end = 20; + + IEnumerable expected = Enumerable.Range(start, end - start); + Assert.Equal(expected, NativeExportsNE.Collections.CreateRange(start, end, out _)); + + List res; + NativeExportsNE.Collections.CreateRange_Out(start, end, out _, out res); + Assert.Equal(expected, res); + } + + [Fact] + public void NullBlittableElementCollectionReturnedFromNative() + { + Assert.Null(NativeExportsNE.Collections.CreateRange(1, 0, out _)); + + List res; + NativeExportsNE.Collections.CreateRange_Out(1, 0, out _, out res); + Assert.Null(res); + } + + private static List GetStringList() + { + return new() + { + "ABCdef 123$%^", + "🍜 !! 🍜 !!", + "🌲 木 🔥 火 🌾 土 🛡 金 🌊 水" , + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vitae posuere mauris, sed ultrices leo. Suspendisse potenti. Mauris enim enim, blandit tincidunt consequat in, varius sit amet neque. Morbi eget porttitor ex. Duis mattis aliquet ante quis imperdiet. Duis sit.", + string.Empty, + null + }; + } + + [Fact] + public void ByValueCollectionWithNonBlittableElements() + { + var strings = GetStringList(); + Assert.Equal(strings.Sum(str => str?.Length ?? 0), NativeExportsNE.Collections.SumStringLengths(strings)); + } + + [Fact] + public void ByValueNullCollectionWithNonBlittableElements() + { + Assert.Equal(0, NativeExportsNE.Collections.SumStringLengths(null)); + } + + [Fact] + public void ByRefCollectionWithNonBlittableElements() + { + var strings = GetStringList(); + var expectedStrings = strings.Select(s => ReverseChars(s)).ToList(); + NativeExportsNE.Collections.ReverseStrings_Ref(ref strings, out _); + + Assert.Equal((IEnumerable)expectedStrings, strings); + } + + [Fact] + public void ReturnCollectionWithNonBlittableElements() + { + var strings = GetStringList(); + var expectedStrings = strings.Select(s => ReverseChars(s)).ToList(); + Assert.Equal(expectedStrings, NativeExportsNE.Collections.ReverseStrings_Return(strings, out _)); + + List res; + NativeExportsNE.Collections.ReverseStrings_Out(strings, out _, out res); + Assert.Equal(expectedStrings, res); + } + + [Fact] + public void ByRefNullCollectionWithNonBlittableElements() + { + List strings = null; + NativeExportsNE.Collections.ReverseStrings_Ref(ref strings, out _); + + Assert.Null(strings); + } + + [Fact] + public void ReturnNullCollectionWithNonBlittableElements() + { + List strings = null; + Assert.Null(NativeExportsNE.Collections.ReverseStrings_Return(strings, out _)); + + List res; + NativeExportsNE.Collections.ReverseStrings_Out(strings, out _, out res); + Assert.Null(res); + } + + [Fact] + public void ConstantSizeCollection() + { + var longVal = 0x12345678ABCDEF10L; + + Assert.Equal(longVal, MemoryMarshal.Read(CollectionsMarshal.AsSpan(NativeExportsNE.Collections.GetLongBytes(longVal)))); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void CollectionWithSimpleNonBlittableTypeMarshalling(bool result) + { + var boolValues = new List + { + new BoolStruct + { + b1 = true, + b2 = true, + b3 = true, + }, + new BoolStruct + { + b1 = true, + b2 = true, + b3 = true, + }, + new BoolStruct + { + b1 = true, + b2 = true, + b3 = result, + }, + }; + + Assert.Equal(result, NativeExportsNE.Collections.AndAllMembers(boolValues, boolValues.Count)); + } + + private static string ReverseChars(string value) + { + if (value == null) + return null; + + var chars = value.ToCharArray(); + Array.Reverse(chars); + return new string(chars); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/Constants.cs b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/Constants.cs new file mode 100644 index 0000000000000..9ea08ea2fe8ae --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/Constants.cs @@ -0,0 +1,10 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace DllImportGenerator.IntegrationTests +{ + partial class NativeExportsNE + { + public const string NativeExportsNE_Binary = "Microsoft.Interop.Tests." + nameof(NativeExportsNE); + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/CustomMarshallingTests.cs b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/CustomMarshallingTests.cs new file mode 100644 index 0000000000000..134bf87256575 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/CustomMarshallingTests.cs @@ -0,0 +1,175 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.InteropServices; +using System.Text; +using SharedTypes; + +using Xunit; + +namespace DllImportGenerator.IntegrationTests +{ + partial class NativeExportsNE + { + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "stringcontainer_deepduplicate")] + public static partial void DeepDuplicateStrings(StringContainer strings, out StringContainer pStringsOut); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "stringcontainer_reverse_strings")] + public static partial void ReverseStrings(ref StringContainer strings); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "get_long_bytes_as_double")] + public static partial double GetLongBytesAsDouble([MarshalUsing(typeof(DoubleToLongMarshaler))] double d); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "negate_bools")] + public static partial void NegateBools( + BoolStruct boolStruct, + out BoolStruct pBoolStructOut); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "and_bools_ref")] + [return: MarshalAs(UnmanagedType.U1)] + public static partial bool AndBoolsRef(in BoolStruct boolStruct); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "double_int_ref")] + public static partial IntWrapper DoubleIntRef(IntWrapper pInt); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "reverse_replace_ref_ushort")] + public static partial void ReverseReplaceString([MarshalUsing(typeof(Utf16StringMarshaler))] ref string s); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "return_length_ushort")] + public static partial int ReturnStringLength([MarshalUsing(typeof(Utf16StringMarshaler))] string s); + } + + public class CustomMarshallingTests + { + [Fact] + public void NonBlittableStructWithFree() + { + var stringContainer = new StringContainer + { + str1 = "Foo", + str2 = "Bar" + }; + + NativeExportsNE.DeepDuplicateStrings(stringContainer, out var stringContainer2); + + Assert.Equal(stringContainer, stringContainer2); + } + + [Fact] + public void MarshalUsing() + { + double d = 1234.56789; + + Assert.Equal(d, NativeExportsNE.GetLongBytesAsDouble(d)); + } + + [Fact] + public void NonBlittableStructWithoutAllocation() + { + var boolStruct = new BoolStruct + { + b1 = true, + b2 = false, + b3 = true + }; + + NativeExportsNE.NegateBools(boolStruct, out BoolStruct boolStructNegated); + + Assert.Equal(!boolStruct.b1, boolStructNegated.b1); + Assert.Equal(!boolStruct.b2, boolStructNegated.b2); + Assert.Equal(!boolStruct.b3, boolStructNegated.b3); + } + + [Fact] + public void GetPinnableReferenceMarshalling() + { + int originalValue = 42; + var wrapper = new IntWrapper { i = originalValue }; + + var retVal = NativeExportsNE.DoubleIntRef(wrapper); + + Assert.Equal(originalValue * 2, wrapper.i); + Assert.Equal(originalValue * 2, retVal.i); + } + + [Fact] + public void NonBlittableStructRef() + { + var stringContainer = new StringContainer + { + str1 = "Foo", + str2 = "Bar" + }; + + var expected = new StringContainer + { + str1 = ReverseUTF8Bytes(stringContainer.str1), + str2 = ReverseUTF8Bytes(stringContainer.str2) + }; + + var stringContainerCopy = stringContainer; + + NativeExportsNE.ReverseStrings(ref stringContainerCopy); + + Assert.Equal(expected, stringContainerCopy); + } + + [Theory] + [InlineData(true, true, true)] + [InlineData(true, true, false)] + [InlineData(true, false, true)] + [InlineData(true, false, false)] + [InlineData(false, true, true)] + [InlineData(false, true, false)] + [InlineData(false, false, true)] + [InlineData(false, false, false)] + public void NonBlittableStructIn(bool b1, bool b2, bool b3) + { + var container = new BoolStruct + { + b1 = b1, + b2 = b2, + b3 = b3 + }; + + Assert.Equal(b1 && b2 && b3, NativeExportsNE.AndBoolsRef(container)); + } + + [Fact] + public void NonBlittableStructStackallocPinnableNativeMarshalling() + { + string str = "Hello world!"; + Assert.Equal(str.Length, NativeExportsNE.ReturnStringLength(str)); + } + + [Fact] + public void NonBlittableStructPinnableMarshalerPassByRef() + { + string str = "Hello world!"; + string expected = ReverseChars(str); + NativeExportsNE.ReverseReplaceString(ref str); + Assert.Equal(expected, str); + } + + private static string ReverseChars(string value) + { + if (value == null) + return null; + + var chars = value.ToCharArray(); + Array.Reverse(chars); + return new string(chars); + } + + private static string ReverseUTF8Bytes(string value) + { + if (value == null) + return null; + + byte[] bytes = Encoding.UTF8.GetBytes(value); + Array.Reverse(bytes); + return Encoding.UTF8.GetString(bytes); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/DelegateTests.cs b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/DelegateTests.cs new file mode 100644 index 0000000000000..01f86616972fb --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/DelegateTests.cs @@ -0,0 +1,58 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.InteropServices; + +using Xunit; + +namespace DllImportGenerator.IntegrationTests +{ + partial class NativeExportsNE + { + public delegate void VoidVoid(); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "invoke_callback_after_gc")] + public static partial void InvokeAfterGC(VoidVoid cb); + + public delegate int IntIntInt(int a, int b); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "invoke_callback_blittable_args")] + public static partial int InvokeWithBlittableArgument(IntIntInt cb, int a, int b); + } + + public class DelegateTests + { + [Fact] + public void DelegateIsKeptAliveDuringCall() + { + bool wasCalled = false; + NativeExportsNE.InvokeAfterGC(new NativeExportsNE.VoidVoid(Callback)); + Assert.True(wasCalled); + + void Callback() + { + wasCalled = true; + } + } + + [Fact] + public void DelegateIsCalledWithArgumentsInOrder() + { + const int a = 100; + const int b = 50; + int result; + + result = NativeExportsNE.InvokeWithBlittableArgument(new NativeExportsNE.IntIntInt(Callback), a, b); + Assert.Equal(Callback(a, b), result); + + result = NativeExportsNE.InvokeWithBlittableArgument(new NativeExportsNE.IntIntInt(Callback), b, a); + Assert.Equal(Callback(b, a), result); + + static int Callback(int a, int b) + { + // Use a noncommutative operation to validate passed in order. + return a - b; + } + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/Directory.Build.props b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/Directory.Build.props new file mode 100644 index 0000000000000..fa9c3a4001db5 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/Directory.Build.props @@ -0,0 +1,7 @@ + + + + + true + + diff --git a/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/DllImportGenerator.Tests.csproj b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/DllImportGenerator.Tests.csproj new file mode 100644 index 0000000000000..351241b66278d --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/DllImportGenerator.Tests.csproj @@ -0,0 +1,27 @@ + + + $(NetCoreAppCurrent) + false + Preview + true + true + + false + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + + + + diff --git a/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/EnumTests.cs b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/EnumTests.cs new file mode 100644 index 0000000000000..8002e260998d2 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/EnumTests.cs @@ -0,0 +1,117 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Runtime.InteropServices; + +using Xunit; + +namespace DllImportGenerator.IntegrationTests +{ + partial class NativeExportsNE + { + public partial class IntEnum + { + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "subtract_return_int")] + public static partial EnumTests.IntEnum Subtract_Return(EnumTests.IntEnum a, EnumTests.IntEnum b); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "subtract_out_int")] + public static partial void Subtract_Out(EnumTests.IntEnum a, EnumTests.IntEnum b, out EnumTests.IntEnum c); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "subtract_ref_int")] + public static partial void Subtract_Ref(EnumTests.IntEnum a, ref EnumTests.IntEnum b); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "subtract_ref_int")] + public static partial void Subtract_In(EnumTests.IntEnum a, in EnumTests.IntEnum b); + } + + public partial class ByteEnum + { + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "subtract_return_byte")] + public static partial EnumTests.ByteEnum Subtract_Return(EnumTests.ByteEnum a, EnumTests.ByteEnum b); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "subtract_out_byte")] + public static partial void Subtract_Out(EnumTests.ByteEnum a, EnumTests.ByteEnum b, out EnumTests.ByteEnum c); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "subtract_ref_byte")] + public static partial void Subtract_Ref(EnumTests.ByteEnum a, ref EnumTests.ByteEnum b); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "subtract_ref_byte")] + public static partial void Subtract_In(EnumTests.ByteEnum a, in EnumTests.ByteEnum b); + } + } + + public class EnumTests + { + internal enum IntEnum + { + Zero, + One, + Two, + Three, + Max = int.MaxValue + } + + internal enum ByteEnum : byte + { + Zero, + One, + Two, + Three, + Max = byte.MaxValue + } + + [Fact] + public void EnumByValue() + { + { + IntEnum ret = NativeExportsNE.IntEnum.Subtract_Return(IntEnum.Max, IntEnum.Zero); + Assert.Equal(IntEnum.Max, ret); + } + { + ByteEnum ret = NativeExportsNE.ByteEnum.Subtract_Return(ByteEnum.Max, ByteEnum.Zero); + Assert.Equal(ByteEnum.Max, ret); + } + } + + [Fact] + public void EnumByRef() + { + { + IntEnum a = IntEnum.Three; + IntEnum b = IntEnum.Two; + IntEnum expected = IntEnum.One; + + IntEnum ret; + NativeExportsNE.IntEnum.Subtract_Out(a, b, out ret); + Assert.Equal(expected, ret); + + IntEnum refValue = b; + NativeExportsNE.IntEnum.Subtract_In(a, in refValue); + Assert.Equal(expected, refValue); // Value is updated even when passed with in keyword (matches built-in system) + + refValue = b; + NativeExportsNE.IntEnum.Subtract_Ref(a, ref refValue); + Assert.Equal(expected, refValue); + } + + { + ByteEnum a = ByteEnum.Three; + ByteEnum b = ByteEnum.Two; + ByteEnum expected = ByteEnum.One; + + ByteEnum ret; + NativeExportsNE.ByteEnum.Subtract_Out(a, b, out ret); + Assert.Equal(expected, ret); + + ByteEnum refValue = b; + NativeExportsNE.ByteEnum.Subtract_In(a, in refValue); + Assert.Equal(expected, refValue); // Value is updated even when passed with in keyword (matches built-in system) + + refValue = b; + NativeExportsNE.ByteEnum.Subtract_Ref(a, ref refValue); + Assert.Equal(expected, refValue); + } + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/FunctionPointerTests.cs b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/FunctionPointerTests.cs new file mode 100644 index 0000000000000..87332f16e2d67 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/FunctionPointerTests.cs @@ -0,0 +1,119 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +using Xunit; + +namespace DllImportGenerator.IntegrationTests +{ + partial class NativeExportsNE + { + public partial class FunctionPointer + { + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "invoke_managed_callback_after_gc")] + public static unsafe partial void InvokeAfterGC(delegate* cb); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "invoke_callback_after_gc")] + public static unsafe partial void InvokeAfterGC(delegate* unmanaged cb); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "invoke_callback_after_gc")] + public static unsafe partial void InvokeAfterGC(delegate* unmanaged[Stdcall] cb); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "invoke_managed_callback_blittable_args")] + public static unsafe partial int InvokeWithBlittableArgument(delegate* cb, int a, int b); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "invoke_callback_blittable_args")] + public static unsafe partial int InvokeWithBlittableArgument(delegate* unmanaged cb, int a, int b); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "invoke_callback_blittable_args")] + public static unsafe partial int InvokeWithBlittableArgument(delegate* unmanaged[Stdcall] cb, int a, int b); + } + } + + public class FunctionPointerTests + { + private static bool wasCalled; + + [Fact] + public unsafe void InvokedAfterGC() + { + wasCalled = false; + NativeExportsNE.FunctionPointer.InvokeAfterGC(&Callback); + Assert.True(wasCalled); + + wasCalled = false; + NativeExportsNE.FunctionPointer.InvokeAfterGC(&CallbackUnmanaged); + Assert.True(wasCalled); + + wasCalled = false; + NativeExportsNE.FunctionPointer.InvokeAfterGC(&CallbackUnmanagedStdcall); + Assert.True(wasCalled); + + static void Callback() + { + wasCalled = true; + } + + [UnmanagedCallersOnly] + static void CallbackUnmanaged() + { + wasCalled = true; + } + + [UnmanagedCallersOnly(CallConvs = new Type[] { typeof(CallConvStdcall) })] + static void CallbackUnmanagedStdcall() + { + wasCalled = true; + } + } + + [Fact] + public unsafe void CalledWithArgumentsInOrder() + { + const int a = 100; + const int b = 50; + int result; + + int expected = Callback(a, b); + result = NativeExportsNE.FunctionPointer.InvokeWithBlittableArgument(&Callback, a, b); + Assert.Equal(expected, result); + + result = NativeExportsNE.FunctionPointer.InvokeWithBlittableArgument(&CallbackUnmanaged, a, b); + Assert.Equal(expected, result); + + result = NativeExportsNE.FunctionPointer.InvokeWithBlittableArgument(&CallbackUnmanagedStdcall, a, b); + Assert.Equal(expected, result); + + expected = Callback(b, a); + result = NativeExportsNE.FunctionPointer.InvokeWithBlittableArgument(&Callback, b, a); + Assert.Equal(expected, result); + + result = NativeExportsNE.FunctionPointer.InvokeWithBlittableArgument(&CallbackUnmanaged, b, a); + Assert.Equal(expected, result); + + result = NativeExportsNE.FunctionPointer.InvokeWithBlittableArgument(&CallbackUnmanagedStdcall, b, a); + Assert.Equal(expected, result); + + static int Callback(int a, int b) + { + // Use a noncommutative operation to validate passed in order. + return a - b; + } + + [UnmanagedCallersOnly] + static int CallbackUnmanaged(int a, int b) + { + return Callback(a, b); + } + + [UnmanagedCallersOnly(CallConvs = new Type[] { typeof(CallConvStdcall) })] + static int CallbackUnmanagedStdcall(int a, int b) + { + return Callback(a, b); + } + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/PointerTests.cs b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/PointerTests.cs new file mode 100644 index 0000000000000..463ea434d3606 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/PointerTests.cs @@ -0,0 +1,69 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.InteropServices; + +using SharedTypes; + +using Xunit; + +namespace DllImportGenerator.IntegrationTests +{ + partial class NativeExportsNE + { + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "subtract_ref_int")] + public static unsafe partial void Subtract_Int_Ptr(int a, int* b); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "subtract_ref_byte")] + public static unsafe partial void Subtract_Byte_Ptr(byte a, byte* b); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "blittablestructs_double_intfields_byref")] + public static unsafe partial void DoubleIntFields_Ptr(IntFields* result); + } + + public class PointerTests + { + [Fact] + public unsafe void BlittablePrimitive() + { + { + int a = int.MaxValue; + int b = 10; + int expected = a - b; + NativeExportsNE.Subtract_Int_Ptr(a, &b); + Assert.Equal(expected, b); + } + { + byte a = byte.MaxValue; + byte b = 10; + byte expected = (byte)(a - b); + NativeExportsNE.Subtract_Byte_Ptr(a, &b); + Assert.Equal(expected, b); + } + } + + [Fact] + public unsafe void BlittableStruct() + { + const int A = 24, B = 37, C = 59; + var initial = new IntFields() + { + a = A, + b = B, + c = C, + }; + var expected = new IntFields() + { + a = initial.a * 2, + b = initial.b * 2, + c = initial.c * 2, + }; + + var input = initial; + { + NativeExportsNE.DoubleIntFields_Ptr(&input); + Assert.Equal(expected, input); + } + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/PreserveSigTests.cs b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/PreserveSigTests.cs new file mode 100644 index 0000000000000..ee1f351e66f9f --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/PreserveSigTests.cs @@ -0,0 +1,267 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.InteropServices; + +using Xunit; + +namespace DllImportGenerator.IntegrationTests +{ + partial class NativeExportsNE + { + public partial class PreserveSig + { + public partial class False + { + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "hresult_return", PreserveSig = false)] + public static partial void NoReturnValue(int i); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "hresult_out_int", PreserveSig = false)] + public static partial void Int_Out(int i, out int ret); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "hresult_out_int", PreserveSig = false)] + public static partial int Int_AsReturn(int i); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "hresult_out_int", PreserveSig = false)] + public static partial void Bool_Out(int i, [MarshalAs(UnmanagedType.U4)] out bool ret); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "hresult_out_int", PreserveSig = false)] + [return: MarshalAs(UnmanagedType.U4)] + public static partial bool Bool_AsReturn(int i); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "hresult_out_ushort", PreserveSig = false)] + public static partial void Char_Out(int i, [MarshalAs(UnmanagedType.U2)] out char ret); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "hresult_out_ushort", PreserveSig = false)] + [return: MarshalAs(UnmanagedType.U2)] + public static partial char Char_AsReturn(int i); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "hresult_out_ushort_string", PreserveSig = false)] + public static partial void String_Out(int i, [MarshalAs(UnmanagedType.LPWStr)] out string ret); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "hresult_out_ushort_string", PreserveSig = false)] + [return: MarshalAs(UnmanagedType.LPWStr)] + public static partial string String_AsReturn(int i); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "hresult_out_int_array", PreserveSig = false)] + public static partial void IntArray_Out(int i, [MarshalAs(UnmanagedType.LPArray, SizeConst = sizeof(int))] out int[] ret); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "hresult_out_int_array", PreserveSig = false)] + [return: MarshalAs(UnmanagedType.LPArray, SizeConst = sizeof(int))] + public static partial int[] IntArray_AsReturn(int i); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "hresult_out_ushort_string_array", PreserveSig = false)] + public static partial void StringArray_Out(int i, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeConst = sizeof(int))] out string[] ret); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "hresult_out_ushort_string_array", PreserveSig = false)] + [return: MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr, SizeConst = sizeof(int))] + public static partial string[] StringArray_AsReturn(int i); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "hresult_out_handle", PreserveSig = false)] + public static partial void SafeHandle_Out(int hr, out DummySafeHandle ret); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "hresult_out_handle", PreserveSig = false)] + public static partial DummySafeHandle SafeHandle_AsReturn(int hr); + + } + + public class DummySafeHandle : Microsoft.Win32.SafeHandles.SafeHandleMinusOneIsInvalid + { + private DummySafeHandle() : base(ownsHandle: true) { } + protected override bool ReleaseHandle() => true; + } + + public partial class True + { + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "hresult_return", PreserveSig = true)] + public static partial int NoReturnValue(int i); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "hresult_out_int", PreserveSig = true)] + public static partial int Int_Out(int i, out int ret); + } + } + } + + public class PreserveSigTests + { + private const int E_INVALIDARG = unchecked((int)0x80070057); + private const int COR_E_NOTSUPPORTED = unchecked((int)0x80131515); + private const int S_OK = 0; + private const int S_FALSE = 1; + + [Theory] + [InlineData(E_INVALIDARG)] + [InlineData(COR_E_NOTSUPPORTED)] + [InlineData(-1)] + public void PreserveSigFalse_Error(int input) + { + Exception exception = Marshal.GetExceptionForHR(input); + Assert.NotNull(exception); + + int expectedHR = input; + var exceptionType = exception.GetType(); + Assert.Equal(expectedHR, exception.HResult); + Exception ex; + + ex = Assert.Throws(exceptionType, () => NativeExportsNE.PreserveSig.False.NoReturnValue(input)); + Assert.Equal(expectedHR, ex.HResult); + + { + ex = Assert.Throws(exceptionType, () => NativeExportsNE.PreserveSig.False.Int_Out(input, out int ret)); + Assert.Equal(expectedHR, ex.HResult); + + ex = Assert.Throws(exceptionType, () => NativeExportsNE.PreserveSig.False.Int_AsReturn(input)); + Assert.Equal(expectedHR, ex.HResult); + } + { + ex = Assert.Throws(exceptionType, () => NativeExportsNE.PreserveSig.False.Bool_Out(input, out bool ret)); + Assert.Equal(expectedHR, ex.HResult); + + ex = Assert.Throws(exceptionType, () => NativeExportsNE.PreserveSig.False.Bool_AsReturn(input)); + Assert.Equal(expectedHR, ex.HResult); + } + { + ex = Assert.Throws(exceptionType, () => NativeExportsNE.PreserveSig.False.Char_Out(input, out char ret)); + Assert.Equal(expectedHR, ex.HResult); + + ex = Assert.Throws(exceptionType, () => NativeExportsNE.PreserveSig.False.Char_AsReturn(input)); + Assert.Equal(expectedHR, ex.HResult); + } + { + ex = Assert.Throws(exceptionType, () => NativeExportsNE.PreserveSig.False.String_Out(input, out string ret)); + Assert.Equal(expectedHR, ex.HResult); + + ex = Assert.Throws(exceptionType, () => NativeExportsNE.PreserveSig.False.String_AsReturn(input)); + Assert.Equal(expectedHR, ex.HResult); + } + { + ex = Assert.Throws(exceptionType, () => NativeExportsNE.PreserveSig.False.IntArray_Out(input, out int[] ret)); + Assert.Equal(expectedHR, ex.HResult); + + ex = Assert.Throws(exceptionType, () => NativeExportsNE.PreserveSig.False.IntArray_AsReturn(input)); + Assert.Equal(expectedHR, ex.HResult); + } + { + ex = Assert.Throws(exceptionType, () => NativeExportsNE.PreserveSig.False.StringArray_Out(input, out string[] ret)); + Assert.Equal(expectedHR, ex.HResult); + + ex = Assert.Throws(exceptionType, () => NativeExportsNE.PreserveSig.False.StringArray_AsReturn(input)); + Assert.Equal(expectedHR, ex.HResult); + } + { + ex = Assert.Throws(exceptionType, () => NativeExportsNE.PreserveSig.False.SafeHandle_Out(input, out NativeExportsNE.PreserveSig.DummySafeHandle ret)); + Assert.Equal(expectedHR, ex.HResult); + + ex = Assert.Throws(exceptionType, () => NativeExportsNE.PreserveSig.False.SafeHandle_AsReturn(input)); + Assert.Equal(expectedHR, ex.HResult); + } + } + + [Theory] + [InlineData(S_OK)] + [InlineData(S_FALSE)] + [InlineData(10)] + public void PreserveSigFalse_Success(int input) + { + Assert.True(input >= 0); + + NativeExportsNE.PreserveSig.False.NoReturnValue(input); + + { + int expected = input; + + int ret; + NativeExportsNE.PreserveSig.False.Int_Out(input, out ret); + Assert.Equal(expected, ret); + + ret = NativeExportsNE.PreserveSig.False.Int_AsReturn(input); + Assert.Equal(expected, ret); + } + { + bool expected = input != 0; + + bool ret; + NativeExportsNE.PreserveSig.False.Bool_Out(input, out ret); + Assert.Equal(expected, ret); + + ret = NativeExportsNE.PreserveSig.False.Bool_AsReturn(input); + Assert.Equal(expected, ret); + } + { + char expected = (char)input; + + char ret; + NativeExportsNE.PreserveSig.False.Char_Out(input, out ret); + Assert.Equal(expected, ret); + + ret = NativeExportsNE.PreserveSig.False.Char_AsReturn(input); + Assert.Equal(expected, ret); + } + { + string expected = input.ToString(); + + string ret; + NativeExportsNE.PreserveSig.False.String_Out(input, out ret); + Assert.Equal(expected, ret); + + ret = NativeExportsNE.PreserveSig.False.String_AsReturn(input); + Assert.Equal(expected, ret); + } + { + int[] expected = new int[sizeof(int)]; + Array.Fill(expected, input); + + int[] ret; + NativeExportsNE.PreserveSig.False.IntArray_Out(input, out ret); + Assert.Equal(expected, ret); + + ret = NativeExportsNE.PreserveSig.False.IntArray_AsReturn(input); + Assert.Equal(expected, ret); + } + { + string[] expected = new string[sizeof(int)]; + Array.Fill(expected, input.ToString()); + + string[] ret; + NativeExportsNE.PreserveSig.False.StringArray_Out(input, out ret); + Assert.Equal(expected, ret); + + ret = NativeExportsNE.PreserveSig.False.StringArray_AsReturn(input); + Assert.Equal(expected, ret); + } + { + nint expected = input; + + NativeExportsNE.PreserveSig.DummySafeHandle ret; + NativeExportsNE.PreserveSig.False.SafeHandle_Out(input, out ret); + Assert.Equal(expected, (nint)ret.DangerousGetHandle()); + ret.Dispose(); + + ret = NativeExportsNE.PreserveSig.False.SafeHandle_AsReturn(input); + Assert.Equal(expected, (nint)ret.DangerousGetHandle()); + ret.Dispose(); + } + } + + [Theory] + [InlineData(S_OK)] + [InlineData(S_FALSE)] + [InlineData(E_INVALIDARG)] + [InlineData(COR_E_NOTSUPPORTED)] + [InlineData(-1)] + public void PreserveSigTrue(int input) + { + int expected = input; + int hr; + + hr = NativeExportsNE.PreserveSig.True.NoReturnValue(input); + Assert.Equal(expected, hr); + + int ret; + hr = NativeExportsNE.PreserveSig.True.Int_Out(input, out ret); + Assert.Equal(expected, hr); + Assert.Equal(expected, ret); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/SafeHandleTests.cs b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/SafeHandleTests.cs new file mode 100644 index 0000000000000..96c21224e9d95 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/SafeHandleTests.cs @@ -0,0 +1,104 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.InteropServices; + +using Microsoft.Win32.SafeHandles; +using Xunit; + +namespace DllImportGenerator.IntegrationTests +{ + partial class NativeExportsNE + { + public partial class NativeExportsSafeHandle : SafeHandleZeroOrMinusOneIsInvalid + { + private NativeExportsSafeHandle() : base(ownsHandle: true) + { } + + protected override bool ReleaseHandle() + { + bool didRelease = NativeExportsNE.ReleaseHandle(handle); + Assert.True(didRelease); + return didRelease; + } + + public static NativeExportsSafeHandle CreateNewHandle() => AllocateHandle(); + + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "alloc_handle")] + private static partial NativeExportsSafeHandle AllocateHandle(); + } + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "alloc_handle")] + public static partial NativeExportsSafeHandle AllocateHandle(); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "alloc_handle_out")] + public static partial void AllocateHandle(out NativeExportsSafeHandle handle); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "release_handle")] + [return:MarshalAs(UnmanagedType.I1)] + private static partial bool ReleaseHandle(nint handle); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "is_handle_alive")] + [return:MarshalAs(UnmanagedType.I1)] + public static partial bool IsHandleAlive(NativeExportsSafeHandle handle); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "modify_handle")] + public static partial void ModifyHandle(ref NativeExportsSafeHandle handle, [MarshalAs(UnmanagedType.I1)] bool newHandle); + } + + public class SafeHandleTests + { + [Fact] + public void ReturnValue_CreatesSafeHandle() + { + using NativeExportsNE.NativeExportsSafeHandle handle = NativeExportsNE.AllocateHandle(); + Assert.False(handle.IsClosed); + Assert.False(handle.IsInvalid); + } + + [Fact] + public void ReturnValue_CreatesSafeHandle_DirectConstructorCall() + { + using NativeExportsNE.NativeExportsSafeHandle handle = NativeExportsNE.NativeExportsSafeHandle.CreateNewHandle(); + Assert.False(handle.IsClosed); + Assert.False(handle.IsInvalid); + } + + [Fact] + public void ByValue_CorrectlyUnwrapsHandle() + { + using NativeExportsNE.NativeExportsSafeHandle handle = NativeExportsNE.AllocateHandle(); + Assert.True(NativeExportsNE.IsHandleAlive(handle)); + } + + [Fact] + public void ByRefOut_CreatesSafeHandle() + { + NativeExportsNE.NativeExportsSafeHandle handle; + NativeExportsNE.AllocateHandle(out handle); + Assert.False(handle.IsClosed); + Assert.False(handle.IsInvalid); + handle.Dispose(); + } + + [Fact] + public void ByRefSameValue_UsesSameHandleInstance() + { + using NativeExportsNE.NativeExportsSafeHandle handleToDispose = NativeExportsNE.AllocateHandle(); + NativeExportsNE.NativeExportsSafeHandle handle = handleToDispose; + NativeExportsNE.ModifyHandle(ref handle, newHandle: false); + Assert.Same(handleToDispose, handle); + } + + [Fact] + public void ByRefDifferentValue_UsesNewHandleInstance() + { + using NativeExportsNE.NativeExportsSafeHandle handleToDispose = NativeExportsNE.AllocateHandle(); + NativeExportsNE.NativeExportsSafeHandle handle = handleToDispose; + NativeExportsNE.ModifyHandle(ref handle, newHandle: true); + Assert.NotSame(handleToDispose, handle); + handle.Dispose(); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/SetLastErrorTests.cs b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/SetLastErrorTests.cs new file mode 100644 index 0000000000000..4f05e0e568e88 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/SetLastErrorTests.cs @@ -0,0 +1,98 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.InteropServices; + +using Xunit; + +namespace DllImportGenerator.IntegrationTests +{ + [BlittableType] + public struct SetLastErrorMarshaller + { + public int val; + + public SetLastErrorMarshaller(int i) + { + val = i; + } + + public int ToManaged() + { + // Explicity set the last error to something else on unmarshalling + Marshal.SetLastPInvokeError(val * 2); + return val; + } + } + + partial class NativeExportsNE + { + public partial class SetLastError + { + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "set_error", SetLastError = true)] + public static partial int SetError(int error, byte shouldSetError); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "set_error", SetLastError = true)] + [return: MarshalUsing(typeof(SetLastErrorMarshaller))] + public static partial int SetError_CustomMarshallingSetsError(int error, byte shouldSetError); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "set_error_return_string", SetLastError = true)] + [return: MarshalAs(UnmanagedType.LPWStr)] + public static partial string SetError_NonBlittableSignature(int error, [MarshalAs(UnmanagedType.U1)] bool shouldSetError, [MarshalAs(UnmanagedType.LPWStr)] string errorString); + } + } + + public class SetLastErrorTests + { + [Theory] + [InlineData(0)] + [InlineData(2)] + [InlineData(-5)] + public void LastWin32Error_HasExpectedValue(int error) + { + string errorString = error.ToString(); + string ret = NativeExportsNE.SetLastError.SetError_NonBlittableSignature(error, shouldSetError: true, errorString); + Assert.Equal(error, Marshal.GetLastWin32Error()); + Assert.Equal(errorString, ret); + + // Clear the last error + Marshal.SetLastPInvokeError(0); + + NativeExportsNE.SetLastError.SetError(error, shouldSetError: 1); + Assert.Equal(error, Marshal.GetLastWin32Error()); + + Marshal.SetLastPInvokeError(0); + + // Custom marshalling sets the last error on unmarshalling. + // Last error should reflect error from native call, not unmarshalling. + NativeExportsNE.SetLastError.SetError_CustomMarshallingSetsError(error, shouldSetError: 1); + Assert.Equal(error, Marshal.GetLastWin32Error()); + } + + [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/60271", TestRuntimes.Mono)] + public void ClearPreviousError() + { + int error = 100; + Marshal.SetLastPInvokeError(error); + + // Don't actually set the error in the native call. SetLastError=true should clear any existing error. + string errorString = error.ToString(); + string ret = NativeExportsNE.SetLastError.SetError_NonBlittableSignature(error, shouldSetError: false, errorString); + Assert.Equal(0, Marshal.GetLastWin32Error()); + Assert.Equal(errorString, ret); + + Marshal.SetLastPInvokeError(error); + + // Don't actually set the error in the native call. SetLastError=true should clear any existing error. + NativeExportsNE.SetLastError.SetError(error, shouldSetError: 0); + Assert.Equal(0, Marshal.GetLastWin32Error()); + + // Don't actually set the error in the native call. Custom marshalling still sets the last error. + // SetLastError=true should clear any existing error and ignore error set by custom marshalling. + NativeExportsNE.SetLastError.SetError_CustomMarshallingSetsError(error, shouldSetError: 0); + Assert.Equal(0, Marshal.GetLastWin32Error()); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/SpanTests.cs b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/SpanTests.cs new file mode 100644 index 0000000000000..ad61c89cf0dcd --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/SpanTests.cs @@ -0,0 +1,163 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using SharedTypes; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.GeneratedMarshalling; +using System.Text; + +using Xunit; + +namespace DllImportGenerator.IntegrationTests +{ + partial class NativeExportsNE + { + public partial class Span + { + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "sum_int_array")] + public static partial int Sum([MarshalUsing(typeof(SpanMarshaller))] Span values, int numValues); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "sum_int_array")] + public static partial int SumNeverNull([MarshalUsing(typeof(NeverNullSpanMarshaller))] Span values, int numValues); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "sum_int_array")] + public static partial int SumNeverNull([MarshalUsing(typeof(NeverNullReadOnlySpanMarshaller))] ReadOnlySpan values, int numValues); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "sum_int_array_ref")] + public static partial int SumInArray([MarshalUsing(typeof(SpanMarshaller))] in Span values, int numValues); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "duplicate_int_array")] + public static partial void Duplicate([MarshalUsing(typeof(SpanMarshaller), CountElementName = "numValues")] ref Span values, int numValues); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "duplicate_int_array")] + public static partial void DuplicateRaw([MarshalUsing(typeof(DirectSpanMarshaller), CountElementName = "numValues")] ref Span values, int numValues); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "create_range_array")] + [return: MarshalUsing(typeof(SpanMarshaller), CountElementName = "numValues")] + public static partial Span CreateRange(int start, int end, out int numValues); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "create_range_array_out")] + public static partial void CreateRange_Out(int start, int end, out int numValues, [MarshalUsing(typeof(SpanMarshaller), CountElementName = "numValues")] out Span res); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "get_long_bytes")] + [return: MarshalUsing(typeof(SpanMarshaller), ConstantElementCount = sizeof(long))] + public static partial Span GetLongBytes(long l); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "and_all_members")] + [return: MarshalAs(UnmanagedType.U1)] + public static partial bool AndAllMembers([MarshalUsing(typeof(SpanMarshaller))] Span pArray, int length); + } + } + + public class SpanTests + { + [Fact] + public void BlittableElementSpanMarshalledToNativeAsExpected() + { + var list = new int[] { 1, 5, 79, 165, 32, 3 }; + Assert.Equal(list.Sum(), NativeExportsNE.Span.Sum(list, list.Length)); + } + + [Fact] + public void DefaultBlittableElementSpanMarshalledToNativeAsExpected() + { + Assert.Equal(-1, NativeExportsNE.Span.Sum(default, 0)); + } + + [Fact] + public void NeverNullSpanMarshallerMarshalsDefaultAsNonNull() + { + Assert.Equal(0, NativeExportsNE.Span.SumNeverNull(Span.Empty, 0)); + } + + [Fact] + public void NeverNullReadOnlySpanMarshallerMarshalsDefaultAsNonNull() + { + Assert.Equal(0, NativeExportsNE.Span.SumNeverNull(ReadOnlySpan.Empty, 0)); + } + + [Fact] + public void BlittableElementSpanInParameter() + { + var list = new int[] { 1, 5, 79, 165, 32, 3 }; + Assert.Equal(list.Sum(), NativeExportsNE.Span.SumInArray(list, list.Length)); + } + + [Fact] + public void BlittableElementSpanRefParameter() + { + var list = new int[] { 1, 5, 79, 165, 32, 3 }; + Span newSpan = list; + NativeExportsNE.Span.Duplicate(ref newSpan, list.Length); + Assert.Equal((IEnumerable)list, newSpan.ToArray()); + } + + [Fact] + public unsafe void DirectSpanMarshaller() + { + var list = new int[] { 1, 5, 79, 165, 32, 3 }; + Span newSpan = list; + NativeExportsNE.Span.DuplicateRaw(ref newSpan, list.Length); + Assert.Equal((IEnumerable)list, newSpan.ToArray()); + Marshal.FreeCoTaskMem((IntPtr)Unsafe.AsPointer(ref newSpan.GetPinnableReference())); + } + + [Fact] + public void BlittableElementSpanReturnedFromNative() + { + int start = 5; + int end = 20; + + IEnumerable expected = Enumerable.Range(start, end - start); + Assert.Equal(expected, NativeExportsNE.Collections.CreateRange(start, end, out _)); + + Span res; + NativeExportsNE.Span.CreateRange_Out(start, end, out _, out res); + Assert.Equal(expected, res.ToArray()); + } + + [Fact] + public void NullBlittableElementSpanReturnedFromNative() + { + Assert.Null(NativeExportsNE.Collections.CreateRange(1, 0, out _)); + + Span res; + NativeExportsNE.Span.CreateRange_Out(1, 0, out _, out res); + Assert.True(res.IsEmpty); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void SpanWithSimpleNonBlittableTypeMarshalling(bool result) + { + var boolValues = new BoolStruct[] + { + new BoolStruct + { + b1 = true, + b2 = true, + b3 = true, + }, + new BoolStruct + { + b1 = true, + b2 = true, + b3 = true, + }, + new BoolStruct + { + b1 = true, + b2 = true, + b3 = result, + }, + }; + + Assert.Equal(result, NativeExportsNE.Span.AndAllMembers(boolValues, boolValues.Length)); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/StringTests.cs b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/StringTests.cs new file mode 100644 index 0000000000000..db99bf81a8bc1 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.Tests/StringTests.cs @@ -0,0 +1,567 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Text; + +using Xunit; + +namespace DllImportGenerator.IntegrationTests +{ + partial class NativeExportsNE + { + private class EntryPoints + { + private const string ReturnLength = "return_length"; + private const string ReverseReturn = "reverse_return"; + private const string ReverseOut = "reverse_out"; + private const string ReverseInplace = "reverse_inplace_ref"; + private const string ReverseReplace = "reverse_replace_ref"; + + private const string UShortSuffix = "_ushort"; + private const string ByteSuffix = "_byte"; + + public class Byte + { + public const string ReturnLength = EntryPoints.ReturnLength + ByteSuffix; + public const string ReverseReturn = EntryPoints.ReverseReturn + ByteSuffix; + public const string ReverseOut = EntryPoints.ReverseOut + ByteSuffix; + public const string ReverseInplace = EntryPoints.ReverseInplace + ByteSuffix; + public const string ReverseReplace = EntryPoints.ReverseReplace + ByteSuffix; + } + + public class UShort + { + public const string ReturnLength = EntryPoints.ReturnLength + UShortSuffix; + public const string ReverseReturn = EntryPoints.ReverseReturn + UShortSuffix; + public const string ReverseOut = EntryPoints.ReverseOut + UShortSuffix; + public const string ReverseInplace = EntryPoints.ReverseInplace + UShortSuffix; + public const string ReverseReplace = EntryPoints.ReverseReplace + UShortSuffix; + } + } + + public partial class Unicode + { + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.UShort.ReturnLength, CharSet = CharSet.Unicode)] + public static partial int ReturnLength(string s); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.UShort.ReverseReturn, CharSet = CharSet.Unicode)] + public static partial string Reverse_Return(string s); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.UShort.ReverseOut, CharSet = CharSet.Unicode)] + public static partial void Reverse_Out(string s, out string ret); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.UShort.ReverseInplace, CharSet = CharSet.Unicode)] + public static partial void Reverse_Ref(ref string s); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.UShort.ReverseInplace, CharSet = CharSet.Unicode)] + public static partial void Reverse_In(in string s); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.UShort.ReverseReplace, CharSet = CharSet.Unicode)] + public static partial void Reverse_Replace_Ref(ref string s); + } + + public partial class LPTStr + { + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.UShort.ReturnLength)] + public static partial int ReturnLength([MarshalAs(UnmanagedType.LPTStr)] string s); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.UShort.ReturnLength, CharSet = CharSet.None)] + public static partial int ReturnLength_IgnoreCharSet([MarshalAs(UnmanagedType.LPTStr)] string s); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.UShort.ReverseReturn)] + [return: MarshalAs(UnmanagedType.LPTStr)] + public static partial string Reverse_Return([MarshalAs(UnmanagedType.LPTStr)] string s); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.UShort.ReverseOut)] + public static partial void Reverse_Out([MarshalAs(UnmanagedType.LPTStr)] string s, [MarshalAs(UnmanagedType.LPTStr)] out string ret); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.UShort.ReverseInplace)] + public static partial void Reverse_Ref([MarshalAs(UnmanagedType.LPTStr)] ref string s); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.UShort.ReverseInplace)] + public static partial void Reverse_In([MarshalAs(UnmanagedType.LPTStr)] in string s); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.UShort.ReverseInplace)] + public static partial void Reverse_Replace_Ref([MarshalAs(UnmanagedType.LPTStr)] ref string s); + } + + public partial class LPWStr + { + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.UShort.ReturnLength)] + public static partial int ReturnLength([MarshalAs(UnmanagedType.LPWStr)] string s); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.UShort.ReturnLength, CharSet = CharSet.None)] + public static partial int ReturnLength_IgnoreCharSet([MarshalAs(UnmanagedType.LPWStr)] string s); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.UShort.ReverseReturn)] + [return: MarshalAs(UnmanagedType.LPWStr)] + public static partial string Reverse_Return([MarshalAs(UnmanagedType.LPWStr)] string s); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.UShort.ReverseOut)] + public static partial void Reverse_Out([MarshalAs(UnmanagedType.LPWStr)] string s, [MarshalAs(UnmanagedType.LPWStr)] out string ret); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.UShort.ReverseInplace)] + public static partial void Reverse_Ref([MarshalAs(UnmanagedType.LPWStr)] ref string s); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.UShort.ReverseInplace)] + public static partial void Reverse_In([MarshalAs(UnmanagedType.LPWStr)] in string s); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.UShort.ReverseInplace)] + public static partial void Reverse_Replace_Ref([MarshalAs(UnmanagedType.LPWStr)] ref string s); + } + + public partial class LPUTF8Str + { + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.Byte.ReturnLength)] + public static partial int ReturnLength([MarshalAs(UnmanagedType.LPUTF8Str)] string s); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.Byte.ReturnLength, CharSet = CharSet.None)] + public static partial int ReturnLength_IgnoreCharSet([MarshalAs(UnmanagedType.LPUTF8Str)] string s); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.Byte.ReverseReturn)] + [return: MarshalAs(UnmanagedType.LPUTF8Str)] + public static partial string Reverse_Return([MarshalAs(UnmanagedType.LPUTF8Str)] string s); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.Byte.ReverseOut)] + public static partial void Reverse_Out([MarshalAs(UnmanagedType.LPUTF8Str)] string s, [MarshalAs(UnmanagedType.LPUTF8Str)] out string ret); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.Byte.ReverseInplace)] + public static partial void Reverse_In([MarshalAs(UnmanagedType.LPUTF8Str)] in string s); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.Byte.ReverseInplace)] + public static partial void Reverse_Ref([MarshalAs(UnmanagedType.LPUTF8Str)] ref string s); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.Byte.ReverseInplace)] + public static partial void Reverse_Replace_Ref([MarshalAs(UnmanagedType.LPUTF8Str)] ref string s); + } + + public partial class Ansi + { + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.Byte.ReturnLength, CharSet = CharSet.Ansi)] + public static partial int ReturnLength(string s); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.Byte.ReverseReturn, CharSet = CharSet.Ansi)] + public static partial string Reverse_Return(string s); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.Byte.ReverseOut, CharSet = CharSet.Ansi)] + public static partial void Reverse_Out(string s, out string ret); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.Byte.ReverseInplace, CharSet = CharSet.Ansi)] + public static partial void Reverse_Ref(ref string s); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.Byte.ReverseInplace, CharSet = CharSet.Ansi)] + public static partial void Reverse_In(in string s); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.Byte.ReverseInplace, CharSet = CharSet.Ansi)] + public static partial void Reverse_Replace_Ref(ref string s); + } + + public partial class LPStr + { + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.Byte.ReturnLength)] + public static partial int ReturnLength([MarshalAs(UnmanagedType.LPStr)] string s); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.Byte.ReturnLength, CharSet = CharSet.None)] + public static partial int ReturnLength_IgnoreCharSet([MarshalAs(UnmanagedType.LPStr)] string s); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.Byte.ReverseReturn)] + [return: MarshalAs(UnmanagedType.LPStr)] + public static partial string Reverse_Return([MarshalAs(UnmanagedType.LPStr)] string s); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.Byte.ReverseOut)] + public static partial void Reverse_Out([MarshalAs(UnmanagedType.LPStr)] string s, [MarshalAs(UnmanagedType.LPStr)] out string ret); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.Byte.ReverseInplace)] + public static partial void Reverse_Ref([MarshalAs(UnmanagedType.LPStr)] ref string s); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.Byte.ReverseInplace)] + public static partial void Reverse_In([MarshalAs(UnmanagedType.LPStr)] in string s); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.Byte.ReverseInplace)] + public static partial void Reverse_Replace_Ref([MarshalAs(UnmanagedType.LPStr)] ref string s); + } + + public partial class Auto + { + public partial class Unix + { + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.Byte.ReturnLength, CharSet = CharSet.Auto)] + public static partial int ReturnLength(string s); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.Byte.ReverseReturn, CharSet = CharSet.Auto)] + public static partial string Reverse_Return(string s); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.Byte.ReverseOut, CharSet = CharSet.Auto)] + public static partial void Reverse_Out(string s, out string ret); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.Byte.ReverseInplace, CharSet = CharSet.Auto)] + public static partial void Reverse_Ref(ref string s); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.Byte.ReverseInplace, CharSet = CharSet.Auto)] + public static partial void Reverse_In(in string s); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.Byte.ReverseInplace, CharSet = CharSet.Auto)] + public static partial void Reverse_Replace_Ref(ref string s); + } + + public partial class Windows + { + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.UShort.ReturnLength, CharSet = CharSet.Auto)] + public static partial int ReturnLength(string s); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.UShort.ReverseReturn, CharSet = CharSet.Auto)] + public static partial string Reverse_Return(string s); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.UShort.ReverseOut, CharSet = CharSet.Auto)] + public static partial void Reverse_Out(string s, out string ret); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.UShort.ReverseInplace, CharSet = CharSet.Auto)] + public static partial void Reverse_Ref(ref string s); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.UShort.ReverseInplace, CharSet = CharSet.Auto)] + public static partial void Reverse_In(in string s); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = EntryPoints.UShort.ReverseInplace, CharSet = CharSet.Auto)] + public static partial void Reverse_Replace_Ref(ref string s); + } + } + } + + public class StringTests + { + public static IEnumerable UnicodeStrings() => new [] + { + new object[] { "ABCdef 123$%^" }, + new object[] { "🍜 !! 🍜 !!"}, + new object[] { "🌲 木 🔥 火 🌾 土 🛡 金 🌊 水" }, + new object[] { "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vitae posuere mauris, sed ultrices leo. Suspendisse potenti. Mauris enim enim, blandit tincidunt consequat in, varius sit amet neque. Morbi eget porttitor ex. Duis mattis aliquet ante quis imperdiet. Duis sit." }, + new object[] { string.Empty }, + new object[] { null }, + }; + + [Theory] + [MemberData(nameof(UnicodeStrings))] + public void UnicodeStringMarshalledAsExpected(string value) + { + int expectedLen = value != null ? value.Length : -1; + Assert.Equal(expectedLen, NativeExportsNE.Unicode.ReturnLength(value)); + Assert.Equal(expectedLen, NativeExportsNE.LPWStr.ReturnLength(value)); + Assert.Equal(expectedLen, NativeExportsNE.LPTStr.ReturnLength(value)); + + Assert.Equal(expectedLen, NativeExportsNE.LPWStr.ReturnLength_IgnoreCharSet(value)); + Assert.Equal(expectedLen, NativeExportsNE.LPTStr.ReturnLength_IgnoreCharSet(value)); + } + + [Theory] + [MemberData(nameof(UnicodeStrings))] + public void UnicodeStringReturn(string value) + { + string expected = ReverseChars(value); + + Assert.Equal(expected, NativeExportsNE.Unicode.Reverse_Return(value)); + Assert.Equal(expected, NativeExportsNE.LPWStr.Reverse_Return(value)); + Assert.Equal(expected, NativeExportsNE.LPTStr.Reverse_Return(value)); + + string ret; + NativeExportsNE.Unicode.Reverse_Out(value, out ret); + Assert.Equal(expected, ret); + + ret = null; + NativeExportsNE.LPWStr.Reverse_Out(value, out ret); + Assert.Equal(expected, ret); + + ret = null; + NativeExportsNE.LPWStr.Reverse_Out(value, out ret); + Assert.Equal(expected, ret); + } + + [Theory] + [MemberData(nameof(UnicodeStrings))] + public void UnicodeStringByRef(string value) + { + string refValue = value; + string expected = ReverseChars(value); + + NativeExportsNE.Unicode.Reverse_In(in refValue); + Assert.Equal(value, refValue); // Should not be updated when using 'in' + + NativeExportsNE.LPWStr.Reverse_In(in refValue); + Assert.Equal(value, refValue); // Should not be updated when using 'in' + + NativeExportsNE.LPTStr.Reverse_In(in refValue); + Assert.Equal(value, refValue); // Should not be updated when using 'in' + + refValue = value; + NativeExportsNE.Unicode.Reverse_Ref(ref refValue); + Assert.Equal(expected, refValue); + + refValue = value; + NativeExportsNE.LPWStr.Reverse_Ref(ref refValue); + Assert.Equal(expected, refValue); + + refValue = value; + NativeExportsNE.LPTStr.Reverse_Ref(ref refValue); + Assert.Equal(expected, refValue); + + refValue = value; + NativeExportsNE.Unicode.Reverse_Replace_Ref(ref refValue); + Assert.Equal(expected, refValue); + + refValue = value; + NativeExportsNE.LPWStr.Reverse_Replace_Ref(ref refValue); + Assert.Equal(expected, refValue); + + refValue = value; + NativeExportsNE.LPTStr.Reverse_Replace_Ref(ref refValue); + Assert.Equal(expected, refValue); + } + + [Theory] + [MemberData(nameof(UnicodeStrings))] + public void UTF8StringMarshalledAsExpected(string value) + { + int expectedLen = value != null ? Encoding.UTF8.GetByteCount(value) : -1; + Assert.Equal(expectedLen, NativeExportsNE.LPUTF8Str.ReturnLength(value)); + Assert.Equal(expectedLen, NativeExportsNE.LPUTF8Str.ReturnLength_IgnoreCharSet(value)); + } + + [Theory] + [MemberData(nameof(UnicodeStrings))] + public void UTF8StringReturn(string value) + { + string expected = ReverseBytes(value, Encoding.UTF8); + + Assert.Equal(expected, NativeExportsNE.LPUTF8Str.Reverse_Return(value)); + + string ret; + NativeExportsNE.LPUTF8Str.Reverse_Out(value, out ret); + Assert.Equal(expected, ret); + } + + [Theory] + [MemberData(nameof(UnicodeStrings))] + public void UTF8StringByRef(string value) + { + string refValue = value; + string expected = ReverseBytes(value, Encoding.UTF8); + + NativeExportsNE.LPUTF8Str.Reverse_In(in refValue); + Assert.Equal(value, refValue); // Should not be updated when using 'in' + + refValue = value; + NativeExportsNE.LPUTF8Str.Reverse_Ref(ref refValue); + Assert.Equal(expected, refValue); + + refValue = value; + NativeExportsNE.LPUTF8Str.Reverse_Replace_Ref(ref refValue); + Assert.Equal(expected, refValue); + } + + [Theory] + [MemberData(nameof(UnicodeStrings))] + public void AnsiStringMarshalledAsExpected(string value) + { + int expectedLen = value != null + ? OperatingSystem.IsWindows() ? GetLengthAnsi(value) : Encoding.UTF8.GetByteCount(value) + : -1; + + Assert.Equal(expectedLen, NativeExportsNE.Ansi.ReturnLength(value)); + Assert.Equal(expectedLen, NativeExportsNE.LPStr.ReturnLength(value)); + + Assert.Equal(expectedLen, NativeExportsNE.LPStr.ReturnLength_IgnoreCharSet(value)); + } + + [Theory] + [MemberData(nameof(UnicodeStrings))] + public void AnsiStringReturn(string value) + { + string expected = OperatingSystem.IsWindows() ? ReverseAnsi(value) : ReverseBytes(value, Encoding.UTF8); + + Assert.Equal(expected, NativeExportsNE.Ansi.Reverse_Return(value)); + Assert.Equal(expected, NativeExportsNE.LPStr.Reverse_Return(value)); + + string ret; + NativeExportsNE.Ansi.Reverse_Out(value, out ret); + Assert.Equal(expected, ret); + + ret = null; + NativeExportsNE.LPStr.Reverse_Out(value, out ret); + Assert.Equal(expected, ret); + } + + [Theory] + [MemberData(nameof(UnicodeStrings))] + public void AnsiStringByRef(string value) + { + string refValue = value; + string expected = OperatingSystem.IsWindows() ? ReverseAnsi(value) : ReverseBytes(value, Encoding.UTF8); + + NativeExportsNE.Ansi.Reverse_In(in refValue); + Assert.Equal(value, refValue); // Should not be updated when using 'in' + + NativeExportsNE.LPStr.Reverse_In(in refValue); + Assert.Equal(value, refValue); // Should not be updated when using 'in' + + refValue = value; + NativeExportsNE.Ansi.Reverse_Ref(ref refValue); + Assert.Equal(expected, refValue); + + refValue = value; + NativeExportsNE.LPStr.Reverse_Ref(ref refValue); + Assert.Equal(expected, refValue); + + refValue = value; + NativeExportsNE.Ansi.Reverse_Replace_Ref(ref refValue); + Assert.Equal(expected, refValue); + + refValue = value; + NativeExportsNE.LPStr.Reverse_Replace_Ref(ref refValue); + Assert.Equal(expected, refValue); + } + + [Theory] + [MemberData(nameof(UnicodeStrings))] + public void AutoStringMarshalledAsExpected(string value) + { + if (OperatingSystem.IsWindows()) + { + int expectedLen = value != null ? value.Length : -1; + Assert.Equal(expectedLen, NativeExportsNE.Auto.Windows.ReturnLength(value)); + } + else + { + int expectedLen = value != null ? Encoding.UTF8.GetByteCount(value) : -1; + Assert.Equal(expectedLen, NativeExportsNE.Auto.Unix.ReturnLength(value)); + } + } + + [Theory] + [MemberData(nameof(UnicodeStrings))] + public void AutoStringReturn(string value) + { + if (OperatingSystem.IsWindows()) + { + string expected = ReverseChars(value); + Assert.Equal(expected, NativeExportsNE.Auto.Windows.Reverse_Return(value)); + + string ret; + NativeExportsNE.Auto.Windows.Reverse_Out(value, out ret); + Assert.Equal(expected, ret); + } + else + { + string expected = ReverseBytes(value, Encoding.UTF8); + Assert.Equal(expected, NativeExportsNE.Auto.Unix.Reverse_Return(value)); + + string ret; + NativeExportsNE.Auto.Unix.Reverse_Out(value, out ret); + Assert.Equal(expected, ret); + } + } + + [Theory] + [MemberData(nameof(UnicodeStrings))] + public void AutoStringByRef(string value) + { + string refValue = value; + + if (OperatingSystem.IsWindows()) + { + string expected = ReverseChars(value); + NativeExportsNE.Auto.Windows.Reverse_In(in refValue); + Assert.Equal(value, refValue); // Should not be updated when using 'in' + + refValue = value; + NativeExportsNE.Auto.Windows.Reverse_Ref(ref refValue); + Assert.Equal(expected, refValue); + + refValue = value; + NativeExportsNE.Auto.Windows.Reverse_Replace_Ref(ref refValue); + Assert.Equal(expected, refValue); + + } + else + { + string expected = ReverseBytes(value, Encoding.UTF8); + NativeExportsNE.Auto.Unix.Reverse_In(in refValue); + Assert.Equal(value, refValue); // Should not be updated when using 'in' + + refValue = value; + NativeExportsNE.Auto.Unix.Reverse_Ref(ref refValue); + Assert.Equal(expected, refValue); + + refValue = value; + NativeExportsNE.Auto.Unix.Reverse_Replace_Ref(ref refValue); + Assert.Equal(expected, refValue); + } + } + + private static string ReverseChars(string value) + { + if (value == null) + return null; + + var chars = value.ToCharArray(); + Array.Reverse(chars); + return new string(chars); + } + + private static string ReverseBytes(string value, Encoding encoding) + { + if (value == null) + return null; + + byte[] bytes = encoding.GetBytes(value); + Array.Reverse(bytes); + return encoding.GetString(bytes); + } + + public static string ReverseAnsi(string value) + { + if (value == null) + return null; + + string ansi; + IntPtr ptr = Marshal.StringToCoTaskMemAnsi(value); + + try + { + unsafe + { + ansi = new string((sbyte*)ptr.ToPointer()); + } + } + finally + { + Marshal.FreeCoTaskMem(ptr); + } + + return ReverseChars(ansi); + } + + public static int GetLengthAnsi(string value) + { + int len = 0; + IntPtr ptr = Marshal.StringToCoTaskMemAnsi(value); + + try + { + byte nextByte = Marshal.ReadByte(ptr, len); + while (nextByte != '\0') + { + len++; + nextByte = Marshal.ReadByte(ptr, len); + } + } + finally + { + Marshal.FreeCoTaskMem(ptr); + } + + return len; + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/AdditionalAttributesOnStub.cs b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/AdditionalAttributesOnStub.cs new file mode 100644 index 0000000000000..83872bdad7ec4 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/AdditionalAttributesOnStub.cs @@ -0,0 +1,141 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Testing; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Text; +using System.Threading.Tasks; +using Xunit; + +namespace DllImportGenerator.UnitTests +{ + public class AdditionalAttributesOnStub + { + [Fact] + public async Task SkipLocalsInitAdded() + { + string source = @" +using System.Runtime.InteropServices; +partial class C +{ + [GeneratedDllImportAttribute(""DoesNotExist"")] + public static partial void Method(); +}"; + Compilation comp = await TestUtils.CreateCompilation(source); + + Compilation newComp = TestUtils.RunGenerators(comp, out _, new Microsoft.Interop.DllImportGenerator()); + + ITypeSymbol c = newComp.GetTypeByMetadataName("C")!; + IMethodSymbol stubMethod = c.GetMembers().OfType().Single(m => m.Name == "Method"); + Assert.Contains(stubMethod.GetAttributes(), attr => attr.AttributeClass!.ToDisplayString() == typeof(SkipLocalsInitAttribute).FullName); + } + + public static IEnumerable GetDownlevelTargetFrameworks() + { + yield return new object[] { ReferenceAssemblies.Net.Net50, true }; + yield return new object[] { ReferenceAssemblies.NetCore.NetCoreApp31, false }; + yield return new object[] { ReferenceAssemblies.NetStandard.NetStandard20, false }; + yield return new object[] { ReferenceAssemblies.NetFramework.Net48.Default, false }; + } + + [Theory] + [MemberData(nameof(GetDownlevelTargetFrameworks))] + public async Task SkipLocalsInitOnDownlevelTargetFrameworks(ReferenceAssemblies referenceAssemblies, bool expectSkipLocalsInit) + { + string source = @" +using System.Runtime.InteropServices; +namespace System.Runtime.InteropServices +{ + sealed class GeneratedDllImportAttribute : System.Attribute + { + public GeneratedDllImportAttribute(string a) { } + } +}partial class C +{ + [GeneratedDllImportAttribute(""DoesNotExist"")] + public static partial void Method(); +}"; + Compilation comp = await TestUtils.CreateCompilationWithReferenceAssemblies(source, referenceAssemblies); + + Compilation newComp = TestUtils.RunGenerators(comp, out _, new Microsoft.Interop.DllImportGenerator()); + + ITypeSymbol c = newComp.GetTypeByMetadataName("C")!; + IMethodSymbol stubMethod = c.GetMembers().OfType().Single(m => m.Name == "Method"); + if (expectSkipLocalsInit) + { + Assert.Contains(stubMethod.GetAttributes(), attr => attr.AttributeClass!.ToDisplayString() == typeof(SkipLocalsInitAttribute).FullName); + } + else + { + Assert.DoesNotContain(stubMethod.GetAttributes(), attr => attr.AttributeClass!.ToDisplayString() == typeof(SkipLocalsInitAttribute).FullName); + } + } + + [Fact] + public async Task SkipLocalsInitNotAddedWhenDefinedAtModuleLevel() + { + string source = @" +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; +[module:SkipLocalsInit] +partial class C +{ + [GeneratedDllImportAttribute(""DoesNotExist"")] + public static partial void Method(); +}"; + Compilation comp = await TestUtils.CreateCompilation(source); + + Compilation newComp = TestUtils.RunGenerators(comp, out _, new Microsoft.Interop.DllImportGenerator()); + + ITypeSymbol c = newComp.GetTypeByMetadataName("C")!; + IMethodSymbol stubMethod = c.GetMembers().OfType().Single(m => m.Name == "Method"); + Assert.DoesNotContain(stubMethod.GetAttributes(), attr => attr.AttributeClass!.ToDisplayString() == typeof(SkipLocalsInitAttribute).FullName); + } + + [Fact] + public async Task SkipLocalsInitNotAddedWhenDefinedAtClassLevel() + { + string source = @" +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; +[SkipLocalsInit] +partial class C +{ + [GeneratedDllImportAttribute(""DoesNotExist"")] + public static partial void Method(); +}"; + Compilation comp = await TestUtils.CreateCompilation(source); + + Compilation newComp = TestUtils.RunGenerators(comp, out _, new Microsoft.Interop.DllImportGenerator()); + + ITypeSymbol c = newComp.GetTypeByMetadataName("C")!; + IMethodSymbol stubMethod = c.GetMembers().OfType().Single(m => m.Name == "Method"); + Assert.DoesNotContain(stubMethod.GetAttributes(), attr => attr.AttributeClass!.ToDisplayString() == typeof(SkipLocalsInitAttribute).FullName); + } + + [Fact] + public async Task SkipLocalsInitNotAddedWhenDefinedOnMethodByUser() + { + string source = @" +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; +partial class C +{ + [SkipLocalsInit] + [GeneratedDllImportAttribute(""DoesNotExist"")] + public static partial void Method(); +}"; + Compilation comp = await TestUtils.CreateCompilation(source); + + Compilation newComp = TestUtils.RunGenerators(comp, out _, new Microsoft.Interop.DllImportGenerator()); + + ITypeSymbol c = newComp.GetTypeByMetadataName("C")!; + IMethodSymbol stubMethod = c.GetMembers().OfType().Single(m => m.Name == "Method"); + Assert.DoesNotContain(newComp.GetDiagnostics(), d => d.Id != "CS0579"); // No duplicate attribute error + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/AttributeForwarding.cs b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/AttributeForwarding.cs new file mode 100644 index 0000000000000..959a6402dda2f --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/AttributeForwarding.cs @@ -0,0 +1,201 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Xunit; + +namespace DllImportGenerator.UnitTests +{ + public class AttributeForwarding + { + [Theory] + [InlineData("SuppressGCTransition", "System.Runtime.InteropServices.SuppressGCTransitionAttribute")] + [InlineData("UnmanagedCallConv", "System.Runtime.InteropServices.UnmanagedCallConvAttribute")] + public async Task KnownParameterlessAttribute(string attributeSourceName, string attributeMetadataName) + { + string source = @$" +using System.Runtime.InteropServices; +partial class C +{{ + [{attributeSourceName}] + [GeneratedDllImportAttribute(""DoesNotExist"")] + public static partial void Method1(); +}} +"; + Compilation origComp = await TestUtils.CreateCompilation(source); + Compilation newComp = TestUtils.RunGenerators(origComp, out _, new Microsoft.Interop.DllImportGenerator()); + Assert.Empty(newComp.GetDiagnostics()); + + ITypeSymbol attributeType = newComp.GetTypeByMetadataName(attributeMetadataName)!; + + Assert.NotNull(attributeType); + + // The last syntax tree is the generated code + IMethodSymbol targetMethod = GetGeneratedPInvokeTargetFromCompilation(newComp); + + Assert.Contains( + targetMethod.GetAttributes(), + attr => SymbolEqualityComparer.Default.Equals(attr.AttributeClass, attributeType)); + } + + [Fact] + public async Task UnmanagedCallConvAttribute_EmptyCallConvArray() + { + string source = @" +using System; +using System.Runtime.InteropServices; +partial class C +{ + [UnmanagedCallConv(CallConvs = new Type[0])] + [GeneratedDllImportAttribute(""DoesNotExist"")] + public static partial void Method1(); +} +"; + Compilation origComp = await TestUtils.CreateCompilation(source); + Compilation newComp = TestUtils.RunGenerators(origComp, out _, new Microsoft.Interop.DllImportGenerator()); + Assert.Empty(newComp.GetDiagnostics()); + + ITypeSymbol attributeType = newComp.GetTypeByMetadataName("System.Runtime.InteropServices.UnmanagedCallConvAttribute")!; + + Assert.NotNull(attributeType); + + // The last syntax tree is the generated code + IMethodSymbol targetMethod = GetGeneratedPInvokeTargetFromCompilation(newComp); + + Assert.Contains( + targetMethod.GetAttributes(), + attr => SymbolEqualityComparer.Default.Equals(attr.AttributeClass, attributeType) + && attr.NamedArguments.Length == 1 + && attr.NamedArguments[0].Key == "CallConvs" + && attr.NamedArguments[0].Value.Values.Length == 0); + } + + [Fact] + public async Task UnmanagedCallConvAttribute_SingleCallConvType() + { + string source = @" +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +partial class C +{ + [UnmanagedCallConv(CallConvs = new[]{typeof(CallConvStdcall)})] + [GeneratedDllImportAttribute(""DoesNotExist"")] + public static partial void Method1(); +} +"; + Compilation origComp = await TestUtils.CreateCompilation(source); + Compilation newComp = TestUtils.RunGenerators(origComp, out _, new Microsoft.Interop.DllImportGenerator()); + Assert.Empty(newComp.GetDiagnostics()); + + ITypeSymbol attributeType = newComp.GetTypeByMetadataName("System.Runtime.InteropServices.UnmanagedCallConvAttribute")!; + ITypeSymbol callConvType = newComp.GetTypeByMetadataName("System.Runtime.CompilerServices.CallConvStdcall")!; + + Assert.NotNull(attributeType); + + // The last syntax tree is the generated code + IMethodSymbol targetMethod = GetGeneratedPInvokeTargetFromCompilation(newComp); + + Assert.Contains( + targetMethod.GetAttributes(), + attr => SymbolEqualityComparer.Default.Equals(attr.AttributeClass, attributeType) + && attr.NamedArguments.Length == 1 + && attr.NamedArguments[0].Key == "CallConvs" + && attr.NamedArguments[0].Value.Values.Length == 1 + && SymbolEqualityComparer.Default.Equals( + (INamedTypeSymbol?)attr.NamedArguments[0].Value.Values[0].Value!, + callConvType)); + } + + [Fact] + public async Task UnmanagedCallConvAttribute_MultipleCallConvTypes() + { + string source = @" +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +partial class C +{ + [UnmanagedCallConv(CallConvs = new[]{typeof(CallConvStdcall), typeof(CallConvSuppressGCTransition)})] + [GeneratedDllImportAttribute(""DoesNotExist"")] + public static partial void Method1(); +} +"; + Compilation origComp = await TestUtils.CreateCompilation(source); + Compilation newComp = TestUtils.RunGenerators(origComp, out _, new Microsoft.Interop.DllImportGenerator()); + Assert.Empty(newComp.GetDiagnostics()); + + ITypeSymbol attributeType = newComp.GetTypeByMetadataName("System.Runtime.InteropServices.UnmanagedCallConvAttribute")!; + ITypeSymbol callConvType = newComp.GetTypeByMetadataName("System.Runtime.CompilerServices.CallConvStdcall")!; + ITypeSymbol callConvType2 = newComp.GetTypeByMetadataName("System.Runtime.CompilerServices.CallConvSuppressGCTransition")!; + + Assert.NotNull(attributeType); + + // The last syntax tree is the generated code + IMethodSymbol targetMethod = GetGeneratedPInvokeTargetFromCompilation(newComp); + + Assert.Contains( + targetMethod.GetAttributes(), + attr => SymbolEqualityComparer.Default.Equals(attr.AttributeClass, attributeType) + && attr.NamedArguments.Length == 1 + && attr.NamedArguments[0].Key == "CallConvs" + && attr.NamedArguments[0].Value.Values.Length == 2 + && SymbolEqualityComparer.Default.Equals( + (INamedTypeSymbol?)attr.NamedArguments[0].Value.Values[0].Value!, + callConvType) + && SymbolEqualityComparer.Default.Equals( + (INamedTypeSymbol?)attr.NamedArguments[0].Value.Values[1].Value!, + callConvType2)); + } + + [Fact] + public async Task OtherAttributeType() + { + string source = @" +using System; +using System.Runtime.InteropServices; + +class OtherAttribute : Attribute {} + +partial class C +{ + [Other] + [GeneratedDllImportAttribute(""DoesNotExist"")] + public static partial void Method1(); +} +"; + Compilation origComp = await TestUtils.CreateCompilation(source); + Compilation newComp = TestUtils.RunGenerators(origComp, out _, new Microsoft.Interop.DllImportGenerator()); + + Assert.Empty(newComp.GetDiagnostics()); + + ITypeSymbol attributeType = newComp.GetTypeByMetadataName("OtherAttribute")!; + + Assert.NotNull(attributeType); + + // The last syntax tree is the generated code + IMethodSymbol targetMethod = GetGeneratedPInvokeTargetFromCompilation(newComp); + + Assert.DoesNotContain( + targetMethod.GetAttributes(), + attr => SymbolEqualityComparer.Default.Equals(attr.AttributeClass, attributeType)); + } + + private static IMethodSymbol GetGeneratedPInvokeTargetFromCompilation(Compilation newComp) + { + SyntaxTree generatedCode = newComp.SyntaxTrees.Last(); + SemanticModel model = newComp.GetSemanticModel(generatedCode); + + var localFunctions = generatedCode.GetRoot() + .DescendantNodes().OfType() + .ToList(); + Assert.Single(localFunctions); + IMethodSymbol targetMethod = (IMethodSymbol)model.GetDeclaredSymbol(localFunctions[0])!; + return targetMethod; + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/CodeSnippets.cs b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/CodeSnippets.cs new file mode 100644 index 0000000000000..746646fd523b7 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/CodeSnippets.cs @@ -0,0 +1,1423 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.InteropServices; + +namespace DllImportGenerator.UnitTests +{ + internal static class CodeSnippets + { + /// + /// Trivial declaration of GeneratedDllImport usage + /// + public static readonly string TrivialClassDeclarations = @" +using System.Runtime.InteropServices; +partial class Basic +{ + [GeneratedDllImportAttribute(""DoesNotExist"")] + public static partial void Method1(); + + [GeneratedDllImport(""DoesNotExist"")] + public static partial void Method2(); + + [System.Runtime.InteropServices.GeneratedDllImportAttribute(""DoesNotExist"")] + public static partial void Method3(); + + [System.Runtime.InteropServices.GeneratedDllImport(""DoesNotExist"")] + public static partial void Method4(); +} +"; + /// + /// Trivial declaration of GeneratedDllImport usage + /// + public static readonly string TrivialStructDeclarations = @" +using System.Runtime.InteropServices; +partial struct Basic +{ + [GeneratedDllImportAttribute(""DoesNotExist"")] + public static partial void Method1(); + + [GeneratedDllImport(""DoesNotExist"")] + public static partial void Method2(); + + [System.Runtime.InteropServices.GeneratedDllImportAttribute(""DoesNotExist"")] + public static partial void Method3(); + + [System.Runtime.InteropServices.GeneratedDllImport(""DoesNotExist"")] + public static partial void Method4(); +} +"; + + /// + /// Declaration with multiple attributes + /// + public static readonly string MultipleAttributes = @" +using System; +using System.Runtime.InteropServices; + +sealed class DummyAttribute : Attribute +{ + public DummyAttribute() { } +} + +sealed class Dummy2Attribute : Attribute +{ + public Dummy2Attribute(string input) { } +} + +partial class Test +{ + [DummyAttribute] + [GeneratedDllImport(""DoesNotExist""), Dummy2Attribute(""string value"")] + public static partial void Method(); +} +"; + + /// + /// Validate nested namespaces are handled + /// + public static readonly string NestedNamespace = @" +using System.Runtime.InteropServices; +namespace NS +{ + namespace InnerNS + { + partial class Test + { + [GeneratedDllImport(""DoesNotExist"")] + public static partial void Method1(); + } + } +} +namespace NS.InnerNS +{ + partial class Test + { + [GeneratedDllImport(""DoesNotExist"")] + public static partial void Method2(); + } +} +"; + + /// + /// Validate nested types are handled. + /// + public static readonly string NestedTypes = @" +using System.Runtime.InteropServices; +namespace NS +{ + partial class OuterClass + { + partial class InnerClass + { + [GeneratedDllImport(""DoesNotExist"")] + public static partial void Method(); + } + } + partial struct OuterStruct + { + partial struct InnerStruct + { + [GeneratedDllImport(""DoesNotExist"")] + public static partial void Method(); + } + } + partial class OuterClass + { + partial struct InnerStruct + { + [GeneratedDllImport(""DoesNotExist"")] + public static partial void Method(); + } + } + partial struct OuterStruct + { + partial class InnerClass + { + [GeneratedDllImport(""DoesNotExist"")] + public static partial void Method(); + } + } +} +"; + + /// + /// Declaration with user defined EntryPoint. + /// + public static readonly string UserDefinedEntryPoint = @" +using System.Runtime.InteropServices; +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 with all supported DllImport named arguments. + /// + public static readonly string AllSupportedDllImportNamedArguments = @" +using System.Runtime.InteropServices; +partial class Test +{ + [GeneratedDllImport(""DoesNotExist"", + CharSet = CharSet.Unicode, + EntryPoint = ""UserDefinedEntryPoint"", + ExactSpelling = true, + PreserveSig = false, + SetLastError = 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); + private const int One = 1; + private const int Two = 2; + + [GeneratedDllImport(nameof(Test), + CharSet = (CharSet)2, + EntryPoint = EntryPointName, + ExactSpelling = 0 != 1, + PreserveSig = IsTrue, + SetLastError = IsFalse)] + public static partial void Method1(); + + [GeneratedDllImport(nameof(Test), + CharSet = (CharSet)Two, + EntryPoint = EntryPointName, + ExactSpelling = One != Two, + PreserveSig = !IsFalse, + SetLastError = !IsTrue)] + public static partial void Method2(); +} +"; + + /// + /// Declaration with default parameters. + /// + public static readonly string DefaultParameters = @" +using System.Runtime.InteropServices; +partial class Test +{ + [GeneratedDllImport(""DoesNotExist"")] + public static partial void Method(int t = 0); +} +"; + + /// + /// Declaration with LCIDConversionAttribute. + /// + public static readonly string LCIDConversionAttribute = @" +using System.Runtime.InteropServices; +partial class Test +{ + [LCIDConversion(0)] + [GeneratedDllImport(""DoesNotExist"")] + public static partial void Method(); +} +"; + + /// + /// Define a MarshalAsAttribute with a customer marshaller to parameters and return types. + /// + public static readonly string MarshalAsCustomMarshalerOnTypes = @" +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.CustomMarshaler, MarshalTypeRef = typeof(NS.MyCustomMarshaler), MarshalCookie=""COOKIE1"")] + public static partial bool Method1([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof(NS.MyCustomMarshaler), MarshalCookie=""COOKIE2"")]bool t); + + [GeneratedDllImport(""DoesNotExist"")] + [return: MarshalAs(UnmanagedType.CustomMarshaler, MarshalType = ""NS.MyCustomMarshaler"", MarshalCookie=""COOKIE3"")] + public static partial bool Method2([MarshalAs(UnmanagedType.CustomMarshaler, MarshalType = ""NS.MyCustomMarshaler"", MarshalCookie=""COOKIE4"")]bool t); +} +"; + + /// + /// Declaration with user defined attributes with prefixed name. + /// + public static readonly string UserDefinedPrefixedAttributes = @" +using System; +using System.Runtime.InteropServices; + +namespace System.Runtime.InteropServices +{ + // Prefix with ATTRIBUTE so the lengths will match during check. + sealed class ATTRIBUTEGeneratedDllImportAttribute : Attribute + { + public ATTRIBUTEGeneratedDllImportAttribute(string a) { } + } +} + +partial class Test +{ + [ATTRIBUTEGeneratedDllImportAttribute(""DoesNotExist"")] + public static partial void Method1(); + + [ATTRIBUTEGeneratedDllImport(""DoesNotExist"")] + public static partial void Method2(); + + [System.Runtime.InteropServices.ATTRIBUTEGeneratedDllImport(""DoesNotExist"")] + public static partial void Method3(); +} +"; + + /// + /// Declaration with parameters with set. + /// + public static string BasicParametersAndModifiersWithCharSet(string typename, CharSet value) => @$" +using System.Runtime.InteropServices; +partial class Test +{{ + [GeneratedDllImport(""DoesNotExist"", CharSet = CharSet.{value})] + public static partial {typename} Method( + {typename} p, + in {typename} pIn, + ref {typename} pRef, + out {typename} pOut); +}} +"; + + public static string BasicParametersAndModifiersWithCharSet(CharSet value) => + BasicParametersAndModifiersWithCharSet(typeof(T).ToString(), value); + + /// + /// Declaration with parameters. + /// + public static string BasicParametersAndModifiers(string typeName) => @$" +using System.Runtime.InteropServices; +partial class Test +{{ + [GeneratedDllImport(""DoesNotExist"")] + public static partial {typeName} Method( + {typeName} p, + in {typeName} pIn, + ref {typeName} pRef, + out {typeName} pOut); +}}"; + + /// + /// Declaration with parameters. + /// + public static string BasicParametersAndModifiersNoRef(string typeName) => @$" +using System.Runtime.InteropServices; +partial class Test +{{ + [GeneratedDllImport(""DoesNotExist"")] + public static partial {typeName} Method( + {typeName} p, + in {typeName} pIn, + out {typeName} pOut); +}}"; + + /// + /// Declaration with parameters and unsafe. + /// + public static string BasicParametersAndModifiersUnsafe(string typeName) => @$" +using System.Runtime.InteropServices; +partial class Test +{{ + [GeneratedDllImport(""DoesNotExist"")] + public static unsafe partial {typeName} Method( + {typeName} p, + in {typeName} pIn, + ref {typeName} pRef, + out {typeName} pOut); +}}"; + + public static string BasicParametersAndModifiers() => BasicParametersAndModifiers(typeof(T).ToString()); + + /// + /// Declaration with [In, Out] style attributes on a by-value parameter. + /// + public static string ByValueParameterWithModifier(string typeName, string attributeName) => @$" +using System.Runtime.InteropServices; +partial class Test +{{ + [GeneratedDllImport(""DoesNotExist"")] + public static partial void Method( + [{attributeName}] {typeName} p); +}}"; + + public static string ByValueParameterWithModifier(string attributeName) => ByValueParameterWithModifier(typeof(T).ToString(), attributeName); + + /// + /// Declaration with by-value parameter with custom name. + /// + public static string ByValueParameterWithName(string methodName, string paramName) => @$" +using System.Runtime.InteropServices; +partial class Test +{{ + [GeneratedDllImport(""DoesNotExist"")] + public static partial void {methodName}( + int {paramName}); +}}"; + + /// + /// Declaration with parameters with MarshalAs. + /// + public static string MarshalAsParametersAndModifiers(string typeName, UnmanagedType unmanagedType) => @$" +using System.Runtime.InteropServices; +partial class Test +{{ + [GeneratedDllImport(""DoesNotExist"")] + [return: MarshalAs(UnmanagedType.{unmanagedType})] + public static partial {typeName} Method( + [MarshalAs(UnmanagedType.{unmanagedType})] {typeName} p, + [MarshalAs(UnmanagedType.{unmanagedType})] in {typeName} pIn, + [MarshalAs(UnmanagedType.{unmanagedType})] ref {typeName} pRef, + [MarshalAs(UnmanagedType.{unmanagedType})] out {typeName} pOut); +}} +"; + + /// + /// Declaration with parameters with MarshalAs. + /// + public static string MarshalAsParametersAndModifiersUnsafe(string typeName, UnmanagedType unmanagedType) => @$" +using System.Runtime.InteropServices; +partial class Test +{{ + [GeneratedDllImport(""DoesNotExist"")] + [return: MarshalAs(UnmanagedType.{unmanagedType})] + public static unsafe partial {typeName} Method( + [MarshalAs(UnmanagedType.{unmanagedType})] {typeName} p, + [MarshalAs(UnmanagedType.{unmanagedType})] in {typeName} pIn, + [MarshalAs(UnmanagedType.{unmanagedType})] ref {typeName} pRef, + [MarshalAs(UnmanagedType.{unmanagedType})] out {typeName} pOut); +}} +"; + + public static string MarshalAsParametersAndModifiers(UnmanagedType unmanagedType) => MarshalAsParametersAndModifiers(typeof(T).ToString(), unmanagedType); + + /// + /// Declaration with enum parameters. + /// + public static string EnumParameters => @$" +using System.Runtime.InteropServices; +using NS; + +namespace NS +{{ + enum MyEnum {{ A, B, C }} +}} + +partial class Test +{{ + [GeneratedDllImport(""DoesNotExist"")] + public static partial MyEnum Method( + MyEnum p, + in MyEnum pIn, + ref MyEnum pRef, + out MyEnum pOut); +}}"; + + /// + /// Declaration with pointer parameters. + /// + public static string PointerParameters() => BasicParametersAndModifiersUnsafe($"{typeof(T)}*"); + + /// + /// Declaration with PreserveSig = false. + /// + public static string PreserveSigFalse(string typeName) => @$" +using System.Runtime.InteropServices; +partial class Test +{{ + [GeneratedDllImport(""DoesNotExist"", PreserveSig = false)] + public static partial {typeName} Method1(); + + [GeneratedDllImport(""DoesNotExist"", PreserveSig = false)] + public static partial {typeName} Method2({typeName} p); +}}"; + + public static string PreserveSigFalse() => PreserveSigFalse(typeof(T).ToString()); + + /// + /// Declaration with PreserveSig = false and void return. + /// + public static readonly string PreserveSigFalseVoidReturn = @$" +using System.Runtime.InteropServices; +partial class Test +{{ + [GeneratedDllImport(""DoesNotExist"", PreserveSig = false)] + public static partial void Method(); +}}"; + + public static string DelegateParametersAndModifiers = BasicParametersAndModifiers("MyDelegate") + @" +delegate int MyDelegate(int a);"; + public static string DelegateMarshalAsParametersAndModifiers = MarshalAsParametersAndModifiers("MyDelegate", UnmanagedType.FunctionPtr) + @" +delegate int MyDelegate(int a);"; + + private static string BlittableMyStruct(string modifier = "") => $@"#pragma warning disable CS0169 +{modifier} unsafe struct MyStruct +{{ + private int i; + private short s; + private long l; + private double d; + private int* iptr; + private short* sptr; + private long* lptr; + private double* dptr; + private void* vptr; +}}"; + + public static string BlittableStructParametersAndModifiers = BasicParametersAndModifiers("MyStruct") + $@" +[BlittableType] +{BlittableMyStruct()} +"; + + public static string MarshalAsArrayParametersAndModifiers(string elementType) => $@" +using System.Runtime.InteropServices; +partial class Test +{{ + [GeneratedDllImport(""DoesNotExist"")] + [return:MarshalAs(UnmanagedType.LPArray, SizeConst=10)] + public static partial {elementType}[] Method( + {elementType}[] p, + in {elementType}[] pIn, + int pRefSize, + [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=2)] ref {elementType}[] pRef, + [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=5, SizeConst=4)] out {elementType}[] pOut, + out int pOutSize + ); +}}"; + + public static string MarshalAsArrayParametersAndModifiers() => MarshalAsArrayParametersAndModifiers(typeof(T).ToString()); + + public static string MarshalAsArrayParameterWithSizeParam(string sizeParamType, bool isByRef) => $@" +using System.Runtime.InteropServices; +partial class Test +{{ + [GeneratedDllImport(""DoesNotExist"")] + public static partial void Method( + {(isByRef ? "ref" : "")} {sizeParamType} pRefSize, + [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] ref int[] pRef + ); +}}"; + + public static string MarshalAsArrayParameterWithSizeParam(bool isByRef) => MarshalAsArrayParameterWithSizeParam(typeof(T).ToString(), isByRef); + + + public static string MarshalAsArrayParameterWithNestedMarshalInfo(string elementType, UnmanagedType nestedMarshalInfo) => $@" +using System.Runtime.InteropServices; +partial class Test +{{ + [GeneratedDllImport(""DoesNotExist"")] + public static partial void Method( + [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.{nestedMarshalInfo})] {elementType}[] pRef + ); +}}"; + + public static string MarshalAsArrayParameterWithNestedMarshalInfo(UnmanagedType nestedMarshalType) => MarshalAsArrayParameterWithNestedMarshalInfo(typeof(T).ToString(), nestedMarshalType); + + public static string ArrayPreserveSigFalse(string elementType) => $@" +using System.Runtime.InteropServices; +partial class Test +{{ + [GeneratedDllImport(""DoesNotExist"", PreserveSig = false)] + [return:MarshalAs(UnmanagedType.LPArray, SizeConst=10)] + public static partial {elementType}[] Method1(); + + [GeneratedDllImport(""DoesNotExist"", PreserveSig = false)] + [return:MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] + public static partial {elementType}[] Method2(int i); +}}"; + + public static string ArrayPreserveSigFalse() => ArrayPreserveSigFalse(typeof(T).ToString()); + + /// + /// Declaration with parameters with MarshalAs. + /// + public static string MarshalUsingParametersAndModifiers(string typeName, string nativeTypeName) => @$" +using System.Runtime.InteropServices; +partial class Test +{{ + [GeneratedDllImport(""DoesNotExist"")] + [return: MarshalUsing(typeof({nativeTypeName}))] + public static partial {typeName} Method( + [MarshalUsing(typeof({nativeTypeName}))] {typeName} p, + [MarshalUsing(typeof({nativeTypeName}))] in {typeName} pIn, + [MarshalUsing(typeof({nativeTypeName}))] ref {typeName} pRef, + [MarshalUsing(typeof({nativeTypeName}))] out {typeName} pOut); +}} +"; + + public static string CustomStructMarshallingParametersAndModifiers = BasicParametersAndModifiers("S") + @" +[NativeMarshalling(typeof(Native))] +struct S +{ + public bool b; +} + +struct Native +{ + private int i; + public Native(S s) + { + i = s.b ? 1 : 0; + } + + public S ToManaged() => new S { b = i != 0 }; +} +"; + + public static string CustomStructMarshallingMarshalUsingParametersAndModifiers = MarshalUsingParametersAndModifiers("S", "Native") + @" +struct S +{ + public bool b; +} + +struct Native +{ + private int i; + public Native(S s) + { + i = s.b ? 1 : 0; + } + + public S ToManaged() => new S { b = i != 0 }; +} +"; + + public static string CustomStructMarshallingStackallocParametersAndModifiersNoRef = BasicParametersAndModifiersNoRef("S") + @" +[NativeMarshalling(typeof(Native))] +struct S +{ + public bool b; +} + +struct Native +{ + private int i; + public Native(S s, System.Span b) + { + i = s.b ? 1 : 0; + } + + public S ToManaged() => new S { b = i != 0 }; + + public const int StackBufferSize = 1; +} +"; + public static string CustomStructMarshallingStackallocOnlyRefParameter = BasicParameterWithByRefModifier("ref", "S") + @" +[NativeMarshalling(typeof(Native))] +struct S +{ + public bool b; +} + +struct Native +{ + private int i; + public Native(S s, System.Span b) + { + i = s.b ? 1 : 0; + } + + public S ToManaged() => new S { b = i != 0 }; + + public const int StackBufferSize = 1; +} +"; + public static string CustomStructMarshallingOptionalStackallocParametersAndModifiers = BasicParametersAndModifiers("S") + @" +[NativeMarshalling(typeof(Native))] +struct S +{ + public bool b; +} + +struct Native +{ + private int i; + public Native(S s, System.Span b) + { + i = s.b ? 1 : 0; + } + public Native(S s) + { + i = s.b ? 1 : 0; + } + + public S ToManaged() => new S { b = i != 0 }; + + public const int StackBufferSize = 1; +} +"; + + public static string CustomStructMarshallingStackallocValuePropertyParametersAndModifiersNoRef = BasicParametersAndModifiersNoRef("S") + @" +[NativeMarshalling(typeof(Native))] +struct S +{ + public bool b; +} + +struct Native +{ + public Native(S s, System.Span b) + { + Value = s.b ? 1 : 0; + } + + public S ToManaged() => new S { b = Value != 0 }; + + public int Value { get; set; } + + public const int StackBufferSize = 1; +} +"; + public static string CustomStructMarshallingValuePropertyParametersAndModifiers = BasicParametersAndModifiers("S") + @" +[NativeMarshalling(typeof(Native))] +struct S +{ + public bool b; +} + +struct Native +{ + public Native(S s) + { + Value = s.b ? 1 : 0; + } + + public S ToManaged() => new S { b = Value != 0 }; + + public int Value { get; set; } +} +"; + public static string CustomStructMarshallingPinnableParametersAndModifiers = BasicParametersAndModifiers("S") + @" +[NativeMarshalling(typeof(Native))] +class S +{ + public int i; + + public ref int GetPinnableReference() => ref i; +} + +unsafe struct Native +{ + private int* ptr; + public Native(S s) + { + ptr = (int*)Marshal.AllocHGlobal(sizeof(int)); + *ptr = s.i; + } + + public S ToManaged() => new S { i = *ptr }; + + public nint Value + { + get => (nint)ptr; + set => ptr = (int*)value; + } +} +"; + + public static string CustomStructMarshallingNativeTypePinnable = @" +using System.Runtime.InteropServices; +using System; + +[NativeMarshalling(typeof(Native))] +class S +{ + public byte c; +} + +unsafe ref struct Native +{ + private byte* ptr; + private Span stackBuffer; + + public Native(S s) : this() + { + ptr = (byte*)Marshal.AllocCoTaskMem(sizeof(byte)); + *ptr = s.c; + } + + public Native(S s, Span buffer) : this() + { + stackBuffer = buffer; + stackBuffer[0] = s.c; + } + + public ref byte GetPinnableReference() => ref (ptr != null ? ref *ptr : ref stackBuffer.GetPinnableReference()); + + public S ToManaged() + { + return new S { c = *ptr }; + } + + public byte* Value + { + get => ptr != null ? ptr : throw new InvalidOperationException(); + set => ptr = value; + } + + public void FreeNative() + { + if (ptr != null) + { + Marshal.FreeCoTaskMem((IntPtr)ptr); + } + } + + public const int StackBufferSize = 1; +} + +partial class Test +{ + [GeneratedDllImport(""DoesNotExist"")] + public static partial void Method( + S s, + in S sIn); +} +"; + + public static string CustomStructMarshallingByRefValueProperty = BasicParametersAndModifiers("S") + @" +[NativeMarshalling(typeof(Native))] +class S +{ + public byte c = 0; +} + +unsafe struct Native +{ + private S value; + + public Native(S s) : this() + { + value = s; + } + + public ref byte Value { get => ref value.c; } +} +"; + + public static string BasicParameterWithByRefModifier(string byRefKind, string typeName) => @$" +using System.Runtime.InteropServices; +partial class Test +{{ + [GeneratedDllImport(""DoesNotExist"")] + public static partial void Method( + {byRefKind} {typeName} p); +}}"; + + public static string BasicParameterByValue(string typeName) => @$" +using System.Runtime.InteropServices; +partial class Test +{{ + [GeneratedDllImport(""DoesNotExist"")] + public static partial void Method( + {typeName} p); +}}"; + + public static string BasicReturnType(string typeName) => @$" +using System.Runtime.InteropServices; +partial class Test +{{ + [GeneratedDllImport(""DoesNotExist"")] + public static partial {typeName} Method(); +}}"; + + public static string CustomStructMarshallingManagedToNativeOnlyOutParameter => BasicParameterWithByRefModifier("out", "S") + @" +[NativeMarshalling(typeof(Native))] +[StructLayout(LayoutKind.Sequential)] +struct S +{ + public bool b; +} + +struct Native +{ + private int i; + public Native(S s) + { + i = s.b ? 1 : 0; + } +} +"; + + public static string CustomStructMarshallingManagedToNativeOnlyReturnValue => BasicReturnType("S") + @" +[NativeMarshalling(typeof(Native))] +[StructLayout(LayoutKind.Sequential)] +struct S +{ + public bool b; +} + +struct Native +{ + private int i; + public Native(S s) + { + i = s.b ? 1 : 0; + } +} +"; + + public static string CustomStructMarshallingNativeToManagedOnlyInParameter => BasicParameterWithByRefModifier("in", "S") + @" +[NativeMarshalling(typeof(Native))] +struct S +{ + public bool b; +} + +[StructLayout(LayoutKind.Sequential)] +struct Native +{ + private int i; + public S ToManaged() => new S { b = i != 0 }; +} +"; + + public static string ArrayMarshallingWithCustomStructElementWithValueProperty => MarshalAsArrayParametersAndModifiers("IntStructWrapper") + @" +[NativeMarshalling(typeof(IntStructWrapperNative))] +public struct IntStructWrapper +{ + public int Value; +} + +public struct IntStructWrapperNative +{ + public IntStructWrapperNative(IntStructWrapper managed) + { + Value = managed.Value; + } + + public int Value { get; set; } + + public IntStructWrapper ToManaged() => new IntStructWrapper { Value = Value }; +} +"; + + public static string ArrayMarshallingWithCustomStructElement => MarshalAsArrayParametersAndModifiers("IntStructWrapper") + @" +[NativeMarshalling(typeof(IntStructWrapperNative))] +public struct IntStructWrapper +{ + public int Value; +} + +public struct IntStructWrapperNative +{ + private int value; + + public IntStructWrapperNative(IntStructWrapper managed) + { + value = managed.Value; + } + + public IntStructWrapper ToManaged() => new IntStructWrapper { Value = value }; +} +"; + + public static string SafeHandleWithCustomDefaultConstructorAccessibility(bool privateCtor) => BasicParametersAndModifiers("MySafeHandle") + $@" +class MySafeHandle : SafeHandle +{{ + {(privateCtor ? "private" : "public")} MySafeHandle() : base(System.IntPtr.Zero, true) {{ }} + + public override bool IsInvalid => handle == System.IntPtr.Zero; + + protected override bool ReleaseHandle() => true; +}}"; + + public static string PreprocessorIfAroundFullFunctionDefinition(string define) => + @$" +partial class Test +{{ +#if {define} + [System.Runtime.InteropServices.GeneratedDllImport(""DoesNotExist"")] + public static partial int Method( + int p, + in int pIn, + out int pOut); +#endif +}}"; + + public static string PreprocessorIfAroundFullFunctionDefinitionWithFollowingFunction(string define) => + @$" +using System.Runtime.InteropServices; +partial class Test +{{ +#if {define} + [GeneratedDllImport(""DoesNotExist"")] + public static partial int Method( + int p, + in int pIn, + out int pOut); +#endif + public static int Method2( + SafeHandle p) => throw null; +}}"; + + public static string PreprocessorIfAfterAttributeAroundFunction(string define) => + @$" +using System.Runtime.InteropServices; +partial class Test +{{ + [GeneratedDllImport(""DoesNotExist"")] +#if {define} + public static partial int Method( + int p, + in int pIn, + out int pOut); +#else + public static partial int Method2( + int p, + in int pIn, + out int pOut); +#endif +}}"; + + public static string PreprocessorIfAfterAttributeAroundFunctionAdditionalFunctionAfter(string define) => + @$" +using System.Runtime.InteropServices; +partial class Test +{{ + [GeneratedDllImport(""DoesNotExist"")] +#if {define} + public static partial int Method( + int p, + in int pIn, + out int pOut); +#else + public static partial int Method2( + int p, + in int pIn, + out int pOut); +#endif + public static int Foo() => throw null; +}}"; + + public static string MaybeBlittableGenericTypeParametersAndModifiers(string typeArgument) => BasicParametersAndModifiers($"Generic<{typeArgument}>") + @" +[BlittableType] +struct Generic +{ +#pragma warning disable CS0649 + public T field; +} +"; + + public static string MaybeBlittableGenericTypeParametersAndModifiers() => + MaybeBlittableGenericTypeParametersAndModifiers(typeof(T).ToString()); + + public static string ImplicitlyBlittableStructParametersAndModifiers(string visibility = "") => BasicParametersAndModifiers("MyStruct") + $@" +// Implicitly blittable +{BlittableMyStruct(visibility)} +"; + + public static string ImplicitlyBlittableGenericTypeParametersAndModifiers(string typeArgument, string visibility = "") => BasicParametersAndModifiers($"Generic<{typeArgument}>") + $@" +{visibility} struct Generic +{{ +#pragma warning disable CS0649 +#pragma warning disable CS0169 + public T field; +}} +"; + + public static string ImplicitlyBlittableGenericTypeParametersAndModifiers(string visibility = "") => + ImplicitlyBlittableGenericTypeParametersAndModifiers(typeof(T).ToString(), visibility); + + public static string RecursiveImplicitlyBlittableStruct => BasicParametersAndModifiers("RecursiveStruct") + @" +struct RecursiveStruct +{ + RecursiveStruct s; + int i; +}"; + public static string MutuallyRecursiveImplicitlyBlittableStruct => BasicParametersAndModifiers("RecursiveStruct1") + @" +struct RecursiveStruct1 +{ + RecursiveStruct2 s; + int i; +} + +struct RecursiveStruct2 +{ + RecursiveStruct1 s; + int i; +}"; + + public static string CollectionByValue(string elementType) => BasicParameterByValue($"TestCollection<{elementType}>") + @" +[NativeMarshalling(typeof(Marshaller<>))] +class TestCollection {} + +[GenericContiguousCollectionMarshaller] +ref struct Marshaller +{ + public Marshaller(TestCollection managed, int nativeElementSize) : this() {} + public System.Span ManagedValues { get; } + public System.Span NativeValueStorage { get; } + public System.IntPtr Value { get; } +} +"; + + public static string CollectionByValue() => CollectionByValue(typeof(T).ToString()); + + public static string MarshalUsingCollectionCountInfoParametersAndModifiers(string collectionType) => $@" +using System.Runtime.InteropServices; +partial class Test +{{ + [GeneratedDllImport(""DoesNotExist"")] + [return:MarshalUsing(ConstantElementCount=10)] + public static partial {collectionType} Method( + {collectionType} p, + in {collectionType} pIn, + int pRefSize, + [MarshalUsing(CountElementName = ""pRefSize"")] ref {collectionType} pRef, + [MarshalUsing(CountElementName = ""pOutSize"")] out {collectionType} pOut, + out int pOutSize + ); +}}"; + + public static string CustomCollectionWithMarshaller(bool enableDefaultMarshalling) + { + string nativeMarshallingAttribute = enableDefaultMarshalling ? "[NativeMarshalling(typeof(Marshaller<>))]" : string.Empty; + return nativeMarshallingAttribute + @"class TestCollection {} + +[GenericContiguousCollectionMarshaller] +ref struct Marshaller +{ + public Marshaller(int nativeElementSize) : this() {} + public Marshaller(TestCollection managed, int nativeElementSize) : this() {} + public System.Span ManagedValues { get; } + public System.Span NativeValueStorage { get; } + public System.IntPtr Value { get; set; } + public void SetUnmarshalledCollectionLength(int length) {} + public TestCollection ToManaged() => throw null; +}"; + } + + public static string MarshalUsingCollectionCountInfoParametersAndModifiers() => MarshalUsingCollectionCountInfoParametersAndModifiers(typeof(T).ToString()); + + public static string CustomCollectionDefaultMarshallerParametersAndModifiers(string elementType) => MarshalUsingCollectionCountInfoParametersAndModifiers($"TestCollection<{elementType}>") + CustomCollectionWithMarshaller(enableDefaultMarshalling: true); + + public static string CustomCollectionDefaultMarshallerParametersAndModifiers() => CustomCollectionDefaultMarshallerParametersAndModifiers(typeof(T).ToString()); + + public static string MarshalUsingCollectionParametersAndModifiers(string collectionType, string marshallerType) => $@" +using System.Runtime.InteropServices; +partial class Test +{{ + [GeneratedDllImport(""DoesNotExist"")] + [return:MarshalUsing(typeof({marshallerType}), ConstantElementCount=10)] + public static partial {collectionType} Method( + [MarshalUsing(typeof({marshallerType}))] {collectionType} p, + [MarshalUsing(typeof({marshallerType}))] in {collectionType} pIn, + int pRefSize, + [MarshalUsing(typeof({marshallerType}), CountElementName = ""pRefSize"")] ref {collectionType} pRef, + [MarshalUsing(typeof({marshallerType}), CountElementName = ""pOutSize"")] out {collectionType} pOut, + out int pOutSize + ); +}}"; + + public static string CustomCollectionCustomMarshallerParametersAndModifiers(string elementType) => MarshalUsingCollectionParametersAndModifiers($"TestCollection<{elementType}>", $"Marshaller<{elementType}>") + CustomCollectionWithMarshaller(enableDefaultMarshalling: false); + + public static string CustomCollectionCustomMarshallerParametersAndModifiers() => CustomCollectionCustomMarshallerParametersAndModifiers(typeof(T).ToString()); + + public static string MarshalUsingCollectionReturnValueLength(string collectionType, string marshallerType) => $@" +using System.Runtime.InteropServices; +partial class Test +{{ + [GeneratedDllImport(""DoesNotExist"")] + public static partial int Method( + [MarshalUsing(typeof({marshallerType}), CountElementName = MarshalUsingAttribute.ReturnsCountValue)] out {collectionType} pOut + ); +}}"; + + public static string CustomCollectionCustomMarshallerReturnValueLength(string elementType) => MarshalUsingCollectionReturnValueLength($"TestCollection<{elementType}>", $"Marshaller<{elementType}>") + CustomCollectionWithMarshaller(enableDefaultMarshalling: false); + + public static string CustomCollectionCustomMarshallerReturnValueLength() => CustomCollectionCustomMarshallerReturnValueLength(typeof(T).ToString()); + + public static string MarshalUsingArrayParameterWithSizeParam(string sizeParamType, bool isByRef) => $@" +using System.Runtime.InteropServices; +partial class Test +{{ + [GeneratedDllImport(""DoesNotExist"")] + public static partial void Method( + {(isByRef ? "ref" : "")} {sizeParamType} pRefSize, + [MarshalUsing(CountElementName = ""pRefSize"")] ref int[] pRef + ); +}}"; + + public static string MarshalUsingArrayParameterWithSizeParam(bool isByRef) => MarshalUsingArrayParameterWithSizeParam(typeof(T).ToString(), isByRef); + + public static string MarshalUsingCollectionWithConstantAndElementCount => $@" +using System.Runtime.InteropServices; +partial class Test +{{ + [GeneratedDllImport(""DoesNotExist"")] + public static partial void Method( + int pRefSize, + [MarshalUsing(ConstantElementCount = 10, CountElementName = ""pRefSize"")] ref int[] pRef + ); +}}"; + + public static string MarshalUsingCollectionWithNullElementName => $@" +using System.Runtime.InteropServices; +partial class Test +{{ + [GeneratedDllImport(""DoesNotExist"")] + public static partial void Method( + int pRefSize, + [MarshalUsing(CountElementName = null)] ref int[] pRef + ); +}}"; + + public static string GenericCollectionMarshallingArityMismatch => BasicParameterByValue("TestCollection") + @" +[NativeMarshalling(typeof(Marshaller<,>))] +class TestCollection {} + +[GenericContiguousCollectionMarshaller] +ref struct Marshaller +{ + public Marshaller(TestCollection managed, int nativeElementSize) : this() {} + public System.Span ManagedValues { get; } + public System.Span NativeValueStorage { get; } + public System.IntPtr Value { get; } + public TestCollection ToManaged() => throw null; +}"; + + public static string GenericCollectionWithCustomElementMarshalling => @" +using System.Runtime.InteropServices; +partial class Test +{ + [GeneratedDllImport(""DoesNotExist"")] + [return:MarshalUsing(ConstantElementCount=10)] + [return:MarshalUsing(typeof(IntWrapper), ElementIndirectionLevel = 1)] + public static partial TestCollection Method( + [MarshalUsing(typeof(IntWrapper), ElementIndirectionLevel = 1)] TestCollection p, + [MarshalUsing(typeof(IntWrapper), ElementIndirectionLevel = 1)] in TestCollection pIn, + int pRefSize, + [MarshalUsing(CountElementName = ""pRefSize""), MarshalUsing(typeof(IntWrapper), ElementIndirectionLevel = 1)] ref TestCollection pRef, + [MarshalUsing(CountElementName = ""pOutSize"")][MarshalUsing(typeof(IntWrapper), ElementIndirectionLevel = 1)] out TestCollection pOut, + out int pOutSize + ); +} + +struct IntWrapper +{ + public IntWrapper(int i){} + public int ToManaged() => throw null; +} + +" + CustomCollectionWithMarshaller(enableDefaultMarshalling: true); + + public static string GenericCollectionWithCustomElementMarshallingDuplicateElementIndirectionLevel => @" +using System.Runtime.InteropServices; +partial class Test +{ + [GeneratedDllImport(""DoesNotExist"")] + public static partial void Method( + [MarshalUsing(typeof(IntWrapper), ElementIndirectionLevel = 1)] [MarshalUsing(typeof(IntWrapper), ElementIndirectionLevel = 1)] TestCollection p); +} + +struct IntWrapper +{ + public IntWrapper(int i){} + public int ToManaged() => throw null; +} + +" + CustomCollectionWithMarshaller(enableDefaultMarshalling: true); + + public static string GenericCollectionWithCustomElementMarshallingUnusedElementIndirectionLevel => @" +using System.Runtime.InteropServices; +partial class Test +{ + [GeneratedDllImport(""DoesNotExist"")] + public static partial void Method( + [MarshalUsing(typeof(IntWrapper), ElementIndirectionLevel = 2)] TestCollection p); +} + +struct IntWrapper +{ + public IntWrapper(int i){} + public int ToManaged() => throw null; +} + +" + CustomCollectionWithMarshaller(enableDefaultMarshalling: true); + + public static string MarshalAsAndMarshalUsingOnReturnValue => @" +using System.Runtime.InteropServices; +partial class Test +{ + [GeneratedDllImport(""DoesNotExist"")] + [return:MarshalUsing(ConstantElementCount=10)] + [return:MarshalAs(UnmanagedType.LPArray, SizeConst=10)] + public static partial int[] Method(); +} +"; + + public static string RecursiveCountElementNameOnReturnValue => @" +using System.Runtime.InteropServices; +partial class Test +{ + [GeneratedDllImport(""DoesNotExist"")] + [return:MarshalUsing(CountElementName=MarshalUsingAttribute.ReturnsCountValue)] + public static partial int[] Method(); +} +"; + + public static string RecursiveCountElementNameOnParameter => @" +using System.Runtime.InteropServices; +partial class Test +{ + [GeneratedDllImport(""DoesNotExist"")] + public static partial void Method( + [MarshalUsing(CountElementName=""arr"")] ref int[] arr + ); +} +"; + public static string MutuallyRecursiveCountElementNameOnParameter => @" +using System.Runtime.InteropServices; +partial class Test +{ + [GeneratedDllImport(""DoesNotExist"")] + public static partial void Method( + [MarshalUsing(CountElementName=""arr2"")] ref int[] arr, + [MarshalUsing(CountElementName=""arr"")] ref int[] arr2 + ); +} +"; + public static string MutuallyRecursiveSizeParamIndexOnParameter => @" +using System.Runtime.InteropServices; +partial class Test +{ + [GeneratedDllImport(""DoesNotExist"")] + public static partial void Method( + [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=1)] ref int[] arr, + [MarshalAs(UnmanagedType.LPArray, SizeParamIndex=0)] ref int[] arr2 + ); +} +"; + + public static string CollectionsOfCollectionsStress => @" +using System.Runtime.InteropServices; +partial class Test +{ + [GeneratedDllImport(""DoesNotExist"")] + public static partial void Method( + [MarshalUsing(CountElementName=""arr0"", ElementIndirectionLevel = 0)] + [MarshalUsing(CountElementName=""arr1"", ElementIndirectionLevel = 1)] + [MarshalUsing(CountElementName=""arr2"", ElementIndirectionLevel = 2)] + [MarshalUsing(CountElementName=""arr3"", ElementIndirectionLevel = 3)] + [MarshalUsing(CountElementName=""arr4"", ElementIndirectionLevel = 4)] + [MarshalUsing(CountElementName=""arr5"", ElementIndirectionLevel = 5)] + [MarshalUsing(CountElementName=""arr6"", ElementIndirectionLevel = 6)] + [MarshalUsing(CountElementName=""arr7"", ElementIndirectionLevel = 7)] + [MarshalUsing(CountElementName=""arr8"", ElementIndirectionLevel = 8)] + [MarshalUsing(CountElementName=""arr9"", ElementIndirectionLevel = 9)] + [MarshalUsing(CountElementName=""arr10"", ElementIndirectionLevel = 10)] ref int[][][][][][][][][][][] arr11, + [MarshalUsing(CountElementName=""arr0"", ElementIndirectionLevel = 0)] + [MarshalUsing(CountElementName=""arr1"", ElementIndirectionLevel = 1)] + [MarshalUsing(CountElementName=""arr2"", ElementIndirectionLevel = 2)] + [MarshalUsing(CountElementName=""arr3"", ElementIndirectionLevel = 3)] + [MarshalUsing(CountElementName=""arr4"", ElementIndirectionLevel = 4)] + [MarshalUsing(CountElementName=""arr5"", ElementIndirectionLevel = 5)] + [MarshalUsing(CountElementName=""arr6"", ElementIndirectionLevel = 6)] + [MarshalUsing(CountElementName=""arr7"", ElementIndirectionLevel = 7)] + [MarshalUsing(CountElementName=""arr8"", ElementIndirectionLevel = 8)] + [MarshalUsing(CountElementName=""arr9"", ElementIndirectionLevel = 9)]ref int[][][][][][][][][][] arr10, + [MarshalUsing(CountElementName=""arr0"", ElementIndirectionLevel = 0)] + [MarshalUsing(CountElementName=""arr1"", ElementIndirectionLevel = 1)] + [MarshalUsing(CountElementName=""arr2"", ElementIndirectionLevel = 2)] + [MarshalUsing(CountElementName=""arr3"", ElementIndirectionLevel = 3)] + [MarshalUsing(CountElementName=""arr4"", ElementIndirectionLevel = 4)] + [MarshalUsing(CountElementName=""arr5"", ElementIndirectionLevel = 5)] + [MarshalUsing(CountElementName=""arr6"", ElementIndirectionLevel = 6)] + [MarshalUsing(CountElementName=""arr7"", ElementIndirectionLevel = 7)] + [MarshalUsing(CountElementName=""arr8"", ElementIndirectionLevel = 8)]ref int[][][][][][][][][] arr9, + [MarshalUsing(CountElementName=""arr0"", ElementIndirectionLevel = 0)] + [MarshalUsing(CountElementName=""arr1"", ElementIndirectionLevel = 1)] + [MarshalUsing(CountElementName=""arr2"", ElementIndirectionLevel = 2)] + [MarshalUsing(CountElementName=""arr3"", ElementIndirectionLevel = 3)] + [MarshalUsing(CountElementName=""arr4"", ElementIndirectionLevel = 4)] + [MarshalUsing(CountElementName=""arr5"", ElementIndirectionLevel = 5)] + [MarshalUsing(CountElementName=""arr6"", ElementIndirectionLevel = 6)] + [MarshalUsing(CountElementName=""arr7"", ElementIndirectionLevel = 7)]ref int[][][][][][][][][] arr8, + [MarshalUsing(CountElementName=""arr0"", ElementIndirectionLevel = 0)] + [MarshalUsing(CountElementName=""arr1"", ElementIndirectionLevel = 1)] + [MarshalUsing(CountElementName=""arr2"", ElementIndirectionLevel = 2)] + [MarshalUsing(CountElementName=""arr3"", ElementIndirectionLevel = 3)] + [MarshalUsing(CountElementName=""arr4"", ElementIndirectionLevel = 4)] + [MarshalUsing(CountElementName=""arr5"", ElementIndirectionLevel = 5)] + [MarshalUsing(CountElementName=""arr6"", ElementIndirectionLevel = 6)]ref int[][][][][][][] arr7, + [MarshalUsing(CountElementName=""arr0"", ElementIndirectionLevel = 0)] + [MarshalUsing(CountElementName=""arr1"", ElementIndirectionLevel = 1)] + [MarshalUsing(CountElementName=""arr2"", ElementIndirectionLevel = 2)] + [MarshalUsing(CountElementName=""arr3"", ElementIndirectionLevel = 3)] + [MarshalUsing(CountElementName=""arr4"", ElementIndirectionLevel = 4)] + [MarshalUsing(CountElementName=""arr5"", ElementIndirectionLevel = 5)]ref int[][][][][][] arr6, + [MarshalUsing(CountElementName=""arr0"", ElementIndirectionLevel = 0)] + [MarshalUsing(CountElementName=""arr1"", ElementIndirectionLevel = 1)] + [MarshalUsing(CountElementName=""arr2"", ElementIndirectionLevel = 2)] + [MarshalUsing(CountElementName=""arr3"", ElementIndirectionLevel = 3)] + [MarshalUsing(CountElementName=""arr4"", ElementIndirectionLevel = 4)]ref int[][][][][] arr5, + [MarshalUsing(CountElementName=""arr0"", ElementIndirectionLevel = 0)] + [MarshalUsing(CountElementName=""arr1"", ElementIndirectionLevel = 1)] + [MarshalUsing(CountElementName=""arr2"", ElementIndirectionLevel = 2)] + [MarshalUsing(CountElementName=""arr3"", ElementIndirectionLevel = 3)]ref int[][][][] arr4, + [MarshalUsing(CountElementName=""arr0"", ElementIndirectionLevel = 0)] + [MarshalUsing(CountElementName=""arr1"", ElementIndirectionLevel = 1)] + [MarshalUsing(CountElementName=""arr2"", ElementIndirectionLevel = 2)]ref int[][][] arr3, + [MarshalUsing(CountElementName=""arr0"", ElementIndirectionLevel = 0)] + [MarshalUsing(CountElementName=""arr1"", ElementIndirectionLevel = 1)]ref int[][] arr2, + [MarshalUsing(CountElementName=""arr0"", ElementIndirectionLevel = 0)]ref int[] arr1, + ref int arr0 + ); +} +"; + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/CompileFails.cs b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/CompileFails.cs new file mode 100644 index 0000000000000..30895d04149d9 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/CompileFails.cs @@ -0,0 +1,170 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Threading.Tasks; + +using Microsoft.CodeAnalysis; +using Xunit; + +namespace DllImportGenerator.UnitTests +{ + public class CompileFails + { + public static IEnumerable CodeSnippetsToCompile() + { + // Not GeneratedDllImportAttribute + yield return new object[] { CodeSnippets.UserDefinedPrefixedAttributes, 0, 3 }; + + // No explicit marshalling for char or string + yield return new object[] { CodeSnippets.BasicParametersAndModifiers(), 5, 0 }; + yield return new object[] { CodeSnippets.BasicParametersAndModifiers(), 5, 0 }; + yield return new object[] { CodeSnippets.BasicParametersAndModifiers(), 5, 0 }; + yield return new object[] { CodeSnippets.BasicParametersAndModifiers(), 5, 0 }; + yield return new object[] { CodeSnippets.PreserveSigFalse(), 3, 0 }; + yield return new object[] { CodeSnippets.PreserveSigFalse(), 3, 0 }; + + // Unsupported CharSet + yield return new object[] { CodeSnippets.BasicParametersAndModifiersWithCharSet(CharSet.Auto), 5, 0 }; + yield return new object[] { CodeSnippets.BasicParametersAndModifiersWithCharSet(CharSet.Ansi), 5, 0 }; + yield return new object[] { CodeSnippets.BasicParametersAndModifiersWithCharSet(CharSet.None), 5, 0 }; + yield return new object[] { CodeSnippets.BasicParametersAndModifiersWithCharSet(CharSet.None), 5, 0 }; + + // Unsupported UnmanagedType + yield return new object[] { CodeSnippets.MarshalAsParametersAndModifiers(UnmanagedType.I1), 5, 0 }; + yield return new object[] { CodeSnippets.MarshalAsParametersAndModifiers(UnmanagedType.U1), 5, 0 }; + yield return new object[] { CodeSnippets.MarshalAsParametersAndModifiers(UnmanagedType.SafeArray), 10, 0 }; + + // Unsupported MarshalAsAttribute usage + // * UnmanagedType.CustomMarshaler, MarshalTypeRef, MarshalType, MarshalCookie + yield return new object[] { CodeSnippets.MarshalAsCustomMarshalerOnTypes, 16, 0 }; + + // Unsupported [In, Out] attributes usage + // Blittable array + yield return new object[] { CodeSnippets.ByValueParameterWithModifier("Out"), 1, 0 }; + yield return new object[] { CodeSnippets.ByValueParameterWithModifier("In, Out"), 1, 0 }; + + // By ref with [In, Out] attributes + yield return new object[] { CodeSnippets.ByValueParameterWithModifier("in int", "In"), 1, 0 }; + yield return new object[] { CodeSnippets.ByValueParameterWithModifier("ref int", "In"), 1, 0 }; + yield return new object[] { CodeSnippets.ByValueParameterWithModifier("ref int", "In, Out"), 1, 0 }; + yield return new object[] { CodeSnippets.ByValueParameterWithModifier("out int", "Out"), 1, 0 }; + + // By value non-array with [In, Out] attributes + yield return new object[] { CodeSnippets.ByValueParameterWithModifier("In"), 1, 0 }; + yield return new object[] { CodeSnippets.ByValueParameterWithModifier("Out"), 1, 0 }; + yield return new object[] { CodeSnippets.ByValueParameterWithModifier("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 }; + + // No size information for array marshalling from unmanaged to managed + // * return, out, ref + yield return new object[] { CodeSnippets.BasicParametersAndModifiers(), 3, 0 }; + yield return new object[] { CodeSnippets.BasicParametersAndModifiers(), 3, 0 }; + yield return new object[] { CodeSnippets.BasicParametersAndModifiers(), 3, 0 }; + yield return new object[] { CodeSnippets.BasicParametersAndModifiers(), 3, 0 }; + yield return new object[] { CodeSnippets.BasicParametersAndModifiers(), 3, 0 }; + yield return new object[] { CodeSnippets.BasicParametersAndModifiers(), 3, 0 }; + yield return new object[] { CodeSnippets.BasicParametersAndModifiers(), 3, 0 }; + yield return new object[] { CodeSnippets.BasicParametersAndModifiers(), 3, 0 }; + yield return new object[] { CodeSnippets.BasicParametersAndModifiers(), 3, 0 }; + yield return new object[] { CodeSnippets.BasicParametersAndModifiers(), 3, 0 }; + yield return new object[] { CodeSnippets.BasicParametersAndModifiers(), 3, 0 }; + yield return new object[] { CodeSnippets.BasicParametersAndModifiers(), 3, 0 }; + yield return new object[] { CodeSnippets.BasicParametersAndModifiers(), 3, 0 }; + + // Collection with non-integer size param + yield return new object[] { CodeSnippets.MarshalAsArrayParameterWithSizeParam(isByRef: false), 1, 0 }; + yield return new object[] { CodeSnippets.MarshalAsArrayParameterWithSizeParam(isByRef: false), 1, 0 }; + yield return new object[] { CodeSnippets.MarshalAsArrayParameterWithSizeParam(isByRef: false), 1, 0 }; + yield return new object[] { CodeSnippets.MarshalUsingArrayParameterWithSizeParam(isByRef: false), 1, 0 }; + yield return new object[] { CodeSnippets.MarshalUsingArrayParameterWithSizeParam(isByRef: false), 1, 0 }; + yield return new object[] { CodeSnippets.MarshalUsingArrayParameterWithSizeParam(isByRef: false), 1, 0 }; + + + // Custom type marshalling with invalid members + yield return new object[] { CodeSnippets.CustomStructMarshallingByRefValueProperty, 3, 0 }; + yield return new object[] { CodeSnippets.CustomStructMarshallingManagedToNativeOnlyOutParameter, 1, 0 }; + yield return new object[] { CodeSnippets.CustomStructMarshallingManagedToNativeOnlyReturnValue, 1, 0 }; + yield return new object[] { CodeSnippets.CustomStructMarshallingNativeToManagedOnlyInParameter, 1, 0 }; + yield return new object[] { CodeSnippets.CustomStructMarshallingStackallocOnlyRefParameter, 1, 0 }; + + // Abstract SafeHandle type by reference + yield return new object[] { CodeSnippets.BasicParameterWithByRefModifier("ref", "System.Runtime.InteropServices.SafeHandle"), 1, 0 }; + + // Non-blittable instantiation of generic type + yield return new object[] { CodeSnippets.MaybeBlittableGenericTypeParametersAndModifiers(), 5, 0 }; + + // No marshalling annotations + + yield return new object[] { CodeSnippets.ImplicitlyBlittableStructParametersAndModifiers("public"), 5, 0 }; + yield return new object[] { CodeSnippets.ImplicitlyBlittableGenericTypeParametersAndModifiers(), 5, 0 }; + yield return new object[] { CodeSnippets.ImplicitlyBlittableGenericTypeParametersAndModifiers("public"), 5, 0 }; + + // Collection with constant and element size parameter + yield return new object[] { CodeSnippets.MarshalUsingCollectionWithConstantAndElementCount, 2, 0 }; + + // Collection with null element size parameter name + yield return new object[] { CodeSnippets.MarshalUsingCollectionWithNullElementName, 2, 0 }; + + // Generic collection marshaller has different arity than collection. + yield return new object[] { CodeSnippets.GenericCollectionMarshallingArityMismatch, 2, 0 }; + + yield return new object[] { CodeSnippets.MarshalAsAndMarshalUsingOnReturnValue, 2, 0 }; + yield return new object[] { CodeSnippets.GenericCollectionWithCustomElementMarshallingDuplicateElementIndirectionLevel, 2, 0 }; + yield return new object[] { CodeSnippets.GenericCollectionWithCustomElementMarshallingUnusedElementIndirectionLevel, 1, 0 }; + yield return new object[] { CodeSnippets.RecursiveCountElementNameOnReturnValue, 2, 0 }; + yield return new object[] { CodeSnippets.RecursiveCountElementNameOnParameter, 2, 0 }; + yield return new object[] { CodeSnippets.MutuallyRecursiveCountElementNameOnParameter, 4, 0 }; + yield return new object[] { CodeSnippets.MutuallyRecursiveSizeParamIndexOnParameter, 4, 0 }; + } + + [Theory] + [MemberData(nameof(CodeSnippetsToCompile))] + public async Task ValidateSnippets(string source, int expectedGeneratorErrors, int expectedCompilerErrors) + { + Compilation comp = await TestUtils.CreateCompilation(source); + TestUtils.AssertPreSourceGeneratorCompilation(comp); + + var newComp = TestUtils.RunGenerators(comp, out var generatorDiags, new Microsoft.Interop.DllImportGenerator()); + + // Verify the compilation failed with errors. + int generatorErrors = generatorDiags.Count(d => d.Severity == DiagnosticSeverity.Error); + Assert.Equal(expectedGeneratorErrors, generatorErrors); + + int compilerErrors = newComp.GetDiagnostics().Count(d => d.Severity == DiagnosticSeverity.Error); + Assert.Equal(expectedCompilerErrors, compilerErrors); + } + + public static IEnumerable CodeSnippetsToCompile_InvalidCode() + { + yield return new object[] { CodeSnippets.RecursiveImplicitlyBlittableStruct, 5, 1 }; + yield return new object[] { CodeSnippets.MutuallyRecursiveImplicitlyBlittableStruct, 5, 2 }; + } + + [Theory] + [MemberData(nameof(CodeSnippetsToCompile_InvalidCode))] + public async Task ValidateSnippets_InvalidCodeGracefulFailure(string source, int expectedGeneratorErrors, int expectedCompilerErrors) + { + // Do not validate that the compilation has no errors that the generator will not fix. + Compilation comp = await TestUtils.CreateCompilation(source); + + var newComp = TestUtils.RunGenerators(comp, out var generatorDiags, new Microsoft.Interop.DllImportGenerator()); + + // Verify the compilation failed with errors. + int generatorErrors = generatorDiags.Count(d => d.Severity == DiagnosticSeverity.Error); + Assert.Equal(expectedGeneratorErrors, generatorErrors); + + int compilerErrors = newComp.GetDiagnostics().Count(d => d.Severity == DiagnosticSeverity.Error); + Assert.Equal(expectedCompilerErrors, compilerErrors); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/Compiles.cs b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/Compiles.cs new file mode 100644 index 0000000000000..a49ac3a06c515 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/Compiles.cs @@ -0,0 +1,393 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.CodeAnalysis; +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Threading.Tasks; +using Xunit; + +namespace DllImportGenerator.UnitTests +{ + public class Compiles + { + public static IEnumerable CodeSnippetsToCompile() + { + yield return new[] { CodeSnippets.TrivialClassDeclarations }; + yield return new[] { CodeSnippets.TrivialStructDeclarations }; + yield return new[] { CodeSnippets.MultipleAttributes }; + yield return new[] { CodeSnippets.NestedNamespace }; + yield return new[] { CodeSnippets.NestedTypes }; + yield return new[] { CodeSnippets.UserDefinedEntryPoint }; + yield return new[] { CodeSnippets.AllSupportedDllImportNamedArguments }; + yield return new[] { CodeSnippets.DefaultParameters }; + yield return new[] { CodeSnippets.UseCSharpFeaturesForConstants }; + + // Parameter / return types + yield return new[] { CodeSnippets.BasicParametersAndModifiers() }; + yield return new[] { CodeSnippets.BasicParametersAndModifiers() }; + yield return new[] { CodeSnippets.BasicParametersAndModifiers() }; + yield return new[] { CodeSnippets.BasicParametersAndModifiers() }; + yield return new[] { CodeSnippets.BasicParametersAndModifiers() }; + yield return new[] { CodeSnippets.BasicParametersAndModifiers() }; + yield return new[] { CodeSnippets.BasicParametersAndModifiers() }; + yield return new[] { CodeSnippets.BasicParametersAndModifiers() }; + yield return new[] { CodeSnippets.BasicParametersAndModifiers() }; + yield return new[] { CodeSnippets.BasicParametersAndModifiers() }; + yield return new[] { CodeSnippets.BasicParametersAndModifiers() }; + yield return new[] { CodeSnippets.BasicParametersAndModifiers() }; + yield return new[] { CodeSnippets.BasicParametersAndModifiers() }; + + // Arrays + yield return new[] { CodeSnippets.MarshalAsArrayParametersAndModifiers() }; + yield return new[] { CodeSnippets.MarshalAsArrayParametersAndModifiers() }; + yield return new[] { CodeSnippets.MarshalAsArrayParametersAndModifiers() }; + yield return new[] { CodeSnippets.MarshalAsArrayParametersAndModifiers() }; + yield return new[] { CodeSnippets.MarshalAsArrayParametersAndModifiers() }; + yield return new[] { CodeSnippets.MarshalAsArrayParametersAndModifiers() }; + yield return new[] { CodeSnippets.MarshalAsArrayParametersAndModifiers() }; + yield return new[] { CodeSnippets.MarshalAsArrayParametersAndModifiers() }; + yield return new[] { CodeSnippets.MarshalAsArrayParametersAndModifiers() }; + yield return new[] { CodeSnippets.MarshalAsArrayParametersAndModifiers() }; + yield return new[] { CodeSnippets.MarshalAsArrayParametersAndModifiers() }; + yield return new[] { CodeSnippets.MarshalAsArrayParametersAndModifiers() }; + yield return new[] { CodeSnippets.MarshalAsArrayParametersAndModifiers() }; + yield return new[] { CodeSnippets.MarshalAsArrayParameterWithSizeParam(isByRef: false) }; + yield return new[] { CodeSnippets.MarshalAsArrayParameterWithSizeParam(isByRef: false) }; + yield return new[] { CodeSnippets.MarshalAsArrayParameterWithSizeParam(isByRef: false) }; + yield return new[] { CodeSnippets.MarshalAsArrayParameterWithSizeParam(isByRef: false) }; + yield return new[] { CodeSnippets.MarshalAsArrayParameterWithSizeParam(isByRef: false) }; + yield return new[] { CodeSnippets.MarshalAsArrayParameterWithSizeParam(isByRef: false) }; + yield return new[] { CodeSnippets.MarshalAsArrayParameterWithSizeParam(isByRef: false) }; + yield return new[] { CodeSnippets.MarshalAsArrayParameterWithSizeParam(isByRef: false) }; + yield return new[] { CodeSnippets.MarshalAsArrayParameterWithSizeParam(isByRef: false) }; + yield return new[] { CodeSnippets.MarshalAsArrayParameterWithSizeParam(isByRef: false) }; + yield return new[] { CodeSnippets.MarshalAsArrayParameterWithSizeParam(isByRef: true) }; + yield return new[] { CodeSnippets.MarshalAsArrayParameterWithSizeParam(isByRef: true) }; + yield return new[] { CodeSnippets.MarshalAsArrayParameterWithSizeParam(isByRef: true) }; + yield return new[] { CodeSnippets.MarshalAsArrayParameterWithSizeParam(isByRef: true) }; + yield return new[] { CodeSnippets.MarshalAsArrayParameterWithSizeParam(isByRef: true) }; + yield return new[] { CodeSnippets.MarshalAsArrayParameterWithSizeParam(isByRef: true) }; + yield return new[] { CodeSnippets.MarshalAsArrayParameterWithSizeParam(isByRef: true) }; + yield return new[] { CodeSnippets.MarshalAsArrayParameterWithSizeParam(isByRef: true) }; + yield return new[] { CodeSnippets.MarshalAsArrayParameterWithSizeParam(isByRef: true) }; + yield return new[] { CodeSnippets.MarshalAsArrayParameterWithSizeParam(isByRef: true) }; + + // CharSet + yield return new[] { CodeSnippets.BasicParametersAndModifiersWithCharSet(CharSet.Unicode) }; + yield return new[] { CodeSnippets.BasicParametersAndModifiersWithCharSet(CharSet.Unicode) }; + yield return new[] { CodeSnippets.BasicParametersAndModifiersWithCharSet(CharSet.Ansi) }; + yield return new[] { CodeSnippets.BasicParametersAndModifiersWithCharSet(CharSet.Auto) }; + + // MarshalAs + yield return new[] { CodeSnippets.MarshalAsParametersAndModifiers(UnmanagedType.Bool) }; + yield return new[] { CodeSnippets.MarshalAsParametersAndModifiers(UnmanagedType.VariantBool) }; + yield return new[] { CodeSnippets.MarshalAsParametersAndModifiers(UnmanagedType.I1) }; + yield return new[] { CodeSnippets.MarshalAsParametersAndModifiers(UnmanagedType.I2) }; + yield return new[] { CodeSnippets.MarshalAsParametersAndModifiers(UnmanagedType.U2) }; + yield return new[] { CodeSnippets.MarshalAsParametersAndModifiers(UnmanagedType.SysInt) }; + yield return new[] { CodeSnippets.MarshalAsParametersAndModifiers(UnmanagedType.SysUInt) }; + yield return new[] { CodeSnippets.MarshalAsParametersAndModifiers(UnmanagedType.LPWStr) }; + yield return new[] { CodeSnippets.MarshalAsParametersAndModifiers(UnmanagedType.LPTStr) }; + yield return new[] { CodeSnippets.MarshalAsParametersAndModifiers(UnmanagedType.LPUTF8Str) }; + yield return new[] { CodeSnippets.MarshalAsParametersAndModifiers(UnmanagedType.LPStr) }; + yield return new[] { CodeSnippets.MarshalAsArrayParameterWithNestedMarshalInfo(UnmanagedType.LPWStr) }; + yield return new[] { CodeSnippets.MarshalAsArrayParameterWithNestedMarshalInfo(UnmanagedType.LPUTF8Str) }; + yield return new[] { CodeSnippets.MarshalAsArrayParameterWithNestedMarshalInfo(UnmanagedType.LPStr) }; + + // [In, Out] attributes + // By value non-blittable array + yield return new[] { CodeSnippets.ByValueParameterWithModifier("Out") }; + yield return new[] { CodeSnippets.ByValueParameterWithModifier("In, Out") }; + + // Enums + yield return new[] { CodeSnippets.EnumParameters }; + + // Pointers + yield return new[] { CodeSnippets.PointerParameters() }; + yield return new[] { CodeSnippets.PointerParameters() }; + yield return new[] { CodeSnippets.PointerParameters() }; + yield return new[] { CodeSnippets.PointerParameters() }; + yield return new[] { CodeSnippets.PointerParameters() }; + yield return new[] { CodeSnippets.PointerParameters() }; + yield return new[] { CodeSnippets.PointerParameters() }; + yield return new[] { CodeSnippets.PointerParameters() }; + yield return new[] { CodeSnippets.PointerParameters() }; + yield return new[] { CodeSnippets.PointerParameters() }; + yield return new[] { CodeSnippets.PointerParameters() }; + yield return new[] { CodeSnippets.PointerParameters() }; + yield return new[] { CodeSnippets.PointerParameters() }; + yield return new[] { CodeSnippets.BasicParametersAndModifiersUnsafe("void*") }; + + // Delegates + yield return new[] { CodeSnippets.DelegateParametersAndModifiers }; + yield return new[] { CodeSnippets.DelegateMarshalAsParametersAndModifiers }; + + // Function pointers + yield return new[] { CodeSnippets.BasicParametersAndModifiersUnsafe("delegate* ") }; + yield return new[] { CodeSnippets.BasicParametersAndModifiersUnsafe("delegate* unmanaged") }; + yield return new[] { CodeSnippets.BasicParametersAndModifiersUnsafe("delegate* unmanaged") }; + yield return new[] { CodeSnippets.BasicParametersAndModifiersUnsafe("delegate* unmanaged[Stdcall]") }; + yield return new[] { CodeSnippets.MarshalAsParametersAndModifiersUnsafe("delegate* ", UnmanagedType.FunctionPtr) }; + yield return new[] { CodeSnippets.MarshalAsParametersAndModifiersUnsafe("delegate* unmanaged", UnmanagedType.FunctionPtr) }; + + // Structs + yield return new[] { CodeSnippets.BlittableStructParametersAndModifiers }; + + // SafeHandle + yield return new[] { CodeSnippets.BasicParametersAndModifiers("Microsoft.Win32.SafeHandles.SafeFileHandle") }; + yield return new[] { CodeSnippets.BasicParameterByValue("System.Runtime.InteropServices.SafeHandle") }; + yield return new[] { CodeSnippets.SafeHandleWithCustomDefaultConstructorAccessibility(privateCtor: false) }; + yield return new[] { CodeSnippets.SafeHandleWithCustomDefaultConstructorAccessibility(privateCtor: true) }; + + // PreserveSig + yield return new[] { CodeSnippets.PreserveSigFalseVoidReturn }; + yield return new[] { CodeSnippets.PreserveSigFalse() }; + yield return new[] { CodeSnippets.PreserveSigFalse() }; + yield return new[] { CodeSnippets.PreserveSigFalse() }; + yield return new[] { CodeSnippets.PreserveSigFalse() }; + yield return new[] { CodeSnippets.PreserveSigFalse() }; + yield return new[] { CodeSnippets.PreserveSigFalse() }; + yield return new[] { CodeSnippets.PreserveSigFalse() }; + yield return new[] { CodeSnippets.PreserveSigFalse() }; + yield return new[] { CodeSnippets.PreserveSigFalse() }; + yield return new[] { CodeSnippets.PreserveSigFalse() }; + yield return new[] { CodeSnippets.PreserveSigFalse() }; + yield return new[] { CodeSnippets.PreserveSigFalse() }; + yield return new[] { CodeSnippets.PreserveSigFalse() }; + yield return new[] { CodeSnippets.PreserveSigFalse("Microsoft.Win32.SafeHandles.SafeFileHandle") }; + yield return new[] { CodeSnippets.ArrayPreserveSigFalse() }; + yield return new[] { CodeSnippets.ArrayPreserveSigFalse() }; + yield return new[] { CodeSnippets.ArrayPreserveSigFalse() }; + yield return new[] { CodeSnippets.ArrayPreserveSigFalse() }; + yield return new[] { CodeSnippets.ArrayPreserveSigFalse() }; + yield return new[] { CodeSnippets.ArrayPreserveSigFalse() }; + yield return new[] { CodeSnippets.ArrayPreserveSigFalse() }; + yield return new[] { CodeSnippets.ArrayPreserveSigFalse() }; + yield return new[] { CodeSnippets.ArrayPreserveSigFalse() }; + yield return new[] { CodeSnippets.ArrayPreserveSigFalse() }; + yield return new[] { CodeSnippets.ArrayPreserveSigFalse() }; + yield return new[] { CodeSnippets.ArrayPreserveSigFalse() }; + yield return new[] { CodeSnippets.ArrayPreserveSigFalse() }; + + // Custom type marshalling + yield return new[] { CodeSnippets.CustomStructMarshallingParametersAndModifiers }; + yield return new[] { CodeSnippets.CustomStructMarshallingStackallocParametersAndModifiersNoRef }; + yield return new[] { CodeSnippets.CustomStructMarshallingStackallocValuePropertyParametersAndModifiersNoRef }; + yield return new[] { CodeSnippets.CustomStructMarshallingOptionalStackallocParametersAndModifiers }; + yield return new[] { CodeSnippets.CustomStructMarshallingValuePropertyParametersAndModifiers }; + yield return new[] { CodeSnippets.CustomStructMarshallingPinnableParametersAndModifiers }; + yield return new[] { CodeSnippets.CustomStructMarshallingNativeTypePinnable }; + yield return new[] { CodeSnippets.CustomStructMarshallingMarshalUsingParametersAndModifiers }; + yield return new[] { CodeSnippets.ArrayMarshallingWithCustomStructElement }; + yield return new[] { CodeSnippets.ArrayMarshallingWithCustomStructElementWithValueProperty }; + + // Escaped C# keyword identifiers + yield return new[] { CodeSnippets.ByValueParameterWithName("Method", "@event") }; + yield return new[] { CodeSnippets.ByValueParameterWithName("Method", "@var") }; + yield return new[] { CodeSnippets.ByValueParameterWithName("@params", "i") }; + + // Generics + yield return new[] { CodeSnippets.MaybeBlittableGenericTypeParametersAndModifiers() }; + yield return new[] { CodeSnippets.MaybeBlittableGenericTypeParametersAndModifiers() }; + yield return new[] { CodeSnippets.MaybeBlittableGenericTypeParametersAndModifiers() }; + yield return new[] { CodeSnippets.MaybeBlittableGenericTypeParametersAndModifiers() }; + yield return new[] { CodeSnippets.MaybeBlittableGenericTypeParametersAndModifiers() }; + yield return new[] { CodeSnippets.MaybeBlittableGenericTypeParametersAndModifiers() }; + yield return new[] { CodeSnippets.MaybeBlittableGenericTypeParametersAndModifiers() }; + yield return new[] { CodeSnippets.MaybeBlittableGenericTypeParametersAndModifiers() }; + yield return new[] { CodeSnippets.MaybeBlittableGenericTypeParametersAndModifiers() }; + yield return new[] { CodeSnippets.MaybeBlittableGenericTypeParametersAndModifiers() }; + yield return new[] { CodeSnippets.MaybeBlittableGenericTypeParametersAndModifiers() }; + yield return new[] { CodeSnippets.MaybeBlittableGenericTypeParametersAndModifiers() }; + + // Implicit blittable types + yield return new[] { CodeSnippets.ImplicitlyBlittableStructParametersAndModifiers() }; + yield return new[] { CodeSnippets.ImplicitlyBlittableStructParametersAndModifiers("internal") }; + yield return new[] { CodeSnippets.ImplicitlyBlittableGenericTypeParametersAndModifiers() }; + yield return new[] { CodeSnippets.ImplicitlyBlittableGenericTypeParametersAndModifiers("internal") }; + + // Custom collection marshalling + yield return new[] { CodeSnippets.CollectionByValue() }; + yield return new[] { CodeSnippets.CollectionByValue() }; + yield return new[] { CodeSnippets.CollectionByValue() }; + yield return new[] { CodeSnippets.CollectionByValue() }; + yield return new[] { CodeSnippets.CollectionByValue() }; + yield return new[] { CodeSnippets.CollectionByValue() }; + yield return new[] { CodeSnippets.CollectionByValue() }; + yield return new[] { CodeSnippets.CollectionByValue() }; + yield return new[] { CodeSnippets.CollectionByValue() }; + yield return new[] { CodeSnippets.CollectionByValue() }; + yield return new[] { CodeSnippets.CollectionByValue() }; + yield return new[] { CodeSnippets.CollectionByValue() }; + yield return new[] { CodeSnippets.CollectionByValue() }; + yield return new[] { CodeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers() }; + yield return new[] { CodeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers() }; + yield return new[] { CodeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers() }; + yield return new[] { CodeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers() }; + yield return new[] { CodeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers() }; + yield return new[] { CodeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers() }; + yield return new[] { CodeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers() }; + yield return new[] { CodeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers() }; + yield return new[] { CodeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers() }; + yield return new[] { CodeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers() }; + yield return new[] { CodeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers() }; + yield return new[] { CodeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers() }; + yield return new[] { CodeSnippets.MarshalUsingCollectionCountInfoParametersAndModifiers() }; + yield return new[] { CodeSnippets.CustomCollectionDefaultMarshallerParametersAndModifiers() }; + yield return new[] { CodeSnippets.CustomCollectionDefaultMarshallerParametersAndModifiers() }; + yield return new[] { CodeSnippets.CustomCollectionDefaultMarshallerParametersAndModifiers() }; + yield return new[] { CodeSnippets.CustomCollectionDefaultMarshallerParametersAndModifiers() }; + yield return new[] { CodeSnippets.CustomCollectionDefaultMarshallerParametersAndModifiers() }; + yield return new[] { CodeSnippets.CustomCollectionDefaultMarshallerParametersAndModifiers() }; + yield return new[] { CodeSnippets.CustomCollectionDefaultMarshallerParametersAndModifiers() }; + yield return new[] { CodeSnippets.CustomCollectionDefaultMarshallerParametersAndModifiers() }; + yield return new[] { CodeSnippets.CustomCollectionDefaultMarshallerParametersAndModifiers() }; + yield return new[] { CodeSnippets.CustomCollectionDefaultMarshallerParametersAndModifiers() }; + yield return new[] { CodeSnippets.CustomCollectionDefaultMarshallerParametersAndModifiers() }; + yield return new[] { CodeSnippets.CustomCollectionDefaultMarshallerParametersAndModifiers() }; + yield return new[] { CodeSnippets.CustomCollectionDefaultMarshallerParametersAndModifiers() }; + yield return new[] { CodeSnippets.CustomCollectionCustomMarshallerParametersAndModifiers() }; + yield return new[] { CodeSnippets.CustomCollectionCustomMarshallerParametersAndModifiers() }; + yield return new[] { CodeSnippets.CustomCollectionCustomMarshallerParametersAndModifiers() }; + yield return new[] { CodeSnippets.CustomCollectionCustomMarshallerParametersAndModifiers() }; + yield return new[] { CodeSnippets.CustomCollectionCustomMarshallerParametersAndModifiers() }; + yield return new[] { CodeSnippets.CustomCollectionCustomMarshallerParametersAndModifiers() }; + yield return new[] { CodeSnippets.CustomCollectionCustomMarshallerParametersAndModifiers() }; + yield return new[] { CodeSnippets.CustomCollectionCustomMarshallerParametersAndModifiers() }; + yield return new[] { CodeSnippets.CustomCollectionCustomMarshallerParametersAndModifiers() }; + yield return new[] { CodeSnippets.CustomCollectionCustomMarshallerParametersAndModifiers() }; + yield return new[] { CodeSnippets.CustomCollectionCustomMarshallerParametersAndModifiers() }; + yield return new[] { CodeSnippets.CustomCollectionCustomMarshallerParametersAndModifiers() }; + yield return new[] { CodeSnippets.CustomCollectionCustomMarshallerParametersAndModifiers() }; + yield return new[] { CodeSnippets.CustomCollectionCustomMarshallerReturnValueLength() }; + yield return new[] { CodeSnippets.GenericCollectionWithCustomElementMarshalling }; + yield return new[] { CodeSnippets.CollectionsOfCollectionsStress }; + } + + [Theory] + [MemberData(nameof(CodeSnippetsToCompile))] + public async Task ValidateSnippets(string source) + { + Compilation comp = await TestUtils.CreateCompilation(source); + TestUtils.AssertPreSourceGeneratorCompilation(comp); + + var newComp = TestUtils.RunGenerators(comp, out var generatorDiags, new Microsoft.Interop.DllImportGenerator()); + Assert.Empty(generatorDiags); + + var newCompDiags = newComp.GetDiagnostics(); + Assert.Empty(newCompDiags); + } + + public static IEnumerable CodeSnippetsToCompileWithPreprocessorSymbols() + { + yield return new object[] { CodeSnippets.PreprocessorIfAroundFullFunctionDefinition("Foo"), new string[] { "Foo" } }; + yield return new object[] { CodeSnippets.PreprocessorIfAroundFullFunctionDefinition("Foo"), Array.Empty() }; + yield return new object[] { CodeSnippets.PreprocessorIfAroundFullFunctionDefinitionWithFollowingFunction("Foo"), new string[] { "Foo" } }; + yield return new object[] { CodeSnippets.PreprocessorIfAroundFullFunctionDefinitionWithFollowingFunction("Foo"), Array.Empty() }; + yield return new object[] { CodeSnippets.PreprocessorIfAfterAttributeAroundFunction("Foo"), new string[] { "Foo" } }; + yield return new object[] { CodeSnippets.PreprocessorIfAfterAttributeAroundFunction("Foo"), Array.Empty() }; + yield return new object[] { CodeSnippets.PreprocessorIfAfterAttributeAroundFunctionAdditionalFunctionAfter("Foo"), new string[] { "Foo" } }; + yield return new object[] { CodeSnippets.PreprocessorIfAfterAttributeAroundFunctionAdditionalFunctionAfter("Foo"), Array.Empty() }; + } + + [Theory] + [MemberData(nameof(CodeSnippetsToCompileWithPreprocessorSymbols))] + public async Task ValidateSnippetsWithPreprocessorDefintions(string source, IEnumerable preprocessorSymbols) + { + Compilation comp = await TestUtils.CreateCompilation(source, preprocessorSymbols: preprocessorSymbols); + TestUtils.AssertPreSourceGeneratorCompilation(comp); + + var newComp = TestUtils.RunGenerators(comp, out var generatorDiags, new Microsoft.Interop.DllImportGenerator()); + Assert.Empty(generatorDiags); + + var newCompDiags = newComp.GetDiagnostics(); + Assert.Empty(newCompDiags); + } + + public static IEnumerable CodeSnippetsToCompileWithForwarder() + { + yield return new[] { CodeSnippets.UserDefinedEntryPoint }; + yield return new[] { CodeSnippets.AllSupportedDllImportNamedArguments }; + + // Parameter / return types (supported in DllImportGenerator) + yield return new[] { CodeSnippets.BasicParametersAndModifiers() }; + // Parameter / return types (not supported in DllImportGenerator) + yield return new[] { CodeSnippets.BasicParametersAndModifiers() }; + } + + [Theory] + [MemberData(nameof(CodeSnippetsToCompileWithForwarder))] + public async Task ValidateSnippetsWithForwarder(string source) + { + Compilation comp = await TestUtils.CreateCompilation(source); + TestUtils.AssertPreSourceGeneratorCompilation(comp); + + var newComp = TestUtils.RunGenerators( + comp, + new DllImportGeneratorOptionsProvider(useMarshalType: false, generateForwarders: true), + out var generatorDiags, + new Microsoft.Interop.DllImportGenerator()); + + Assert.Empty(generatorDiags); + + var newCompDiags = newComp.GetDiagnostics(); + Assert.Empty(newCompDiags); + } + + public static IEnumerable CodeSnippetsToCompileWithMarshalType() + { + yield break; + } + +#pragma warning disable xUnit1004 // Test methods should not be skipped. + // If we have any new experimental APIs that we are implementing that have not been approved, + // we will add new scenarios for this test. + [Theory(Skip = "No current scenarios to test.")] +#pragma warning restore + [MemberData(nameof(CodeSnippetsToCompileWithMarshalType))] + public async Task ValidateSnippetsWithMarshalType(string source) + { + Compilation comp = await TestUtils.CreateCompilation(source); + TestUtils.AssertPreSourceGeneratorCompilation(comp); + + var newComp = TestUtils.RunGenerators( + comp, + new DllImportGeneratorOptionsProvider(useMarshalType: true, generateForwarders: false), + out var generatorDiags, + new Microsoft.Interop.DllImportGenerator()); + + Assert.Empty(generatorDiags); + + var newCompDiags = newComp.GetDiagnostics(); + + Assert.All(newCompDiags, diag => + { + Assert.Equal("CS0117", diag.Id); + Assert.StartsWith("'Marshal' does not contain a definition for ", diag.GetMessage()); + }); + } + + public static IEnumerable CodeSnippetsToCompileMultipleSources() + { + yield return new object[] { new[] { CodeSnippets.BasicParametersAndModifiers(), CodeSnippets.MarshalAsParametersAndModifiers(UnmanagedType.Bool) } }; + yield return new object[] { new[] { CodeSnippets.BasicParametersAndModifiersWithCharSet(CharSet.Unicode), CodeSnippets.MarshalAsParametersAndModifiers(UnmanagedType.Bool) } }; + yield return new object[] { new[] { CodeSnippets.BasicParameterByValue("int[]"), CodeSnippets.BasicParameterWithByRefModifier("ref", "int") } }; + } + + [Theory] + [MemberData(nameof(CodeSnippetsToCompileMultipleSources))] + public async Task ValidateSnippetsWithMultipleSources(string[] sources) + { + Compilation comp = await TestUtils.CreateCompilation(sources); + TestUtils.AssertPreSourceGeneratorCompilation(comp); + + var newComp = TestUtils.RunGenerators(comp, out var generatorDiags, new Microsoft.Interop.DllImportGenerator()); + Assert.Empty(generatorDiags); + + var newCompDiags = newComp.GetDiagnostics(); + Assert.Empty(newCompDiags); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/ConvertToGeneratedDllImportAnalyzerTests.cs b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/ConvertToGeneratedDllImportAnalyzerTests.cs new file mode 100644 index 0000000000000..45cd06a401ccc --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/ConvertToGeneratedDllImportAnalyzerTests.cs @@ -0,0 +1,163 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Xunit; +using static Microsoft.Interop.Analyzers.ConvertToGeneratedDllImportAnalyzer; + +using VerifyCS = DllImportGenerator.UnitTests.Verifiers.CSharpAnalyzerVerifier; + +namespace DllImportGenerator.UnitTests +{ + public class ConvertToGeneratedDllImportAnalyzerTests + { + public static IEnumerable MarshallingRequiredTypes() => new[] + { + new object[] { typeof(bool) }, + new object[] { typeof(char) }, + new object[] { typeof(string) }, + new object[] { typeof(int[]) }, + new object[] { typeof(string[]) }, + new object[] { typeof(ConsoleKeyInfo) }, // struct + }; + + public static IEnumerable NoMarshallingRequiredTypes() => new[] + { + new object[] { typeof(byte) }, + new object[] { typeof(int) }, + new object[] { typeof(byte*) }, + new object[] { typeof(int*) }, + new object[] { typeof(bool*) }, + new object[] { typeof(char*) }, + new object[] { typeof(delegate* ) }, + new object[] { typeof(IntPtr) }, + new object[] { typeof(ConsoleKey) }, // enum + }; + + [Theory] + [MemberData(nameof(MarshallingRequiredTypes))] + public async Task TypeRequiresMarshalling_ReportsDiagnostic(Type type) + { + string source = DllImportWithType(type.FullName!); + await VerifyCS.VerifyAnalyzerAsync( + source, + VerifyCS.Diagnostic(ConvertToGeneratedDllImport) + .WithLocation(0) + .WithArguments("Method_Parameter"), + VerifyCS.Diagnostic(ConvertToGeneratedDllImport) + .WithLocation(1) + .WithArguments("Method_Return")); + } + + [Theory] + [MemberData(nameof(MarshallingRequiredTypes))] + [MemberData(nameof(NoMarshallingRequiredTypes))] + public async Task ByRef_ReportsDiagnostic(Type type) + { + string typeName = type.FullName!; + string source = @$" +using System.Runtime.InteropServices; +unsafe partial class Test +{{ + [DllImport(""DoesNotExist"")] + public static extern void {{|#0:Method_In|}}(in {typeName} p); + + [DllImport(""DoesNotExist"")] + public static extern void {{|#1:Method_Out|}}(out {typeName} p); + + [DllImport(""DoesNotExist"")] + public static extern void {{|#2:Method_Ref|}}(ref {typeName} p); +}} +"; + await VerifyCS.VerifyAnalyzerAsync( + source, + VerifyCS.Diagnostic(ConvertToGeneratedDllImport) + .WithLocation(0) + .WithArguments("Method_In"), + VerifyCS.Diagnostic(ConvertToGeneratedDllImport) + .WithLocation(1) + .WithArguments("Method_Out"), + VerifyCS.Diagnostic(ConvertToGeneratedDllImport) + .WithLocation(2) + .WithArguments("Method_Ref")); + } + + [Fact] + public async Task PreserveSigFalse_ReportsDiagnostic() + { + string source = @$" +using System.Runtime.InteropServices; +partial class Test +{{ + [DllImport(""DoesNotExist"", PreserveSig = false)] + public static extern void {{|#0:Method1|}}(); + + [DllImport(""DoesNotExist"", PreserveSig = true)] + public static extern void Method2(); +}} +"; + await VerifyCS.VerifyAnalyzerAsync( + source, + VerifyCS.Diagnostic(ConvertToGeneratedDllImport) + .WithLocation(0) + .WithArguments("Method1")); + } + + [Fact] + public async Task SetLastErrorTrue_ReportsDiagnostic() + { + string source = @$" +using System.Runtime.InteropServices; +partial class Test +{{ + [DllImport(""DoesNotExist"", SetLastError = false)] + public static extern void Method1(); + + [DllImport(""DoesNotExist"", SetLastError = true)] + public static extern void {{|#0:Method2|}}(); +}} +"; + await VerifyCS.VerifyAnalyzerAsync( + source, + VerifyCS.Diagnostic(ConvertToGeneratedDllImport) + .WithLocation(0) + .WithArguments("Method2")); + } + + [Theory] + [MemberData(nameof(NoMarshallingRequiredTypes))] + public async Task BlittablePrimitive_NoDiagnostic(Type type) + { + string source = DllImportWithType(type.FullName!); + await VerifyCS.VerifyAnalyzerAsync(source); + } + + [Fact] + public async Task NotDllImport_NoDiagnostic() + { + string source = @$" +using System.Runtime.InteropServices; +partial class Test +{{ + public static extern bool Method1(bool p, in bool pIn, ref bool pRef, out bool pOut); + public static extern int Method2(int p, in int pIn, ref int pRef, out int pOut); +}} +"; + await VerifyCS.VerifyAnalyzerAsync(source); + } + + private static string DllImportWithType(string typeName) => @$" +using System.Runtime.InteropServices; +unsafe partial class Test +{{ + [DllImport(""DoesNotExist"")] + public static extern void {{|#0:Method_Parameter|}}({typeName} p); + + [DllImport(""DoesNotExist"")] + public static extern {typeName} {{|#1:Method_Return|}}(); +}} +"; + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/ConvertToGeneratedDllImportFixerTests.cs b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/ConvertToGeneratedDllImportFixerTests.cs new file mode 100644 index 0000000000000..5ac4063756c53 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/ConvertToGeneratedDllImportFixerTests.cs @@ -0,0 +1,370 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Threading.Tasks; +using Xunit; +using static Microsoft.Interop.Analyzers.ConvertToGeneratedDllImportFixer; + +using VerifyCS = DllImportGenerator.UnitTests.Verifiers.CSharpCodeFixVerifier< + Microsoft.Interop.Analyzers.ConvertToGeneratedDllImportAnalyzer, + Microsoft.Interop.Analyzers.ConvertToGeneratedDllImportFixer>; + +namespace DllImportGenerator.UnitTests +{ + public class ConvertToGeneratedDllImportFixerTests + { + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task Basic(bool usePreprocessorDefines) + { + string source = @$" +using System.Runtime.InteropServices; +partial class Test +{{ + [DllImport(""DoesNotExist"")] + public static extern int [|Method|](out int ret); +}}"; + // Fixed source will have CS8795 (Partial method must have an implementation) without generator run + string fixedSource = usePreprocessorDefines + ? @$" +using System.Runtime.InteropServices; +partial class Test +{{ +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(""DoesNotExist"")] + public static partial int {{|CS8795:Method|}}(out int ret); +#else + [DllImport(""DoesNotExist"")] + public static extern int Method(out int ret); +#endif +}}" + : @$" +using System.Runtime.InteropServices; +partial class Test +{{ + [GeneratedDllImport(""DoesNotExist"")] + public static partial int {{|CS8795:Method|}}(out int ret); +}}"; + await VerifyCS.VerifyCodeFixAsync( + source, + fixedSource, + usePreprocessorDefines ? WithPreprocessorDefinesKey : NoPreprocessorDefinesKey); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task Comments(bool usePreprocessorDefines) + { + string source = @$" +using System.Runtime.InteropServices; +partial class Test +{{ + // P/Invoke + [DllImport(/*name*/""DoesNotExist"")] // comment + public static extern int [|Method1|](out int ret); + + /** P/Invoke **/ + [DllImport(""DoesNotExist"") /*name*/] + // < ... > + public static extern int [|Method2|](out int ret); +}}"; + // Fixed source will have CS8795 (Partial method must have an implementation) without generator run + string fixedSource = usePreprocessorDefines + ? @$" +using System.Runtime.InteropServices; +partial class Test +{{ + // P/Invoke +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(/*name*/""DoesNotExist"")] // comment + public static partial int {{|CS8795:Method1|}}(out int ret); +#else + [DllImport(/*name*/""DoesNotExist"")] // comment + public static extern int Method1(out int ret); +#endif + + /** P/Invoke **/ +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(""DoesNotExist"") /*name*/] + // < ... > + public static partial int {{|CS8795:Method2|}}(out int ret); +#else + [DllImport(""DoesNotExist"") /*name*/] + // < ... > + public static extern int Method2(out int ret); +#endif +}}" + : @$" +using System.Runtime.InteropServices; +partial class Test +{{ + // P/Invoke + [GeneratedDllImport(/*name*/""DoesNotExist"")] // comment + public static partial int {{|CS8795:Method1|}}(out int ret); + + /** P/Invoke **/ + [GeneratedDllImport(""DoesNotExist"") /*name*/] + // < ... > + public static partial int {{|CS8795:Method2|}}(out int ret); +}}"; + await VerifyCS.VerifyCodeFixAsync( + source, + fixedSource, + usePreprocessorDefines ? WithPreprocessorDefinesKey : NoPreprocessorDefinesKey); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task MultipleAttributes(bool usePreprocessorDefines) + { + string source = @$" +using System.Runtime.InteropServices; +partial class Test +{{ + [System.ComponentModel.Description(""Test""), DllImport(""DoesNotExist"")] + public static extern int [|Method1|](out int ret); + + [System.ComponentModel.Description(""Test"")] + [DllImport(""DoesNotExist"")] + [return: MarshalAs(UnmanagedType.I4)] + public static extern int [|Method2|](out int ret); +}}"; + // Fixed source will have CS8795 (Partial method must have an implementation) without generator run + string fixedSource = usePreprocessorDefines + ? @$" +using System.Runtime.InteropServices; +partial class Test +{{ +#if DLLIMPORTGENERATOR_ENABLED + [System.ComponentModel.Description(""Test""), GeneratedDllImport(""DoesNotExist"")] + public static partial int {{|CS8795:Method1|}}(out int ret); +#else + [System.ComponentModel.Description(""Test""), DllImport(""DoesNotExist"")] + public static extern int Method1(out int ret); +#endif + +#if DLLIMPORTGENERATOR_ENABLED + [System.ComponentModel.Description(""Test"")] + [GeneratedDllImport(""DoesNotExist"")] + [return: MarshalAs(UnmanagedType.I4)] + public static partial int {{|CS8795:Method2|}}(out int ret); +#else + [System.ComponentModel.Description(""Test"")] + [DllImport(""DoesNotExist"")] + [return: MarshalAs(UnmanagedType.I4)] + public static extern int Method2(out int ret); +#endif +}}" + : @$" +using System.Runtime.InteropServices; +partial class Test +{{ + [System.ComponentModel.Description(""Test""), GeneratedDllImport(""DoesNotExist"")] + public static partial int {{|CS8795:Method1|}}(out int ret); + + [System.ComponentModel.Description(""Test"")] + [GeneratedDllImport(""DoesNotExist"")] + [return: MarshalAs(UnmanagedType.I4)] + public static partial int {{|CS8795:Method2|}}(out int ret); +}}"; + await VerifyCS.VerifyCodeFixAsync( + source, + fixedSource, + usePreprocessorDefines ? WithPreprocessorDefinesKey : NoPreprocessorDefinesKey); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task NamedArguments(bool usePreprocessorDefines) + { + string source = @$" +using System.Runtime.InteropServices; +partial class Test +{{ + [DllImport(""DoesNotExist"", EntryPoint = ""Entry"")] + public static extern int [|Method1|](out int ret); + + [DllImport(""DoesNotExist"", EntryPoint = ""Entry"", CharSet = CharSet.Unicode)] + public static extern int [|Method2|](out int ret); +}}"; + // Fixed source will have CS8795 (Partial method must have an implementation) without generator run + string fixedSource = usePreprocessorDefines + ? @$" +using System.Runtime.InteropServices; +partial class Test +{{ +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(""DoesNotExist"", EntryPoint = ""Entry"")] + public static partial int {{|CS8795:Method1|}}(out int ret); +#else + [DllImport(""DoesNotExist"", EntryPoint = ""Entry"")] + public static extern int Method1(out int ret); +#endif + +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(""DoesNotExist"", EntryPoint = ""Entry"", CharSet = CharSet.Unicode)] + public static partial int {{|CS8795:Method2|}}(out int ret); +#else + [DllImport(""DoesNotExist"", EntryPoint = ""Entry"", CharSet = CharSet.Unicode)] + public static extern int Method2(out int ret); +#endif +}}" : @$" +using System.Runtime.InteropServices; +partial class Test +{{ + [GeneratedDllImport(""DoesNotExist"", EntryPoint = ""Entry"")] + public static partial int {{|CS8795:Method1|}}(out int ret); + + [GeneratedDllImport(""DoesNotExist"", EntryPoint = ""Entry"", CharSet = CharSet.Unicode)] + public static partial int {{|CS8795:Method2|}}(out int ret); +}}"; + await VerifyCS.VerifyCodeFixAsync( + source, + fixedSource, + usePreprocessorDefines ? WithPreprocessorDefinesKey : NoPreprocessorDefinesKey); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task RemoveableNamedArguments(bool usePreprocessorDefines) + { + string source = @$" +using System.Runtime.InteropServices; +partial class Test +{{ + [DllImport(""DoesNotExist"", BestFitMapping = false, EntryPoint = ""Entry"")] + public static extern int [|Method1|](out int ret); + + [DllImport(""DoesNotExist"", ThrowOnUnmappableChar = false)] + public static extern int [|Method2|](out int ret); +}}"; + // Fixed source will have CS8795 (Partial method must have an implementation) without generator run + string fixedSource = usePreprocessorDefines + ? @$" +using System.Runtime.InteropServices; +partial class Test +{{ +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(""DoesNotExist"", EntryPoint = ""Entry"")] + public static partial int {{|CS8795:Method1|}}(out int ret); +#else + [DllImport(""DoesNotExist"", BestFitMapping = false, EntryPoint = ""Entry"")] + public static extern int Method1(out int ret); +#endif + +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(""DoesNotExist"")] + public static partial int {{|CS8795:Method2|}}(out int ret); +#else + [DllImport(""DoesNotExist"", ThrowOnUnmappableChar = false)] + public static extern int Method2(out int ret); +#endif +}}" : @$" +using System.Runtime.InteropServices; +partial class Test +{{ + [GeneratedDllImport(""DoesNotExist"", EntryPoint = ""Entry"")] + public static partial int {{|CS8795:Method1|}}(out int ret); + + [GeneratedDllImport(""DoesNotExist"")] + public static partial int {{|CS8795:Method2|}}(out int ret); +}}"; + await VerifyCS.VerifyCodeFixAsync( + source, + fixedSource, + usePreprocessorDefines ? WithPreprocessorDefinesKey : NoPreprocessorDefinesKey); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public async Task ReplaceableExplicitPlatformDefaultCallingConvention(bool usePreprocessorDefines) + { + string source = @$" +using System.Runtime.InteropServices; +partial class Test +{{ + [DllImport(""DoesNotExist"", CallingConvention = CallingConvention.Winapi, EntryPoint = ""Entry"")] + public static extern int [|Method1|](out int ret); +}}"; + // Fixed source will have CS8795 (Partial method must have an implementation) without generator run + string fixedSource = usePreprocessorDefines + ? @$" +using System.Runtime.InteropServices; +partial class Test +{{ +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(""DoesNotExist"", EntryPoint = ""Entry"")] + public static partial int {{|CS8795:Method1|}}(out int ret); +#else + [DllImport(""DoesNotExist"", CallingConvention = CallingConvention.Winapi, EntryPoint = ""Entry"")] + public static extern int Method1(out int ret); +#endif +}}" : @$" +using System.Runtime.InteropServices; +partial class Test +{{ + [GeneratedDllImport(""DoesNotExist"", EntryPoint = ""Entry"")] + public static partial int {{|CS8795:Method1|}}(out int ret); +}}"; + await VerifyCS.VerifyCodeFixAsync( + source, + fixedSource, + usePreprocessorDefines ? WithPreprocessorDefinesKey : NoPreprocessorDefinesKey); + } + + [Theory] + [InlineData(CallingConvention.Cdecl, typeof(CallConvCdecl), true)] + [InlineData(CallingConvention.Cdecl, typeof(CallConvCdecl), false)] + [InlineData(CallingConvention.StdCall, typeof(CallConvStdcall), true)] + [InlineData(CallingConvention.StdCall, typeof(CallConvStdcall), false)] + [InlineData(CallingConvention.ThisCall, typeof(CallConvThiscall), true)] + [InlineData(CallingConvention.ThisCall, typeof(CallConvThiscall), false)] + [InlineData(CallingConvention.FastCall, typeof(CallConvFastcall), true)] + [InlineData(CallingConvention.FastCall, typeof(CallConvFastcall), false)] + public async Task ReplaceableCallingConvention(CallingConvention callConv, Type callConvType, bool usePreprocessorDefines) + { + string source = @$" +using System.Runtime.InteropServices; +partial class Test +{{ + [DllImport(""DoesNotExist"", CallingConvention = CallingConvention.{callConv}, EntryPoint = ""Entry"")] + public static extern int [|Method1|](out int ret); +}}"; + // Fixed source will have CS8795 (Partial method must have an implementation) without generator run + string fixedSource = usePreprocessorDefines + ? @$" +using System.Runtime.InteropServices; +partial class Test +{{ +#if DLLIMPORTGENERATOR_ENABLED + [GeneratedDllImport(""DoesNotExist"", EntryPoint = ""Entry"")] + [UnmanagedCallConv(CallConvs = new System.Type[] {{ typeof({callConvType.FullName}) }})] + public static partial int {{|CS8795:Method1|}}(out int ret); +#else + [DllImport(""DoesNotExist"", CallingConvention = CallingConvention.{callConv}, EntryPoint = ""Entry"")] + public static extern int Method1(out int ret); +#endif +}}" : @$" +using System.Runtime.InteropServices; +partial class Test +{{ + [GeneratedDllImport(""DoesNotExist"", EntryPoint = ""Entry"")] + [UnmanagedCallConv(CallConvs = new System.Type[] {{ typeof({callConvType.FullName}) }})] + public static partial int {{|CS8795:Method1|}}(out int ret); +}}"; + await VerifyCS.VerifyCodeFixAsync( + source, + fixedSource, + usePreprocessorDefines ? WithPreprocessorDefinesKey : NoPreprocessorDefinesKey); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/Diagnostics.cs b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/Diagnostics.cs new file mode 100644 index 0000000000000..df6da9008696a --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/Diagnostics.cs @@ -0,0 +1,414 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Threading.Tasks; + +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Testing; +using Microsoft.Interop; +using Xunit; + +namespace DllImportGenerator.UnitTests +{ + public class Diagnostics + { + public enum TargetFramework + { + Framework, + Core, + Standard, + Net + } + + [Theory] + [InlineData(TargetFramework.Framework)] + [InlineData(TargetFramework.Core)] + [InlineData(TargetFramework.Standard)] + public async Task TargetFrameworkNotSupported_ReportsDiagnostic(TargetFramework targetFramework) + { + string source = @" +using System.Runtime.InteropServices; +namespace System.Runtime.InteropServices +{ + // Define attribute for pre-.NET 5.0 + sealed class GeneratedDllImportAttribute : System.Attribute + { + public GeneratedDllImportAttribute(string a) { } + } +} +partial class Test +{ + [GeneratedDllImport(""DoesNotExist"")] + public static partial void Method(); +} +"; + Compilation comp = await TestUtils.CreateCompilationWithReferenceAssemblies(source, GetReferenceAssemblies(targetFramework)); + TestUtils.AssertPreSourceGeneratorCompilation(comp); + + var newComp = TestUtils.RunGenerators(comp, out var generatorDiags, new Microsoft.Interop.DllImportGenerator()); + DiagnosticResult[] expectedDiags = new DiagnosticResult[] + { + new DiagnosticResult(GeneratorDiagnostics.TargetFrameworkNotSupported) + .WithArguments("5.0") + }; + VerifyDiagnostics(expectedDiags, GetSortedDiagnostics(generatorDiags)); + + var newCompDiags = newComp.GetDiagnostics(); + Assert.Empty(newCompDiags); + } + + [Theory] + [InlineData(TargetFramework.Framework)] + [InlineData(TargetFramework.Core)] + [InlineData(TargetFramework.Standard)] + public async Task TargetFrameworkNotSupported_NoGeneratedDllImport_NoDiagnostic(TargetFramework targetFramework) + { + string source = @" +using System.Runtime.InteropServices; +partial class Test +{ + [DllImport(""DoesNotExist"")] + public static extern void Method(); +} +"; + Compilation comp = await TestUtils.CreateCompilationWithReferenceAssemblies(source, GetReferenceAssemblies(targetFramework)); + TestUtils.AssertPreSourceGeneratorCompilation(comp); + + var newComp = TestUtils.RunGenerators(comp, out var generatorDiags, new Microsoft.Interop.DllImportGenerator()); + Assert.Empty(generatorDiags); + + var newCompDiags = newComp.GetDiagnostics(); + Assert.Empty(newCompDiags); + } + + [Fact] + public async Task ParameterTypeNotSupported_ReportsDiagnostic() + { + string source = @" +using System.Collections.Generic; +using System.Runtime.InteropServices; +namespace NS +{ + class MyClass { } +} +partial class Test +{ + [GeneratedDllImport(""DoesNotExist"")] + public static partial void Method1(NS.MyClass c); + + [GeneratedDllImport(""DoesNotExist"")] + public static partial void Method2(int i, List list); +} +"; + Compilation comp = await TestUtils.CreateCompilation(source); + TestUtils.AssertPreSourceGeneratorCompilation(comp); + + var newComp = TestUtils.RunGenerators(comp, out var generatorDiags, new Microsoft.Interop.DllImportGenerator()); + DiagnosticResult[] expectedDiags = new DiagnosticResult[] + { + (new DiagnosticResult(GeneratorDiagnostics.ParameterTypeNotSupported)) + .WithSpan(11, 51, 11, 52) + .WithArguments("NS.MyClass", "c"), + (new DiagnosticResult(GeneratorDiagnostics.ParameterTypeNotSupported)) + .WithSpan(14, 57, 14, 61) + .WithArguments("System.Collections.Generic.List", "list"), + }; + VerifyDiagnostics(expectedDiags, GetSortedDiagnostics(generatorDiags)); + + var newCompDiags = newComp.GetDiagnostics(); + Assert.Empty(newCompDiags); + } + + [Fact] + public async Task ReturnTypeNotSupported_ReportsDiagnostic() + { + string source = @" +using System.Collections.Generic; +using System.Runtime.InteropServices; +namespace NS +{ + class MyClass { } +} +partial class Test +{ + [GeneratedDllImport(""DoesNotExist"")] + public static partial NS.MyClass Method1(); + + [GeneratedDllImport(""DoesNotExist"")] + public static partial List Method2(); +} +"; + Compilation comp = await TestUtils.CreateCompilation(source); + TestUtils.AssertPreSourceGeneratorCompilation(comp); + + var newComp = TestUtils.RunGenerators(comp, out var generatorDiags, new Microsoft.Interop.DllImportGenerator()); + DiagnosticResult[] expectedDiags = new DiagnosticResult[] + { + (new DiagnosticResult(GeneratorDiagnostics.ReturnTypeNotSupported)) + .WithSpan(11, 38, 11, 45) + .WithArguments("NS.MyClass", "Method1"), + (new DiagnosticResult(GeneratorDiagnostics.ReturnTypeNotSupported)) + .WithSpan(14, 37, 14, 44) + .WithArguments("System.Collections.Generic.List", "Method2"), + }; + VerifyDiagnostics(expectedDiags, GetSortedDiagnostics(generatorDiags)); + + var newCompDiags = newComp.GetDiagnostics(); + Assert.Empty(newCompDiags); + } + + [Fact] + public async Task ParameterTypeNotSupportedWithDetails_ReportsDiagnostic() + { + string source = @" +using System.Runtime.InteropServices; +partial class Test +{ + [GeneratedDllImport(""DoesNotExist"")] + public static partial void Method(char c, string s); +} +"; + Compilation comp = await TestUtils.CreateCompilation(source); + TestUtils.AssertPreSourceGeneratorCompilation(comp); + + var newComp = TestUtils.RunGenerators(comp, out var generatorDiags, new Microsoft.Interop.DllImportGenerator()); + DiagnosticResult[] expectedDiags = new DiagnosticResult[] + { + (new DiagnosticResult(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)) + .WithSpan(6, 44, 6, 45), + (new DiagnosticResult(GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails)) + .WithSpan(6, 54, 6, 55), + }; + VerifyDiagnostics(expectedDiags, GetSortedDiagnostics(generatorDiags)); + + var newCompDiags = newComp.GetDiagnostics(); + Assert.Empty(newCompDiags); + } + + [Fact] + public async Task ReturnTypeNotSupportedWithDetails_ReportsDiagnostic() + { + string source = @" +using System.Runtime.InteropServices; +partial class Test +{ + [GeneratedDllImport(""DoesNotExist"")] + public static partial char Method1(); + + [GeneratedDllImport(""DoesNotExist"")] + public static partial string Method2(); +} +"; + Compilation comp = await TestUtils.CreateCompilation(source); + TestUtils.AssertPreSourceGeneratorCompilation(comp); + + var newComp = TestUtils.RunGenerators(comp, out var generatorDiags, new Microsoft.Interop.DllImportGenerator()); + DiagnosticResult[] expectedDiags = new DiagnosticResult[] + { + (new DiagnosticResult(GeneratorDiagnostics.ReturnTypeNotSupportedWithDetails)) + .WithSpan(6, 32, 6, 39), + (new DiagnosticResult(GeneratorDiagnostics.ReturnTypeNotSupportedWithDetails)) + .WithSpan(9, 34, 9, 41), + }; + VerifyDiagnostics(expectedDiags, GetSortedDiagnostics(generatorDiags)); + + var newCompDiags = newComp.GetDiagnostics(); + Assert.Empty(newCompDiags); + } + + [Fact] + public async Task ParameterConfigurationNotSupported_ReportsDiagnostic() + { + string source = @" +using System.Runtime.InteropServices; +partial class Test +{ + [GeneratedDllImport(""DoesNotExist"")] + public static partial void Method1([MarshalAs(UnmanagedType.BStr)] int i1, int i2); + + [GeneratedDllImport(""DoesNotExist"")] + public static partial void Method2(bool b1, [MarshalAs(UnmanagedType.FunctionPtr)] bool b2); +} +"; + Compilation comp = await TestUtils.CreateCompilation(source); + TestUtils.AssertPreSourceGeneratorCompilation(comp); + + var newComp = TestUtils.RunGenerators(comp, out var generatorDiags, new Microsoft.Interop.DllImportGenerator()); + DiagnosticResult[] expectedDiags = new DiagnosticResult[] + { + (new DiagnosticResult(GeneratorDiagnostics.ParameterConfigurationNotSupported)) + .WithSpan(6, 76, 6, 78) + .WithArguments(nameof(MarshalAsAttribute), "i1"), + (new DiagnosticResult(GeneratorDiagnostics.ParameterConfigurationNotSupported)) + .WithSpan(9, 93, 9, 95) + .WithArguments(nameof(MarshalAsAttribute), "b2"), + }; + VerifyDiagnostics(expectedDiags, GetSortedDiagnostics(generatorDiags)); + + var newCompDiags = newComp.GetDiagnostics(); + Assert.Empty(newCompDiags); + } + + [Fact] + public async Task ReturnConfigurationNotSupported_ReportsDiagnostic() + { + string source = @" +using System.Runtime.InteropServices; +partial class Test +{ + [GeneratedDllImport(""DoesNotExist"")] + [return: MarshalAs(UnmanagedType.BStr)] + public static partial int Method1(int i); + + [GeneratedDllImport(""DoesNotExist"")] + [return: MarshalAs(UnmanagedType.FunctionPtr)] + public static partial bool Method2(bool b); +} +"; + Compilation comp = await TestUtils.CreateCompilation(source); + TestUtils.AssertPreSourceGeneratorCompilation(comp); + + var newComp = TestUtils.RunGenerators(comp, out var generatorDiags, new Microsoft.Interop.DllImportGenerator()); + DiagnosticResult[] expectedDiags = new DiagnosticResult[] + { + (new DiagnosticResult(GeneratorDiagnostics.ReturnConfigurationNotSupported)) + .WithSpan(7, 31, 7, 38) + .WithArguments(nameof(MarshalAsAttribute), "Method1"), + (new DiagnosticResult(GeneratorDiagnostics.ReturnConfigurationNotSupported)) + .WithSpan(11, 32, 11, 39) + .WithArguments(nameof(MarshalAsAttribute), "Method2"), + }; + VerifyDiagnostics(expectedDiags, GetSortedDiagnostics(generatorDiags)); + + var newCompDiags = newComp.GetDiagnostics(); + Assert.Empty(newCompDiags); + } + + [Fact] + public async Task MarshalAsUnmanagedTypeNotSupported_ReportsDiagnostic() + { + string source = @" +using System.Runtime.InteropServices; +partial class Test +{ + [GeneratedDllImport(""DoesNotExist"")] + [return: MarshalAs(1)] + public static partial int Method1(int i); + + [GeneratedDllImport(""DoesNotExist"")] + public static partial bool Method2([MarshalAs((short)0)] bool b); +} +"; + Compilation comp = await TestUtils.CreateCompilation(source); + TestUtils.AssertPreSourceGeneratorCompilation(comp); + + var newComp = TestUtils.RunGenerators(comp, out var generatorDiags, new Microsoft.Interop.DllImportGenerator()); + DiagnosticResult[] expectedDiags = new DiagnosticResult[] + { + (new DiagnosticResult(GeneratorDiagnostics.ConfigurationValueNotSupported)) + .WithSpan(6, 14, 6, 26) + .WithArguments(1, nameof(UnmanagedType)), + (new DiagnosticResult(GeneratorDiagnostics.ReturnConfigurationNotSupported)) + .WithSpan(7, 31, 7, 38) + .WithArguments(nameof(MarshalAsAttribute), "Method1"), + (new DiagnosticResult(GeneratorDiagnostics.ConfigurationValueNotSupported)) + .WithSpan(10, 41, 10, 60) + .WithArguments(0, nameof(UnmanagedType)), + (new DiagnosticResult(GeneratorDiagnostics.ParameterConfigurationNotSupported)) + .WithSpan(10, 67, 10, 68) + .WithArguments(nameof(MarshalAsAttribute), "b"), + }; + VerifyDiagnostics(expectedDiags, GetSortedDiagnostics(generatorDiags)); + + var newCompDiags = newComp.GetDiagnostics(); + Assert.Empty(newCompDiags); + } + + [Fact] + public async Task MarshalAsFieldNotSupported_ReportsDiagnostic() + { + string source = @" +using System.Runtime.InteropServices; +partial class Test +{ + [GeneratedDllImport(""DoesNotExist"")] + [return: MarshalAs(UnmanagedType.I4, SafeArraySubType=VarEnum.VT_I4)] + public static partial int Method1(int i); + + [GeneratedDllImport(""DoesNotExist"")] + public static partial bool Method2([MarshalAs(UnmanagedType.I1, IidParameterIndex = 1)] bool b); +} +"; + Compilation comp = await TestUtils.CreateCompilation(source); + TestUtils.AssertPreSourceGeneratorCompilation(comp); + + var newComp = TestUtils.RunGenerators(comp, out var generatorDiags, new Microsoft.Interop.DllImportGenerator()); + DiagnosticResult[] expectedDiags = new DiagnosticResult[] + { + (new DiagnosticResult(GeneratorDiagnostics.ConfigurationNotSupported)) + .WithSpan(6, 14, 6, 73) + .WithArguments($"{nameof(MarshalAsAttribute)}{Type.Delimiter}{nameof(MarshalAsAttribute.SafeArraySubType)}"), + (new DiagnosticResult(GeneratorDiagnostics.ConfigurationNotSupported)) + .WithSpan(10, 41, 10, 91) + .WithArguments($"{nameof(MarshalAsAttribute)}{Type.Delimiter}{nameof(MarshalAsAttribute.IidParameterIndex)}"), + }; + VerifyDiagnostics(expectedDiags, GetSortedDiagnostics(generatorDiags)); + var newCompDiags = newComp.GetDiagnostics(); + Assert.Empty(newCompDiags); + } + + private static void VerifyDiagnostics(DiagnosticResult[] expectedDiagnostics, Diagnostic[] actualDiagnostics) + { + Assert.Equal(expectedDiagnostics.Length, actualDiagnostics.Length); + for (var i = 0; i < expectedDiagnostics.Length; i++) + { + DiagnosticResult expected = expectedDiagnostics[i]; + Diagnostic actual = actualDiagnostics[i]; + + Assert.Equal(expected.Id, actual.Id); + Assert.Equal(expected.Severity, actual.Severity); + if (expected.HasLocation) + { + FileLinePositionSpan expectedSpan = expected.Spans[0].Span; + FileLinePositionSpan actualSpan = actual.Location.GetLineSpan(); + Assert.Equal(expectedSpan, actualSpan); + } + + if (expected.MessageArguments is null) + { + Assert.Equal(expected.MessageFormat, actual.Descriptor.MessageFormat); + } + else + { + Assert.Equal(expected.Message, actual.GetMessage()); + } + } + } + + private static Diagnostic[] GetSortedDiagnostics(IEnumerable diagnostics) + { + return diagnostics + .OrderBy(d => d.Location.GetLineSpan().Path, StringComparer.Ordinal) + .ThenBy(d => d.Location.SourceSpan.Start) + .ThenBy(d => d.Location.SourceSpan.End) + .ThenBy(d => d.Id) + .ToArray(); + } + + private static ReferenceAssemblies GetReferenceAssemblies(TargetFramework targetFramework) + { + return targetFramework switch + { + TargetFramework.Framework => ReferenceAssemblies.NetFramework.Net48.Default, + TargetFramework.Standard => ReferenceAssemblies.NetStandard.NetStandard21, + TargetFramework.Core => ReferenceAssemblies.NetCore.NetCoreApp31, + TargetFramework.Net => ReferenceAssemblies.Net.Net50, + _ => ReferenceAssemblies.Default + }; + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/Directory.Build.props b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/Directory.Build.props new file mode 100644 index 0000000000000..fa9c3a4001db5 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/Directory.Build.props @@ -0,0 +1,7 @@ + + + + + true + + diff --git a/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/DllImportGenerator.UnitTests.csproj b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/DllImportGenerator.UnitTests.csproj new file mode 100644 index 0000000000000..6186cea54a53b --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/DllImportGenerator.UnitTests.csproj @@ -0,0 +1,29 @@ + + + + $(NetCoreAppCurrent) + false + Preview + enable + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + + + + diff --git a/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/DllImportGeneratorOptionsProvider.cs b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/DllImportGeneratorOptionsProvider.cs new file mode 100644 index 0000000000000..8459d2fd4425c --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/DllImportGeneratorOptionsProvider.cs @@ -0,0 +1,74 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics.CodeAnalysis; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.Interop; + +namespace DllImportGenerator.UnitTests +{ + /// + /// An implementation of that provides configuration in code + /// of the options supported by the DllImportGenerator source generator. Used for testing various configurations. + /// + internal class DllImportGeneratorOptionsProvider : AnalyzerConfigOptionsProvider + { + public DllImportGeneratorOptionsProvider(bool useMarshalType, bool generateForwarders) + { + GlobalOptions = new GlobalGeneratorOptions(useMarshalType, generateForwarders); + } + + public override AnalyzerConfigOptions GlobalOptions { get; } + + public override AnalyzerConfigOptions GetOptions(SyntaxTree tree) + { + return EmptyOptions.Instance; + } + + public override AnalyzerConfigOptions GetOptions(AdditionalText textFile) + { + return EmptyOptions.Instance; + } + + private class GlobalGeneratorOptions : AnalyzerConfigOptions + { + private readonly bool _useMarshalType = false; + private readonly bool _generateForwarders = false; + public GlobalGeneratorOptions(bool useMarshalType, bool generateForwarders) + { + _useMarshalType = useMarshalType; + _generateForwarders = generateForwarders; + } + + public override bool TryGetValue(string key, [NotNullWhen(true)] out string? value) + { + switch (key) + { + case OptionsHelper.UseMarshalTypeOption: + value = _useMarshalType.ToString(); + return true; + + case OptionsHelper.GenerateForwardersOption: + value = _generateForwarders.ToString(); + return true; + + default: + value = null; + return false; + } + } + } + + private class EmptyOptions : AnalyzerConfigOptions + { + public override bool TryGetValue(string key, [NotNullWhen(true)] out string? value) + { + value = null; + return false; + } + + public static AnalyzerConfigOptions Instance = new EmptyOptions(); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/GeneratedDllImportAnalyzerTests.cs b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/GeneratedDllImportAnalyzerTests.cs new file mode 100644 index 0000000000000..6aae75c8c5add --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/GeneratedDllImportAnalyzerTests.cs @@ -0,0 +1,196 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Threading.Tasks; +using Xunit; +using static Microsoft.Interop.Analyzers.GeneratedDllImportAnalyzer; + +using VerifyCS = DllImportGenerator.UnitTests.Verifiers.CSharpAnalyzerVerifier; + +namespace DllImportGenerator.UnitTests +{ + public class GeneratedDllImportAnalyzerTests + { + [Fact] + public async Task NonPartialMethod_ReportsDiagnostic() + { + string source = @" +using System.Runtime.InteropServices; +partial class Test +{ + [GeneratedDllImport(""DoesNotExist"")] + public static void {|#0:Method1|}() { } + + [GeneratedDllImport(""DoesNotExist"")] + static void {|#1:Method2|}() { } + + [GeneratedDllImport(""DoesNotExist"")] + public static extern void {|#2:ExternMethod1|}(); + + [GeneratedDllImport(""DoesNotExist"")] + static extern void {|#3:ExternMethod2|}(); +} +"; + await VerifyCS.VerifyAnalyzerAsync( + source, + VerifyCS.Diagnostic(GeneratedDllImportMissingModifiers) + .WithLocation(0) + .WithArguments("Method1"), + VerifyCS.Diagnostic(GeneratedDllImportMissingModifiers) + .WithLocation(1) + .WithArguments("Method2"), + VerifyCS.Diagnostic(GeneratedDllImportMissingModifiers) + .WithLocation(2) + .WithArguments("ExternMethod1"), + VerifyCS.Diagnostic(GeneratedDllImportMissingModifiers) + .WithLocation(3) + .WithArguments("ExternMethod2")); + } + + [Fact] + public async Task NonStaticMethod_ReportsDiagnostic() + { + string source = @" +using System.Runtime.InteropServices; +partial class Test +{ + [GeneratedDllImport(""DoesNotExist"")] + public partial void {|#0:Method1|}(); + + [GeneratedDllImport(""DoesNotExist"")] + partial void {|#1:Method2|}(); +} + +partial class Test +{ + public partial void {|#3:Method1|}() { } +} +"; + await VerifyCS.VerifyAnalyzerAsync( + source, + VerifyCS.Diagnostic(GeneratedDllImportMissingModifiers) + .WithLocation(0) + .WithArguments("Method1"), + VerifyCS.Diagnostic(GeneratedDllImportMissingModifiers) + .WithLocation(1) + .WithArguments("Method2"), + VerifyCS.Diagnostic(GeneratedDllImportMissingModifiers) + .WithLocation(3) + .WithArguments("Method1")); + } + + [Fact] + public async Task NonPartialNonStaticMethod_ReportsDiagnostic() + { + string source = @" +using System.Runtime.InteropServices; +partial class Test +{ + [GeneratedDllImport(""DoesNotExist"")] + public void {|#0:Method1|}() { } + + [GeneratedDllImport(""DoesNotExist"")] + void {|#1:Method2|}() { } + + [GeneratedDllImport(""DoesNotExist"")] + public extern void {|#2:ExternMethod1|}(); + + [GeneratedDllImport(""DoesNotExist"")] + extern void {|#3:ExternMethod2|}(); +} +"; + await VerifyCS.VerifyAnalyzerAsync( + source, + VerifyCS.Diagnostic(GeneratedDllImportMissingModifiers) + .WithLocation(0) + .WithArguments("Method1"), + VerifyCS.Diagnostic(GeneratedDllImportMissingModifiers) + .WithLocation(1) + .WithArguments("Method2"), + VerifyCS.Diagnostic(GeneratedDllImportMissingModifiers) + .WithLocation(2) + .WithArguments("ExternMethod1"), + VerifyCS.Diagnostic(GeneratedDllImportMissingModifiers) + .WithLocation(3) + .WithArguments("ExternMethod2")); + } + + [Fact] + public async Task NotGeneratedDllImport_NoDiagnostic() + { + string source = @" +using System.Runtime.InteropServices; +partial class Test +{ + public void Method1() { } + partial void Method2(); +} +"; + await VerifyCS.VerifyAnalyzerAsync(source); + } + + [Fact] + public async Task StaticPartialMethod_NoDiagnostic() + { + string source = @" +using System.Runtime.InteropServices; +partial class Test +{ + [GeneratedDllImport(""DoesNotExist"")] + static partial void Method2(); +} +"; + await VerifyCS.VerifyAnalyzerAsync(source); + } + + [Theory] + [InlineData("class")] + [InlineData("struct")] + [InlineData("record")] + + public async Task NonPartialParentType_Diagnostic(string typeKind) + { + string source = $@" +using System.Runtime.InteropServices; +{typeKind} {{|#0:Test|}} +{{ + [GeneratedDllImport(""DoesNotExist"")] + static partial void {{|CS0751:Method2|}}(); +}} +"; + + await VerifyCS.VerifyAnalyzerAsync( + source, + VerifyCS.Diagnostic(GeneratedDllImportContainingTypeMissingModifiers) + .WithLocation(0) + .WithArguments("Test")); + } + + [Theory] + [InlineData("class")] + [InlineData("struct")] + [InlineData("record")] + + public async Task NonPartialGrandparentType_Diagnostic(string typeKind) + { + + string source = $@" +using System.Runtime.InteropServices; +{typeKind} {{|#0:Test|}} +{{ + partial class TestInner + {{ + [GeneratedDllImport(""DoesNotExist"")] + static partial void Method2(); + }} +}} +"; + + await VerifyCS.VerifyAnalyzerAsync( + source, + VerifyCS.Diagnostic(GeneratedDllImportContainingTypeMissingModifiers) + .WithLocation(0) + .WithArguments("Test")); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/IncrementalGenerationTests.cs b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/IncrementalGenerationTests.cs new file mode 100644 index 0000000000000..75e5de8f546ed --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/IncrementalGenerationTests.cs @@ -0,0 +1,210 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.Text; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Xunit; +using static Microsoft.Interop.DllImportGenerator; + +namespace DllImportGenerator.UnitTests +{ + public class IncrementalGenerationTests + { + public const string RequiresIncrementalSyntaxTreeModifySupport = "The GeneratorDriver treats all SyntaxTree replace operations on a Compilation as an Add/Remove operation instead of a Modify operation" + + ", so all cached results based on that input are thrown out. As a result, we cannot validate that unrelated changes within the same SyntaxTree do not cause regeneration."; + + [Fact] + public async Task AddingNewUnrelatedType_DoesNotRegenerateSource() + { + string source = CodeSnippets.BasicParametersAndModifiers(); + + Compilation comp1 = await TestUtils.CreateCompilation(source); + + Microsoft.Interop.DllImportGenerator generator = new(); + GeneratorDriver driver = TestUtils.CreateDriver(comp1, null, new IIncrementalGenerator[] { generator }); + + driver = driver.RunGenerators(comp1); + + generator.IncrementalTracker = new IncrementalityTracker(); + + Compilation comp2 = comp1.AddSyntaxTrees(CSharpSyntaxTree.ParseText("struct Foo {}", new CSharpParseOptions(LanguageVersion.Preview))); + driver.RunGenerators(comp2); + + Assert.Collection(generator.IncrementalTracker.ExecutedSteps, + step => + { + Assert.Equal(IncrementalityTracker.StepName.CalculateStubInformation, step.Step); + }); + } + +#pragma warning disable xUnit1004 // Test methods should not be skipped. These tests will be updated to use the new incremental work tracking APIs and enabled then. + [Fact(Skip = RequiresIncrementalSyntaxTreeModifySupport)] +#pragma warning restore + public async Task AppendingUnrelatedSource_DoesNotRegenerateSource() + { + string source = $"namespace NS{{{CodeSnippets.BasicParametersAndModifiers()}}}"; + + SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(source, new CSharpParseOptions(LanguageVersion.Preview)); + + Compilation comp1 = await TestUtils.CreateCompilation(new[] { syntaxTree }); + + Microsoft.Interop.DllImportGenerator generator = new(); + GeneratorDriver driver = TestUtils.CreateDriver(comp1, null, new[] { generator }); + + driver = driver.RunGenerators(comp1); + + generator.IncrementalTracker = new IncrementalityTracker(); + + SyntaxTree newTree = syntaxTree.WithRootAndOptions(syntaxTree.GetCompilationUnitRoot().AddMembers(SyntaxFactory.ParseMemberDeclaration("struct Foo {}")!), syntaxTree.Options); + + Compilation comp2 = comp1.ReplaceSyntaxTree(comp1.SyntaxTrees.First(), newTree); + driver.RunGenerators(comp2); + + Assert.Collection(generator.IncrementalTracker.ExecutedSteps, + step => + { + Assert.Equal(IncrementalityTracker.StepName.CalculateStubInformation, step.Step); + }); + } + + [Fact] + public async Task AddingFileWithNewGeneratedDllImport_DoesNotRegenerateOriginalMethod() + { + string source = CodeSnippets.BasicParametersAndModifiers(); + + Compilation comp1 = await TestUtils.CreateCompilation(source); + + Microsoft.Interop.DllImportGenerator generator = new(); + GeneratorDriver driver = TestUtils.CreateDriver(comp1, null, new[] { generator }); + + driver = driver.RunGenerators(comp1); + + generator.IncrementalTracker = new IncrementalityTracker(); + + Compilation comp2 = comp1.AddSyntaxTrees(CSharpSyntaxTree.ParseText(CodeSnippets.BasicParametersAndModifiers(), new CSharpParseOptions(LanguageVersion.Preview))); + driver.RunGenerators(comp2); + + Assert.Equal(2, generator.IncrementalTracker.ExecutedSteps.Count(s => s.Step == IncrementalityTracker.StepName.CalculateStubInformation)); + Assert.Equal(1, generator.IncrementalTracker.ExecutedSteps.Count(s => s.Step == IncrementalityTracker.StepName.GenerateSingleStub)); + Assert.Equal(1, generator.IncrementalTracker.ExecutedSteps.Count(s => s.Step == IncrementalityTracker.StepName.NormalizeWhitespace)); + Assert.Equal(1, generator.IncrementalTracker.ExecutedSteps.Count(s => s.Step == IncrementalityTracker.StepName.ConcatenateStubs)); + Assert.Equal(1, generator.IncrementalTracker.ExecutedSteps.Count(s => s.Step == IncrementalityTracker.StepName.OutputSourceFile)); + } + + [Fact] + public async Task ReplacingFileWithNewGeneratedDllImport_DoesNotRegenerateStubsInOtherFiles() + { + string source = CodeSnippets.BasicParametersAndModifiers(); + + Compilation comp1 = await TestUtils.CreateCompilation(new string[] { CodeSnippets.BasicParametersAndModifiers(), CodeSnippets.BasicParametersAndModifiers() }); + + Microsoft.Interop.DllImportGenerator generator = new(); + GeneratorDriver driver = TestUtils.CreateDriver(comp1, null, new[] { generator }); + + driver = driver.RunGenerators(comp1); + + generator.IncrementalTracker = new IncrementalityTracker(); + + Compilation comp2 = comp1.ReplaceSyntaxTree(comp1.SyntaxTrees.First(), CSharpSyntaxTree.ParseText(CodeSnippets.BasicParametersAndModifiers(), new CSharpParseOptions(LanguageVersion.Preview))); + driver.RunGenerators(comp2); + + Assert.Equal(2, generator.IncrementalTracker.ExecutedSteps.Count(s => s.Step == IncrementalityTracker.StepName.CalculateStubInformation)); + Assert.Equal(1, generator.IncrementalTracker.ExecutedSteps.Count(s => s.Step == IncrementalityTracker.StepName.GenerateSingleStub)); + Assert.Equal(1, generator.IncrementalTracker.ExecutedSteps.Count(s => s.Step == IncrementalityTracker.StepName.NormalizeWhitespace)); + Assert.Equal(1, generator.IncrementalTracker.ExecutedSteps.Count(s => s.Step == IncrementalityTracker.StepName.ConcatenateStubs)); + Assert.Equal(1, generator.IncrementalTracker.ExecutedSteps.Count(s => s.Step == IncrementalityTracker.StepName.OutputSourceFile)); + } + + [Fact] + public async Task ChangingMarshallingStrategy_RegeneratesStub() + { + string stubSource = CodeSnippets.BasicParametersAndModifiers("CustomType"); + + string customTypeImpl1 = "struct CustomType { System.IntPtr handle; }"; + + string customTypeImpl2 = "class CustomType : Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid { public CustomType():base(true){} protected override bool ReleaseHandle(){return true;} }"; + + + Compilation comp1 = await TestUtils.CreateCompilation(stubSource); + + SyntaxTree customTypeImpl1Tree = CSharpSyntaxTree.ParseText(customTypeImpl1, new CSharpParseOptions(LanguageVersion.Preview)); + comp1 = comp1.AddSyntaxTrees(customTypeImpl1Tree); + + Microsoft.Interop.DllImportGenerator generator = new(); + GeneratorDriver driver = TestUtils.CreateDriver(comp1, null, new[] { generator }); + + driver = driver.RunGenerators(comp1); + + generator.IncrementalTracker = new IncrementalityTracker(); + + Compilation comp2 = comp1.ReplaceSyntaxTree(customTypeImpl1Tree, CSharpSyntaxTree.ParseText(customTypeImpl2, new CSharpParseOptions(LanguageVersion.Preview))); + driver.RunGenerators(comp2); + + Assert.Collection(generator.IncrementalTracker.ExecutedSteps, + step => + { + Assert.Equal(IncrementalityTracker.StepName.CalculateStubInformation, step.Step); + }, + step => + { + Assert.Equal(IncrementalityTracker.StepName.GenerateSingleStub, step.Step); + }, + step => + { + Assert.Equal(IncrementalityTracker.StepName.NormalizeWhitespace, step.Step); + }, + step => + { + Assert.Equal(IncrementalityTracker.StepName.ConcatenateStubs, step.Step); + }, + step => + { + Assert.Equal(IncrementalityTracker.StepName.OutputSourceFile, step.Step); + }); + } + +#pragma warning disable xUnit1004 // Test methods should not be skipped. These tests will be updated to use the new incremental work tracking APIs and enabled then. + [Fact(Skip = RequiresIncrementalSyntaxTreeModifySupport)] +#pragma warning restore + public async Task ChangingMarshallingAttributes_SameStrategy_DoesNotRegenerate() + { + string source = CodeSnippets.BasicParametersAndModifiers(); + + SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(source, new CSharpParseOptions(LanguageVersion.Preview)); + + Compilation comp1 = await TestUtils.CreateCompilation(new[] { syntaxTree }); + + Microsoft.Interop.DllImportGenerator generator = new(); + GeneratorDriver driver = TestUtils.CreateDriver(comp1, null, new[] { generator }); + + driver = driver.RunGenerators(comp1); + + generator.IncrementalTracker = new IncrementalityTracker(); + + SyntaxTree newTree = syntaxTree.WithRootAndOptions( + syntaxTree.GetCompilationUnitRoot().AddMembers( + SyntaxFactory.ParseMemberDeclaration( + CodeSnippets.MarshalAsParametersAndModifiers(System.Runtime.InteropServices.UnmanagedType.Bool))!), + syntaxTree.Options); + + Compilation comp2 = comp1.ReplaceSyntaxTree(comp1.SyntaxTrees.First(), newTree); + driver.RunGenerators(comp2); + + Assert.Collection(generator.IncrementalTracker.ExecutedSteps, + step => + { + Assert.Equal(IncrementalityTracker.StepName.CalculateStubInformation, step.Step); + }, + step => + { + Assert.Equal(IncrementalityTracker.StepName.GenerateSingleStub, step.Step); + }); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/ManualTypeMarshallingAnalyzerTests.cs b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/ManualTypeMarshallingAnalyzerTests.cs new file mode 100644 index 0000000000000..dc8981b28c4fb --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/ManualTypeMarshallingAnalyzerTests.cs @@ -0,0 +1,1517 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Testing; +using System.Collections.Generic; +using System.Threading.Tasks; +using Xunit; +using static Microsoft.Interop.Analyzers.ManualTypeMarshallingAnalyzer; + +using VerifyCS = DllImportGenerator.UnitTests.Verifiers.CSharpAnalyzerVerifier; + +namespace DllImportGenerator.UnitTests +{ + public class ManualTypeMarshallingAnalyzerTests + { + public static IEnumerable NonBlittableTypeMarkedBlittable_ReportsDiagnostic_TestData { + get + { + yield return new object[] + { + @" +using System.Runtime.InteropServices; + +[{|#0:BlittableType|}] +struct S +{ + public bool field; +} +" + }; + yield return new object[] + { + @" +using System.Runtime.InteropServices; + +[{|#0:BlittableType|}] +struct S +{ + public char field; +} +" + }; + yield return new object[] + { + +@" +using System.Runtime.InteropServices; + +[{|#0:BlittableType|}] +struct S +{ + public string field; +} +" + }; + } + } + + [MemberData(nameof(NonBlittableTypeMarkedBlittable_ReportsDiagnostic_TestData))] + [Theory] + public async Task NonBlittableTypeMarkedBlittable_ReportsDiagnostic(string source) + { + var diagnostic = VerifyCS.Diagnostic(BlittableTypeMustBeBlittableRule).WithLocation(0).WithArguments("S"); + await VerifyCS.VerifyAnalyzerAsync(source, diagnostic); + } + + [Fact] + public async Task BlittablePrimitiveFields_MarkedBlittable_NoDiagnostic() + { + + string source = @" +using System.Runtime.InteropServices; + +[BlittableType] +struct S +{ + public int field; +} +"; + await VerifyCS.VerifyAnalyzerAsync(source); + } + + [Fact] + public async Task BlittableEnumFields_MarkedBlittable_NoDiagnostic() + { + + string source = @" +using System.Runtime.InteropServices; + +enum E { Zero, One, Two } + +[BlittableType] +struct S +{ + public E field; +} +"; + await VerifyCS.VerifyAnalyzerAsync(source); + } + + [Fact] + public async Task BlittableStructFields_MarkedBlittable_NoDiagnostic() + { + string source = @" +using System.Runtime.InteropServices; + +[BlittableType] +struct S +{ + public T field; +} + +[BlittableType] +struct T +{ + public int field; +} +"; + await VerifyCS.VerifyAnalyzerAsync(source); + } + + [Fact] + public async Task NonBlittableFields_MarkedBlittable_ReportDiagnosticOnFieldTypeDefinition() + { + string source = @" +using System.Runtime.InteropServices; + +[BlittableType] +struct S +{ + public T field; +} + +[{|#0:BlittableType|}] +struct T +{ + public bool field; +} +"; + var diagnostic = VerifyCS.Diagnostic(BlittableTypeMustBeBlittableRule).WithLocation(0).WithArguments("T"); + await VerifyCS.VerifyAnalyzerAsync(source, diagnostic); + } + + [Fact] + public async Task NonUnmanagedTypeMarkedBlittable_ReportsDiagnosticOnStructType() + { + string source = @" +using System.Runtime.InteropServices; + +[BlittableType] +struct S +{ + public T field; +} + +[{|#0:BlittableType|}] +struct T +{ + public string field; +} +"; + await VerifyCS.VerifyAnalyzerAsync(source, + VerifyCS.Diagnostic(BlittableTypeMustBeBlittableRule).WithLocation(0).WithArguments("T")); + } + + [Fact] + public async Task BlittableTypeWithNonBlittableStaticField_DoesNotReportDiagnostic() + { + string source = @" +using System.Runtime.InteropServices; + +[BlittableType] +struct S +{ + public static string Static; + public int instance; +} +"; + await VerifyCS.VerifyAnalyzerAsync(source); + } + + [Fact] + public async Task NullNativeType_ReportsDiagnostic() + { + string source = @" +using System.Runtime.InteropServices; + +[{|#0:NativeMarshalling(null)|}] +struct S +{ + public string s; +}"; + + await VerifyCS.VerifyAnalyzerAsync(source, + VerifyCS.Diagnostic(NativeTypeMustBeNonNullRule).WithLocation(0).WithArguments("S")); + } + + [Fact] + public async Task NonNamedNativeType_ReportsDiagnostic() + { + string source = @" +using System.Runtime.InteropServices; + +[{|#0:NativeMarshalling(typeof(int*))|}] +struct S +{ + public string s; +}"; + + await VerifyCS.VerifyAnalyzerAsync(source, + VerifyCS.Diagnostic(NativeTypeMustHaveRequiredShapeRule).WithLocation(0).WithArguments("int*", "S")); + } + + [Fact] + public async Task NonBlittableNativeType_ReportsDiagnostic() + { + string source = @" +using System.Runtime.InteropServices; + +[NativeMarshalling(typeof(Native))] +struct S +{ + public string s; +} + +struct {|#0:Native|} +{ + private string value; + + public Native(S s) + { + value = s.s; + } + + public S ToManaged() => new S { s = value }; +}"; + await VerifyCS.VerifyAnalyzerAsync(source, + VerifyCS.Diagnostic(NativeTypeMustBeBlittableRule).WithLocation(0).WithArguments("Native", "S")); + } + + [Fact] + public async Task ClassNativeType_ReportsDiagnostic() + { + string source = @" +using System; +using System.Runtime.InteropServices; + +[NativeMarshalling(typeof(Native))] +struct S +{ + public string s; +} + +class {|#0:Native|} +{ + private IntPtr value; + + public Native(S s) + { + } + + public S ToManaged() => new S(); +}"; + await VerifyCS.VerifyAnalyzerAsync(source, + VerifyCS.Diagnostic(NativeTypeMustHaveRequiredShapeRule).WithLocation(0).WithArguments("Native", "S")); + } + + [Fact] + public async Task BlittableNativeType_DoesNotReportDiagnostic() + { + string source = @" +using System; +using System.Runtime.InteropServices; + +[NativeMarshalling(typeof(Native))] +struct S +{ + public string s; +} + +[BlittableType] +struct Native +{ + private IntPtr value; + + public Native(S s) + { + value = IntPtr.Zero; + } + + public S ToManaged() => new S(); +}"; + + await VerifyCS.VerifyAnalyzerAsync(source); + } + + [Fact] + public async Task BlittableNativeWithNonBlittableValueProperty_ReportsDiagnostic() + { + string source = @" +using System; +using System.Runtime.InteropServices; + +[NativeMarshalling(typeof(Native))] +struct S +{ + public string s; +} + +[BlittableType] +struct Native +{ + private IntPtr value; + + public Native(S s) + { + value = IntPtr.Zero; + } + + public S ToManaged() => new S(); + + public string {|#0:Value|} { get => null; set {} } +}"; + + await VerifyCS.VerifyAnalyzerAsync(source, + VerifyCS.Diagnostic(NativeTypeMustBeBlittableRule).WithLocation(0).WithArguments("string", "S")); + } + + [Fact] + public async Task NonBlittableNativeTypeWithBlittableValueProperty_DoesNotReportDiagnostic() + { + string source = @" +using System; +using System.Runtime.InteropServices; + +[NativeMarshalling(typeof(Native))] +struct S +{ + public string s; +} + +struct Native +{ + private string value; + + public Native(S s) + { + value = s.s; + } + + public S ToManaged() => new S() { s = value }; + + public IntPtr Value { get => IntPtr.Zero; set {} } +}"; + + await VerifyCS.VerifyAnalyzerAsync(source); + } + + [Fact] + public async Task ClassNativeTypeWithValueProperty_ReportsDiagnostic() + { + string source = @" +using System; +using System.Runtime.InteropServices; + +[NativeMarshalling(typeof(Native))] +struct S +{ + public string s; +} + +class {|#0:Native|} +{ + private string value; + + public Native(S s) + { + value = s.s; + } + + public S ToManaged() => new S() { s = value }; + + public IntPtr Value { get => IntPtr.Zero; set {} } +}"; + + await VerifyCS.VerifyAnalyzerAsync(source, + VerifyCS.Diagnostic(NativeTypeMustHaveRequiredShapeRule).WithLocation(0).WithArguments("Native", "S")); + } + + [Fact] + public async Task NonBlittableGetPinnableReferenceReturnType_ReportsDiagnostic() + { + string source = @" +using System; +using System.Runtime.InteropServices; + +[NativeMarshalling(typeof(Native))] +class S +{ + public char c; + + public ref char {|#0:GetPinnableReference|}() => ref c; +} + +unsafe struct Native +{ + private IntPtr value; + + public Native(S s) + { + value = IntPtr.Zero; + } + + public S ToManaged() => new S(); + + public IntPtr Value { get => IntPtr.Zero; set {} } +}"; + + await VerifyCS.VerifyAnalyzerAsync(source, + VerifyCS.Diagnostic(GetPinnableReferenceReturnTypeBlittableRule).WithLocation(0)); + } + + + [Fact] + public async Task BlittableGetPinnableReferenceReturnType_DoesNotReportDiagnostic() + { + string source = @" +using System; +using System.Runtime.InteropServices; + +[NativeMarshalling(typeof(Native))] +class S +{ + public byte c; + + public ref byte GetPinnableReference() => ref c; +} + +unsafe struct Native +{ + private IntPtr value; + + public Native(S s) : this() + { + value = IntPtr.Zero; + } + + public S ToManaged() => new S(); + + public IntPtr Value { get => IntPtr.Zero; set {} } +}"; + + await VerifyCS.VerifyAnalyzerAsync(source); + } + + [Fact] + public async Task TypeWithGetPinnableReferenceNonPointerReturnType_ReportsDiagnostic() + { + string source = @" +using System; +using System.Runtime.InteropServices; + +[NativeMarshalling(typeof(Native))] +class S +{ + public byte c; + + public ref byte GetPinnableReference() => ref c; +} + +unsafe struct Native +{ + private IntPtr value; + + public Native(S s) : this() + { + value = IntPtr.Zero; + } + + public S ToManaged() => new S(); + + public int {|#0:Value|} { get => 0; set {} } +}"; + + await VerifyCS.VerifyAnalyzerAsync(source, + VerifyCS.Diagnostic(NativeTypeMustBePointerSizedRule).WithLocation(0).WithArguments("int", "S")); + } + + [Fact] + public async Task TypeWithGetPinnableReferencePointerReturnType_DoesNotReportDiagnostic() + { + string source = @" +using System; +using System.Runtime.InteropServices; + +[NativeMarshalling(typeof(Native))] +class S +{ + public byte c; + + public ref byte GetPinnableReference() => ref c; +} + +unsafe struct Native +{ + private IntPtr value; + + public Native(S s) : this() + { + value = IntPtr.Zero; + } + + public S ToManaged() => new S(); + + public int* Value { get => null; set {} } +}"; + + await VerifyCS.VerifyAnalyzerAsync(source); + } + + [Fact] + public async Task TypeWithGetPinnableReferenceByRefReturnType_ReportsDiagnostic() + { + string source = @" +using System; +using System.Runtime.InteropServices; + +[NativeMarshalling(typeof(Native))] +class S +{ + public byte c; + + public ref byte GetPinnableReference() => ref c; +} + +unsafe struct Native +{ + private S value; + + public Native(S s) : this() + { + value = s; + } + + public ref byte {|#0:Value|} { get => ref value.GetPinnableReference(); } +}"; + + await VerifyCS.VerifyAnalyzerAsync(source, + VerifyCS.Diagnostic(RefValuePropertyUnsupportedRule).WithLocation(0).WithArguments("Native")); + } + + [Fact] + public async Task NativeTypeWithGetPinnableReferenceByRefReturnType_ReportsDiagnostic() + { + string source = @" +using System; +using System.Runtime.InteropServices; + +[NativeMarshalling(typeof(Native))] +class S +{ + public byte c; +} + +unsafe struct Native +{ + private S value; + + public Native(S s) : this() + { + value = s; + } + + public ref byte GetPinnableReference() => ref value.c; + + public ref byte {|#0:Value|} { get => ref GetPinnableReference(); } +}"; + + await VerifyCS.VerifyAnalyzerAsync(source, + VerifyCS.Diagnostic(RefValuePropertyUnsupportedRule).WithLocation(0).WithArguments("Native")); + } + + [Fact] + public async Task BlittableValueTypeWithNoFields_DoesNotReportDiagnostic() + { + string source = @" +using System; +using System.Runtime.InteropServices; + +[BlittableType] +struct S +{ +}"; + + await VerifyCS.VerifyAnalyzerAsync(source); + } + + [Fact] + public async Task NativeTypeWithNoMarshallingMethods_ReportsDiagnostic() + { + string source = @" +using System; +using System.Runtime.InteropServices; + +[NativeMarshalling(typeof(Native))] +class S +{ + public byte c; +} + +[BlittableType] +struct {|#0:Native|} +{ +}"; + + await VerifyCS.VerifyAnalyzerAsync(source, + VerifyCS.Diagnostic(NativeTypeMustHaveRequiredShapeRule).WithLocation(0).WithArguments("Native", "S")); + } + + [Fact] + public async Task CollectionNativeTypeWithNoMarshallingMethods_ReportsDiagnostic() + { + string source = @" +using System; +using System.Runtime.InteropServices; + +[NativeMarshalling(typeof(Native))] +class S +{ + public byte c; +} + +[GenericContiguousCollectionMarshaller] +struct {|#0:Native|} +{ +}"; + + await VerifyCS.VerifyAnalyzerAsync(source, + VerifyCS.Diagnostic(CollectionNativeTypeMustHaveRequiredShapeRule).WithLocation(0).WithArguments("Native", "S")); + } + + [Fact] + public async Task CollectionNativeTypeWithWrongConstructor_ReportsDiagnostic() + { + string source = @" +using System; +using System.Runtime.InteropServices; + +[NativeMarshalling(typeof(Native))] +class S +{ + public byte c; +} + +[GenericContiguousCollectionMarshaller] +ref struct {|#0:Native|} +{ + public Native(S s) : this() {} + + public Span ManagedValues { get; set; } + public Span NativeValueStorage { get; set; } + + public IntPtr Value { get; } +}"; + + await VerifyCS.VerifyAnalyzerAsync(source, + VerifyCS.Diagnostic(CollectionNativeTypeMustHaveRequiredShapeRule).WithLocation(0).WithArguments("Native", "S")); + } + + [Fact] + public async Task CollectionNativeTypeWithCorrectConstructor_DoesNotReportDiagnostic() + { + string source = @" +using System; +using System.Runtime.InteropServices; + +[NativeMarshalling(typeof(Native))] +class S +{ + public byte c; +} + +[GenericContiguousCollectionMarshaller] +ref struct Native +{ + public Native(S s, int nativeElementSize) : this() {} + + public Span ManagedValues { get; set; } + public Span NativeValueStorage { get; set; } + + public IntPtr Value { get; } +}"; + + await VerifyCS.VerifyAnalyzerAsync(source); + } + + [Fact] + public async Task CollectionNativeTypeWithIncorrectStackallocConstructor_ReportsDiagnostic() + { + string source = @" +using System; +using System.Runtime.InteropServices; + +[NativeMarshalling(typeof(Native))] +class S +{ + public byte c; +} + +[GenericContiguousCollectionMarshaller] +ref struct {|#0:Native|} +{ + public Native(S s, Span stackSpace) : this() {} + + public const int StackBufferSize = 1; + + public Span ManagedValues { get; set; } + public Span NativeValueStorage { get; set; } + + public IntPtr Value { get; } +}"; + + await VerifyCS.VerifyAnalyzerAsync(source, + VerifyCS.Diagnostic(CollectionNativeTypeMustHaveRequiredShapeRule).WithLocation(0).WithArguments("Native", "S")); + } + + [Fact] + public async Task CollectionNativeTypeWithOnlyStackallocConstructor_ReportsDiagnostic() + { + string source = @" +using System; +using System.Runtime.InteropServices; + +[NativeMarshalling(typeof(Native))] +class S +{ + public byte c; +} + +[GenericContiguousCollectionMarshaller] +ref struct {|#0:Native|} +{ + public Native(S s, Span stackSpace, int nativeElementSize) : this() {} + + public const int StackBufferSize = 1; + + public Span ManagedValues { get; set; } + public Span NativeValueStorage { get; set; } + + public IntPtr Value { get; } +}"; + + await VerifyCS.VerifyAnalyzerAsync(source, + VerifyCS.Diagnostic(StackallocMarshallingShouldSupportAllocatingMarshallingFallbackRule).WithLocation(0).WithArguments("Native", "S")); + } + + [Fact] + public async Task CollectionNativeTypeWithMissingManagedValuesProperty_ReportsDiagnostic() + { + string source = @" +using System; +using System.Runtime.InteropServices; + +[NativeMarshalling(typeof(Native))] +class S +{ + public byte c; +} + +[GenericContiguousCollectionMarshaller] +ref struct {|#0:Native|} +{ + public Native(S s, int nativeElementSize) : this() {} + + public Span NativeValueStorage { get; set; } + + public IntPtr Value { get; } +}"; + + await VerifyCS.VerifyAnalyzerAsync(source, + VerifyCS.Diagnostic(CollectionNativeTypeMustHaveRequiredShapeRule).WithLocation(0).WithArguments("Native", "S")); + } + + [Fact] + public async Task CollectionNativeTypeWithMissingNativeValueStorageProperty_ReportsDiagnostic() + { + string source = @" +using System; +using System.Runtime.InteropServices; + +[NativeMarshalling(typeof(Native))] +class S +{ + public byte c; +} + +[GenericContiguousCollectionMarshaller] +ref struct {|#0:Native|} +{ + public Native(S s, int nativeElementSize) : this() {} + + public Span ManagedValues { get; set; } + + public IntPtr Value { get; } +}"; + + await VerifyCS.VerifyAnalyzerAsync(source, + VerifyCS.Diagnostic(CollectionNativeTypeMustHaveRequiredShapeRule).WithLocation(0).WithArguments("Native", "S")); + } + + [Fact] + public async Task NativeTypeWithOnlyConstructor_DoesNotReportDiagnostic() + { + string source = @" +using System; +using System.Runtime.InteropServices; + +[NativeMarshalling(typeof(Native))] +class S +{ + public byte c; +} + +[BlittableType] +struct Native +{ + public Native(S s) {} +}"; + + await VerifyCS.VerifyAnalyzerAsync(source); + } + + [Fact] + public async Task NativeTypeWithOnlyToManagedMethod_DoesNotReportDiagnostic() + { + string source = @" +using System; +using System.Runtime.InteropServices; + +[NativeMarshalling(typeof(Native))] +class S +{ + public byte c; +} + +[BlittableType] +struct Native +{ + public S ToManaged() => new S(); +}"; + + await VerifyCS.VerifyAnalyzerAsync(source); + } + + [Fact] + public async Task NativeTypeWithOnlyStackallocConstructor_ReportsDiagnostic() + { + string source = @" +using System; +using System.Runtime.InteropServices; + +[NativeMarshalling(typeof(Native))] +class S +{ + public byte c; +} + +[BlittableType] +struct {|#0:Native|} +{ + public Native(S s, Span buffer) {} + + public const int StackBufferSize = 0x100; +}"; + + await VerifyCS.VerifyAnalyzerAsync(source, + VerifyCS.Diagnostic(StackallocMarshallingShouldSupportAllocatingMarshallingFallbackRule).WithLocation(0).WithArguments("Native")); + } + + [Fact] + public async Task TypeWithOnlyNativeStackallocConstructorAndGetPinnableReference_ReportsDiagnostics() + { + string source = @" +using System; +using System.Runtime.InteropServices; + +[{|#0:NativeMarshalling(typeof(Native))|}] +class S +{ + public byte c; + public ref byte GetPinnableReference() => ref c; +} + +struct {|#1:Native|} +{ + public Native(S s, Span buffer) {} + + public IntPtr Value => IntPtr.Zero; + + public const int StackBufferSize = 0x100; +}"; + + await VerifyCS.VerifyAnalyzerAsync(source, + VerifyCS.Diagnostic(StackallocMarshallingShouldSupportAllocatingMarshallingFallbackRule).WithLocation(1).WithArguments("Native"), + VerifyCS.Diagnostic(GetPinnableReferenceShouldSupportAllocatingMarshallingFallbackRule).WithLocation(0).WithArguments("S", "Native")); + } + + [Fact] + public async Task NativeTypeWithConstructorAndSetOnlyValueProperty_ReportsDiagnostic() + { + string source = @" +using System; +using System.Runtime.InteropServices; + +[NativeMarshalling(typeof(Native))] +class S +{ + public byte c; +} + +struct Native +{ + public Native(S s) {} + + public IntPtr {|#0:Value|} { set {} } +}"; + + await VerifyCS.VerifyAnalyzerAsync(source, + VerifyCS.Diagnostic(ValuePropertyMustHaveGetterRule).WithLocation(0).WithArguments("Native")); + } + + [Fact] + public async Task NativeTypeWithToManagedAndGetOnlyValueProperty_ReportsDiagnostic() + { + string source = @" +using System; +using System.Runtime.InteropServices; + +[NativeMarshalling(typeof(Native))] +class S +{ + public byte c; +} + +struct Native +{ + public S ToManaged() => new S(); + + public IntPtr {|#0:Value|} => IntPtr.Zero; +}"; + + await VerifyCS.VerifyAnalyzerAsync(source, + VerifyCS.Diagnostic(ValuePropertyMustHaveSetterRule).WithLocation(0).WithArguments("Native")); + } + + [Fact] + public async Task BlittableNativeTypeOnMarshalUsingParameter_DoesNotReportDiagnostic() + { + string source = @" +using System; +using System.Runtime.InteropServices; + +struct S +{ + public string s; +} + +[BlittableType] +struct Native +{ + private IntPtr value; + + public Native(S s) + { + value = IntPtr.Zero; + } + + public S ToManaged() => new S(); +} + + +static class Test +{ + static void Foo([MarshalUsing(typeof(Native))] S s) + {} +} +"; + await VerifyCS.VerifyAnalyzerAsync(source); + } + + [Fact] + public async Task NonBlittableNativeTypeOnMarshalUsingParameter_ReportsDiagnostic() + { + string source = @" +using System; +using System.Runtime.InteropServices; + +struct S +{ + public string s; +} + +struct {|#0:Native|} +{ + private string value; + + public Native(S s) : this() + { + } + + public S ToManaged() => new S(); +} + + +static class Test +{ + static void Foo([MarshalUsing(typeof(Native))] S s) + {} +} +"; + await VerifyCS.VerifyAnalyzerAsync(source, + VerifyCS.Diagnostic(NativeTypeMustBeBlittableRule).WithLocation(0).WithArguments("Native", "S")); + } + + [Fact] + public async Task NonBlittableNativeTypeOnMarshalUsingParameter_MultipleCompilations_ReportsDiagnostic_WithLocation() + { + string source1 = @" +using System; +using System.Runtime.InteropServices; + +public struct S +{ + public string s; +} + +public struct Native +{ + private string value; + + public Native(S s) : this() + { + } + + public S ToManaged() => new S(); +} +"; + Compilation compilation1 = await TestUtils.CreateCompilation(source1); + + string source2 = @" +using System; +using System.Runtime.InteropServices; + +static class Test +{ + static void Foo([{|#0:MarshalUsing(typeof(Native))|}] S s) + {} +} +"; + var test = new Verifiers.CSharpCodeFixVerifier.Test + { + ExpectedDiagnostics = + { + VerifyCS.Diagnostic(NativeTypeMustBeBlittableRule).WithLocation(0).WithArguments("Native", "S") + }, + SolutionTransforms = + { + (solution, projectId) => solution.AddMetadataReference(projectId, compilation1.ToMetadataReference()) + }, + TestCode = source2 + }; + + await test.RunAsync(); + } + + [Fact] + public async Task NonBlittableNativeTypeOnMarshalUsingReturn_ReportsDiagnostic() + { + string source = @" +using System; +using System.Runtime.InteropServices; + +struct S +{ + public string s; +} + +struct {|#0:Native|} +{ + private string value; + + public Native(S s) : this() + { + } + + public S ToManaged() => new S(); +} + + +static class Test +{ + [return: MarshalUsing(typeof(Native))] + static S Foo() => new S(); +} +"; + await VerifyCS.VerifyAnalyzerAsync(source, + VerifyCS.Diagnostic(NativeTypeMustBeBlittableRule).WithLocation(0).WithArguments("Native", "S")); + } + + [Fact] + public async Task NonBlittableNativeTypeOnMarshalUsingField_ReportsDiagnostic() + { + string source = @" +using System; +using System.Runtime.InteropServices; + +struct S +{ + public string s; +} + +struct {|#0:Native|} +{ + private string value; + + public Native(S s) : this() + { + } + + public S ToManaged() => new S(); +} + + +struct Test +{ + [MarshalUsing(typeof(Native))] + S s; +} +"; + await VerifyCS.VerifyAnalyzerAsync(source, + VerifyCS.Diagnostic(NativeTypeMustBeBlittableRule).WithLocation(0).WithArguments("Native", "S")); + } + + + [Fact] + public async Task GenericNativeTypeWithValueTypeValueProperty_DoesNotReportDiagnostic() + { + string source = @" +using System.Runtime.InteropServices; + +[NativeMarshalling(typeof(Native))] +struct S +{ + public string s; +} + +struct Native + where T : new() +{ + public Native(T s) + { + Value = 0; + } + + public T ToManaged() => new T(); + + public int Value { get; set; } +}"; + await VerifyCS.VerifyAnalyzerAsync(source); + } + + [Fact] + public async Task GenericNativeTypeWithGenericMemberInstantiatedWithBlittable_DoesNotReportDiagnostic() + { + + string source = @" +using System.Runtime.InteropServices; + +[NativeMarshalling(typeof(Native))] +struct S +{ + public string s; +} + +struct Native + where T : new() +{ + public Native(S s) + { + Value = new T(); + } + + public S ToManaged() => new S(); + + public T Value { get; set; } +}"; + await VerifyCS.VerifyAnalyzerAsync(source); + } + + [Fact] + public async Task UninstantiatedGenericNativeTypeOnNonGeneric_ReportsDiagnostic() + { + + string source = @" +using System.Runtime.InteropServices; + +[{|#0:NativeMarshalling(typeof(Native<>))|}] +struct S +{ + public string s; +} + +struct Native + where T : new() +{ + public Native(S s) + { + Value = new T(); + } + + public S ToManaged() => new S(); + + public T Value { get; set; } +}"; + await VerifyCS.VerifyAnalyzerAsync(source, VerifyCS.Diagnostic(NativeGenericTypeMustBeClosedOrMatchArityRule).WithLocation(0).WithArguments("Native<>", "S")); + } + + [Fact] + public async Task UninstantiatedGenericNativeTypeOnGenericWithArityMismatch_ReportsDiagnostic() + { + string source = @" +using System.Runtime.InteropServices; + +[{|#0:NativeMarshalling(typeof(Native<,>))|}] +struct S +{ + public string s; +} + +struct Native + where T : new() +{ + public Native(S s) + { + Value = 0; + } + + public S ToManaged() => new S(); + + public int Value { get; set; } +}"; + await VerifyCS.VerifyAnalyzerAsync(source, VerifyCS.Diagnostic(NativeGenericTypeMustBeClosedOrMatchArityRule).WithLocation(0).WithArguments("Native<,>", "S")); + } + + [Fact] + public async Task UninstantiatedGenericNativeTypeOnGenericWithArityMatch_DoesNotReportDiagnostic() + { + string source = @" +using System.Runtime.InteropServices; + +[NativeMarshalling(typeof(Native<>))] +struct S +{ + public T t; +} + +struct Native + where T : new() +{ + public Native(S s) + { + Value = 0; + } + + public S ToManaged() => new S(); + + public int Value { get; set; } +}"; + await VerifyCS.VerifyAnalyzerAsync(source); + } + + [Fact] + public async Task ValueTypeContainingPointerBlittableType_DoesNotReportDiagnostic() + { + var source = @" +using System.Runtime.InteropServices; + +[BlittableType] +unsafe struct S +{ + private int* ptr; +}"; + await VerifyCS.VerifyAnalyzerAsync(source); + } + + [Fact] + public async Task ValueTypeContainingPointerToNonBlittableType_ReportsDiagnostic() + { + var source = @" +using System.Runtime.InteropServices; + +[{|#0:BlittableType|}] +unsafe struct S +{ + private bool* ptr; +}"; + await VerifyCS.VerifyAnalyzerAsync(source, + VerifyCS.Diagnostic(BlittableTypeMustBeBlittableRule).WithLocation(0).WithArguments("S")); + } + + [Fact] + public async Task BlittableValueTypeContainingPointerToSelf_DoesNotReportDiagnostic() + { + + var source = @" +using System.Runtime.InteropServices; + +[BlittableType] +unsafe struct S +{ + private int fld; + private S* ptr; +}"; + await VerifyCS.VerifyAnalyzerAsync(source); + } + + [Fact] + public async Task NonBlittableValueTypeContainingPointerToSelf_ReportsDiagnostic() + { + var source = @" +using System.Runtime.InteropServices; + +[{|#0:BlittableType|}] +unsafe struct S +{ + private bool fld; + private S* ptr; +}"; + await VerifyCS.VerifyAnalyzerAsync(source, + VerifyCS.Diagnostic(BlittableTypeMustBeBlittableRule).WithLocation(0).WithArguments("S")); + } + + [Fact] + public async Task BlittableTypeContainingFunctionPointer_DoesNotReportDiagnostic() + { + var source = @" +using System.Runtime.InteropServices; + +[BlittableType] +unsafe struct S +{ + private delegate* ptr; +}"; + await VerifyCS.VerifyAnalyzerAsync(source); + } + + [Fact] + public async Task BlittableGenericTypeInBlittableType_DoesNotReportDiagnostic() + { + + var source = @" +using System.Runtime.InteropServices; + +[BlittableType] +struct G +{ + T fld; +} + +[BlittableType] +unsafe struct S +{ + private G field; +}"; + await VerifyCS.VerifyAnalyzerAsync(source); + } + + [Fact] + public async Task NonBlittableGenericTypeInBlittableType_ReportsDiagnostic() + { + var source = @" +using System.Runtime.InteropServices; + +[BlittableType] +struct G +{ + T fld; +} + +[{|#0:BlittableType|}] +unsafe struct S +{ + private G field; +}"; + await VerifyCS.VerifyAnalyzerAsync(source, + VerifyCS.Diagnostic(BlittableTypeMustBeBlittableRule).WithLocation(0).WithArguments("S")); + } + + [Fact] + public async Task BlittableGenericTypeTypeParameterReferenceType_ReportsDiagnostic() + { + var source = @" +using System.Runtime.InteropServices; + +[{|#0:BlittableType|}] +struct G where T : class +{ + T fld; +}"; + await VerifyCS.VerifyAnalyzerAsync(source, + VerifyCS.Diagnostic(BlittableTypeMustBeBlittableRule).WithLocation(0).WithArguments("G")); + } + + [Fact] + public async Task BlittableGenericTypeContainingGenericType_DoesNotReportDiagnostic() + { + var source = @" +using System.Runtime.InteropServices; + +[BlittableType] +struct G +{ + T fld; +} + +[BlittableType] +struct F +{ + G fld; +} +"; + await VerifyCS.VerifyAnalyzerAsync(source); + } + + [Fact] + public async Task BlittableNestedGenericType_DoesNotReportDiagnostic() + { + var source = @" +using System.Runtime.InteropServices; + +struct C +{ + [BlittableType] + public struct G + { + T fld; + } +} + +[BlittableType] +struct S +{ + C.G g; +} +"; + await VerifyCS.VerifyAnalyzerAsync(source); + } + + [Fact] + public async Task BlittableNestedGenericTypeWithReferenceTypeGenericParameter_DoesNotReportDiagnostic() + { + var source = @" +using System.Runtime.InteropServices; + +struct C where T : class +{ + [{|#0:BlittableType|}] + struct G + { + T fld; + } +} +"; + await VerifyCS.VerifyAnalyzerAsync(source, + VerifyCS.Diagnostic(BlittableTypeMustBeBlittableRule).WithLocation(0).WithArguments("C.G")); + } + + [Fact] + public async Task BlittableGenericTypeWithReferenceTypeParameterNotUsedInFieldType_DoesNotReportDiagnostic() + { + var source = @" +using System.Runtime.InteropServices; + +[BlittableType] +struct G where U : class +{ + T fld; +}"; + await VerifyCS.VerifyAnalyzerAsync(source); + } + + [Fact] + public async Task NativeTypeWithStackallocConstructorWithoutBufferSize_ReportsDiagnostic() + { + string source = @" +using System; +using System.Runtime.InteropServices; + +[NativeMarshalling(typeof(Native))] +class S +{ + public byte c; +} + +[BlittableType] +struct Native +{ + public Native(S s) {} + public {|#0:Native|}(S s, Span buffer) {} +}"; + + await VerifyCS.VerifyAnalyzerAsync(source, + VerifyCS.Diagnostic(StackallocConstructorMustHaveStackBufferSizeConstantRule).WithLocation(0).WithArguments("Native")); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/TestUtils.cs b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/TestUtils.cs new file mode 100644 index 0000000000000..41e52104f1643 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/TestUtils.cs @@ -0,0 +1,169 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing; +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace DllImportGenerator.UnitTests +{ + internal static class TestUtils + { + /// + /// Assert the pre-srouce generator compilation has only + /// the expected failure diagnostics. + /// + /// + public static void AssertPreSourceGeneratorCompilation(Compilation comp) + { + var allowedDiagnostics = new HashSet() + { + "CS8795", // Partial method impl missing + "CS0234", // Missing type or namespace - GeneratedDllImportAttribute + "CS0246", // Missing type or namespace - GeneratedDllImportAttribute + "CS8019", // Unnecessary using + }; + var compDiags = comp.GetDiagnostics(); + Assert.All(compDiags, diag => + { + Assert.Subset(allowedDiagnostics, new HashSet { diag.Id }); + }); + } + + /// + /// Create a compilation given source + /// + /// Source to compile + /// Output type + /// Whether or not use of the unsafe keyword should be allowed + /// The resulting compilation + public static Task CreateCompilation(string source, OutputKind outputKind = OutputKind.DynamicallyLinkedLibrary, bool allowUnsafe = true, IEnumerable? preprocessorSymbols = null) + { + return CreateCompilation(new[] { source }, outputKind, allowUnsafe, preprocessorSymbols); + } + + /// + /// Create a compilation given sources + /// + /// Sources to compile + /// Output type + /// Whether or not use of the unsafe keyword should be allowed + /// The resulting compilation + public static Task CreateCompilation(string[] sources, OutputKind outputKind = OutputKind.DynamicallyLinkedLibrary, bool allowUnsafe = true, IEnumerable? preprocessorSymbols = null) + { + return CreateCompilation( + sources.Select(source => + CSharpSyntaxTree.ParseText(source, new CSharpParseOptions(LanguageVersion.Preview, preprocessorSymbols: preprocessorSymbols))).ToArray(), + outputKind, + allowUnsafe, + preprocessorSymbols); + } + + /// + /// Create a compilation given sources + /// + /// Sources to compile + /// Output type + /// Whether or not use of the unsafe keyword should be allowed + /// The resulting compilation + public static async Task CreateCompilation(SyntaxTree[] sources, OutputKind outputKind = OutputKind.DynamicallyLinkedLibrary, bool allowUnsafe = true, IEnumerable? preprocessorSymbols = null) + { + var (mdRefs, ancillary) = GetReferenceAssemblies(); + + return CSharpCompilation.Create("compilation", + sources, + (await mdRefs.ResolveAsync(LanguageNames.CSharp, CancellationToken.None)).Add(ancillary), + new CSharpCompilationOptions(outputKind, allowUnsafe: allowUnsafe)); + } + + /// + /// Create a compilation given source and reference assemblies + /// + /// Source to compile + /// Reference assemblies to include + /// Output type + /// Whether or not use of the unsafe keyword should be allowed + /// The resulting compilation + public static Task CreateCompilationWithReferenceAssemblies(string source, ReferenceAssemblies referenceAssemblies, OutputKind outputKind = OutputKind.DynamicallyLinkedLibrary, bool allowUnsafe = true) + { + return CreateCompilationWithReferenceAssemblies(new[] { CSharpSyntaxTree.ParseText(source, new CSharpParseOptions(LanguageVersion.Preview)) }, referenceAssemblies, outputKind, allowUnsafe); + } + + /// + /// Create a compilation given source and reference assemblies + /// + /// Source to compile + /// Reference assemblies to include + /// Output type + /// Whether or not use of the unsafe keyword should be allowed + /// The resulting compilation + public static async Task CreateCompilationWithReferenceAssemblies(SyntaxTree[] sources, ReferenceAssemblies referenceAssemblies, OutputKind outputKind = OutputKind.DynamicallyLinkedLibrary, bool allowUnsafe = true) + { + return CSharpCompilation.Create("compilation", + sources, + (await referenceAssemblies.ResolveAsync(LanguageNames.CSharp, CancellationToken.None)), + new CSharpCompilationOptions(outputKind, allowUnsafe: allowUnsafe)); + } + + public static (ReferenceAssemblies, MetadataReference) GetReferenceAssemblies() + { + // TODO: When .NET 6.0 releases, we can simplify this. + var referenceAssemblies = new ReferenceAssemblies( + "net6.0", + new PackageIdentity( + "Microsoft.NETCore.App.Ref", + "6.0.0-preview.7.21377.19"), + Path.Combine("ref", "net6.0")) + .WithNuGetConfigFilePath(Path.Combine(Path.GetDirectoryName(typeof(TestUtils).Assembly.Location)!, "NuGet.config")); + + // Include the assembly containing the new attribute and all of its references. + // [TODO] Remove once the attribute has been added to the BCL + var attrAssem = typeof(GeneratedDllImportAttribute).GetTypeInfo().Assembly; + + return (referenceAssemblies, MetadataReference.CreateFromFile(attrAssem.Location)); + } + + /// + /// Run the supplied generators on the compilation. + /// + /// Compilation target + /// Resulting diagnostics + /// Source generator instances + /// The resulting compilation + public static Compilation RunGenerators(Compilation comp, out ImmutableArray diagnostics, params IIncrementalGenerator[] generators) + { + CreateDriver(comp, null, generators).RunGeneratorsAndUpdateCompilation(comp, out var d, out diagnostics); + return d; + } + + /// + /// Run the supplied generators on the compilation. + /// + /// Compilation target + /// Resulting diagnostics + /// Source generator instances + /// The resulting compilation + public static Compilation RunGenerators(Compilation comp, AnalyzerConfigOptionsProvider options, out ImmutableArray diagnostics, params IIncrementalGenerator[] generators) + { + CreateDriver(comp, options, generators).RunGeneratorsAndUpdateCompilation(comp, out var d, out diagnostics); + return d; + } + + public static GeneratorDriver CreateDriver(Compilation c, AnalyzerConfigOptionsProvider? options, IIncrementalGenerator[] generators) + => CSharpGeneratorDriver.Create( + ImmutableArray.Create(generators.Select(gen => gen.AsSourceGenerator()).ToArray()), + parseOptions: (CSharpParseOptions)c.SyntaxTrees.First().Options, + optionsProvider: options); + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/Verifiers/CSharpAnalyzerVerifier.cs b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/Verifiers/CSharpAnalyzerVerifier.cs new file mode 100644 index 0000000000000..bd54db652e4c2 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/Verifiers/CSharpAnalyzerVerifier.cs @@ -0,0 +1,45 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Testing.XUnit; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing; + +namespace DllImportGenerator.UnitTests.Verifiers +{ + public static class CSharpAnalyzerVerifier + where TAnalyzer : DiagnosticAnalyzer, new() + { + /// + public static DiagnosticResult Diagnostic() + => AnalyzerVerifier.Diagnostic(); + + /// + public static DiagnosticResult Diagnostic(string diagnosticId) + => AnalyzerVerifier.Diagnostic(diagnosticId); + + /// + public static DiagnosticResult Diagnostic(DiagnosticDescriptor descriptor) + => AnalyzerVerifier.Diagnostic(descriptor); + + /// + public static async Task VerifyAnalyzerAsync(string source, params DiagnosticResult[] expected) + { + var test = new Test + { + TestCode = source, + }; + + test.ExpectedDiagnostics.AddRange(expected); + await test.RunAsync(CancellationToken.None); + } + + // Code fix tests support both analyzer and code fix testing. This test class is derived from the code fix test + // to avoid the need to maintain duplicate copies of the customization work. + internal class Test : CSharpCodeFixVerifier.Test + { } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/Verifiers/CSharpCodeFixVerifier.cs b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/Verifiers/CSharpCodeFixVerifier.cs new file mode 100644 index 0000000000000..136c88a9cd45d --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/Verifiers/CSharpCodeFixVerifier.cs @@ -0,0 +1,121 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Immutable; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Testing; +using Microsoft.CodeAnalysis.CSharp.Testing.XUnit; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Testing; +using Microsoft.CodeAnalysis.Testing.Verifiers; + +namespace DllImportGenerator.UnitTests.Verifiers +{ + public static class CSharpCodeFixVerifier + where TAnalyzer : DiagnosticAnalyzer, new() + where TCodeFix : CodeFixProvider, new() + { + /// + public static DiagnosticResult Diagnostic() + => CodeFixVerifier.Diagnostic(); + + /// + public static DiagnosticResult Diagnostic(string diagnosticId) + => CodeFixVerifier.Diagnostic(diagnosticId); + + /// + public static DiagnosticResult Diagnostic(DiagnosticDescriptor descriptor) + => CodeFixVerifier.Diagnostic(descriptor); + + /// + public static async Task VerifyAnalyzerAsync(string source, params DiagnosticResult[] expected) + { + var test = new Test + { + TestCode = source, + }; + + test.ExpectedDiagnostics.AddRange(expected); + await test.RunAsync(CancellationToken.None); + } + + /// + public static async Task VerifyCodeFixAsync(string source, string fixedSource, string? codeActionEquivalenceKey = null) + => await VerifyCodeFixAsync(source, DiagnosticResult.EmptyDiagnosticResults, fixedSource, codeActionEquivalenceKey); + + /// + public static async Task VerifyCodeFixAsync(string source, DiagnosticResult expected, string fixedSource, string? codeActionEquivalenceKey = null) + => await VerifyCodeFixAsync(source, new[] { expected }, fixedSource, codeActionEquivalenceKey); + + /// + public static async Task VerifyCodeFixAsync(string source, DiagnosticResult[] expected, string fixedSource, string? codeActionEquivalenceKey = null) + { + var test = new Test + { + TestCode = source, + FixedCode = fixedSource, + CodeActionEquivalenceKey = codeActionEquivalenceKey, + CodeActionValidationMode = CodeActionValidationMode.None, + }; + + test.ExpectedDiagnostics.AddRange(expected); + await test.RunAsync(CancellationToken.None); + } + + internal class Test : CSharpCodeFixTest + { + public Test() + { + var (refAssem, ancillary) = TestUtils.GetReferenceAssemblies(); + ReferenceAssemblies = refAssem; + SolutionTransforms.Add((solution, projectId) => + { + var project = solution.GetProject(projectId)!; + var compilationOptions = project.CompilationOptions!; + var diagnosticOptions = compilationOptions.SpecificDiagnosticOptions.SetItems(CSharpVerifierHelper.NullableWarnings); + + // Explicitly enable diagnostics that are not enabled by default + var enableAnalyzersOptions = new System.Collections.Generic.Dictionary(); + foreach (var analyzer in GetDiagnosticAnalyzers().ToImmutableArray()) + { + foreach (var diagnostic in analyzer.SupportedDiagnostics) + { + if (diagnostic.IsEnabledByDefault) + continue; + + // Map the default severity to the reporting behaviour. + // We cannot simply use ReportDiagnostic.Default here, as diagnostics that are not enabled by default + // are treated as suppressed (regardless of their default severity). + var report = diagnostic.DefaultSeverity switch + { + DiagnosticSeverity.Error => ReportDiagnostic.Error, + DiagnosticSeverity.Warning => ReportDiagnostic.Warn, + DiagnosticSeverity.Info => ReportDiagnostic.Info, + DiagnosticSeverity.Hidden => ReportDiagnostic.Hidden, + _ => ReportDiagnostic.Default + }; + enableAnalyzersOptions.Add(diagnostic.Id, report); + } + } + + compilationOptions = compilationOptions.WithSpecificDiagnosticOptions( + compilationOptions.SpecificDiagnosticOptions + .SetItems(CSharpVerifierHelper.NullableWarnings) + .AddRange(enableAnalyzersOptions)); + solution = solution.WithProjectCompilationOptions(projectId, compilationOptions); + solution = solution.WithProjectMetadataReferences(projectId, project.MetadataReferences.Concat(ImmutableArray.Create(ancillary))); + solution = solution.WithProjectParseOptions(projectId, ((CSharpParseOptions)project.ParseOptions!).WithLanguageVersion(LanguageVersion.Preview)); + return solution; + }); + } + + protected override ParseOptions CreateParseOptions() + => ((CSharpParseOptions)base.CreateParseOptions()).WithPreprocessorSymbols("DLLIMPORTGENERATOR_ENABLED"); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/Verifiers/CSharpVerifierHelper.cs b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/Verifiers/CSharpVerifierHelper.cs new file mode 100644 index 0000000000000..e55e91ea57f5d --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/DllImportGenerator.UnitTests/Verifiers/CSharpVerifierHelper.cs @@ -0,0 +1,29 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Immutable; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; + +namespace DllImportGenerator.UnitTests.Verifiers +{ + internal static class CSharpVerifierHelper + { + /// + /// By default, the compiler reports diagnostics for nullable reference types at + /// , and the analyzer test framework defaults to only validating + /// diagnostics at . This map contains all compiler diagnostic IDs + /// related to nullability mapped to , which is then used to enable all + /// of these warnings for default validation during analyzer and code fix tests. + /// + internal static ImmutableDictionary NullableWarnings { get; } = GetNullableWarningsFromCompiler(); + + private static ImmutableDictionary GetNullableWarningsFromCompiler() + { + string[] args = { "/warnaserror:nullable" }; + var commandLineArguments = CSharpCommandLineParser.Default.Parse(args, baseDirectory: Environment.CurrentDirectory, sdkDirectory: Environment.CurrentDirectory); + return commandLineArguments.CompilationOptions.SpecificDiagnosticOptions; + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComDisabled/System.Runtime.InteropServices.ComDisabled.Tests.csproj b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.ComDisabled.UnitTests/System.Runtime.InteropServices.ComDisabled.Tests.csproj similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/ComDisabled/System.Runtime.InteropServices.ComDisabled.Tests.csproj rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.ComDisabled.UnitTests/System.Runtime.InteropServices.ComDisabled.Tests.csproj diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComDisabled/System/Runtime/InteropServices/Marshal/MarshalComDisabledTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.ComDisabled.UnitTests/System/Runtime/InteropServices/Marshal/MarshalComDisabledTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/ComDisabled/System/Runtime/InteropServices/Marshal/MarshalComDisabledTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.ComDisabled.UnitTests/System/Runtime/InteropServices/Marshal/MarshalComDisabledTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/AssemblyInfo.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/AssemblyInfo.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/AssemblyInfo.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/AssemblyInfo.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.Tests.csproj b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System.Runtime.InteropServices.Tests.csproj similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.Tests.csproj rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System.Runtime.InteropServices.Tests.csproj diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/DllNotFoundExceptionTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/DllNotFoundExceptionTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/DllNotFoundExceptionTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/DllNotFoundExceptionTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/CompilerServices/IDispatchConstantAttributeTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/CompilerServices/IDispatchConstantAttributeTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/CompilerServices/IDispatchConstantAttributeTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/CompilerServices/IDispatchConstantAttributeTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/CompilerServices/IUnknownConstantAttributeTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/CompilerServices/IUnknownConstantAttributeTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/CompilerServices/IUnknownConstantAttributeTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/CompilerServices/IUnknownConstantAttributeTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ArrayWithOffsetTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ArrayWithOffsetTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ArrayWithOffsetTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ArrayWithOffsetTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/AutomationProxyAttributeTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/AutomationProxyAttributeTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/AutomationProxyAttributeTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/AutomationProxyAttributeTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/BStrWrapperTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/BStrWrapperTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/BStrWrapperTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/BStrWrapperTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/BestFitMappingAttributeTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/BestFitMappingAttributeTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/BestFitMappingAttributeTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/BestFitMappingAttributeTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/CLongTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/CLongTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/CLongTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/CLongTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/CULongTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/CULongTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/CULongTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/CULongTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/CallingConventionTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/CallingConventionTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/CallingConventionTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/CallingConventionTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ClassInterfaceAttributeTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ClassInterfaceAttributeTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ClassInterfaceAttributeTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ClassInterfaceAttributeTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/CoClassAttributeTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/CoClassAttributeTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/CoClassAttributeTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/CoClassAttributeTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/CollectionsMarshalTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/CollectionsMarshalTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/CollectionsMarshalTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/CollectionsMarshalTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ComAliasNameAttributeTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ComAliasNameAttributeTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ComAliasNameAttributeTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ComAliasNameAttributeTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ComAwareEventInfoTests.Windows.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ComAwareEventInfoTests.Windows.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ComAwareEventInfoTests.Windows.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ComAwareEventInfoTests.Windows.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ComAwareEventInfoTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ComAwareEventInfoTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ComAwareEventInfoTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ComAwareEventInfoTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ComCompatibleVersionAttributeTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ComCompatibleVersionAttributeTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ComCompatibleVersionAttributeTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ComCompatibleVersionAttributeTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ComConversionLossAttributeTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ComConversionLossAttributeTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ComConversionLossAttributeTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ComConversionLossAttributeTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ComDefaultInterfaceAttributeTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ComDefaultInterfaceAttributeTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ComDefaultInterfaceAttributeTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ComDefaultInterfaceAttributeTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ComEventInterfaceAttributeTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ComEventInterfaceAttributeTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ComEventInterfaceAttributeTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ComEventInterfaceAttributeTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ComEventsHelperTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ComEventsHelperTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ComEventsHelperTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ComEventsHelperTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ComRegisterFunctionAttributeTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ComRegisterFunctionAttributeTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ComRegisterFunctionAttributeTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ComRegisterFunctionAttributeTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ComSourceInterfacesAttributeTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ComSourceInterfacesAttributeTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ComSourceInterfacesAttributeTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ComSourceInterfacesAttributeTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ComUnregisterFunctionAttributeTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ComUnregisterFunctionAttributeTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ComUnregisterFunctionAttributeTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ComUnregisterFunctionAttributeTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ComVisibleAttributeTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ComVisibleAttributeTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ComVisibleAttributeTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ComVisibleAttributeTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/CurrencyWrapperTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/CurrencyWrapperTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/CurrencyWrapperTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/CurrencyWrapperTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/DefaultCharSetAttributeTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/DefaultCharSetAttributeTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/DefaultCharSetAttributeTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/DefaultCharSetAttributeTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/DefaultDllImportSearchPathsAttributeTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/DefaultDllImportSearchPathsAttributeTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/DefaultDllImportSearchPathsAttributeTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/DefaultDllImportSearchPathsAttributeTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/DefaultParameterValueAttributeTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/DefaultParameterValueAttributeTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/DefaultParameterValueAttributeTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/DefaultParameterValueAttributeTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/DispIdAttributeTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/DispIdAttributeTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/DispIdAttributeTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/DispIdAttributeTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/DispatchWrapperTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/DispatchWrapperTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/DispatchWrapperTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/DispatchWrapperTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/DllImportAttributeTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/DllImportAttributeTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/DllImportAttributeTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/DllImportAttributeTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ErrorWrapperTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ErrorWrapperTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ErrorWrapperTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ErrorWrapperTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/FieldOffsetAttributeTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/FieldOffsetAttributeTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/FieldOffsetAttributeTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/FieldOffsetAttributeTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/GCHandleTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/GCHandleTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/GCHandleTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/GCHandleTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/GuidAttributeTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/GuidAttributeTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/GuidAttributeTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/GuidAttributeTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/HandleCollectorTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/HandleCollectorTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/HandleCollectorTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/HandleCollectorTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/HandleRefTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/HandleRefTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/HandleRefTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/HandleRefTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/IDispatchImplAttributeTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/IDispatchImplAttributeTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/IDispatchImplAttributeTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/IDispatchImplAttributeTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ImportedFromTypeLibAttributeTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ImportedFromTypeLibAttributeTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ImportedFromTypeLibAttributeTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ImportedFromTypeLibAttributeTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/InterfaceTypeAttributeTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/InterfaceTypeAttributeTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/InterfaceTypeAttributeTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/InterfaceTypeAttributeTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/LCIDConversionAttributeTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/LCIDConversionAttributeTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/LCIDConversionAttributeTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/LCIDConversionAttributeTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ManagedToNativeComInteropStubAttributeTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ManagedToNativeComInteropStubAttributeTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ManagedToNativeComInteropStubAttributeTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ManagedToNativeComInteropStubAttributeTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/AddRefTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/AddRefTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/AddRefTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/AddRefTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/AllocHGlobalTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/AllocHGlobalTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/AllocHGlobalTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/AllocHGlobalTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/BindToMonikerTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/BindToMonikerTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/BindToMonikerTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/BindToMonikerTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ChangeWrapperHandleStrengthTests.Windows.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/ChangeWrapperHandleStrengthTests.Windows.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ChangeWrapperHandleStrengthTests.Windows.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/ChangeWrapperHandleStrengthTests.Windows.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ChangeWrapperHandleStrengthTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/ChangeWrapperHandleStrengthTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ChangeWrapperHandleStrengthTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/ChangeWrapperHandleStrengthTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Common/COMWrappersImpl.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/Common/COMWrappersImpl.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Common/COMWrappersImpl.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/Common/COMWrappersImpl.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Common/CommonTypes.Windows.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/Common/CommonTypes.Windows.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Common/CommonTypes.Windows.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/Common/CommonTypes.Windows.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Common/CommonTypes.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/Common/CommonTypes.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Common/CommonTypes.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/Common/CommonTypes.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Common/Variant.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/Common/Variant.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Common/Variant.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/Common/Variant.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Copy/ByteArrayTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/Copy/ByteArrayTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Copy/ByteArrayTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/Copy/ByteArrayTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Copy/CharArrayTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/Copy/CharArrayTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Copy/CharArrayTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/Copy/CharArrayTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Copy/DoubleArrayTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/Copy/DoubleArrayTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Copy/DoubleArrayTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/Copy/DoubleArrayTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Copy/Int16ArrayTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/Copy/Int16ArrayTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Copy/Int16ArrayTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/Copy/Int16ArrayTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Copy/Int32ArrayTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/Copy/Int32ArrayTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Copy/Int32ArrayTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/Copy/Int32ArrayTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Copy/Int64ArrayTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/Copy/Int64ArrayTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Copy/Int64ArrayTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/Copy/Int64ArrayTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Copy/IntPtrArrayTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/Copy/IntPtrArrayTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Copy/IntPtrArrayTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/Copy/IntPtrArrayTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Copy/SingleArrayTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/Copy/SingleArrayTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/Copy/SingleArrayTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/Copy/SingleArrayTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/CreateAggregatedObjectTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/CreateAggregatedObjectTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/CreateAggregatedObjectTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/CreateAggregatedObjectTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/CreateWrapperOfTypeTests.Windows.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/CreateWrapperOfTypeTests.Windows.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/CreateWrapperOfTypeTests.Windows.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/CreateWrapperOfTypeTests.Windows.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/CreateWrapperOfTypeTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/CreateWrapperOfTypeTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/CreateWrapperOfTypeTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/CreateWrapperOfTypeTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/DestroyStructureTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/DestroyStructureTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/DestroyStructureTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/DestroyStructureTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/FinalReleaseComObjectTests.Windows.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/FinalReleaseComObjectTests.Windows.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/FinalReleaseComObjectTests.Windows.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/FinalReleaseComObjectTests.Windows.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/FinalReleaseComObjectTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/FinalReleaseComObjectTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/FinalReleaseComObjectTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/FinalReleaseComObjectTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/FreeBSTRTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/FreeBSTRTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/FreeBSTRTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/FreeBSTRTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/FreeCoTaskMemTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/FreeCoTaskMemTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/FreeCoTaskMemTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/FreeCoTaskMemTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/FreeHGlobalTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/FreeHGlobalTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/FreeHGlobalTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/FreeHGlobalTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GenerateGuidForTypeTests.Windows.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GenerateGuidForTypeTests.Windows.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GenerateGuidForTypeTests.Windows.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GenerateGuidForTypeTests.Windows.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GenerateGuidForTypeTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GenerateGuidForTypeTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GenerateGuidForTypeTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GenerateGuidForTypeTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GenerateProgIdForTypeTests.Windows.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GenerateProgIdForTypeTests.Windows.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GenerateProgIdForTypeTests.Windows.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GenerateProgIdForTypeTests.Windows.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GenerateProgIdForTypeTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GenerateProgIdForTypeTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GenerateProgIdForTypeTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GenerateProgIdForTypeTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetComInterfaceForObjectTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetComInterfaceForObjectTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetComInterfaceForObjectTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetComInterfaceForObjectTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetComObjectDataTests.Windows.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetComObjectDataTests.Windows.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetComObjectDataTests.Windows.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetComObjectDataTests.Windows.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetComObjectDataTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetComObjectDataTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetComObjectDataTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetComObjectDataTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetDelegateForFunctionPointerTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetDelegateForFunctionPointerTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetDelegateForFunctionPointerTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetDelegateForFunctionPointerTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetEndComSlotTests.Windows.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetEndComSlotTests.Windows.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetEndComSlotTests.Windows.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetEndComSlotTests.Windows.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetEndComSlotTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetEndComSlotTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetEndComSlotTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetEndComSlotTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetExceptionCodeTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetExceptionCodeTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetExceptionCodeTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetExceptionCodeTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetExceptionForHRTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetExceptionForHRTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetExceptionForHRTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetExceptionForHRTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetExceptionPointersTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetExceptionPointersTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetExceptionPointersTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetExceptionPointersTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetFunctionPointerForDelegateTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetFunctionPointerForDelegateTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetFunctionPointerForDelegateTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetFunctionPointerForDelegateTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetHINSTANCETests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetHINSTANCETests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetHINSTANCETests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetHINSTANCETests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetHRForExceptionTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetHRForExceptionTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetHRForExceptionTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetHRForExceptionTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetIDispatchForObjectTests.Windows.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetIDispatchForObjectTests.Windows.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetIDispatchForObjectTests.Windows.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetIDispatchForObjectTests.Windows.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetIDispatchForObjectTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetIDispatchForObjectTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetIDispatchForObjectTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetIDispatchForObjectTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetIUnknownForObjectTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetIUnknownForObjectTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetIUnknownForObjectTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetIUnknownForObjectTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetNativeVariantForObjectTests.Windows.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetNativeVariantForObjectTests.Windows.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetNativeVariantForObjectTests.Windows.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetNativeVariantForObjectTests.Windows.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetNativeVariantForObjectTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetNativeVariantForObjectTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetNativeVariantForObjectTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetNativeVariantForObjectTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetObjectForIUnknownTests.Windows.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetObjectForIUnknownTests.Windows.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetObjectForIUnknownTests.Windows.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetObjectForIUnknownTests.Windows.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetObjectForIUnknownTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetObjectForIUnknownTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetObjectForIUnknownTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetObjectForIUnknownTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetObjectForNativeVariantTests.Windows.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetObjectForNativeVariantTests.Windows.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetObjectForNativeVariantTests.Windows.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetObjectForNativeVariantTests.Windows.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetObjectForNativeVariantTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetObjectForNativeVariantTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetObjectForNativeVariantTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetObjectForNativeVariantTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetObjectsForNativeVariantsTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetObjectsForNativeVariantsTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetObjectsForNativeVariantsTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetObjectsForNativeVariantsTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetStartComSlotTests.Windows.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetStartComSlotTests.Windows.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetStartComSlotTests.Windows.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetStartComSlotTests.Windows.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetStartComSlotTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetStartComSlotTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetStartComSlotTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetStartComSlotTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetTypeFromCLSIDTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetTypeFromCLSIDTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetTypeFromCLSIDTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetTypeFromCLSIDTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetTypeInfoNameTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetTypeInfoNameTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetTypeInfoNameTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetTypeInfoNameTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetTypedObjectForIUnknownTests.Windows.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetTypedObjectForIUnknownTests.Windows.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetTypedObjectForIUnknownTests.Windows.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetTypedObjectForIUnknownTests.Windows.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetTypedObjectForIUnknownTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetTypedObjectForIUnknownTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetTypedObjectForIUnknownTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetTypedObjectForIUnknownTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetUniqueObjectForIUnknownTests.Windows.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetUniqueObjectForIUnknownTests.Windows.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetUniqueObjectForIUnknownTests.Windows.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetUniqueObjectForIUnknownTests.Windows.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetUniqueObjectForIUnknownTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetUniqueObjectForIUnknownTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/GetUniqueObjectForIUnknownTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/GetUniqueObjectForIUnknownTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/InitHandleTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/InitHandleTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/InitHandleTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/InitHandleTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/IsComObjectTests.Windows.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/IsComObjectTests.Windows.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/IsComObjectTests.Windows.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/IsComObjectTests.Windows.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/IsComObjectTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/IsComObjectTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/IsComObjectTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/IsComObjectTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/IsTypeVisibleFromComTests.Windows.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/IsTypeVisibleFromComTests.Windows.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/IsTypeVisibleFromComTests.Windows.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/IsTypeVisibleFromComTests.Windows.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/IsTypeVisibleFromComTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/IsTypeVisibleFromComTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/IsTypeVisibleFromComTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/IsTypeVisibleFromComTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/LastErrorTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/LastErrorTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/LastErrorTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/LastErrorTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/OffsetOfTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/OffsetOfTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/OffsetOfTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/OffsetOfTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/PrelinkAllTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/PrelinkAllTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/PrelinkAllTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/PrelinkAllTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/PrelinkTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/PrelinkTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/PrelinkTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/PrelinkTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/PtrToStringAnsiTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/PtrToStringAnsiTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/PtrToStringAnsiTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/PtrToStringAnsiTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/PtrToStringAutoTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/PtrToStringAutoTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/PtrToStringAutoTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/PtrToStringAutoTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/PtrToStringBSTR.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/PtrToStringBSTR.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/PtrToStringBSTR.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/PtrToStringBSTR.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/PtrToStringUTF8Tests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/PtrToStringUTF8Tests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/PtrToStringUTF8Tests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/PtrToStringUTF8Tests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/PtrToStringUniTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/PtrToStringUniTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/PtrToStringUniTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/PtrToStringUniTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/PtrToStructureTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/PtrToStructureTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/PtrToStructureTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/PtrToStructureTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/QueryInterfaceTests.Windows.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/QueryInterfaceTests.Windows.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/QueryInterfaceTests.Windows.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/QueryInterfaceTests.Windows.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/QueryInterfaceTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/QueryInterfaceTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/QueryInterfaceTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/QueryInterfaceTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ReAllocCoTaskMemTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/ReAllocCoTaskMemTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ReAllocCoTaskMemTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/ReAllocCoTaskMemTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ReAllocHGlobalTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/ReAllocHGlobalTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ReAllocHGlobalTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/ReAllocHGlobalTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ReadWrite/ByteTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/ReadWrite/ByteTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ReadWrite/ByteTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/ReadWrite/ByteTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ReadWrite/Int16Tests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/ReadWrite/Int16Tests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ReadWrite/Int16Tests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/ReadWrite/Int16Tests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ReadWrite/Int32Tests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/ReadWrite/Int32Tests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ReadWrite/Int32Tests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/ReadWrite/Int32Tests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ReadWrite/Int64Tests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/ReadWrite/Int64Tests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ReadWrite/Int64Tests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/ReadWrite/Int64Tests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ReadWrite/IntPtrTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/ReadWrite/IntPtrTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ReadWrite/IntPtrTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/ReadWrite/IntPtrTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ReleaseComObjectTests.Windows.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/ReleaseComObjectTests.Windows.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ReleaseComObjectTests.Windows.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/ReleaseComObjectTests.Windows.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ReleaseComObjectTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/ReleaseComObjectTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ReleaseComObjectTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/ReleaseComObjectTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ReleaseTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/ReleaseTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ReleaseTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/ReleaseTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/SecureStringToBSTRTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/SecureStringToBSTRTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/SecureStringToBSTRTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/SecureStringToBSTRTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/SecureStringToCoTaskMemAnsiTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/SecureStringToCoTaskMemAnsiTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/SecureStringToCoTaskMemAnsiTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/SecureStringToCoTaskMemAnsiTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/SecureStringToCoTaskMemUnicodeTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/SecureStringToCoTaskMemUnicodeTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/SecureStringToCoTaskMemUnicodeTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/SecureStringToCoTaskMemUnicodeTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/SecureStringToGlobalAllocAnsiTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/SecureStringToGlobalAllocAnsiTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/SecureStringToGlobalAllocAnsiTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/SecureStringToGlobalAllocAnsiTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/SecureStringToGlobalAllocUnicodeTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/SecureStringToGlobalAllocUnicodeTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/SecureStringToGlobalAllocUnicodeTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/SecureStringToGlobalAllocUnicodeTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/SetComObjectDataTests.Windows.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/SetComObjectDataTests.Windows.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/SetComObjectDataTests.Windows.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/SetComObjectDataTests.Windows.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/SetComObjectDataTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/SetComObjectDataTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/SetComObjectDataTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/SetComObjectDataTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/SizeOfTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/SizeOfTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/SizeOfTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/SizeOfTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/StringMarshalingTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/StringMarshalingTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/StringMarshalingTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/StringMarshalingTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/StringToBSTRTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/StringToBSTRTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/StringToBSTRTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/StringToBSTRTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/StringToCoTaskMemAnsiTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/StringToCoTaskMemAnsiTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/StringToCoTaskMemAnsiTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/StringToCoTaskMemAnsiTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/StringToCoTaskMemAutoTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/StringToCoTaskMemAutoTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/StringToCoTaskMemAutoTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/StringToCoTaskMemAutoTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/StringToCoTaskMemUTF8Tests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/StringToCoTaskMemUTF8Tests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/StringToCoTaskMemUTF8Tests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/StringToCoTaskMemUTF8Tests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/StringToCoTaskMemUniTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/StringToCoTaskMemUniTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/StringToCoTaskMemUniTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/StringToCoTaskMemUniTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/StringToHGlobalAnsiTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/StringToHGlobalAnsiTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/StringToHGlobalAnsiTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/StringToHGlobalAnsiTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/StringToHGlobalAutoTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/StringToHGlobalAutoTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/StringToHGlobalAutoTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/StringToHGlobalAutoTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/StringToHGlobalUniTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/StringToHGlobalUniTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/StringToHGlobalUniTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/StringToHGlobalUniTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/StructureToPtrTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/StructureToPtrTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/StructureToPtrTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/StructureToPtrTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ThrowExceptionForHRTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/ThrowExceptionForHRTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ThrowExceptionForHRTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/ThrowExceptionForHRTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/UnsafeAddrOfPinnedArrayElementTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/UnsafeAddrOfPinnedArrayElementTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/UnsafeAddrOfPinnedArrayElementTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/UnsafeAddrOfPinnedArrayElementTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ZeroFreeCoTaskMemAnsiTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/ZeroFreeCoTaskMemAnsiTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ZeroFreeCoTaskMemAnsiTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/ZeroFreeCoTaskMemAnsiTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ZeroFreeCoTaskMemUTF8Tests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/ZeroFreeCoTaskMemUTF8Tests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ZeroFreeCoTaskMemUTF8Tests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/ZeroFreeCoTaskMemUTF8Tests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ZeroFreeCoTaskMemUnicodeTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/ZeroFreeCoTaskMemUnicodeTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ZeroFreeCoTaskMemUnicodeTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/ZeroFreeCoTaskMemUnicodeTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ZeroFreeGlobalAllocAnsiTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/ZeroFreeGlobalAllocAnsiTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ZeroFreeGlobalAllocAnsiTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/ZeroFreeGlobalAllocAnsiTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ZeroFreeGlobalAllocUnicodeTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/ZeroFreeGlobalAllocUnicodeTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/Marshal/ZeroFreeGlobalAllocUnicodeTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/Marshal/ZeroFreeGlobalAllocUnicodeTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/MarshalAsAttributeTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/MarshalAsAttributeTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/MarshalAsAttributeTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/MarshalAsAttributeTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/NFloatTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/NFloatTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/NFloatTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/NFloatTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/NativeMemoryTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/NativeMemoryTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/NativeMemoryTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/NativeMemoryTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ObjectiveC/LibObjC.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ObjectiveC/LibObjC.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ObjectiveC/LibObjC.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ObjectiveC/LibObjC.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ObjectiveC/MessageSendTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ObjectiveC/MessageSendTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ObjectiveC/MessageSendTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ObjectiveC/MessageSendTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ObjectiveC/PendingExceptionTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ObjectiveC/PendingExceptionTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ObjectiveC/PendingExceptionTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ObjectiveC/PendingExceptionTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/PosixSignalContextTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/PosixSignalContextTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/PosixSignalContextTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/PosixSignalContextTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/PosixSignalRegistrationTests.Unix.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/PosixSignalRegistrationTests.Unix.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/PosixSignalRegistrationTests.Unix.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/PosixSignalRegistrationTests.Unix.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/PosixSignalRegistrationTests.Windows.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/PosixSignalRegistrationTests.Windows.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/PosixSignalRegistrationTests.Windows.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/PosixSignalRegistrationTests.Windows.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/PosixSignalRegistrationTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/PosixSignalRegistrationTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/PosixSignalRegistrationTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/PosixSignalRegistrationTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/PrimaryInteropAssemblyAttributeTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/PrimaryInteropAssemblyAttributeTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/PrimaryInteropAssemblyAttributeTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/PrimaryInteropAssemblyAttributeTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ProgIdAttributeTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ProgIdAttributeTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/ProgIdAttributeTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/ProgIdAttributeTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/RuntimeEnvironmentTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/RuntimeEnvironmentTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/RuntimeEnvironmentTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/RuntimeEnvironmentTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/SafeBufferTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/SafeBufferTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/SafeBufferTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/SafeBufferTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/SetWin32ContextInIDispatchAttributeTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/SetWin32ContextInIDispatchAttributeTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/SetWin32ContextInIDispatchAttributeTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/SetWin32ContextInIDispatchAttributeTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/StructLayoutAttributeTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/StructLayoutAttributeTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/StructLayoutAttributeTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/StructLayoutAttributeTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/TypeIdentifierAttributeTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/TypeIdentifierAttributeTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/TypeIdentifierAttributeTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/TypeIdentifierAttributeTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/TypeLibFuncAttributeTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/TypeLibFuncAttributeTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/TypeLibFuncAttributeTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/TypeLibFuncAttributeTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/TypeLibImportClassAttributeTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/TypeLibImportClassAttributeTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/TypeLibImportClassAttributeTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/TypeLibImportClassAttributeTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/TypeLibTypeAttributeTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/TypeLibTypeAttributeTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/TypeLibTypeAttributeTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/TypeLibTypeAttributeTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/TypeLibVarAttributeTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/TypeLibVarAttributeTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/TypeLibVarAttributeTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/TypeLibVarAttributeTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/TypeLibVersionAttributeTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/TypeLibVersionAttributeTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/TypeLibVersionAttributeTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/TypeLibVersionAttributeTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/UnknownWrapperTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/UnknownWrapperTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/UnknownWrapperTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/UnknownWrapperTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/UnmanagedFunctionPointerAttributeTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/UnmanagedFunctionPointerAttributeTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/UnmanagedFunctionPointerAttributeTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/UnmanagedFunctionPointerAttributeTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/VariantWrapperTests.cs b/src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/VariantWrapperTests.cs similarity index 100% rename from src/libraries/System.Runtime.InteropServices/tests/System/Runtime/InteropServices/VariantWrapperTests.cs rename to src/libraries/System.Runtime.InteropServices/tests/System.Runtime.InteropServices.UnitTests/System/Runtime/InteropServices/VariantWrapperTests.cs diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/Directory.Build.props b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/Directory.Build.props new file mode 100644 index 0000000000000..90c7da2a4a1f0 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/Directory.Build.props @@ -0,0 +1,7 @@ + + + + + true + + diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/Arrays.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/Arrays.cs new file mode 100644 index 0000000000000..3e11f6c91298e --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/Arrays.cs @@ -0,0 +1,216 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using SharedTypes; +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +namespace NativeExports +{ + public static unsafe class Arrays + { + [UnmanagedCallersOnly(EntryPoint = "sum_int_array")] + public static int Sum(int* values, int numValues) + { + if (values == null) + { + return -1; + } + + int sum = 0; + for (int i = 0; i < numValues; i++) + { + sum += values[i]; + } + return sum; + } + + [UnmanagedCallersOnly(EntryPoint = "sum_int_array_ref")] + public static int SumInArray(int** values, int numValues) + { + if (*values == null) + { + return -1; + } + + int sum = 0; + for (int i = 0; i < numValues; i++) + { + sum += (*values)[i]; + } + return sum; + } + + [UnmanagedCallersOnly(EntryPoint = "duplicate_int_array")] + public static void Duplicate(int** values, int numValues) + { + int* newArray = (int*)Marshal.AllocCoTaskMem(sizeof(int) * numValues); + new Span(*values, numValues).CopyTo(new Span(newArray, numValues)); + Marshal.FreeCoTaskMem((IntPtr)(*values)); + *values = newArray; + } + + [UnmanagedCallersOnly(EntryPoint = "create_range_array")] + public static int* CreateRange(int start, int end, int* numValues) + { + return CreateRangeImpl(start, end, numValues); + } + + [UnmanagedCallersOnly(EntryPoint = "create_range_array_out")] + public static void CreateRangeAsOut(int start, int end, int* numValues, int** res) + { + *res = CreateRangeImpl(start, end, numValues); + } + + [UnmanagedCallersOnly(EntryPoint = "fill_range_array")] + [DNNE.C99DeclCode("struct int_struct_wrapper;")] + public static byte FillRange([DNNE.C99Type("struct int_struct_wrapper*")] IntStructWrapperNative* numValues, int length, int start) + { + if (numValues == null) + { + return 0; + } + + for (int i = 0; i < length; i++, start++) + { + numValues[i] = new IntStructWrapperNative { value = start }; + } + + return 1; + } + + [UnmanagedCallersOnly(EntryPoint = "double_values")] + [DNNE.C99DeclCode("struct int_struct_wrapper { int value; };")] + public static void DoubleValues([DNNE.C99Type("struct int_struct_wrapper*")] IntStructWrapperNative* numValues, int length) + { + for (int i = 0; i < length; i++) + { + numValues[i].value *= 2; + } + } + + [UnmanagedCallersOnly(EntryPoint = "sum_string_lengths")] + public static int SumStringLengths(ushort** strArray) + { + if (strArray == null) + { + return 0; + } + int length = 0; + for (int i = 0; (nint)strArray[i] != 0; i++) + { + length += new string((char*)strArray[i]).Length; + } + return length; + } + + [UnmanagedCallersOnly(EntryPoint = "reverse_strings_return")] + public static ushort** ReverseStrings(ushort** strArray, int* numValues) + { + return ReverseStringsImpl(strArray, numValues); + } + + [UnmanagedCallersOnly(EntryPoint = "reverse_strings_out")] + public static void ReverseStringsAsOut(ushort** strArray, int* numValues, ushort*** res) + { + *res = ReverseStringsImpl(strArray, numValues); + } + + [UnmanagedCallersOnly(EntryPoint = "reverse_strings_replace")] + public static void ReverseStringsReplace(ushort*** strArray, int* numValues) + { + ushort** res = ReverseStringsImpl(*strArray, numValues); + Marshal.FreeCoTaskMem((IntPtr)(*strArray)); + *strArray = res; + } + + [UnmanagedCallersOnly(EntryPoint = "get_long_bytes")] + public static byte* GetLongBytes(long l) + { + const int NumBytesInLong = sizeof(long); + + byte* bytes = (byte*)Marshal.AllocCoTaskMem(NumBytesInLong); + MemoryMarshal.Write(new Span(bytes, NumBytesInLong), ref l); + return bytes; + } + + [UnmanagedCallersOnly(EntryPoint = "append_int_to_array")] + public static void Append(int** values, int numOriginalValues, int newValue) + { + int* newArray = (int*)Marshal.AllocCoTaskMem(sizeof(int) * (numOriginalValues + 1)); + new Span(*values, numOriginalValues).CopyTo(new Span(newArray, numOriginalValues)); + newArray[numOriginalValues] = newValue; + *values = newArray; + } + + [UnmanagedCallersOnly(EntryPoint = "and_all_members")] + [DNNE.C99DeclCode("struct bool_struct;")] + public static byte AndAllMembers([DNNE.C99Type("struct bool_struct*")] BoolStructNative* pArray, int length) + { + bool result = true; + for (int i = 0; i < length; i++) + { + BoolStruct managed = pArray[i].ToManaged(); + result &= managed.b1 && managed.b2 && managed.b3; + } + return (byte)(result ? 1 : 0); + } + + [UnmanagedCallersOnly(EntryPoint = "transpose_matrix")] + public static int** TransposeMatrix(int** matrix, int* numRows, int numColumns) + { + int** newRows = (int**)Marshal.AllocCoTaskMem(numColumns * sizeof(int*)); + for (int i = 0; i < numColumns; i++) + { + newRows[i] = (int*)Marshal.AllocCoTaskMem(numRows[i] * sizeof(int)); + for (int j = 0; j < numRows[i]; j++) + { + newRows[i][j] = matrix[j][i]; + } + } + + return newRows; + } + + private static int* CreateRangeImpl(int start, int end, int* numValues) + { + if (start >= end) + { + *numValues = 0; + return null; + } + + *numValues = end - start; + + int* retVal = (int*)Marshal.AllocCoTaskMem(sizeof(int) * (*numValues)); + for (int i = start; i < end; i++) + { + retVal[i - start] = i; + } + + return retVal; + } + + private static ushort** ReverseStringsImpl(ushort** strArray, int* numValues) + { + if (strArray == null) + { + *numValues = 0; + return null; + } + + List newStrings = new List(); + for (int i = 0; (nint)strArray[i] != 0; i++) + { + newStrings.Add((IntPtr)Strings.Reverse(strArray[i])); + } + newStrings.Add(IntPtr.Zero); + + ushort** res = (ushort**)Marshal.AllocCoTaskMem(sizeof(ushort*) * newStrings.Count); + CollectionsMarshal.AsSpan(newStrings).CopyTo(new Span((IntPtr*)(res), newStrings.Count)); + *numValues = newStrings.Count; + return res; + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/BlittableStructs.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/BlittableStructs.cs new file mode 100644 index 0000000000000..f9dbaf9b7e015 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/BlittableStructs.cs @@ -0,0 +1,44 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.InteropServices; + +using SharedTypes; + +namespace NativeExports +{ + public static unsafe class BlittableStructs + { + [UnmanagedCallersOnly(EntryPoint = "blittablestructs_return_instance")] + [DNNE.C99DeclCode("struct int_fields { int a; int b; int c; };")] + [return: DNNE.C99Type("struct int_fields")] + public static IntFields DoubleIntFields([DNNE.C99Type("struct int_fields")] IntFields input) + { + return new IntFields() + { + a = input.a * 2, + b = input.b * 2, + c = input.c * 2, + }; + } + + [UnmanagedCallersOnly(EntryPoint = "blittablestructs_double_intfields_byref")] + public static void DoubleIntFieldsByRef( + [DNNE.C99Type("struct int_fields*")] IntFields* result) + { + result->a *= 2; + result->b *= 2; + result->c *= 2; + } + + [UnmanagedCallersOnly(EntryPoint = "blittablestructs_double_intfields_refreturn")] + public static void DoubleIntFieldsRefReturn( + [DNNE.C99Type("struct int_fields")] IntFields input, + [DNNE.C99Type("struct int_fields*")] IntFields* result) + { + result->a = input.a * 2; + result->b = input.b * 2; + result->c = input.c * 2; + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/Booleans.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/Booleans.cs new file mode 100644 index 0000000000000..20df4b754cdb3 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/Booleans.cs @@ -0,0 +1,34 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.InteropServices; + +namespace NativeExports +{ + public static unsafe class Booleans + { + [UnmanagedCallersOnly(EntryPoint = "bytebool_return_as_uint")] + public static uint ReturnByteAsUInt(byte input) + { + return input; + } + + [UnmanagedCallersOnly(EntryPoint = "variantbool_return_as_uint")] + public static uint ReturnUShortAsUInt(ushort input) + { + return input; + } + + [UnmanagedCallersOnly(EntryPoint = "bool_return_as_uint")] + public static uint ReturnUIntAsUInt(uint input) + { + return input; + } + + [UnmanagedCallersOnly(EntryPoint = "bool_return_as_refuint")] + public static void ReturnUIntAsRefUInt(uint input, uint* res) + { + *res = input; + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/CallingConventions.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/CallingConventions.cs new file mode 100644 index 0000000000000..0b97aaae45ea7 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/CallingConventions.cs @@ -0,0 +1,29 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace NativeExports +{ + class CallingConventions + { + // Use 9 long arguments to ensure we spill to the stack on all platforms. + [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) }, EntryPoint = "add_integers_cdecl")] + public static long AddLongsCdecl(long i, long j, long k, long l, long m, long n, long o, long p, long q) + { + return i + j + k + l + m + n + o + p + q; + } + + [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvStdcall) }, EntryPoint = "add_integers_stdcall")] + public static long AddLongsStdcall(long i, long j, long k, long l, long m, long n, long o, long p, long q) + { + return i + j + k + l + m + n + o + p + q; + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/Characters.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/Characters.cs new file mode 100644 index 0000000000000..ed4e18e22e19d --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/Characters.cs @@ -0,0 +1,36 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.InteropServices; + +namespace NativeExports +{ + public static unsafe class Characters + { + [UnmanagedCallersOnly(EntryPoint = "unicode_return_as_uint")] + public static uint ReturnUnicodeAsUInt(ushort input) + { + return input; + } + + [UnmanagedCallersOnly(EntryPoint = "char_return_as_uint")] + public static uint ReturnUIntAsUInt(uint input) + { + return input; + } + + [UnmanagedCallersOnly(EntryPoint = "char_return_as_refuint")] + public static void ReturnUIntAsRefUInt(uint input, uint* res) + { + *res = input; + } + + [UnmanagedCallersOnly(EntryPoint = "char_reverse_buffer_ref")] + public static void ReverseBuffer(ushort *buffer, int len) + { + var span = new Span(buffer, len); + span.Reverse(); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/CustomMarshalling.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/CustomMarshalling.cs new file mode 100644 index 0000000000000..2da06a7540871 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/CustomMarshalling.cs @@ -0,0 +1,66 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.InteropServices; +using SharedTypes; + +namespace NativeExports +{ + public static unsafe class CustomMarshalling + { + [UnmanagedCallersOnly(EntryPoint = "stringcontainer_deepduplicate")] + [DNNE.C99DeclCode("struct string_container { char* str1; char* str2; };")] + public static void DeepDuplicateStrings( + [DNNE.C99Type("struct string_container")] StringContainerNative strings, + [DNNE.C99Type("struct string_container*")] StringContainerNative* pStringsOut) + { + // Round trip through the managed view to allocate a new native instance. + *pStringsOut = new StringContainerNative(strings.ToManaged()); + } + + [UnmanagedCallersOnly(EntryPoint = "stringcontainer_reverse_strings")] + public static void ReverseStrings( + [DNNE.C99Type("struct string_container*")] StringContainerNative* strings) + { + strings->str1 = (IntPtr)Strings.Reverse((byte*)strings->str1); + strings->str2 = (IntPtr)Strings.Reverse((byte*)strings->str2); + } + + [UnmanagedCallersOnly(EntryPoint = "get_long_bytes_as_double")] + public static double GetLongBytesAsDouble(long l) + { + return *(double*)&l; + } + + [UnmanagedCallersOnly(EntryPoint = "negate_bools")] + [DNNE.C99DeclCode("struct bool_struct { int8_t b1; int8_t b2; int8_t b3; };")] + public static void NegateBools( + [DNNE.C99Type("struct bool_struct")] BoolStructNative boolStruct, + [DNNE.C99Type("struct bool_struct*")] BoolStructNative* pBoolStructOut) + { + *pBoolStructOut = new BoolStructNative + { + b1 = (byte)(boolStruct.b1 != 0 ? 0 : 1), + b2 = (byte)(boolStruct.b2 != 0 ? 0 : 1), + b3 = (byte)(boolStruct.b3 != 0 ? 0 : 1), + }; + } + + [UnmanagedCallersOnly(EntryPoint = "and_bools_ref")] + public static byte AndBoolsRef( + [DNNE.C99Type("struct bool_struct*")] BoolStructNative* boolStruct) + { + return (byte)(boolStruct->b1 != 0 && boolStruct->b2 != 0 && boolStruct->b3 != 0 ? 1 : 0); + } + + [UnmanagedCallersOnly(EntryPoint = "double_int_ref")] + public static int* DoubleIntRef(int* pInt) + { + *pInt *= 2; + int* retVal = (int*)Marshal.AllocCoTaskMem(sizeof(int)); + *retVal = *pInt; + return retVal; + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/DelegatesAndFunctionPointers.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/DelegatesAndFunctionPointers.cs new file mode 100644 index 0000000000000..8925bcd038f2b --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/DelegatesAndFunctionPointers.cs @@ -0,0 +1,53 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.InteropServices; + +namespace NativeExports +{ + public static unsafe class DelegatesAndFunctionPointers + { + [UnmanagedCallersOnly(EntryPoint = "invoke_callback_after_gc")] + public static void InvokeCallbackAfterGCCollect(delegate* unmanaged fptr) + { + // We are at the mercy of the GC to verify our delegate has been retain + // across the native function call. This is a best effort validation. + for (int i = 0; i < 5; ++i) + { + GC.Collect(); + GC.WaitForPendingFinalizers(); + } + + // If the corresponding Delegate was collected, the runtime will rudely abort. + fptr(); + } + + [UnmanagedCallersOnly(EntryPoint = "invoke_managed_callback_after_gc")] + public static void InvokeManagedCallbackAfterGCCollect(void* fptr) + { + // We are at the mercy of the GC to verify our delegate has been retain + // across the native function call. This is a best effort validation. + for (int i = 0; i < 5; ++i) + { + GC.Collect(); + GC.WaitForPendingFinalizers(); + } + + // If the corresponding Delegate was collected, the runtime will rudely abort. + ((delegate*)fptr)(); + } + + [UnmanagedCallersOnly(EntryPoint = "invoke_callback_blittable_args")] + public static int InvokeCallbackWithBlittableArgument(delegate* unmanaged fptr, int a, int b) + { + return fptr(a, b); + } + + [UnmanagedCallersOnly(EntryPoint = "invoke_managed_callback_blittable_args")] + public static int InvokeManagedCallbackWithBlittableArgument(void* fptr, int a, int b) + { + return ((delegate*)fptr)(a, b); + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/Demo.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/Demo.cs new file mode 100644 index 0000000000000..42d55bc5ee9a2 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/Demo.cs @@ -0,0 +1,28 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.InteropServices; + +namespace NativeExports +{ + public static unsafe class Demo + { + [UnmanagedCallersOnly(EntryPoint = "sumi")] + public static int Sum(int a, int b) + { + return a + b; + } + + [UnmanagedCallersOnly(EntryPoint = "sumouti")] + public static void SumOut(int a, int b, int* c) + { + *c = a + b; + } + + [UnmanagedCallersOnly(EntryPoint = "sumrefi")] + public static void SumRef(int a, int* b) + { + *b += a; + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/Error.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/Error.cs new file mode 100644 index 0000000000000..add53a9f9f4ba --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/Error.cs @@ -0,0 +1,69 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.InteropServices; + +namespace NativeExports +{ + public static unsafe class Error + { + private class Kernel32 + { + [DllImport(nameof(Kernel32))] + public static extern void SetLastError(int error); + + [DllImport(nameof(Kernel32))] + public static extern int GetLastError(); + } + + private class libc + { + [DllImport(nameof(libc))] + internal static unsafe extern int* __errno_location(); + + [DllImport(nameof(libc))] + internal static unsafe extern int* __error(); + } + + [UnmanagedCallersOnly(EntryPoint = "set_error")] + public static int SetError(int error, byte shouldSetError) + { + if (shouldSetError != 0) + SetLastError(error); + + return error; + } + + [UnmanagedCallersOnly(EntryPoint = "set_error_return_string")] + public static ushort* SetErrorReturnString(int error, byte shouldSetError, ushort* errorString) + { + ushort* ret = (ushort*)Marshal.StringToCoTaskMemUni(new string((char*)errorString)); + + if (shouldSetError != 0) + SetLastError(error); + + return ret; + } + + private static void SetLastError(int error) + { + if (OperatingSystem.IsWindows()) + { + Kernel32.SetLastError(error); + } + else if (OperatingSystem.IsMacOS()) + { + *libc.__error() = error; + } + else if (OperatingSystem.IsLinux()) + { + *libc.__errno_location() = error; + } + else + { + throw new NotImplementedException(); + } + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/HResult.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/HResult.cs new file mode 100644 index 0000000000000..891dbade60b40 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/HResult.cs @@ -0,0 +1,70 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.InteropServices; + +namespace NativeExports +{ + public static unsafe class HResult + { + [UnmanagedCallersOnly(EntryPoint = "hresult_return")] + public static int Return(int hr) + { + return hr; + } + + [UnmanagedCallersOnly(EntryPoint = "hresult_out_int")] + public static int ReturnAsOutInt(int hr, int* ret) + { + *ret = hr; + return hr; + } + + [UnmanagedCallersOnly(EntryPoint = "hresult_out_ushort")] + public static int ReturnAsOutShort(int hr, ushort* ret) + { + *ret = (ushort)hr; + return hr; + } + + [UnmanagedCallersOnly(EntryPoint = "hresult_out_ushort_string")] + public static int ReturnAsOutString(int hr, ushort** ret) + { + string str = hr.ToString(); + *ret = (ushort*)Marshal.StringToCoTaskMemUni(str); + return hr; + } + + [UnmanagedCallersOnly(EntryPoint = "hresult_out_int_array")] + public static int ReturnAsOutIntArray(int hr, int** ret) + { + const int NumBytesInInt = sizeof(int); + *ret = (int*)Marshal.AllocCoTaskMem(sizeof(int) * NumBytesInInt); + new Span(*ret, NumBytesInInt).Fill(hr); + return hr; + } + + [UnmanagedCallersOnly(EntryPoint = "hresult_out_ushort_string_array")] + public static int ReturnAsOutStringArray(int hr, ushort*** ret) + { + const int NumBytesInInt = sizeof(int); + string str = hr.ToString(); + + *ret = (ushort**)Marshal.AllocCoTaskMem(sizeof(ushort*) * NumBytesInInt); + for (int i = 0; i < NumBytesInInt; i++) + { + (*ret)[i] = (ushort*)Marshal.StringToCoTaskMemUni(str); + } + + return hr; + } + + [UnmanagedCallersOnly(EntryPoint = "hresult_out_handle")] + public static int ReturnAsOutHandle(int hr, nint* handle) + { + *handle = hr; + return hr; + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/Handles.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/Handles.cs new file mode 100644 index 0000000000000..76664b8820879 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/Handles.cs @@ -0,0 +1,86 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.Runtime.InteropServices; + +namespace NativeExports +{ + public static unsafe class Handles + { + /// + /// Using in tests. + /// + private const nint InvalidHandle = -1; + + private static nint LastHandle = 0; + + private static readonly HashSet ActiveHandles = new HashSet(); + + [UnmanagedCallersOnly(EntryPoint = "alloc_handle")] + public static nint AllocateHandle() + { + return AllocateHandleCore(); + } + + [UnmanagedCallersOnly(EntryPoint = "alloc_handle_out")] + public static void AllocateHandleOut(nint* handle) + { + *handle = AllocateHandleCore(); + } + + [UnmanagedCallersOnly(EntryPoint = "release_handle")] + public static byte ReleaseHandle(nint handle) + { + return (byte)(ReleaseHandleCore(handle) ? 1 : 0); + } + + [UnmanagedCallersOnly(EntryPoint = "is_handle_alive")] + public static byte IsHandleAlive(nint handle) + { + return (byte)(IsHandleAliveCore(handle) ? 1 : 0); + } + + [UnmanagedCallersOnly(EntryPoint = "modify_handle")] + public static void ModifyHandle(nint* handle, byte newHandle) + { + if (newHandle != 0) + { + *handle = AllocateHandleCore(); + } + } + + private static object m_lock = new object(); + + private static nint AllocateHandleCore() + { + lock (m_lock) + { + if (LastHandle == int.MaxValue) + { + return InvalidHandle; + } + + nint newHandle = ++LastHandle; + ActiveHandles.Add(newHandle); + return newHandle; + } + } + + private static bool IsHandleAliveCore(nint handle) + { + lock (m_lock) + { + return ActiveHandles.Contains(handle); + } + } + + private static bool ReleaseHandleCore(nint handle) + { + lock (m_lock) + { + return ActiveHandles.Remove(handle); + } + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/NativeExports.csproj b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/NativeExports.csproj new file mode 100644 index 0000000000000..c93a8ac56d9e0 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/NativeExports.csproj @@ -0,0 +1,116 @@ + + + + Microsoft.Interop.Tests.NativeExports + $(NetCoreAppCurrent) + true + true + true + Major + + $(OutputRid) + $(OutputRid) + + + + + + + + + + + + + $(Compiler) + clang + + + + + + + + + + + + + + + + + + + + + --target=$(TargetTriple) --gcc-toolchain=$(ROOTFS_DIR)/usr --sysroot=$(ROOTFS_DIR) + $(CommonToolchainArgs) $(DnneLinkerUserFlags.Replace(';',' ')) + $(CommonToolchainArgs) $(DnneCompilerUserFlags.Replace(';',' ')) + + + + + + arm64-apple-ios14.2-macabi + x86_64-apple-ios13.5-macabi + + + arm64-apple-macos11 + x86_64-apple-macos10.13 + macosx + + + + + + + + + + + + + + + + -target $(TargetTriple) + -isysroot "$(SysRootIncludePath)" -target $(TargetTriple) + + + + + + $([System.IO.Path]::GetDirectoryName('$(AppHostSourcePath)')) + + + diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/Numeric.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/Numeric.cs new file mode 100644 index 0000000000000..b6cff4680b93e --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/Numeric.cs @@ -0,0 +1,46 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.InteropServices; + +namespace NativeExports +{ + public static unsafe class Numeric + { + [UnmanagedCallersOnly(EntryPoint = "subtract_return_byte")] + public static byte SubtractReturnByte(byte a, byte b) + { + return (byte)(a - b); + } + + [UnmanagedCallersOnly(EntryPoint = "subtract_out_byte")] + public static void SubtractReturnAsOutByte(byte a, byte b, byte* ret) + { + *ret = (byte)(a - b); + } + + [UnmanagedCallersOnly(EntryPoint = "subtract_ref_byte")] + public static void SubtractRefByte(byte a, byte* b) + { + *b = (byte)(a - *b); + } + + [UnmanagedCallersOnly(EntryPoint = "subtract_return_int")] + public static int SubtractReturnInt(int a, int b) + { + return a - b; + } + + [UnmanagedCallersOnly(EntryPoint = "subtract_out_int")] + public static void SubtractReturnAsOutInt(int a, int b, int* ret) + { + *ret = a - b; + } + + [UnmanagedCallersOnly(EntryPoint = "subtract_ref_int")] + public static void SubtractRefInt(int a, int* b) + { + *b = a - *b; + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/Strings.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/Strings.cs new file mode 100644 index 0000000000000..acb72da759ce5 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/Strings.cs @@ -0,0 +1,154 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.InteropServices; + +namespace NativeExports +{ + public static unsafe class Strings + { + [UnmanagedCallersOnly(EntryPoint = "return_length_ushort")] + public static int ReturnLengthUShort(ushort* input) + { + if (input == null) + return -1; + + return GetLength(input); + } + + [UnmanagedCallersOnly(EntryPoint = "return_length_byte")] + public static int ReturnLengthByte(byte* input) + { + if (input == null) + return -1; + + return GetLength(input); + } + + [UnmanagedCallersOnly(EntryPoint = "reverse_return_ushort")] + public static ushort* ReverseReturnUShort(ushort* input) + { + return Reverse(input); + } + + [UnmanagedCallersOnly(EntryPoint = "reverse_return_byte")] + public static byte* ReverseReturnByte(byte* input) + { + return Reverse(input); + } + + [UnmanagedCallersOnly(EntryPoint = "reverse_out_ushort")] + public static void ReverseReturnAsOutUShort(ushort* input, ushort** ret) + { + *ret = Reverse(input); + } + + [UnmanagedCallersOnly(EntryPoint = "reverse_out_byte")] + public static void ReverseReturnAsOutByte(byte* input, byte** ret) + { + *ret = Reverse(input); + } + + [UnmanagedCallersOnly(EntryPoint = "reverse_inplace_ref_ushort")] + public static void ReverseInPlaceUShort(ushort** refInput) + { + if (*refInput == null) + return; + + int len = GetLength(*refInput); + var span = new Span(*refInput, len); + span.Reverse(); + } + + [UnmanagedCallersOnly(EntryPoint = "reverse_inplace_ref_byte")] + public static void ReverseInPlaceByte(byte** refInput) + { + int len = GetLength(*refInput); + var span = new Span(*refInput, len); + span.Reverse(); + } + + [UnmanagedCallersOnly(EntryPoint = "reverse_replace_ref_ushort")] + public static void ReverseReplaceRefUShort(ushort** s) + { + if (*s == null) + return; + + ushort* ret = Reverse(*s); + Marshal.FreeCoTaskMem((IntPtr)(*s)); + *s = ret; + } + + [UnmanagedCallersOnly(EntryPoint = "reverse_replace_ref_byte")] + public static void ReverseReplaceRefByte(byte** s) + { + if (*s == null) + return; + + byte* ret = Reverse(*s); + Marshal.FreeCoTaskMem((IntPtr)(*s)); + *s = ret; + } + + internal static ushort* Reverse(ushort *s) + { + if (s == null) + return null; + + int len = GetLength(s); + ushort* ret = (ushort*)Marshal.AllocCoTaskMem((len + 1) * sizeof(ushort)); + var span = new Span(ret, len); + + new Span(s, len).CopyTo(span); + span.Reverse(); + ret[len] = 0; + return ret; + } + + internal static byte* Reverse(byte* s) + { + if (s == null) + return null; + + int len = GetLength(s); + byte* ret = (byte*)Marshal.AllocCoTaskMem((len + 1) * sizeof(byte)); + var span = new Span(ret, len); + + new Span(s, len).CopyTo(span); + span.Reverse(); + ret[len] = 0; + return ret; + } + + private static int GetLength(ushort* input) + { + if (input == null) + return 0; + + int len = 0; + while (*input != 0) + { + input++; + len++; + } + + return len; + } + + private static int GetLength(byte* input) + { + if (input == null) + return 0; + + int len = 0; + while (*input != 0) + { + input++; + len++; + } + + return len; + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/Blittable.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/Blittable.cs new file mode 100644 index 0000000000000..dec9f74ab4923 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/Blittable.cs @@ -0,0 +1,16 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.InteropServices; + +namespace SharedTypes +{ + [BlittableType] + public struct IntFields + { + public int a; + public int b; + public int c; + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/DNNE.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/DNNE.cs new file mode 100644 index 0000000000000..0b3dd369433a9 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/DNNE.cs @@ -0,0 +1,14 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace DNNE +{ + public class C99DeclCodeAttribute : System.Attribute + { + public C99DeclCodeAttribute(string code) { } + } + public class C99TypeAttribute : System.Attribute + { + public C99TypeAttribute(string code) { } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/NonBlittable.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/NonBlittable.cs new file mode 100644 index 0000000000000..5d46f83e845ed --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/NonBlittable.cs @@ -0,0 +1,335 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Runtime.InteropServices; + +namespace SharedTypes +{ + [NativeMarshalling(typeof(StringContainerNative))] + public struct StringContainer + { + public string str1; + public string str2; + } + + [BlittableType] + public struct StringContainerNative + { + public IntPtr str1; + public IntPtr str2; + + public StringContainerNative(StringContainer managed) + { + str1 = Marshal.StringToCoTaskMemUTF8(managed.str1); + str2 = Marshal.StringToCoTaskMemUTF8(managed.str2); + } + + public StringContainer ToManaged() + { + return new StringContainer + { + str1 = Marshal.PtrToStringUTF8(str1), + str2 = Marshal.PtrToStringUTF8(str2) + }; + } + + public void FreeNative() + { + Marshal.FreeCoTaskMem(str1); + Marshal.FreeCoTaskMem(str2); + } + } + + public struct DoubleToLongMarshaler + { + public long l; + + public DoubleToLongMarshaler(double d) + { + l = MemoryMarshal.Cast(MemoryMarshal.CreateSpan(ref d, 1))[0]; + } + + public double ToManaged() => MemoryMarshal.Cast(MemoryMarshal.CreateSpan(ref l, 1))[0]; + + public long Value + { + get => l; + set => l = value; + } + } + + [NativeMarshalling(typeof(BoolStructNative))] + public struct BoolStruct + { + public bool b1; + public bool b2; + public bool b3; + } + + [BlittableType] + public struct BoolStructNative + { + public byte b1; + public byte b2; + public byte b3; + public BoolStructNative(BoolStruct bs) + { + b1 = (byte)(bs.b1 ? 1 : 0); + b2 = (byte)(bs.b2 ? 1 : 0); + b3 = (byte)(bs.b3 ? 1 : 0); + } + + public BoolStruct ToManaged() + { + return new BoolStruct + { + b1 = b1 != 0, + b2 = b2 != 0, + b3 = b3 != 0 + }; + } + } + + [NativeMarshalling(typeof(IntWrapperMarshaler))] + public class IntWrapper + { + public int i; + + public ref int GetPinnableReference() => ref i; + } + + public unsafe struct IntWrapperMarshaler + { + public IntWrapperMarshaler(IntWrapper managed) + { + Value = (int*)Marshal.AllocCoTaskMem(sizeof(int)); + *Value = managed.i; + } + + public int* Value { get; set; } + + public IntWrapper ToManaged() => new IntWrapper { i = *Value }; + + public void FreeNative() + { + Marshal.FreeCoTaskMem((IntPtr)Value); + } + } + + public unsafe ref struct Utf16StringMarshaler + { + private ushort* ptr; + private Span span; + + public Utf16StringMarshaler(string str) + { + ptr = str is null ? null : (ushort*)Marshal.StringToCoTaskMemUni(str); + span = default; + } + + public Utf16StringMarshaler(string str, Span buffer) + { + if (str is null) + { + ptr = null; + span = default; + } + else if ((str.Length + 1) < StackBufferSize) + { + span = MemoryMarshal.Cast(buffer); + str.AsSpan().CopyTo(MemoryMarshal.Cast(buffer)); + // Supplied memory is in an undefined state so ensure + // there is a trailing null in the buffer. + span[str.Length] = '\0'; + ptr = null; + } + else + { + span = default; + ptr = (ushort*)Marshal.StringToCoTaskMemUni(str); + } + } + + public ref ushort GetPinnableReference() + { + if (ptr != null) + { + return ref *ptr; + } + return ref span.GetPinnableReference(); + } + + public ushort* Value + { + get + { + if (ptr == null && span != default) + { + throw new InvalidOperationException(); + } + return ptr; + } + set + { + ptr = value; + span = default; + } + } + + public string ToManaged() + { + if (ptr == null && span == default) + { + return null; + } + else if (ptr != null) + { + return Marshal.PtrToStringUni((IntPtr)ptr); + } + else + { + return MemoryMarshal.Cast(span).ToString(); + } + } + + public void FreeNative() + { + if (ptr != null) + { + Marshal.FreeCoTaskMem((IntPtr)ptr); + } + } + + public const int StackBufferSize = 0x100; + } + + [NativeMarshalling(typeof(IntStructWrapperNative))] + public struct IntStructWrapper + { + public int Value; + } + + public struct IntStructWrapperNative + { + public int value; + public IntStructWrapperNative(IntStructWrapper managed) + { + value = managed.Value; + } + + public IntStructWrapper ToManaged() => new IntStructWrapper { Value = value }; + } + + [GenericContiguousCollectionMarshaller] + public unsafe ref struct ListMarshaller + { + private List managedList; + private readonly int sizeOfNativeElement; + private IntPtr allocatedMemory; + + public ListMarshaller(int sizeOfNativeElement) + : this() + { + this.sizeOfNativeElement = sizeOfNativeElement; + } + + public ListMarshaller(List managed, int sizeOfNativeElement) + { + allocatedMemory = default; + this.sizeOfNativeElement = sizeOfNativeElement; + if (managed is null) + { + managedList = null; + NativeValueStorage = default; + return; + } + managedList = managed; + this.sizeOfNativeElement = sizeOfNativeElement; + // Always allocate at least one byte when the array is zero-length. + int spaceToAllocate = Math.Max(managed.Count * sizeOfNativeElement, 1); + allocatedMemory = Marshal.AllocCoTaskMem(spaceToAllocate); + NativeValueStorage = new Span((void*)allocatedMemory, spaceToAllocate); + } + + public ListMarshaller(List managed, Span stackSpace, int sizeOfNativeElement) + { + allocatedMemory = default; + this.sizeOfNativeElement = sizeOfNativeElement; + if (managed is null) + { + managedList = null; + NativeValueStorage = default; + return; + } + managedList = managed; + // Always allocate at least one byte when the array is zero-length. + int spaceToAllocate = Math.Max(managed.Count * sizeOfNativeElement, 1); + if (spaceToAllocate <= stackSpace.Length) + { + NativeValueStorage = stackSpace[0..spaceToAllocate]; + } + else + { + allocatedMemory = Marshal.AllocCoTaskMem(spaceToAllocate); + NativeValueStorage = new Span((void*)allocatedMemory, spaceToAllocate); + } + } + + /// + /// Stack-alloc threshold set to 256 bytes to enable small arrays to be passed on the stack. + /// Number kept small to ensure that P/Invokes with a lot of array parameters doesn't + /// blow the stack since this is a new optimization in the code-generated interop. + /// + public const int StackBufferSize = 0x200; + + public Span ManagedValues => CollectionsMarshal.AsSpan(managedList); + + public Span NativeValueStorage { get; private set; } + + public ref byte GetPinnableReference() => ref NativeValueStorage.GetPinnableReference(); + + public void SetUnmarshalledCollectionLength(int length) + { + managedList = new List(length); + for (int i = 0; i < length; i++) + { + managedList.Add(default); + } + } + + public byte* Value + { + get + { + Debug.Assert(managedList is null || allocatedMemory != IntPtr.Zero); + return (byte*)allocatedMemory; + } + set + { + if (value == null) + { + managedList = null; + NativeValueStorage = default; + } + else + { + allocatedMemory = (IntPtr)value; + NativeValueStorage = new Span(value, (managedList?.Count ?? 0) * sizeOfNativeElement); + } + } + } + + public List ToManaged() => managedList; + + public void FreeNative() + { + if (allocatedMemory != IntPtr.Zero) + { + Marshal.FreeCoTaskMem(allocatedMemory); + } + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/SharedTypes.csproj b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/SharedTypes.csproj new file mode 100644 index 0000000000000..d04a12ecddd30 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/SharedTypes.csproj @@ -0,0 +1,12 @@ + + + + $(NetCoreAppCurrent) + true + + + + + + + diff --git a/src/libraries/System.Security.AccessControl/src/System.Security.AccessControl.csproj b/src/libraries/System.Security.AccessControl/src/System.Security.AccessControl.csproj index ae2bd9f64570a..1e5c1ebda3fb6 100644 --- a/src/libraries/System.Security.AccessControl/src/System.Security.AccessControl.csproj +++ b/src/libraries/System.Security.AccessControl/src/System.Security.AccessControl.csproj @@ -1,4 +1,4 @@ - + true $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent) @@ -84,6 +84,7 @@ + diff --git a/src/libraries/System.Security.AccessControl/src/System/Security/AccessControl/Win32.cs b/src/libraries/System.Security.AccessControl/src/System/Security/AccessControl/Win32.cs index 15f3301eb7daa..fda6a851db428 100644 --- a/src/libraries/System.Security.AccessControl/src/System/Security/AccessControl/Win32.cs +++ b/src/libraries/System.Security.AccessControl/src/System/Security/AccessControl/Win32.cs @@ -66,7 +66,7 @@ internal static int ConvertSdToSddl( // Wrapper around advapi32.GetSecurityInfo // - internal static int GetSecurityInfo( + internal static unsafe int GetSecurityInfo( ResourceType resourceType, string? name, SafeHandle? handle, @@ -130,7 +130,7 @@ out RawSecurityDescriptor? resultSd } else { - errorCode = (int)Interop.Advapi32.GetSecurityInfoByHandle(handle, (uint)resourceType, (uint)SecurityInfos, out SidOwner, out SidGroup, out Dacl, out Sacl, out ByteArray); + errorCode = (int)Interop.Advapi32.GetSecurityInfoByHandle(handle, (uint)resourceType, (uint)SecurityInfos, &SidOwner, &SidGroup, &Dacl, &Sacl, &ByteArray); } } else diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/HashProviderDispenser.OSX.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/HashProviderDispenser.OSX.cs index 3bc72d0e62deb..c562dfff5a907 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/HashProviderDispenser.OSX.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/HashProviderDispenser.OSX.cs @@ -45,6 +45,7 @@ public static unsafe int MacData( fixed (byte* pSource = source) fixed (byte* pDestination = destination) { + int digestSize; int ret = Interop.AppleCrypto.HmacOneShot( algorithm, pKey, @@ -53,7 +54,7 @@ public static unsafe int MacData( source.Length, pDestination, destination.Length, - out int digestSize); + &digestSize); if (ret != 1) { @@ -74,13 +75,14 @@ public static unsafe int HashData(string hashAlgorithmId, ReadOnlySpan sou fixed (byte* pSource = source) fixed (byte* pDestination = destination) { + int digestSize; int ret = Interop.AppleCrypto.DigestOneShot( algorithm, pSource, source.Length, pDestination, destination.Length, - out int digestSize); + &digestSize); if (ret != 1) { diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/HashProviderDispenser.Unix.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/HashProviderDispenser.Unix.cs index 3a7b7974455df..669faad082928 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/HashProviderDispenser.Unix.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/HashProviderDispenser.Unix.cs @@ -61,7 +61,7 @@ public static unsafe int HashData(string hashAlgorithmId, ReadOnlySpan sou fixed (byte* pDestination = destination) { uint length = (uint)destination.Length; - Check(Interop.Crypto.EvpDigestOneShot(evpType, pSource, source.Length, pDestination, ref length)); + Check(Interop.Crypto.EvpDigestOneShot(evpType, pSource, source.Length, pDestination, &length)); Debug.Assert(length == hashSize); } diff --git a/src/libraries/System.Security.Cryptography.Cng/src/System.Security.Cryptography.Cng.csproj b/src/libraries/System.Security.Cryptography.Cng/src/System.Security.Cryptography.Cng.csproj index c8e8bb0e3200f..ed2e6f564ff92 100644 --- a/src/libraries/System.Security.Cryptography.Cng/src/System.Security.Cryptography.Cng.csproj +++ b/src/libraries/System.Security.Cryptography.Cng/src/System.Security.Cryptography.Cng.csproj @@ -366,6 +366,7 @@ + diff --git a/src/libraries/System.Security.Cryptography.Csp/src/System.Security.Cryptography.Csp.csproj b/src/libraries/System.Security.Cryptography.Csp/src/System.Security.Cryptography.Csp.csproj index e5e96801c984e..842f0cce0a79f 100644 --- a/src/libraries/System.Security.Cryptography.Csp/src/System.Security.Cryptography.Csp.csproj +++ b/src/libraries/System.Security.Cryptography.Csp/src/System.Security.Cryptography.Csp.csproj @@ -127,6 +127,7 @@ + diff --git a/src/libraries/System.Security.Cryptography.Encoding/src/System.Security.Cryptography.Encoding.csproj b/src/libraries/System.Security.Cryptography.Encoding/src/System.Security.Cryptography.Encoding.csproj index ea5329594dcfb..c957f51337e5c 100644 --- a/src/libraries/System.Security.Cryptography.Encoding/src/System.Security.Cryptography.Encoding.csproj +++ b/src/libraries/System.Security.Cryptography.Encoding/src/System.Security.Cryptography.Encoding.csproj @@ -124,6 +124,7 @@ + diff --git a/src/libraries/System.Security.Cryptography.OpenSsl/src/System.Security.Cryptography.OpenSsl.csproj b/src/libraries/System.Security.Cryptography.OpenSsl/src/System.Security.Cryptography.OpenSsl.csproj index 89fdccd055e31..e24fb40cf9d06 100644 --- a/src/libraries/System.Security.Cryptography.OpenSsl/src/System.Security.Cryptography.OpenSsl.csproj +++ b/src/libraries/System.Security.Cryptography.OpenSsl/src/System.Security.Cryptography.OpenSsl.csproj @@ -160,6 +160,7 @@ + diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/Native/Interop.crypt32.cs b/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/Native/Interop.crypt32.cs index 2b59f383266d2..24eb1081904a4 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/Native/Interop.crypt32.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/Native/Interop.crypt32.cs @@ -22,8 +22,8 @@ internal static partial class Interop { public static partial class crypt32 { - [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] - public static extern unsafe bool CryptQueryObject( + [GeneratedDllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] + public static unsafe partial bool CryptQueryObject( CertQueryObjectType dwObjectType, void* pvObject, ExpectedContentTypeFlags dwExpectedContentTypeFlags, @@ -37,8 +37,8 @@ public static extern unsafe bool CryptQueryObject( out SafeCertContextHandle ppvContext ); - [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] - public static extern unsafe bool CryptQueryObject( + [GeneratedDllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] + public static unsafe partial bool CryptQueryObject( CertQueryObjectType dwObjectType, void* pvObject, ExpectedContentTypeFlags dwExpectedContentTypeFlags, @@ -52,8 +52,8 @@ public static extern unsafe bool CryptQueryObject( IntPtr ppvContext ); - [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] - public static extern unsafe bool CryptQueryObject( + [GeneratedDllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] + public static unsafe partial bool CryptQueryObject( CertQueryObjectType dwObjectType, void* pvObject, ExpectedContentTypeFlags dwExpectedContentTypeFlags, @@ -68,26 +68,26 @@ IntPtr ppvContext ); - [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] - public static extern bool CertGetCertificateContextProperty(SafeCertContextHandle pCertContext, CertContextPropId dwPropId, [Out] byte[]? pvData, [In, Out] ref int pcbData); + [GeneratedDllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] + public static partial bool CertGetCertificateContextProperty(SafeCertContextHandle pCertContext, CertContextPropId dwPropId, byte[]? pvData, ref int pcbData); - [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] - public static extern bool CertGetCertificateContextProperty(SafeCertContextHandle pCertContext, CertContextPropId dwPropId, [Out] out CRYPTOAPI_BLOB pvData, [In, Out] ref int pcbData); + [GeneratedDllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] + public static partial bool CertGetCertificateContextProperty(SafeCertContextHandle pCertContext, CertContextPropId dwPropId, out CRYPTOAPI_BLOB pvData, ref int pcbData); - [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] - public static extern bool CertGetCertificateContextProperty(SafeCertContextHandle pCertContext, CertContextPropId dwPropId, [Out] out IntPtr pvData, [In, Out] ref int pcbData); + [GeneratedDllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] + public static partial bool CertGetCertificateContextProperty(SafeCertContextHandle pCertContext, CertContextPropId dwPropId, out IntPtr pvData, ref int pcbData); - [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true, EntryPoint = "CertGetCertificateContextProperty")] - public static extern unsafe bool CertGetCertificateContextPropertyString(SafeCertContextHandle pCertContext, CertContextPropId dwPropId, byte* pvData, ref int pcbData); + [GeneratedDllImport(Libraries.Crypt32, EntryPoint = "CertGetCertificateContextProperty", CharSet = CharSet.Unicode, SetLastError = true)] + public static unsafe partial bool CertGetCertificateContextPropertyString(SafeCertContextHandle pCertContext, CertContextPropId dwPropId, byte* pvData, ref int pcbData); - [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] - public static extern unsafe bool CertSetCertificateContextProperty(SafeCertContextHandle pCertContext, CertContextPropId dwPropId, CertSetPropertyFlags dwFlags, [In] CRYPTOAPI_BLOB* pvData); + [GeneratedDllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] + public static unsafe partial bool CertSetCertificateContextProperty(SafeCertContextHandle pCertContext, CertContextPropId dwPropId, CertSetPropertyFlags dwFlags, CRYPTOAPI_BLOB* pvData); - [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] - public static extern unsafe bool CertSetCertificateContextProperty(SafeCertContextHandle pCertContext, CertContextPropId dwPropId, CertSetPropertyFlags dwFlags, [In] CRYPT_KEY_PROV_INFO* pvData); + [GeneratedDllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] + public static unsafe partial bool CertSetCertificateContextProperty(SafeCertContextHandle pCertContext, CertContextPropId dwPropId, CertSetPropertyFlags dwFlags, CRYPT_KEY_PROV_INFO* pvData); - [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] - public static extern unsafe bool CertSetCertificateContextProperty(SafeCertContextHandle pCertContext, CertContextPropId dwPropId, CertSetPropertyFlags dwFlags, [In] SafeNCryptKeyHandle keyHandle); + [GeneratedDllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] + public static unsafe partial bool CertSetCertificateContextProperty(SafeCertContextHandle pCertContext, CertContextPropId dwPropId, CertSetPropertyFlags dwFlags, SafeNCryptKeyHandle keyHandle); public static unsafe string CertGetNameString( SafeCertContextHandle certContext, @@ -114,34 +114,34 @@ public static unsafe string CertGetNameString( } } - [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true, EntryPoint = "CertGetNameStringW")] - private static extern unsafe int CertGetNameString(SafeCertContextHandle pCertContext, CertNameType dwType, CertNameFlags dwFlags, in CertNameStringType pvTypePara, char* pszNameString, int cchNameString); + [GeneratedDllImport(Libraries.Crypt32, EntryPoint = "CertGetNameStringW", CharSet = CharSet.Unicode, SetLastError = true)] + private static unsafe partial int CertGetNameString(SafeCertContextHandle pCertContext, CertNameType dwType, CertNameFlags dwFlags, in CertNameStringType pvTypePara, char* pszNameString, int cchNameString); - [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] - public static extern SafeCertContextHandle CertDuplicateCertificateContext(IntPtr pCertContext); + [GeneratedDllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] + public static partial SafeCertContextHandle CertDuplicateCertificateContext(IntPtr pCertContext); - [DllImport(Libraries.Crypt32, SetLastError = true)] - public static extern SafeX509ChainHandle CertDuplicateCertificateChain(IntPtr pChainContext); + [GeneratedDllImport(Libraries.Crypt32, SetLastError = true)] + public static partial SafeX509ChainHandle CertDuplicateCertificateChain(IntPtr pChainContext); - [DllImport(Libraries.Crypt32, SetLastError = true)] - internal static extern SafeCertStoreHandle CertDuplicateStore(IntPtr hCertStore); + [GeneratedDllImport(Libraries.Crypt32, SetLastError = true)] + internal static partial SafeCertStoreHandle CertDuplicateStore(IntPtr hCertStore); - [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true, EntryPoint = "CertDuplicateCertificateContext")] - public static extern SafeCertContextHandleWithKeyContainerDeletion CertDuplicateCertificateContextWithKeyContainerDeletion(IntPtr pCertContext); + [GeneratedDllImport(Libraries.Crypt32, EntryPoint = "CertDuplicateCertificateContext", CharSet = CharSet.Unicode, SetLastError = true)] + public static partial SafeCertContextHandleWithKeyContainerDeletion CertDuplicateCertificateContextWithKeyContainerDeletion(IntPtr pCertContext); public static SafeCertStoreHandle CertOpenStore(CertStoreProvider lpszStoreProvider, CertEncodingType dwMsgAndCertEncodingType, IntPtr hCryptProv, CertStoreFlags dwFlags, string? pvPara) { return CertOpenStore((IntPtr)lpszStoreProvider, dwMsgAndCertEncodingType, hCryptProv, dwFlags, pvPara); } - [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] - private static extern SafeCertStoreHandle CertOpenStore(IntPtr lpszStoreProvider, CertEncodingType dwMsgAndCertEncodingType, IntPtr hCryptProv, CertStoreFlags dwFlags, [MarshalAs(UnmanagedType.LPWStr)] string? pvPara); + [GeneratedDllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] + private static partial SafeCertStoreHandle CertOpenStore(IntPtr lpszStoreProvider, CertEncodingType dwMsgAndCertEncodingType, IntPtr hCryptProv, CertStoreFlags dwFlags, [MarshalAs(UnmanagedType.LPWStr)] string? pvPara); - [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] - public static extern bool CertAddCertificateContextToStore(SafeCertStoreHandle hCertStore, SafeCertContextHandle pCertContext, CertStoreAddDisposition dwAddDisposition, IntPtr ppStoreContext); + [GeneratedDllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] + public static partial bool CertAddCertificateContextToStore(SafeCertStoreHandle hCertStore, SafeCertContextHandle pCertContext, CertStoreAddDisposition dwAddDisposition, IntPtr ppStoreContext); - [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] - public static extern bool CertAddCertificateLinkToStore(SafeCertStoreHandle hCertStore, SafeCertContextHandle pCertContext, CertStoreAddDisposition dwAddDisposition, IntPtr ppStoreContext); + [GeneratedDllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] + public static partial bool CertAddCertificateLinkToStore(SafeCertStoreHandle hCertStore, SafeCertContextHandle pCertContext, CertStoreAddDisposition dwAddDisposition, IntPtr ppStoreContext); /// /// A less error-prone wrapper for CertEnumCertificatesInStore(). @@ -174,56 +174,56 @@ public static unsafe bool CertEnumCertificatesInStore(SafeCertStoreHandle hCertS return false; } - [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] - private static extern unsafe CERT_CONTEXT* CertEnumCertificatesInStore(SafeCertStoreHandle hCertStore, CERT_CONTEXT* pPrevCertContext); + [GeneratedDllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] + private static unsafe partial CERT_CONTEXT* CertEnumCertificatesInStore(SafeCertStoreHandle hCertStore, CERT_CONTEXT* pPrevCertContext); - [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] - public static extern SafeCertStoreHandle PFXImportCertStore([In] ref CRYPTOAPI_BLOB pPFX, SafePasswordHandle password, PfxCertStoreFlags dwFlags); + [GeneratedDllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] + public static partial SafeCertStoreHandle PFXImportCertStore(ref CRYPTOAPI_BLOB pPFX, SafePasswordHandle password, PfxCertStoreFlags dwFlags); - [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] - public static extern unsafe bool CryptMsgGetParam(SafeCryptMsgHandle hCryptMsg, CryptMessageParameterType dwParamType, int dwIndex, byte* pvData, [In, Out] ref int pcbData); + [GeneratedDllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] + public static unsafe partial bool CryptMsgGetParam(SafeCryptMsgHandle hCryptMsg, CryptMessageParameterType dwParamType, int dwIndex, byte* pvData, ref int pcbData); - [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] - public static extern bool CryptMsgGetParam(SafeCryptMsgHandle hCryptMsg, CryptMessageParameterType dwParamType, int dwIndex, out int pvData, [In, Out] ref int pcbData); + [GeneratedDllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] + public static partial bool CryptMsgGetParam(SafeCryptMsgHandle hCryptMsg, CryptMessageParameterType dwParamType, int dwIndex, out int pvData, ref int pcbData); - [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] - public static extern bool CertSerializeCertificateStoreElement(SafeCertContextHandle pCertContext, int dwFlags, [Out] byte[]? pbElement, [In, Out] ref int pcbElement); + [GeneratedDllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] + public static partial bool CertSerializeCertificateStoreElement(SafeCertContextHandle pCertContext, int dwFlags, byte[]? pbElement, ref int pcbElement); - [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] - public static extern bool PFXExportCertStore(SafeCertStoreHandle hStore, [In, Out] ref CRYPTOAPI_BLOB pPFX, SafePasswordHandle szPassword, PFXExportFlags dwFlags); + [GeneratedDllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] + public static partial bool PFXExportCertStore(SafeCertStoreHandle hStore, ref CRYPTOAPI_BLOB pPFX, SafePasswordHandle szPassword, PFXExportFlags dwFlags); - [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true, EntryPoint = "CertStrToNameW")] - public static extern bool CertStrToName(CertEncodingType dwCertEncodingType, string pszX500, CertNameStrTypeAndFlags dwStrType, IntPtr pvReserved, [Out] byte[]? pbEncoded, [In, Out] ref int pcbEncoded, IntPtr ppszError); + [GeneratedDllImport(Libraries.Crypt32, EntryPoint = "CertStrToNameW", CharSet = CharSet.Unicode, SetLastError = true)] + public static partial bool CertStrToName(CertEncodingType dwCertEncodingType, string pszX500, CertNameStrTypeAndFlags dwStrType, IntPtr pvReserved, byte[]? pbEncoded, ref int pcbEncoded, IntPtr ppszError); public static bool CryptDecodeObject(CertEncodingType dwCertEncodingType, CryptDecodeObjectStructType lpszStructType, byte[] pbEncoded, int cbEncoded, CryptDecodeObjectFlags dwFlags, byte[]? pvStructInfo, ref int pcbStructInfo) { return CryptDecodeObject(dwCertEncodingType, (IntPtr)lpszStructType, pbEncoded, cbEncoded, dwFlags, pvStructInfo, ref pcbStructInfo); } - [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] - private static extern bool CryptDecodeObject(CertEncodingType dwCertEncodingType, IntPtr lpszStructType, [In] byte[] pbEncoded, int cbEncoded, CryptDecodeObjectFlags dwFlags, [Out] byte[]? pvStructInfo, [In, Out] ref int pcbStructInfo); + [GeneratedDllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] + private static partial bool CryptDecodeObject(CertEncodingType dwCertEncodingType, IntPtr lpszStructType, byte[] pbEncoded, int cbEncoded, CryptDecodeObjectFlags dwFlags, byte[]? pvStructInfo, ref int pcbStructInfo); public static unsafe bool CryptDecodeObjectPointer(CertEncodingType dwCertEncodingType, CryptDecodeObjectStructType lpszStructType, byte[] pbEncoded, int cbEncoded, CryptDecodeObjectFlags dwFlags, void* pvStructInfo, ref int pcbStructInfo) { return CryptDecodeObjectPointer(dwCertEncodingType, (IntPtr)lpszStructType, pbEncoded, cbEncoded, dwFlags, pvStructInfo, ref pcbStructInfo); } - [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true, EntryPoint = "CryptDecodeObject")] - private static extern unsafe bool CryptDecodeObjectPointer(CertEncodingType dwCertEncodingType, IntPtr lpszStructType, [In] byte[] pbEncoded, int cbEncoded, CryptDecodeObjectFlags dwFlags, [Out] void* pvStructInfo, [In, Out] ref int pcbStructInfo); + [GeneratedDllImport(Libraries.Crypt32, EntryPoint = "CryptDecodeObject", CharSet = CharSet.Unicode, SetLastError = true)] + private static unsafe partial bool CryptDecodeObjectPointer(CertEncodingType dwCertEncodingType, IntPtr lpszStructType, byte[] pbEncoded, int cbEncoded, CryptDecodeObjectFlags dwFlags, void* pvStructInfo, ref int pcbStructInfo); - [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true, EntryPoint = "CryptDecodeObject")] - public static extern unsafe bool CryptDecodeObjectPointer(CertEncodingType dwCertEncodingType, [MarshalAs(UnmanagedType.LPStr)] string lpszStructType, [In] byte[] pbEncoded, int cbEncoded, CryptDecodeObjectFlags dwFlags, [Out] void* pvStructInfo, [In, Out] ref int pcbStructInfo); + [GeneratedDllImport(Libraries.Crypt32, EntryPoint = "CryptDecodeObject", CharSet = CharSet.Unicode, SetLastError = true)] + public static unsafe partial bool CryptDecodeObjectPointer(CertEncodingType dwCertEncodingType, [MarshalAs(UnmanagedType.LPStr)] string lpszStructType, byte[] pbEncoded, int cbEncoded, CryptDecodeObjectFlags dwFlags, void* pvStructInfo, ref int pcbStructInfo); public static unsafe bool CryptEncodeObject(CertEncodingType dwCertEncodingType, CryptDecodeObjectStructType lpszStructType, void* pvStructInfo, byte[]? pbEncoded, ref int pcbEncoded) { return CryptEncodeObject(dwCertEncodingType, (IntPtr)lpszStructType, pvStructInfo, pbEncoded, ref pcbEncoded); } - [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] - private static extern unsafe bool CryptEncodeObject(CertEncodingType dwCertEncodingType, IntPtr lpszStructType, void* pvStructInfo, [Out] byte[]? pbEncoded, [In, Out] ref int pcbEncoded); + [GeneratedDllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] + private static unsafe partial bool CryptEncodeObject(CertEncodingType dwCertEncodingType, IntPtr lpszStructType, void* pvStructInfo, byte[]? pbEncoded, ref int pcbEncoded); - [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] - public static extern unsafe bool CryptEncodeObject(CertEncodingType dwCertEncodingType, [MarshalAs(UnmanagedType.LPStr)] string lpszStructType, void* pvStructInfo, [Out] byte[]? pbEncoded, [In, Out] ref int pcbEncoded); + [GeneratedDllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] + public static unsafe partial bool CryptEncodeObject(CertEncodingType dwCertEncodingType, [MarshalAs(UnmanagedType.LPStr)] string lpszStructType, void* pvStructInfo, byte[]? pbEncoded, ref int pcbEncoded); public static unsafe byte[] EncodeObject(CryptDecodeObjectStructType lpszStructType, void* decoded) { @@ -262,20 +262,20 @@ internal static SafeChainEngineHandle CertCreateCertificateChainEngine(ref CERT_ return chainEngineHandle; } - [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] - private static extern bool CertCreateCertificateChainEngine(ref CERT_CHAIN_ENGINE_CONFIG pConfig, out SafeChainEngineHandle hChainEngineHandle); + [GeneratedDllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] + private static partial bool CertCreateCertificateChainEngine(ref CERT_CHAIN_ENGINE_CONFIG pConfig, out SafeChainEngineHandle hChainEngineHandle); [DllImport(Libraries.Crypt32)] public static extern void CertFreeCertificateChainEngine(IntPtr hChainEngine); - [DllImport(Libraries.Crypt32, SetLastError = true)] - public static extern unsafe bool CertGetCertificateChain(IntPtr hChainEngine, SafeCertContextHandle pCertContext, FILETIME* pTime, SafeCertStoreHandle hStore, [In] ref CERT_CHAIN_PARA pChainPara, CertChainFlags dwFlags, IntPtr pvReserved, out SafeX509ChainHandle ppChainContext); + [GeneratedDllImport(Libraries.Crypt32, SetLastError = true)] + public static unsafe partial bool CertGetCertificateChain(IntPtr hChainEngine, SafeCertContextHandle pCertContext, FILETIME* pTime, SafeCertStoreHandle hStore, ref CERT_CHAIN_PARA pChainPara, CertChainFlags dwFlags, IntPtr pvReserved, out SafeX509ChainHandle ppChainContext); - [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] - public static extern bool CryptHashPublicKeyInfo(IntPtr hCryptProv, int algId, int dwFlags, CertEncodingType dwCertEncodingType, [In] ref CERT_PUBLIC_KEY_INFO pInfo, [Out] byte[] pbComputedHash, [In, Out] ref int pcbComputedHash); + [GeneratedDllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] + public static partial bool CryptHashPublicKeyInfo(IntPtr hCryptProv, int algId, int dwFlags, CertEncodingType dwCertEncodingType, ref CERT_PUBLIC_KEY_INFO pInfo, byte[] pbComputedHash, ref int pcbComputedHash); - [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] - public static extern bool CertSaveStore(SafeCertStoreHandle hCertStore, CertEncodingType dwMsgAndCertEncodingType, CertStoreSaveAs dwSaveAs, CertStoreSaveTo dwSaveTo, ref CRYPTOAPI_BLOB pvSaveToPara, int dwFlags); + [GeneratedDllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] + public static partial bool CertSaveStore(SafeCertStoreHandle hCertStore, CertEncodingType dwMsgAndCertEncodingType, CertStoreSaveAs dwSaveAs, CertStoreSaveTo dwSaveTo, ref CRYPTOAPI_BLOB pvSaveToPara, int dwFlags); /// /// A less error-prone wrapper for CertEnumCertificatesInStore(). @@ -291,45 +291,45 @@ public static unsafe bool CertFindCertificateInStore(SafeCertStoreHandle hCertSt return !pCertContext.IsInvalid; } - [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] - private static extern unsafe SafeCertContextHandle CertFindCertificateInStore(SafeCertStoreHandle hCertStore, CertEncodingType dwCertEncodingType, CertFindFlags dwFindFlags, CertFindType dwFindType, void* pvFindPara, CERT_CONTEXT* pPrevCertContext); + [GeneratedDllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] + private static unsafe partial SafeCertContextHandle CertFindCertificateInStore(SafeCertStoreHandle hCertStore, CertEncodingType dwCertEncodingType, CertFindFlags dwFindFlags, CertFindType dwFindType, void* pvFindPara, CERT_CONTEXT* pPrevCertContext); - [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] - public static extern unsafe int CertVerifyTimeValidity([In] ref FILETIME pTimeToVerify, [In] CERT_INFO* pCertInfo); + [GeneratedDllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] + public static unsafe partial int CertVerifyTimeValidity(ref FILETIME pTimeToVerify, CERT_INFO* pCertInfo); - [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] - public static extern unsafe CERT_EXTENSION* CertFindExtension([MarshalAs(UnmanagedType.LPStr)] string pszObjId, int cExtensions, CERT_EXTENSION* rgExtensions); + [GeneratedDllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] + public static unsafe partial CERT_EXTENSION* CertFindExtension([MarshalAs(UnmanagedType.LPStr)] string pszObjId, int cExtensions, CERT_EXTENSION* rgExtensions); // Note: It's somewhat unusual to use an API enum as a parameter type to a P/Invoke but in this case, X509KeyUsageFlags was intentionally designed as bit-wise // identical to the wincrypt CERT_*_USAGE values. - [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] - public static extern unsafe bool CertGetIntendedKeyUsage(CertEncodingType dwCertEncodingType, CERT_INFO* pCertInfo, out X509KeyUsageFlags pbKeyUsage, int cbKeyUsage); + [GeneratedDllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] + public static unsafe partial bool CertGetIntendedKeyUsage(CertEncodingType dwCertEncodingType, CERT_INFO* pCertInfo, out X509KeyUsageFlags pbKeyUsage, int cbKeyUsage); - [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] - public static extern unsafe bool CertGetValidUsages(int cCerts, [In] ref SafeCertContextHandle rghCerts, out int cNumOIDs, [Out] void* rghOIDs, [In, Out] ref int pcbOIDs); + [GeneratedDllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] + public static unsafe partial bool CertGetValidUsages(int cCerts, ref SafeCertContextHandle rghCerts, out int cNumOIDs, void* rghOIDs, ref int pcbOIDs); - [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] - public static extern bool CertControlStore(SafeCertStoreHandle hCertStore, CertControlStoreFlags dwFlags, CertControlStoreType dwControlType, IntPtr pvCtrlPara); + [GeneratedDllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] + public static partial bool CertControlStore(SafeCertStoreHandle hCertStore, CertControlStoreFlags dwFlags, CertControlStoreType dwControlType, IntPtr pvCtrlPara); // Note: CertDeleteCertificateFromStore always calls CertFreeCertificateContext on pCertContext, even if an error is encountered. - [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] - public static extern unsafe bool CertDeleteCertificateFromStore(CERT_CONTEXT* pCertContext); + [GeneratedDllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] + public static unsafe partial bool CertDeleteCertificateFromStore(CERT_CONTEXT* pCertContext); - [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] - public static extern void CertFreeCertificateChain(IntPtr pChainContext); + [GeneratedDllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] + public static partial void CertFreeCertificateChain(IntPtr pChainContext); public static bool CertVerifyCertificateChainPolicy(ChainPolicy pszPolicyOID, SafeX509ChainHandle pChainContext, ref CERT_CHAIN_POLICY_PARA pPolicyPara, ref CERT_CHAIN_POLICY_STATUS pPolicyStatus) { return CertVerifyCertificateChainPolicy((IntPtr)pszPolicyOID, pChainContext, ref pPolicyPara, ref pPolicyStatus); } - [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] - private static extern bool CertVerifyCertificateChainPolicy(IntPtr pszPolicyOID, SafeX509ChainHandle pChainContext, [In] ref CERT_CHAIN_POLICY_PARA pPolicyPara, [In, Out] ref CERT_CHAIN_POLICY_STATUS pPolicyStatus); + [GeneratedDllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] + private static partial bool CertVerifyCertificateChainPolicy(IntPtr pszPolicyOID, SafeX509ChainHandle pChainContext, ref CERT_CHAIN_POLICY_PARA pPolicyPara, ref CERT_CHAIN_POLICY_STATUS pPolicyStatus); - [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] - public static extern unsafe bool CryptImportPublicKeyInfoEx2(CertEncodingType dwCertEncodingType, CERT_PUBLIC_KEY_INFO* pInfo, CryptImportPublicKeyInfoFlags dwFlags, void* pvAuxInfo, out SafeBCryptKeyHandle phKey); + [GeneratedDllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] + public static unsafe partial bool CryptImportPublicKeyInfoEx2(CertEncodingType dwCertEncodingType, CERT_PUBLIC_KEY_INFO* pInfo, CryptImportPublicKeyInfoFlags dwFlags, void* pvAuxInfo, out SafeBCryptKeyHandle phKey); - [DllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] - public static extern bool CryptAcquireCertificatePrivateKey(SafeCertContextHandle pCert, CryptAcquireFlags dwFlags, IntPtr pvParameters, out SafeNCryptKeyHandle phCryptProvOrNCryptKey, out int pdwKeySpec, out bool pfCallerFreeProvOrNCryptKey); + [GeneratedDllImport(Libraries.Crypt32, CharSet = CharSet.Unicode, SetLastError = true)] + public static partial bool CryptAcquireCertificatePrivateKey(SafeCertContextHandle pCert, CryptAcquireFlags dwFlags, IntPtr pvParameters, out SafeNCryptKeyHandle phCryptProvOrNCryptKey, out int pdwKeySpec, out bool pfCallerFreeProvOrNCryptKey); } } diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/Native/Interop.cryptoapi.cs b/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/Native/Interop.cryptoapi.cs index 0e0c6b64ae554..8b3c2d043b457 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/Native/Interop.cryptoapi.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Windows/Native/Interop.cryptoapi.cs @@ -14,8 +14,8 @@ internal static partial class Interop { public static partial class cryptoapi { - [DllImport(Libraries.Advapi32, SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "CryptAcquireContextW")] + [GeneratedDllImport(Libraries.Advapi32, EntryPoint = "CryptAcquireContextW", CharSet = CharSet.Unicode, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] - public static extern unsafe bool CryptAcquireContext(out IntPtr psafeProvHandle, char* pszContainer, char* pszProvider, int dwProvType, CryptAcquireContextFlags dwFlags); + public static unsafe partial bool CryptAcquireContext(out IntPtr psafeProvHandle, char* pszContainer, char* pszProvider, int dwProvType, CryptAcquireContextFlags dwFlags); } } diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/System.Security.Cryptography.X509Certificates.csproj b/src/libraries/System.Security.Cryptography.X509Certificates/src/System.Security.Cryptography.X509Certificates.csproj index 820ec32238c5a..0f3f4f7b6208c 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/System.Security.Cryptography.X509Certificates.csproj +++ b/src/libraries/System.Security.Cryptography.X509Certificates/src/System.Security.Cryptography.X509Certificates.csproj @@ -781,6 +781,7 @@ + diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/tests/System.Security.Cryptography.X509Certificates.Tests.csproj b/src/libraries/System.Security.Cryptography.X509Certificates/tests/System.Security.Cryptography.X509Certificates.Tests.csproj index bf4aada37fe82..4ca7042cfdf90 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/tests/System.Security.Cryptography.X509Certificates.Tests.csproj +++ b/src/libraries/System.Security.Cryptography.X509Certificates/tests/System.Security.Cryptography.X509Certificates.Tests.csproj @@ -1,4 +1,4 @@ - + true $(DefineConstants);HAVE_THUMBPRINT_OVERLOADS @@ -6,6 +6,7 @@ true $(NoWarn);SYSLIB0026;SYSLIB0027;SYSLIB0028 $(NetCoreAppCurrent)-windows;$(NetCoreAppCurrent)-Unix;$(NetCoreAppCurrent)-Android;$(NetCoreAppCurrent)-Browser;$(NetCoreAppCurrent)-OSX;$(NetCoreAppCurrent)-iOS;$(NetCoreAppCurrent)-tvOS + true true diff --git a/src/libraries/System.Security.Principal.Windows/src/System.Security.Principal.Windows.csproj b/src/libraries/System.Security.Principal.Windows/src/System.Security.Principal.Windows.csproj index 60b6dfd35510b..7217065c078e5 100644 --- a/src/libraries/System.Security.Principal.Windows/src/System.Security.Principal.Windows.csproj +++ b/src/libraries/System.Security.Principal.Windows/src/System.Security.Principal.Windows.csproj @@ -136,8 +136,10 @@ + + diff --git a/src/libraries/System.Security.Principal.Windows/src/System/Security/Principal/WindowsIdentity.cs b/src/libraries/System.Security.Principal.Windows/src/System/Security/Principal/WindowsIdentity.cs index 1079b819bafe2..e627638c6fe09 100644 --- a/src/libraries/System.Security.Principal.Windows/src/System/Security/Principal/WindowsIdentity.cs +++ b/src/libraries/System.Security.Principal.Windows/src/System/Security/Principal/WindowsIdentity.cs @@ -128,8 +128,12 @@ public WindowsIdentity(string sUserPrincipalName) byte[] sourceName = { (byte)'C', (byte)'L', (byte)'R', (byte)0 }; TOKEN_SOURCE sourceContext; - if (!Interop.Advapi32.AllocateLocallyUniqueId(out sourceContext.SourceIdentifier)) - throw new SecurityException(new Win32Exception().Message); + unsafe + { + if (!Interop.Advapi32.AllocateLocallyUniqueId(&sourceContext.SourceIdentifier)) + throw new SecurityException(new Win32Exception().Message); + } + sourceContext.SourceName = new byte[TOKEN_SOURCE.TOKEN_SOURCE_LENGTH]; Buffer.BlockCopy(sourceName, 0, sourceContext.SourceName, 0, sourceName.Length); diff --git a/src/libraries/tests.proj b/src/libraries/tests.proj index 67c03272de7ea..d369af6251bed 100644 --- a/src/libraries/tests.proj +++ b/src/libraries/tests.proj @@ -32,6 +32,21 @@ + + + + + + + + + + + + + + + diff --git a/src/samples/Directory.Build.props b/src/samples/Directory.Build.props new file mode 100644 index 0000000000000..4590be123eb7f --- /dev/null +++ b/src/samples/Directory.Build.props @@ -0,0 +1,8 @@ + + + + + true + true + + diff --git a/src/samples/Directory.Build.targets b/src/samples/Directory.Build.targets new file mode 100644 index 0000000000000..74fb272013ea8 --- /dev/null +++ b/src/samples/Directory.Build.targets @@ -0,0 +1,5 @@ + + + + + diff --git a/src/samples/DllImportGeneratorSample/.editorconfig b/src/samples/DllImportGeneratorSample/.editorconfig new file mode 100644 index 0000000000000..0c2c63edc1ba7 --- /dev/null +++ b/src/samples/DllImportGeneratorSample/.editorconfig @@ -0,0 +1,4 @@ +[*.cs] + +# DLLIMPORTGENANALYZER015: Use 'GeneratedDllImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time +dotnet_diagnostic.DLLIMPORTGENANALYZER015.severity = default diff --git a/src/samples/DllImportGeneratorSample/DllImportGeneratorSample.csproj b/src/samples/DllImportGeneratorSample/DllImportGeneratorSample.csproj new file mode 100644 index 0000000000000..32bd062dfe8c7 --- /dev/null +++ b/src/samples/DllImportGeneratorSample/DllImportGeneratorSample.csproj @@ -0,0 +1,24 @@ + + + + Exe + $(NetCoreAppCurrent) + true + preview + enable + + + true + true + false + false + + + + + + + + + diff --git a/src/samples/DllImportGeneratorSample/Program.cs b/src/samples/DllImportGeneratorSample/Program.cs new file mode 100644 index 0000000000000..4a1c8335bf418 --- /dev/null +++ b/src/samples/DllImportGeneratorSample/Program.cs @@ -0,0 +1,41 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.InteropServices; + +namespace Demo +{ + internal static partial class NativeExportsNE + { + public const string NativeExportsNE_Binary = "Microsoft.Interop.Tests." + nameof(NativeExportsNE); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "sumi")] + public static partial int Sum(int a, int b); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "sumouti")] + public static partial void Sum(int a, int b, out int c); + + [GeneratedDllImport(NativeExportsNE_Binary, EntryPoint = "sumrefi")] + public static partial void Sum(int a, ref int b); + } + + internal static class Program + { + public static void Main(string[] args) + { + int a = 12; + int b = 13; + int c = NativeExportsNE.Sum(a, b); + Console.WriteLine($"{a} + {b} = {c}"); + + c = 0; + NativeExportsNE.Sum(a, b, out c); + Console.WriteLine($"{a} + {b} = {c}"); + + c = b; + NativeExportsNE.Sum(a, ref c); + Console.WriteLine($"{a} + {b} = {c}"); + } + } +}