Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Variant marshalling #1142

Merged
merged 16 commits into from
May 28, 2021
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,16 @@ internal static DateTime OleDateTimeToDateTime(double value)
return DateTime.FromOADate(value);
}

internal static long DecimalToOleCurrency(decimal value)
{
return decimal.ToOACurrency(value);
}

internal static decimal OleCurrencyToDecimal(long value)
{
return decimal.FromOACurrency(value);
}

internal static unsafe string BstrBufferToString(char* buffer)
{
if (buffer == null)
Expand Down Expand Up @@ -549,6 +559,18 @@ o is string ||
Marshal.DestroyStructure(address, o.GetType());
}

internal static unsafe void CleanupVariant(IntPtr pDstNativeVariant)
{
#if TARGET_WINDOWS
#pragma warning disable CA1416
Variant* data = (Variant*)pDstNativeVariant;
data->Clear();
#pragma warning restore CA1416
#else
throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop);
#endif
}

[StructLayout(LayoutKind.Sequential)]
internal unsafe struct ModuleFixupCell
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,9 @@
<ItemGroup Condition="'$(TargetsWindows)'=='true'">
<Compile Include="Microsoft\Win32\SafeHandles\SafeThreadPoolIOHandle.cs" />
<Compile Include="System\Runtime\InteropServices\PInvokeMarshal.Windows.cs" />
<Compile Include="$(CommonPath)\System\Runtime\InteropServices\Variant.cs">
<Link>System\Runtime\InteropServices\Variant.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\Interop\Windows\Kernel32\Interop.GetCurrentThreadId.cs">
<Link>Interop\Windows\Kernel32\Interop.GetCurrentThreadId.cs</Link>
</Compile>
Expand All @@ -273,6 +276,9 @@
<Compile Include="$(CommonPath)\Interop\Windows\Ole32\Interop.CoGetApartmentType.cs">
<Link>Interop\Windows\Ole32\Interop.CoGetApartmentType.cs</Link>
</Compile>
<Compile Include="$(CommonPath)\Interop\Windows\OleAut32\Interop.VariantClear.cs">
<Link>Interop\Windows\OleAut32\Interop.VariantClear.cs</Link>
</Compile>
<Compile Include="System\Environment.CoreRT.Windows.cs" />
<Compile Include="System\Environment.CoreRT.Win32.cs" />
<Compile Include="$(CommonPath)\Interop\Windows\Kernel32\Interop.GetTickCount64.cs">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ namespace System.Runtime.InteropServices
{
public static partial class Marshal
{
private static readonly Guid IID_IDispatch = new Guid("00020400-0000-0000-C000-000000000046");
jkotas marked this conversation as resolved.
Show resolved Hide resolved
private const int DISP_E_PARAMNOTFOUND = unchecked((int)0x80020004);

public static int GetHRForException(Exception? e)
{
return PInvokeMarshal.GetHRForException(e);
Expand Down Expand Up @@ -69,7 +72,17 @@ public static int FinalReleaseComObject(object o)
[SupportedOSPlatform("windows")]
public static IntPtr GetComInterfaceForObject(object o, Type T)
{
throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop);
if (o is null)
{
throw new ArgumentNullException(nameof(o));
}

if (T is null)
{
throw new ArgumentNullException(nameof(T));
}

return ComWrappers.ComInterfaceForObject(o, T.GUID);
}

[SupportedOSPlatform("windows")]
Expand All @@ -81,7 +94,7 @@ public static IntPtr GetComInterfaceForObject(object o, Type T, CustomQueryInter
[SupportedOSPlatform("windows")]
public static IntPtr GetComInterfaceForObject<T, TInterface>([DisallowNull] T o)
{
throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop);
return GetComInterfaceForObject(o!, typeof(T));
}

[SupportedOSPlatform("windows")]
Expand All @@ -93,7 +106,12 @@ public static IntPtr GetComInterfaceForObject<T, TInterface>([DisallowNull] T o)
[SupportedOSPlatform("windows")]
public static IntPtr GetIDispatchForObject(object o)
{
throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop);
if (o is null)
{
throw new ArgumentNullException(nameof(o));
}

return ComWrappers.ComInterfaceForObject(o, IID_IDispatch);
}

[SupportedOSPlatform("windows")]
Expand All @@ -103,15 +121,131 @@ public static IntPtr GetIUnknownForObject(object o)
}

[SupportedOSPlatform("windows")]
public static void GetNativeVariantForObject(object? obj, IntPtr pDstNativeVariant)
public static unsafe void GetNativeVariantForObject(object? obj, IntPtr pDstNativeVariant)
{
jkotas marked this conversation as resolved.
Show resolved Hide resolved
throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop);
Variant* data = (Variant*)pDstNativeVariant;
if (obj == null)
{
data->VariantType = VarEnum.VT_EMPTY;
return;
}

