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 vtbls for IWeakReferenceSource and IWeakReference. #1300

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all 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
41 changes: 40 additions & 1 deletion src/Tests/UnitTest/TestComponentCSharp_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Security.Cryptography;
using Windows.Security.Cryptography.Core;
using System.Reflection;
using System.Reflection;
using Windows.Devices.Enumeration;
using Windows.Devices.Enumeration.Pnp;
using System.Diagnostics;

Expand Down Expand Up @@ -2911,6 +2912,44 @@ private void TestExperimentAttribute()
{
CustomExperimentClass custom = new CustomExperimentClass();
custom.f();
}

void OnDeviceAdded(DeviceWatcher sender, DeviceInformation args)
{
}

void OnDeviceUpdated(DeviceWatcher sender, DeviceInformationUpdate args)
{
}

[Fact]
public void TestWeakReferenceEventsFromMultipleContexts()
{
SemaphoreSlim semaphore = new SemaphoreSlim(0);
DeviceWatcher watcher = null;

Thread staThread = new Thread(() =>
{
Assert.True(Thread.CurrentThread.GetApartmentState() == ApartmentState.STA);

watcher = DeviceInformation.CreateWatcher();
var exception = Record.Exception(() => { watcher.Added += OnDeviceAdded; });
Assert.Null(exception);

Thread mtaThread = new Thread(() =>
{
Assert.True(Thread.CurrentThread.GetApartmentState() == ApartmentState.MTA);

exception = Record.Exception(() => { watcher.Updated += OnDeviceUpdated; });
Assert.Null(exception);
});
mtaThread.SetApartmentState(ApartmentState.MTA);
mtaThread.Start();
mtaThread.Join();
});
staThread.SetApartmentState(ApartmentState.STA);
staThread.Start();
staThread.Join();
}
}
}
2 changes: 1 addition & 1 deletion src/WinRT.Runtime/ComWrappersSupport.net5.cs
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,7 @@ private static object CreateObject(IntPtr externalComObject)
{
// IWeakReference is IUnknown-based, so implementations of it may not (and likely won't) implement
// IInspectable. As a result, we need to check for them explicitly.
var iunknownObjRef = ComWrappersSupport.GetObjectReferenceForInterface<IUnknownVftbl>(ptr);
var iunknownObjRef = ComWrappersSupport.GetObjectReferenceForInterface<ABI.WinRT.Interop.IWeakReference.Vftbl>(ptr);
ComWrappersHelper.Init(iunknownObjRef);

return new SingleInterfaceOptimizedObject(typeof(IWeakReference), iunknownObjRef, false);
Expand Down
83 changes: 82 additions & 1 deletion src/WinRT.Runtime/Interop/IWeakReferenceSource.net5.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,45 @@ static class IWeakReferenceSourceMethods
[Guid("00000038-0000-0000-C000-000000000046")]
internal unsafe interface IWeakReferenceSource : global::WinRT.Interop.IWeakReferenceSource
{
[Guid("00000038-0000-0000-C000-000000000046")]
internal struct Vftbl
{
public global::WinRT.Interop.IUnknownVftbl IUnknownVftbl;
private void* _GetWeakReference;
public delegate* unmanaged[Stdcall]<IntPtr, out IntPtr, int> GetWeakReference { get => (delegate* unmanaged[Stdcall]<IntPtr, out IntPtr, int>)_GetWeakReference; set => _GetWeakReference = value; }

public static readonly Vftbl AbiToProjectionVftable;
public static readonly IntPtr AbiToProjectionVftablePtr;

internal delegate int GetWeakReferenceDelegate(IntPtr thisPtr, IntPtr* weakReference);
private static readonly Delegate[] DelegateCache = new Delegate[1];
static Vftbl()
{
AbiToProjectionVftable = new Vftbl
{
IUnknownVftbl = global::WinRT.Interop.IUnknownVftbl.AbiToProjectionVftbl,
_GetWeakReference = Marshal.GetFunctionPointerForDelegate(DelegateCache[0] = new GetWeakReferenceDelegate(Do_Abi_GetWeakReference)).ToPointer(),
};
AbiToProjectionVftablePtr = Marshal.AllocHGlobal(Marshal.SizeOf<Vftbl>());
Marshal.StructureToPtr(AbiToProjectionVftable, AbiToProjectionVftablePtr, false);
}

private static int Do_Abi_GetWeakReference(IntPtr thisPtr, IntPtr* weakReference)
{
*weakReference = default;

try
{
*weakReference = ComWrappersSupport.CreateCCWForObject(new global::WinRT.Interop.ManagedWeakReference(ComWrappersSupport.FindObject<object>(thisPtr))).As<ABI.WinRT.Interop.IWeakReference.Vftbl>().GetRef();
}
catch (Exception __exception__)
{
return __exception__.HResult;
}
return 0;
}
}

internal static readonly Guid IID = InterfaceIIDs.IWeakReferenceSource_IID;

public static IntPtr AbiToProjectionVftablePtr;
Expand Down Expand Up @@ -131,6 +170,48 @@ private static int Do_Abi_GetWeakReference(IntPtr thisPtr, IntPtr* weakReference
[Guid("00000037-0000-0000-C000-000000000046")]
internal unsafe interface IWeakReference : global::WinRT.Interop.IWeakReference
{
[Guid("00000037-0000-0000-C000-000000000046")]
public struct Vftbl
{
public global::WinRT.Interop.IUnknownVftbl IUnknownVftbl;
private void* _Resolve;
public delegate* unmanaged[Stdcall]<IntPtr, ref Guid, out IntPtr, int> Resolve { get => (delegate* unmanaged[Stdcall]<IntPtr, ref Guid, out IntPtr, int>)_Resolve; set => _Resolve = value; }

public static readonly Vftbl AbiToProjectionVftable;
public static readonly IntPtr AbiToProjectionVftablePtr;

public delegate int ResolveDelegate(IntPtr thisPtr, Guid* riid, IntPtr* objectReference);
private static readonly Delegate[] DelegateCache = new Delegate[1];
static Vftbl()
{
AbiToProjectionVftable = new Vftbl
{
IUnknownVftbl = global::WinRT.Interop.IUnknownVftbl.AbiToProjectionVftbl,
_Resolve = Marshal.GetFunctionPointerForDelegate(DelegateCache[0] = new ResolveDelegate(Do_Abi_Resolve)).ToPointer(),
};
AbiToProjectionVftablePtr = Marshal.AllocHGlobal(Marshal.SizeOf<Vftbl>());
Marshal.StructureToPtr(AbiToProjectionVftable, AbiToProjectionVftablePtr, false);
}

private static int Do_Abi_Resolve(IntPtr thisPtr, Guid* riid, IntPtr* objectReference)
{
IObjectReference _objectReference = default;

*objectReference = default;

try
{
_objectReference = global::WinRT.ComWrappersSupport.FindObject<global::WinRT.Interop.IWeakReference>(thisPtr).Resolve(*riid);
*objectReference = _objectReference?.GetRef() ?? IntPtr.Zero;
}
catch (Exception __exception__)
{
return __exception__.HResult;
}
return 0;
}
}

internal static readonly Guid IID = new(0x00000037, 0, 0, 0xC0, 0, 0, 0, 0, 0, 0, 0x46);

public static IntPtr AbiToProjectionVftablePtr;
Expand Down Expand Up @@ -181,6 +262,6 @@ private static int Do_Abi_Resolve(IntPtr thisPtr, Guid* riid, IntPtr* objectRefe
{
MarshalInspectable<object>.DisposeAbi(objRef);
}
}
}
}
}
5 changes: 3 additions & 2 deletions src/cswinrt/strings/WinRT.cs
Original file line number Diff line number Diff line change
Expand Up @@ -544,8 +544,8 @@ public static void Create(IObjectReference obj, int index, System.WeakReference<
if (hr != 0)
{
return;
}

}
target = ABI.WinRT.Interop.IWeakReferenceSourceMethods.GetWeakReference(weakRefSource);
#endif

Expand Down Expand Up @@ -860,6 +860,7 @@ internal static class InterfaceIIDs
internal static readonly Guid IInspectable_IID = new(0xAF86E2E0, 0xB12D, 0x4c6a, 0x9C, 0x5A, 0xD7, 0xAA, 0x65, 0x10, 0x1E, 0x90);
internal static readonly Guid IUnknown_IID = new(0, 0, 0, 0xC0, 0, 0, 0, 0, 0, 0, 0x46);
internal static readonly Guid IWeakReferenceSource_IID = new(0x00000038, 0, 0, 0xC0, 0, 0, 0, 0, 0, 0, 0x46);
internal static readonly Guid IWeakReference_IID = new(0x00000037, 0, 0, 0xC0, 0, 0, 0, 0, 0, 0, 0x46);
}
}

Expand Down