From 030d802f5cc0cc098b833141e80cd678f3914e52 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Thu, 1 Feb 2024 23:24:03 +0100 Subject: [PATCH 1/7] Remove IActivationFactoryVftbl type --- src/WinRT.Runtime/ActivationFactory.cs | 10 +++++----- src/cswinrt/strings/WinRT_Interop.cs | 13 +------------ 2 files changed, 6 insertions(+), 17 deletions(-) diff --git a/src/WinRT.Runtime/ActivationFactory.cs b/src/WinRT.Runtime/ActivationFactory.cs index aabb6dbfb..5649d50ca 100644 --- a/src/WinRT.Runtime/ActivationFactory.cs +++ b/src/WinRT.Runtime/ActivationFactory.cs @@ -99,7 +99,7 @@ private DllModule(string fileName, IntPtr moduleHandle, void* getActivationFacto } } - public (ObjectReference obj, int hr) GetActivationFactory(string runtimeClassId) + public (ObjectReference obj, int hr) GetActivationFactory(string runtimeClassId) { IntPtr instancePtr = IntPtr.Zero; try @@ -110,7 +110,7 @@ private DllModule(string fileName, IntPtr moduleHandle, void* getActivationFacto int hr = _GetActivationFactory(MarshalString.GetAbi(ref __runtimeClassId), &instancePtr); if (hr == 0) { - var objRef = ObjectReference.Attach(ref instancePtr); + var objRef = ObjectReference.Attach(ref instancePtr); return (objRef, hr); } else @@ -205,8 +205,8 @@ public static IObjectReference Get(string typeName) { // Prefer the RoGetActivationFactory HRESULT failure over the LoadLibrary/etc. failure int hr; - ObjectReference factory; - (factory, hr) = WinRTModule.GetActivationFactory(typeName, InterfaceIIDs.IActivationFactory_IID); + ObjectReference factory; + (factory, hr) = WinRTModule.GetActivationFactory(typeName, InterfaceIIDs.IActivationFactory_IID); if (factory != null) { return factory; @@ -271,7 +271,7 @@ public static ObjectReference Get(string typeName, Guid iid) DllModule module = null; if (DllModule.TryLoad(moduleName + ".dll", out module)) { - ObjectReference activationFactory; + ObjectReference activationFactory; (activationFactory, hr) = module.GetActivationFactory(typeName); if (activationFactory != null) { diff --git a/src/cswinrt/strings/WinRT_Interop.cs b/src/cswinrt/strings/WinRT_Interop.cs index a74668155..d089b2981 100644 --- a/src/cswinrt/strings/WinRT_Interop.cs +++ b/src/cswinrt/strings/WinRT_Interop.cs @@ -8,18 +8,7 @@ #pragma warning disable CS0649 namespace WinRT.Interop -{ - // IActivationFactory - [Guid("00000035-0000-0000-C000-000000000046")] - internal unsafe struct IActivationFactoryVftbl - { - public IInspectable.Vftbl IInspectableVftbl; - private void* _ActivateInstance; - public delegate* unmanaged[Stdcall] ActivateInstance => (delegate* unmanaged[Stdcall])_ActivateInstance; - - internal static readonly Guid IID = new(0x00000035, 0, 0, 0xC0, 0, 0, 0, 0, 0, 0, 0x46); - } - +{ // IDelegate internal struct IDelegateVftbl { From 16ba20e28d90cc3815e3428a17e85ed54bb4751e Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Thu, 1 Feb 2024 23:31:43 +0100 Subject: [PATCH 2/7] Move IReferenceTrackerTargetVftbl to runtime --- .../Interop/IReferenceTrackerTargetVftbl.cs | 16 ++++++++++++++++ src/cswinrt/strings/WinRT.cs | 4 +++- src/cswinrt/strings/WinRT_Interop.cs | 16 ---------------- 3 files changed, 19 insertions(+), 17 deletions(-) create mode 100644 src/WinRT.Runtime/Interop/IReferenceTrackerTargetVftbl.cs diff --git a/src/WinRT.Runtime/Interop/IReferenceTrackerTargetVftbl.cs b/src/WinRT.Runtime/Interop/IReferenceTrackerTargetVftbl.cs new file mode 100644 index 000000000..05a79a1bd --- /dev/null +++ b/src/WinRT.Runtime/Interop/IReferenceTrackerTargetVftbl.cs @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; + +namespace WinRT.Interop +{ + internal unsafe struct IReferenceTrackerTargetVftbl + { + public IUnknownVftbl IUnknownVftbl; + public delegate* unmanaged[Stdcall] AddRefFromReferenceTracker; + public delegate* unmanaged[Stdcall] ReleaseFromReferenceTracker; + public delegate* unmanaged[Stdcall] Peg; + public delegate* unmanaged[Stdcall] Unpeg; + } +} diff --git a/src/cswinrt/strings/WinRT.cs b/src/cswinrt/strings/WinRT.cs index 350862aab..a35cd8c41 100644 --- a/src/cswinrt/strings/WinRT.cs +++ b/src/cswinrt/strings/WinRT.cs @@ -124,7 +124,7 @@ public void Dispose() public void InitalizeReferenceTracking(IntPtr ptr) { eventInvokePtr = ptr; - int hr = Marshal.QueryInterface(ptr, ref Unsafe.AsRef(IReferenceTrackerTargetVftbl.IID), out referenceTrackerTargetPtr); + int hr = Marshal.QueryInterface(ptr, ref Unsafe.AsRef(in InterfaceIIDs.IReferenceTrackerTarget_IID), out referenceTrackerTargetPtr); if (hr != 0) { referenceTrackerTargetPtr = default; @@ -465,6 +465,7 @@ internal static class InterfaceIIDs internal static readonly Guid IMarshal_IID = new Guid(new global::System.ReadOnlySpan(new byte[] { 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 })); internal static readonly Guid IContextCallback_IID = new Guid(new global::System.ReadOnlySpan(new byte[] { 0xDA, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 })); internal static readonly Guid ICallbackWithNoReentrancyToApplicationSTA_IID = new Guid(new global::System.ReadOnlySpan(new byte[] { 0x74, 0x97, 0x29, 0x0A, 0x4E, 0x3E, 0x42, 0xFC, 0x1D, 0x9D, 0x72, 0xCE, 0xE1, 0x05, 0xCA, 0x57 })); + internal static readonly Guid IReferenceTrackerTarget_IID = new Guid(new global::System.ReadOnlySpan(new byte[] { 0xF8, 0x43, 0xBD, 0x64, 0xEE, 0xBF, 0xC4, 0x4E, 0xB7, 0xEB, 0x29, 0x35, 0x15, 0x8D, 0xAE, 0x21 })); #else 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); @@ -475,6 +476,7 @@ internal static class InterfaceIIDs internal static readonly Guid IMarshal_IID = new(0x00000003, 0, 0, 0xc0, 0, 0, 0, 0, 0, 0, 0x46); internal static readonly Guid IContextCallback_IID = new(0x000001da, 0, 0, 0xC0, 0, 0, 0, 0, 0, 0, 0x46); internal static readonly Guid ICallbackWithNoReentrancyToApplicationSTA_IID = new(0x0A299774, 0x3E4E, 0xFC42, 0x1D, 0x9D, 0x72, 0xCE, 0xE1, 0x05, 0xCA, 0x57); + internal static readonly Guid IReferenceTrackerTarget_IID = new(0x64BD43F8, 0xbFEE, 0x4EC4, 0xB7, 0xEB, 0x29, 0x35, 0x15, 0x8D, 0xAE, 0x21); #endif } } diff --git a/src/cswinrt/strings/WinRT_Interop.cs b/src/cswinrt/strings/WinRT_Interop.cs index d089b2981..add52ff22 100644 --- a/src/cswinrt/strings/WinRT_Interop.cs +++ b/src/cswinrt/strings/WinRT_Interop.cs @@ -3,7 +3,6 @@ using System; -using System.Runtime.InteropServices; #pragma warning disable CS0649 @@ -14,20 +13,5 @@ internal struct IDelegateVftbl { public IUnknownVftbl IUnknownVftbl; public IntPtr Invoke; - } - - [Guid("64BD43F8-bFEE-4EC4-B7EB-2935158DAE21")] - [StructLayout(LayoutKind.Sequential)] - internal unsafe struct IReferenceTrackerTargetVftbl - { - public global::WinRT.Interop.IUnknownVftbl IUnknownVftbl; - private void* _AddRefFromReferenceTracker; - public delegate* unmanaged[Stdcall] AddRefFromReferenceTracker => (delegate* unmanaged[Stdcall])_AddRefFromReferenceTracker; - private void* _ReleaseFromReferenceTracker; - public delegate* unmanaged[Stdcall] ReleaseFromReferenceTracker => (delegate* unmanaged[Stdcall])_ReleaseFromReferenceTracker; - private void* _Peg; - private void* _Unpeg; - - internal static readonly Guid IID = new(0x64BD43F8, 0xbFEE, 0x4EC4, 0xB7, 0xEB, 0x29, 0x35, 0x15, 0x8D, 0xAE, 0x21); } } From b360bf8fa5978baeeb03635467632297b73e9c73 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Thu, 1 Feb 2024 23:49:21 +0100 Subject: [PATCH 3/7] Move or hide IDelegateVftbl type --- src/WinRT.Runtime/Interop/IDelegateVftbl.cs | 21 +++++++++++++++++++++ src/WinRT.Runtime/Marshalers.cs | 4 ++-- src/cswinrt/code_writers.h | 12 ++++++------ src/cswinrt/strings/WinRT_Interop.cs | 6 ------ 4 files changed, 29 insertions(+), 14 deletions(-) create mode 100644 src/WinRT.Runtime/Interop/IDelegateVftbl.cs diff --git a/src/WinRT.Runtime/Interop/IDelegateVftbl.cs b/src/WinRT.Runtime/Interop/IDelegateVftbl.cs new file mode 100644 index 000000000..1a3409760 --- /dev/null +++ b/src/WinRT.Runtime/Interop/IDelegateVftbl.cs @@ -0,0 +1,21 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; + +namespace WinRT.Interop +{ + // This is internal both in the embedded case, but also if we're on modern .NET, + // because projections only use this vftbl type downlevel, and running older + // projections against a .NET version of CsWinRT is not supported. +#if EMBED || NET + internal +#else + public +#endif + struct IDelegateVftbl + { + public IUnknownVftbl IUnknownVftbl; + public IntPtr Invoke; + } +} diff --git a/src/WinRT.Runtime/Marshalers.cs b/src/WinRT.Runtime/Marshalers.cs index a3d930bbe..b36067e46 100644 --- a/src/WinRT.Runtime/Marshalers.cs +++ b/src/WinRT.Runtime/Marshalers.cs @@ -1668,10 +1668,10 @@ public static IObjectReference CreateMarshaler(object o, Guid delegateIID, bool if (unwrapObject && ComWrappersSupport.TryUnwrapObject(o, out var objRef)) { - return objRef.As(delegateIID); + return objRef.As(delegateIID); } - return ComWrappersSupport.CreateCCWForObject(o, delegateIID); + return ComWrappersSupport.CreateCCWForObject(o, delegateIID); } public static ObjectReferenceValue CreateMarshaler2(object o, Guid delegateIID, bool unwrapObject = true) diff --git a/src/cswinrt/code_writers.h b/src/cswinrt/code_writers.h index aef987b58..6a1afd90d 100644 --- a/src/cswinrt/code_writers.h +++ b/src/cswinrt/code_writers.h @@ -8652,7 +8652,7 @@ return MarshalDelegate.FromAbi<%>(nativeDelegate); public static % CreateRcw(IntPtr ptr) { -return new %(new NativeDelegateWrapper(ComWrappersSupport.GetObjectReferenceForInterface(ptr, GuidGenerator.GetIID(typeof(@%)))).Invoke); +return new %(new NativeDelegateWrapper(ComWrappersSupport.GetObjectReferenceForInterface(ptr, GuidGenerator.GetIID(typeof(@%)))).Invoke); } [global::WinRT.ObjectReferenceWrapper(nameof(_nativeDelegate))] @@ -8662,9 +8662,9 @@ private sealed class NativeDelegateWrapper private sealed class NativeDelegateWrapper : IWinRTObject #endif { -private readonly ObjectReference _nativeDelegate; +private readonly ObjectReference _nativeDelegate; -public NativeDelegateWrapper(ObjectReference nativeDelegate) +public NativeDelegateWrapper(ObjectReference nativeDelegate) { _nativeDelegate = nativeDelegate; } @@ -8792,7 +8792,7 @@ AbiToProjectionVftable = new global::WinRT.Interop.IDelegateVftbl IUnknownVftbl = global::WinRT.Interop.IUnknownVftbl.AbiToProjectionVftbl, Invoke = Marshal.GetFunctionPointerForDelegate(AbiInvokeDelegate) }; -var nativeVftbl = ComWrappersSupport.AllocateVtableMemory(typeof(@%), Marshal.SizeOf()); +var nativeVftbl = ComWrappersSupport.AllocateVtableMemory(typeof(@%), sizeof(IntPtr) * 4); Marshal.StructureToPtr(AbiToProjectionVftable, nativeVftbl, false); AbiToProjectionVftablePtr = nativeVftbl; )", @@ -8802,7 +8802,7 @@ AbiToProjectionVftablePtr = nativeVftbl; else if (!is_generic) { w.write(R"( -AbiToProjectionVftablePtr = ComWrappersSupport.AllocateVtableMemory(typeof(@), sizeof(global::WinRT.Interop.IDelegateVftbl)); +AbiToProjectionVftablePtr = ComWrappersSupport.AllocateVtableMemory(typeof(@), sizeof(IntPtr) * 4); *(global::WinRT.Interop.IUnknownVftbl*)AbiToProjectionVftablePtr = global::WinRT.Interop.IUnknownVftbl.AbiToProjectionVftbl; ((delegate* unmanaged[Stdcall]<%, int>*)AbiToProjectionVftablePtr)[3] = &Do_Abi_Invoke; )", @@ -8817,7 +8817,7 @@ AbiToProjectionVftablePtr = ComWrappersSupport.AllocateVtableMemory(typeof(@), s if (RuntimeFeature.IsDynamicCodeCompiled && %.AbiToProjectionVftablePtr == default) { AbiInvokeDelegate = %; -AbiToProjectionVftablePtr = ComWrappersSupport.AllocateVtableMemory(typeof(@%), sizeof(global::WinRT.Interop.IDelegateVftbl)); +AbiToProjectionVftablePtr = ComWrappersSupport.AllocateVtableMemory(typeof(@%), sizeof(IntPtr) * 4); *(global::WinRT.Interop.IUnknownVftbl*)AbiToProjectionVftablePtr = global::WinRT.Interop.IUnknownVftbl.AbiToProjectionVftbl; ((IntPtr*)AbiToProjectionVftablePtr)[3] = Marshal.GetFunctionPointerForDelegate(AbiInvokeDelegate); } diff --git a/src/cswinrt/strings/WinRT_Interop.cs b/src/cswinrt/strings/WinRT_Interop.cs index add52ff22..16548b914 100644 --- a/src/cswinrt/strings/WinRT_Interop.cs +++ b/src/cswinrt/strings/WinRT_Interop.cs @@ -8,10 +8,4 @@ namespace WinRT.Interop { - // IDelegate - internal struct IDelegateVftbl - { - public IUnknownVftbl IUnknownVftbl; - public IntPtr Invoke; - } } From e36d6c9400e45e2c44dabbb2655b3e8593794187 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Thu, 1 Feb 2024 23:50:13 +0100 Subject: [PATCH 4/7] Delete WinRT_Interop file --- src/cswinrt/cswinrt.vcxproj | 1 - src/cswinrt/cswinrt.vcxproj.filters | 3 --- src/cswinrt/strings/WinRT_Interop.cs | 11 ----------- 3 files changed, 15 deletions(-) delete mode 100644 src/cswinrt/strings/WinRT_Interop.cs diff --git a/src/cswinrt/cswinrt.vcxproj b/src/cswinrt/cswinrt.vcxproj index 674c12582..324404098 100644 --- a/src/cswinrt/cswinrt.vcxproj +++ b/src/cswinrt/cswinrt.vcxproj @@ -112,7 +112,6 @@ - diff --git a/src/cswinrt/cswinrt.vcxproj.filters b/src/cswinrt/cswinrt.vcxproj.filters index 57e31721d..2bd4e9b67 100644 --- a/src/cswinrt/cswinrt.vcxproj.filters +++ b/src/cswinrt/cswinrt.vcxproj.filters @@ -57,9 +57,6 @@ strings - - strings - strings\additions\Windows.Foundation diff --git a/src/cswinrt/strings/WinRT_Interop.cs b/src/cswinrt/strings/WinRT_Interop.cs deleted file mode 100644 index 16548b914..000000000 --- a/src/cswinrt/strings/WinRT_Interop.cs +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - - -using System; - -#pragma warning disable CS0649 - -namespace WinRT.Interop -{ -} From 5a6f4722a5250a0a2dd282a1448ffff8773827c7 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Fri, 2 Feb 2024 02:27:22 +0100 Subject: [PATCH 5/7] Actually delete IReferenceTrackerTargetVftbl --- .../Interop/IReferenceTrackerTargetVftbl.cs | 16 ---------------- src/cswinrt/strings/WinRT.cs | 11 ++++++++--- 2 files changed, 8 insertions(+), 19 deletions(-) delete mode 100644 src/WinRT.Runtime/Interop/IReferenceTrackerTargetVftbl.cs diff --git a/src/WinRT.Runtime/Interop/IReferenceTrackerTargetVftbl.cs b/src/WinRT.Runtime/Interop/IReferenceTrackerTargetVftbl.cs deleted file mode 100644 index 05a79a1bd..000000000 --- a/src/WinRT.Runtime/Interop/IReferenceTrackerTargetVftbl.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - -using System; - -namespace WinRT.Interop -{ - internal unsafe struct IReferenceTrackerTargetVftbl - { - public IUnknownVftbl IUnknownVftbl; - public delegate* unmanaged[Stdcall] AddRefFromReferenceTracker; - public delegate* unmanaged[Stdcall] ReleaseFromReferenceTracker; - public delegate* unmanaged[Stdcall] Peg; - public delegate* unmanaged[Stdcall] Unpeg; - } -} diff --git a/src/cswinrt/strings/WinRT.cs b/src/cswinrt/strings/WinRT.cs index a35cd8c41..9ee667234 100644 --- a/src/cswinrt/strings/WinRT.cs +++ b/src/cswinrt/strings/WinRT.cs @@ -152,9 +152,14 @@ public unsafe bool HasComReferences() if (referenceTrackerTargetPtr != default) { - IReferenceTrackerTargetVftbl vftblReferenceTracker = **(IReferenceTrackerTargetVftbl**)referenceTrackerTargetPtr; - vftblReferenceTracker.AddRefFromReferenceTracker(referenceTrackerTargetPtr); - uint refTrackerCount = vftblReferenceTracker.ReleaseFromReferenceTracker(referenceTrackerTargetPtr); + void** vftblReferenceTracker = *(void***)referenceTrackerTargetPtr; + + // AddRefFromReferenceTracker + _ = ((delegate* unmanaged[Stdcall])(vftblReferenceTracker[3]))(referenceTrackerTargetPtr); + + // ReleaseFromReferenceTracker + uint refTrackerCount = ((delegate* unmanaged[Stdcall])(vftblReferenceTracker[4]))(referenceTrackerTargetPtr); + if (refTrackerCount != 0) { // Note we can't tell if the reference tracker ref is pegged or not, so this is best effort where if there From 1f4dafacf6b933787e3b565f43dcbc9888bbae24 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Fri, 2 Feb 2024 02:38:10 +0100 Subject: [PATCH 6/7] Fix Invoke references in code writer --- src/cswinrt/code_writers.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cswinrt/code_writers.h b/src/cswinrt/code_writers.h index 6a1afd90d..7f8d0f247 100644 --- a/src/cswinrt/code_writers.h +++ b/src/cswinrt/code_writers.h @@ -8915,17 +8915,17 @@ else { if (have_generic_params) { - w.write("var abiInvoke = Marshal.GetDelegateForFunctionPointer(_nativeDelegate.Vftbl.Invoke, Abi_Invoke_Type);"); + w.write("var abiInvoke = Marshal.GetDelegateForFunctionPointer((IntPtr)(*(void***)_nativeDelegate.ThisPtr)[3], Abi_Invoke_Type);"); } else { - w.write("var abiInvoke = Marshal.GetDelegateForFunctionPointer<%>(_nativeDelegate.Vftbl.Invoke);", + w.write("var abiInvoke = Marshal.GetDelegateForFunctionPointer<%>((IntPtr)(*(void***)_nativeDelegate.ThisPtr)[3]);", is_generic ? w.write_temp("@_Delegates.Invoke", type.TypeName()) : "Abi_Invoke"); } } else { - w.write("var abiInvoke = (delegate* unmanaged[Stdcall]<%, int>)(_nativeDelegate.Vftbl.Invoke);", + w.write("var abiInvoke = (delegate* unmanaged[Stdcall]<%, int>)(*(void***)_nativeDelegate.ThisPtr)[3];", bind(signature)); } }), From dd5e6cddc372ec80c6ef8c449581c5904e607703 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Fri, 2 Feb 2024 11:19:44 +0100 Subject: [PATCH 7/7] Fix comment --- src/WinRT.Runtime/Interop/IDelegateVftbl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WinRT.Runtime/Interop/IDelegateVftbl.cs b/src/WinRT.Runtime/Interop/IDelegateVftbl.cs index 1a3409760..cf249cc57 100644 --- a/src/WinRT.Runtime/Interop/IDelegateVftbl.cs +++ b/src/WinRT.Runtime/Interop/IDelegateVftbl.cs @@ -7,7 +7,7 @@ namespace WinRT.Interop { // This is internal both in the embedded case, but also if we're on modern .NET, // because projections only use this vftbl type downlevel, and running older - // projections against a .NET version of CsWinRT is not supported. + // projections against a newer version of CsWinRT is not supported. #if EMBED || NET internal #else