if (obj is bool flag)
jkotas marked this conversation as resolved.
Show resolved Hide resolved
{
data->AsBool = flag;
}
else if (obj is byte b)
{
data->AsUi1 = b;
}
else if (obj is sbyte sb)
{
data->AsI1 = sb;
}
else if (obj is short s)
{
data->AsI2 = s;
}
else if (obj is ushort us)
{
data->AsUi2 = us;
}
else if (obj is int i)
{
data->AsI4 = i;
}
else if (obj is uint ui)
{
data->AsUi4 = ui;
}
else if (obj is long l)
{
data->AsI8 = l;
}
else if (obj is ulong ul)
{
data->AsUi8 = ul;
}
else if (obj is float f)
{
data->AsR4 = f;
}
else if (obj is double d)
{
data->AsR8 = d;
}
else if (obj is DateTime date)
{
data->AsDate = date;
}
else if (obj is decimal dec)
{
data->AsDecimal = dec;
}
else if (obj is char c)
{
data->AsUi2 = c;
}
else if (obj is string str)
{
data->AsBstr = str;
}
else if (obj is BStrWrapper strWrapper)
{
data->AsBstr = strWrapper.WrappedObject;
}
else if (obj is CurrencyWrapper currWrapper)
{
data->AsCy = currWrapper.WrappedObject;
}
else if (obj is UnknownWrapper unkWrapper)
{
data->AsUnknown = unkWrapper.WrappedObject;
}
else if (obj is DispatchWrapper dispWrapper)
{
data->AsDispatch = dispWrapper.WrappedObject;
}
else if (obj is ErrorWrapper errWrapper)
{
data->AsError = errWrapper.ErrorCode;
}
else if (obj is VariantWrapper variantWrapper)
{
// Do not want to implement that yet.
throw new NotSupportedException();
}
else if (obj is DBNull)
{
data->SetAsNULL();
}
else if (obj is System.Reflection.Missing)
{
data->AsError = DISP_E_PARAMNOTFOUND;
}
else
{
var type = obj.GetType();
if (type.IsValueType)
{
throw new NotSupportedException();
}
else if (type.IsArray)
{
// SAFEARRAY impementation goes here.
jkotas marked this conversation as resolved.
Show resolved Hide resolved
throw new NotSupportedException();
}
else
{
data->AsDispatch = obj;
}
}
}

[SupportedOSPlatform("windows")]
public static void GetNativeVariantForObject<T>(T? obj, IntPtr pDstNativeVariant)
{
throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop);
GetNativeVariantForObject((object?)obj, pDstNativeVariant);
}

[SupportedOSPlatform("windows")]
Expand All @@ -127,9 +261,16 @@ public static object GetObjectForIUnknown(IntPtr pUnk)
}

[SupportedOSPlatform("windows")]
public static object? GetObjectForNativeVariant(IntPtr pSrcNativeVariant)
public static unsafe object? GetObjectForNativeVariant(IntPtr pSrcNativeVariant)
{
throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop);
if (pSrcNativeVariant == IntPtr.Zero)
jkotas marked this conversation as resolved.
Show resolved Hide resolved
{
return null;
}

Variant* data = (Variant*)pSrcNativeVariant;

return data->ToObject();
jkotas marked this conversation as resolved.
Show resolved Hide resolved
jkotas marked this conversation as resolved.
Show resolved Hide resolved
}

[return: MaybeNull]
Expand Down
16 changes: 15 additions & 1 deletion src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ internal static TypeDesc GetNativeTypeFromMarshallerKind(TypeDesc type,
case MarshallerKind.CBool:
return context.GetWellKnownType(WellKnownType.Byte);

case MarshallerKind.VariantBool:
return context.GetWellKnownType(WellKnownType.Int16);

case MarshallerKind.Enum:
case MarshallerKind.BlittableStruct:
case MarshallerKind.Decimal:
Expand Down Expand Up @@ -162,6 +165,12 @@ internal static TypeDesc GetNativeTypeFromMarshallerKind(TypeDesc type,
case MarshallerKind.ComInterface:
return context.GetWellKnownType(WellKnownType.IntPtr);

case MarshallerKind.Variant:
return InteropTypes.GetVariant(context);

case MarshallerKind.OleCurrency:
return context.GetWellKnownType(WellKnownType.Int64);

case MarshallerKind.Unknown:
default:
throw new NotSupportedException();
Expand Down Expand Up @@ -254,6 +263,9 @@ internal static MarshallerKind GetMarshallerKind(
case NativeTypeKind.I1:
return MarshallerKind.CBool;

case NativeTypeKind.VariantBool:
return MarshallerKind.VariantBool;

default:
return MarshallerKind.Invalid;
}
Expand Down Expand Up @@ -355,6 +367,8 @@ internal static MarshallerKind GetMarshallerKind(
return MarshallerKind.Decimal;
else if (nativeType == NativeTypeKind.LPStruct && !isField)
return MarshallerKind.BlittableStructPtr;
else if (nativeType == NativeTypeKind.Currency)
return MarshallerKind.OleCurrency;
else
return MarshallerKind.Invalid;
}
Expand Down Expand Up @@ -566,7 +580,7 @@ internal static MarshallerKind GetMarshallerKind(
|| nativeType == NativeTypeKind.IUnknown)
return MarshallerKind.ComInterface;
else
return MarshallerKind.Invalid;
return MarshallerKind.Variant;
}
else if (InteropTypes.IsStringBuilder(context, type))
{
Expand Down
Loading