From e1c803e6baedddc9196fdf479c65389825c612ce Mon Sep 17 00:00:00 2001 From: Andrii Kurdiumov Date: Sun, 22 May 2022 17:28:36 +0600 Subject: [PATCH] Add bunch of comwrappers for Text services --- .../System/Windows/Input/DefaultTextStore.cs | 2 +- .../Input/DefaultTextStoreTextComposition.cs | 4 +- .../Windows/Input/TextServicesCompartment.cs | 8 +- .../Windows/Input/TextServicesContext.cs | 15 +- .../Documents/FrameworkTextComposition.cs | 4 +- .../Windows/Documents/NLGSpellerInterop.cs | 9 +- .../Windows/Documents/TextServicesHost.cs | 5 +- .../System/Windows/Documents/TextStore.cs | 22 +- .../src/Shared/MS/Win32/NativeMethodsCLR.cs | 43 ++-- .../Shared/MS/Win32/UnsafeNativeMethodsCLR.cs | 25 +- .../Win32/UnsafeNativeMethodsTextServices.cs | 4 +- .../WpfComWrappers.IOleDropTargetVtbl.cs | 97 ++++++++ ...pers.ITfContextOwnerCompositionSinkVtbl.cs | 85 +++++++ .../WpfComWrappers.ITfContextOwnerVtbl.cs | 133 +++++++++++ ...Wrappers.ITfTransitoryExtensionSinkVtbl.cs | 49 ++++ .../WpfComWrappers.TfCompartmentWrapper.cs | 50 ++++ .../WpfComWrappers.TfContextWrapper.cs | 224 ++++++++++++++++++ .../WpfComWrappers.TfDocumentMgrWrapper.cs | 208 ++++++++++++++++ .../WpfComWrappers.TfThreadMgrWrapper.cs | 38 +-- .../WindowsBase/MS/Internal/WpfComWrappers.cs | 145 +++++++++++- .../src/WindowsBase/WindowsBase.csproj | 7 + 21 files changed, 1071 insertions(+), 106 deletions(-) create mode 100644 src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/WpfComWrappers.IOleDropTargetVtbl.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/WpfComWrappers.ITfContextOwnerCompositionSinkVtbl.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/WpfComWrappers.ITfContextOwnerVtbl.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/WpfComWrappers.ITfTransitoryExtensionSinkVtbl.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/WpfComWrappers.TfCompartmentWrapper.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/WpfComWrappers.TfContextWrapper.cs create mode 100644 src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/WpfComWrappers.TfDocumentMgrWrapper.cs diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/DefaultTextStore.cs b/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/DefaultTextStore.cs index 833a257e3cd..8981e746b7b 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/DefaultTextStore.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/DefaultTextStore.cs @@ -288,7 +288,7 @@ internal UnsafeNativeMethods.ITfDocumentMgr TransitoryDocumentManager compartment.GetValue(out obj); doc = obj as UnsafeNativeMethods.ITfDocumentMgr; - Marshal.ReleaseComObject(compartment); + ((IDisposable)compartment).Dispose(); return doc; } } diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/DefaultTextStoreTextComposition.cs b/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/DefaultTextStoreTextComposition.cs index ec8fa350a29..e6d49d072bb 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/DefaultTextStoreTextComposition.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/DefaultTextStoreTextComposition.cs @@ -71,8 +71,8 @@ public override void Complete() Marshal.ReleaseComObject(composition); } - Marshal.ReleaseComObject(context); -} + ((IDisposable)context).Dispose(); + } //------------------------------------------------------ // diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/TextServicesCompartment.cs b/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/TextServicesCompartment.cs index a5458cc1d60..6d0ae17e7bb 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/TextServicesCompartment.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/TextServicesCompartment.cs @@ -104,7 +104,7 @@ internal void AdviseNotifySink(UnsafeNativeMethods.ITfCompartmentEventSink sink) Guid guid = UnsafeNativeMethods.IID_ITfCompartmentEventSink; source.AdviseSink(ref guid, sink, out _cookie); - Marshal.ReleaseComObject(compartment); + ((IDisposable)compartment).Dispose(); Marshal.ReleaseComObject(source); } @@ -123,7 +123,7 @@ internal void UnadviseNotifySink() source.UnadviseSink(_cookie); _cookie = UnsafeNativeMethods.TF_INVALID_COOKIE; - Marshal.ReleaseComObject(compartment); + ((IDisposable)compartment).Dispose(); Marshal.ReleaseComObject(source); } @@ -204,7 +204,7 @@ internal object Value compartment.GetValue(out obj); - Marshal.ReleaseComObject(compartment); + ((IDisposable)compartment).Dispose(); return obj; } @@ -216,7 +216,7 @@ internal object Value return; compartment.SetValue(0 /* clientid */, ref value); - Marshal.ReleaseComObject(compartment); + ((IDisposable)compartment).Dispose(); } } diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/TextServicesContext.cs b/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/TextServicesContext.cs index a86fe8a81ec..ed6320a83ae 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/TextServicesContext.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/TextServicesContext.cs @@ -85,7 +85,6 @@ internal void Uninitialize(bool appDomainShutdown) if (_defaultTextStore.DocumentManager != null) { _defaultTextStore.DocumentManager.Pop(UnsafeNativeMethods.PopFlags.TF_POPF_ALL); - Marshal.ReleaseComObject(_defaultTextStore.DocumentManager); _defaultTextStore.DocumentManager = null; } @@ -226,7 +225,7 @@ internal void RegisterTextStore(DefaultTextStore defaultTextStore) doc.Push(context); // Release any native resources we're done with. - Marshal.ReleaseComObject(context); + ((IDisposable)context).Dispose(); // Same DocumentManager and EditCookie in _defaultTextStore. _defaultTextStore.DocumentManager = doc; @@ -375,14 +374,10 @@ private void StartTransitoryExtension() // Advise TransitoryExtension Sink and store the cookie. guid = UnsafeNativeMethods.IID_ITfTransitoryExtensionSink; source = _defaultTextStore.DocumentManager as UnsafeNativeMethods.ITfSource; - if (source != null) - { - // DocumentManager only supports ITfSource on Longhorn, XP does not support it - source.AdviseSink(ref guid, _defaultTextStore, out transitoryExtensionSinkCookie); - _defaultTextStore.TransitoryExtensionSinkCookie = transitoryExtensionSinkCookie; - } + source.AdviseSink(ref guid, _defaultTextStore, out transitoryExtensionSinkCookie); + _defaultTextStore.TransitoryExtensionSinkCookie = transitoryExtensionSinkCookie; - Marshal.ReleaseComObject(comp); + ((IDisposable)comp).Dispose(); } // Stop TransitoryExtesion @@ -417,7 +412,7 @@ private void StopTransitoryExtension() { var = (int)0; comp.SetValue(0, ref var); - Marshal.ReleaseComObject(comp); + ((IDisposable)comp).Dispose(); } } } diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/FrameworkTextComposition.cs b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/FrameworkTextComposition.cs index a1bd4e8f778..47b56e51d52 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/FrameworkTextComposition.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/FrameworkTextComposition.cs @@ -168,7 +168,7 @@ internal static void CompleteCurrentComposition(UnsafeNativeMethods.ITfDocumentM Marshal.ReleaseComObject(composition); } - Marshal.ReleaseComObject(context); + ((IDisposable)context).Dispose(); } internal static UnsafeNativeMethods.ITfCompositionView GetCurrentCompositionView(UnsafeNativeMethods.ITfDocumentMgr documentMgr) @@ -179,7 +179,7 @@ internal static UnsafeNativeMethods.ITfCompositionView GetCurrentCompositionView UnsafeNativeMethods.ITfCompositionView view = GetComposition(context); - Marshal.ReleaseComObject(context); + ((IDisposable)context).Dispose(); return view; } diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/NLGSpellerInterop.cs b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/NLGSpellerInterop.cs index 87b26d83ec3..b2498b311b2 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/NLGSpellerInterop.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/NLGSpellerInterop.cs @@ -606,8 +606,10 @@ private void EnumerateSuggestions() // Convert the VARIANT to string, and add it to our list. // There's some special magic here. The VARIANT is VT_UI2/ByRef. // But under the hood it's really a raw WCHAR *. - suggestions.Add(Marshal.PtrToStringUni(variant.data1.Value)); + suggestions.Add(Marshal.PtrToStringUni(variant.data1)); } + + variant.Clear(); } finally { @@ -1039,10 +1041,7 @@ private static int EnumVariantNext(UnsafeNativeMethods.IEnumVariant variantEnume unsafe { - fixed (void* pVariant = &variant.vt) - { - result = variantEnumerator.Next(1, (IntPtr)pVariant, fetched); - } + result = variantEnumerator.Next(1, (IntPtr)(short*)&variant.vt, fetched); } return result; diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/TextServicesHost.cs b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/TextServicesHost.cs index 24b68803eba..4f8b33d1ff4 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/TextServicesHost.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/TextServicesHost.cs @@ -260,7 +260,8 @@ private object OnUnregisterTextStore(object arg) source.UnadviseSink(textstore.EditSinkCookie); textstore.EditSinkCookie = UnsafeNativeMethods.TF_INVALID_COOKIE; } - Marshal.ReleaseComObject(context); + + ((IDisposable)context).Dispose(); } textstore.DocumentManager.Pop(UnsafeNativeMethods.PopFlags.TF_POPF_ALL); @@ -362,7 +363,7 @@ private void _RegisterTextStore(TextStore textstore) } // Release any native resources we're done with. - Marshal.ReleaseComObject(context); + ((IDisposable)context).Dispose(); textstore.DocumentManager = doc; textstore.ThreadFocusCookie = threadFocusCookie; diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/TextStore.cs b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/TextStore.cs index ac7c8d4ab04..5db8ea189b8 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/TextStore.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/TextStore.cs @@ -1883,7 +1883,7 @@ private bool GetFnReconv(ITextPointer textStart, ITextPointer textEnd, out Unsaf } Marshal.ReleaseComObject(range); - Marshal.ReleaseComObject(context); + ((IDisposable)context).Dispose(); return fReconvertable; } @@ -2813,22 +2813,18 @@ private void PrepareAttributes(InputScope inputScope, double fontSize, FontFamil attrval.overlappedId = (int)_supportingattributes[i].Style; attrval.val = new NativeMethods.VARIANT(); - // This VARIANT is returned to the caller, which supposed to call VariantClear(). - // GC does not have to clear it. - attrval.val.SuppressFinalize(); - switch (_supportingattributes[i].Style) { case AttributeStyle.InputScope: object obj = new InputScopeAttribute(inputScope); attrval.val.vt = (short)NativeMethods.tagVT.VT_UNKNOWN; - attrval.val.data1.Value = Marshal.GetIUnknownForObject(obj); + attrval.val.data1 = Marshal.GetIUnknownForObject(obj); break; case AttributeStyle.Font_Style_Height: // We always evaluate the font size and returns a value. attrval.val.vt = (short)NativeMethods.tagVT.VT_I4; - attrval.val.data1.Value = (IntPtr)(int)fontSize; + attrval.val.data1 = (IntPtr)(int)fontSize; break; case AttributeStyle.Font_FaceName: @@ -2837,24 +2833,24 @@ private void PrepareAttributes(InputScope inputScope, double fontSize, FontFamil if (familyName != null) { attrval.val.vt = (short)NativeMethods.tagVT.VT_BSTR; - attrval.val.data1.Value = Marshal.StringToBSTR(familyName); + attrval.val.data1 = Marshal.StringToBSTR(familyName); } } break; case AttributeStyle.Font_SizePts: attrval.val.vt = (short)NativeMethods.tagVT.VT_I4; - attrval.val.data1.Value = (IntPtr)(int)(fontSize / 96.0 * 72.0); + attrval.val.data1 = (IntPtr)(int)(fontSize / 96.0 * 72.0); break; case AttributeStyle.Text_ReadOnly: attrval.val.vt = (short)NativeMethods.tagVT.VT_BOOL; - attrval.val.data1.Value = IsReadOnly ? (IntPtr)1 : (IntPtr)0; + attrval.val.data1 = IsReadOnly ? (IntPtr)1 : (IntPtr)0; break; case AttributeStyle.Text_Orientation: attrval.val.vt = (short)NativeMethods.tagVT.VT_I4; - attrval.val.data1.Value = (IntPtr)0; + attrval.val.data1 = (IntPtr)0; // Get the transformation that is relative from source. PresentationSource source = null; @@ -2889,7 +2885,7 @@ private void PrepareAttributes(InputScope inputScope, double fontSize, FontFamil else angle = 360 - angleCos; - attrval.val.data1.Value = (IntPtr)((int)angle * 10); + attrval.val.data1 = (IntPtr)((int)angle * 10); } } } @@ -2901,7 +2897,7 @@ private void PrepareAttributes(InputScope inputScope, double fontSize, FontFamil // the vertical writing is not supported yet // attrval.val.vt = (short)NativeMethods.tagVT.VT_BOOL; - attrval.val.data1.Value = (IntPtr)0; + attrval.val.data1 = (IntPtr)0; break; } diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/NativeMethodsCLR.cs b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/NativeMethodsCLR.cs index 316d03bd62e..8553577b232 100644 --- a/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/NativeMethodsCLR.cs +++ b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/NativeMethodsCLR.cs @@ -4361,7 +4361,7 @@ public sealed class CA_STRUCT } #endif [StructLayout(LayoutKind.Sequential)] - public sealed class VARIANT { + public struct VARIANT { [MarshalAs(UnmanagedType.I2)] public short vt; [MarshalAs(UnmanagedType.I2)] @@ -4371,9 +4371,9 @@ public sealed class VARIANT { [MarshalAs(UnmanagedType.I2)] public short reserved3; - public SecurityCriticalDataForSet data1; + public IntPtr data1; - public SecurityCriticalDataForSet data2; + public IntPtr data2; public bool Byref{ @@ -4383,21 +4383,21 @@ public bool Byref{ } public void Clear() { - if ((this.vt == (int)tagVT.VT_UNKNOWN || this.vt == (int)tagVT.VT_DISPATCH) && this.data1.Value != IntPtr.Zero) { - Marshal.Release(this.data1.Value); + if ((this.vt == (int)tagVT.VT_UNKNOWN || this.vt == (int)tagVT.VT_DISPATCH) && this.data1 != IntPtr.Zero) { + Marshal.Release(this.data1); } - if (this.vt == (int)tagVT.VT_BSTR && this.data1.Value != IntPtr.Zero) { - SysFreeString(this.data1.Value); + if (this.vt == (int)tagVT.VT_BSTR && this.data1 != IntPtr.Zero) { + SysFreeString(this.data1); } - this.data1.Value = this.data2.Value = IntPtr.Zero; + this.data1 = this.data2 = IntPtr.Zero; this.vt = (int)tagVT.VT_EMPTY; } - ~VARIANT() { - Clear(); - } + //~VARIANT() { + // Clear(); + //} public void SuppressFinalize() { @@ -4407,7 +4407,7 @@ public void SuppressFinalize() GC.SuppressFinalize(this); } -#if never +#if !UIAUTOMATIONTYPES public static VARIANT FromObject(Object var) { VARIANT v = new VARIANT(); @@ -4496,15 +4496,14 @@ public static VARIANT FromObject(Object var) { return v; } #endif - [DllImport(ExternDll.Oleaut32,CharSet=CharSet.Auto)] private static extern IntPtr SysAllocString([In, MarshalAs(UnmanagedType.LPWStr)]string s); [DllImport(ExternDll.Oleaut32,CharSet=CharSet.Auto)] private static extern void SysFreeString(IntPtr pbstr); public void SetLong(long lVal) { - data1.Value = (IntPtr)(lVal & 0xFFFFFFFF); - data2.Value = (IntPtr)((lVal >> 32) & 0xFFFFFFFF); + data1 = (IntPtr)(lVal & 0xFFFFFFFF); + data2 = (IntPtr)((lVal >> 32) & 0xFFFFFFFF); } public IntPtr ToCoTaskMemPtr() { @@ -4513,13 +4512,13 @@ public IntPtr ToCoTaskMemPtr() { Marshal.WriteInt16(mem, 2, reserved1); Marshal.WriteInt16(mem, 4, reserved2); Marshal.WriteInt16(mem, 6, reserved3); - Marshal.WriteInt32(mem, 8, (int) data1.Value); - Marshal.WriteInt32(mem, 12, (int) data2.Value); + Marshal.WriteInt32(mem, 8, (int) data1); + Marshal.WriteInt32(mem, 12, (int) data2); return mem; } public object ToObject() { - IntPtr val = data1.Value; + IntPtr val = data1; long longVal; int vtType = (int)(this.vt & (short)tagVT.VT_TYPEMASK); @@ -4575,7 +4574,7 @@ public object ToObject() { longVal = Marshal.ReadInt64(val); } else { - longVal = ((uint)data1.Value & 0xffffffff) | ((uint)data2.Value << 32); + longVal = ((uint)data1 & 0xffffffff) | ((uint)data2 << 32); } if (vt == (int)tagVT.VT_I8) { @@ -4599,7 +4598,7 @@ public object ToObject() { case (int)tagVT.VT_CY: // internally currency is 8-byte int scaled by 10,000 - longVal = ((uint)data1.Value & 0xffffffff) | ((uint)data2.Value << 32); + longVal = ((uint)data1 & 0xffffffff) | ((uint)data2 << 32); return new Decimal(longVal); case (int)tagVT.VT_DATE: throw new FormatException(/*SR.GetString(SR.CannotConvertDoubleToDate)*/); @@ -4621,7 +4620,7 @@ public object ToObject() { return val; case (int)tagVT.VT_DECIMAL: - longVal = ((uint)data1.Value & 0xffffffff) | ((uint)data2.Value << 32); + longVal = ((uint)data1 & 0xffffffff) | ((uint)data2 << 32); return new Decimal(longVal); case (int)tagVT.VT_BOOL: @@ -4636,7 +4635,7 @@ public object ToObject() { return guid; case (int)tagVT.VT_FILETIME: - longVal = ((uint)data1.Value & 0xffffffff) | ((uint)data2.Value << 32); + longVal = ((uint)data1 & 0xffffffff) | ((uint)data2 << 32); return new DateTime(longVal); case (int)tagVT.VT_ARRAY: diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/UnsafeNativeMethodsCLR.cs b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/UnsafeNativeMethodsCLR.cs index 3f7a7a66582..fcbdf8dcec9 100644 --- a/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/UnsafeNativeMethodsCLR.cs +++ b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/UnsafeNativeMethodsCLR.cs @@ -947,11 +947,18 @@ public static void ClientToScreen(HandleRef hWnd, ref NativeMethods.POINT pt) [DllImport(ExternDll.User32, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern IntPtr GetForegroundWindow(); +#if !DRT && !UIAUTOMATIONTYPES [DllImport(ExternDll.Ole32, ExactSpelling=true, CharSet=CharSet.Auto)] - public static extern int RegisterDragDrop(HandleRef hwnd, UnsafeNativeMethods.IOleDropTarget target); + private static extern int RegisterDragDrop(HandleRef hwnd, IntPtr target); + public static int RegisterDragDrop(HandleRef hwnd, UnsafeNativeMethods.IOleDropTarget target) + { + var targetPtr = WpfComWrappers.Instance.GetComPointer(target, WpfComWrappers.IID_IOleDropTarget); + return RegisterDragDrop(hwnd, targetPtr); + } [DllImport(ExternDll.Ole32, ExactSpelling=true, CharSet=CharSet.Auto)] public static extern int RevokeDragDrop(HandleRef hwnd); +#endif #if !DRT && !UIAUTOMATIONTYPES [DllImport(ExternDll.User32, CharSet=CharSet.Auto)] @@ -2232,7 +2239,7 @@ public interface IEnumConnectionPoints { #if !DRT && !UIAUTOMATIONTYPES [ComImport(), Guid("00020400-0000-0000-C000-000000000046"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] public interface IDispatch { - #region +#region int GetTypeInfoCount(); @@ -2276,12 +2283,12 @@ HR Invoke( [Out, MarshalAs(UnmanagedType.LPArray)] IntPtr [] pArgErr); - #endregion +#endregion } [ComImport(), Guid("A6EF9860-C720-11D0-9337-00A0C90DCAA9"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)] public interface IDispatchEx : IDispatch { - #region +#region new int GetTypeInfoCount(); @@ -2324,7 +2331,7 @@ public interface IDispatchEx : IDispatch { [Out, MarshalAs(UnmanagedType.LPArray)] IntPtr [] pArgErr); - #endregion +#endregion [PreserveSig] HR GetDispID( @@ -2368,7 +2375,7 @@ public interface IServiceProvider { #endif - #region WebBrowser Related Definitions +#region WebBrowser Related Definitions [ComImport(), Guid("D30C1661-CDAF-11d0-8A3E-00C04FC9E26E"), TypeLibType(TypeLibTypeFlags.FHidden | TypeLibTypeFlags.FDual | TypeLibTypeFlags.FOleAutomation)] public interface IWebBrowser2 @@ -2725,10 +2732,10 @@ internal interface IHTMLDocument [ComImport, Guid("332C4425-26CB-11D0-B483-00C04FD90119"), InterfaceType(ComInterfaceType.InterfaceIsDual)] internal interface IHTMLDocument2: IHTMLDocument { - #region IHTMLDocument - base interface +#region IHTMLDocument - base interface [return: MarshalAs(UnmanagedType.Interface)] new object GetScript(); - #endregion +#endregion IHTMLElementCollection GetAll(); [return: MarshalAs(UnmanagedType.Interface)] /*IHTMLElement*/object GetBody(); @@ -3024,7 +3031,7 @@ [PreserveSig] int ProcessUrlAction(string url, int action, [PreserveSig] int GetZoneMappings(); } #endif - #endregion WebBrowser Related Definitions +#endregion WebBrowser Related Definitions [DllImport(ExternDll.User32, SetLastError=true, CharSet=CharSet.Auto)] public static extern uint GetRawInputDeviceList( diff --git a/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/UnsafeNativeMethodsTextServices.cs b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/UnsafeNativeMethodsTextServices.cs index 9ee2745e14f..1b998449709 100644 --- a/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/UnsafeNativeMethodsTextServices.cs +++ b/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/UnsafeNativeMethodsTextServices.cs @@ -2297,13 +2297,13 @@ public interface ITfContextOwnerCompositionServices /*: ITfContextComposition*/ /// //HRESULT EnumCompositions([out] IEnumITfCompositionView **ppEnum); - void EnumCompositions([MarshalAs(UnmanagedType.Interface)] out object /*IEnumITfCompositionView*/ enumView); + void EnumCompositions([MarshalAs(UnmanagedType.Interface)] out IEnumITfCompositionView enumView); /// //HRESULT FindComposition([in] TfEditCookie ecRead, // [in] ITfRange *pTestRange, // [out] IEnumITfCompositionView **ppEnum); - void FindComposition(int ecRead, ITfRange testRange, [MarshalAs(UnmanagedType.Interface)] out object /*IEnumITfCompositionView*/ enumView); + void FindComposition(int ecRead, ITfRange testRange, [MarshalAs(UnmanagedType.Interface)] out object enumView); /// //HRESULT TakeOwnership([in] TfEditCookie ecWrite, diff --git a/src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/WpfComWrappers.IOleDropTargetVtbl.cs b/src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/WpfComWrappers.IOleDropTargetVtbl.cs new file mode 100644 index 00000000000..531d82daac0 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/WpfComWrappers.IOleDropTargetVtbl.cs @@ -0,0 +1,97 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace MS.Internal; + +using System; +using System.Diagnostics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Windows.Interop; +using MS.Win32; +using static global::MS.Win32.UnsafeNativeMethods; + +internal unsafe partial class WpfComWrappers +{ + internal static class IOleDropTargetVtbl + { + public static IntPtr Create(IntPtr fpQueryInterface, IntPtr fpAddRef, IntPtr fpRelease) + { + IntPtr* vtblRaw = (IntPtr*)RuntimeHelpers.AllocateTypeAssociatedMemory(typeof(IOleDropTargetVtbl), IntPtr.Size * 7); + vtblRaw[0] = fpQueryInterface; + vtblRaw[1] = fpAddRef; + vtblRaw[2] = fpRelease; + vtblRaw[3] = (IntPtr)(delegate* unmanaged)&OleDragEnter; + vtblRaw[4] = (IntPtr)(delegate* unmanaged)&DragOver; + vtblRaw[5] = (IntPtr)(delegate* unmanaged)&DragLeave; + vtblRaw[6] = (IntPtr)(delegate* unmanaged)&Drop; + + return (IntPtr)vtblRaw; + } + + [UnmanagedCallersOnly] + private static int OleDragEnter(IntPtr thisPtr, IntPtr pDataObj, int grfKeyState, long pt, int* pdwEffect) + { + try + { + IOleDropTarget instance = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + // var dataObject = Instance.GetOrCreateObjectForComInstance(pDataObj, CreateObjectFlags.Unwrap); + var dataObject = Marshal.GetObjectForIUnknown(pDataObj); + return instance.OleDragEnter(dataObject, grfKeyState, pt, ref *pdwEffect); + } + catch (Exception ex) + { + Debug.WriteLine(ex); + return ex.HResult; + } + } + + [UnmanagedCallersOnly] + private static int DragOver(IntPtr thisPtr, int grfKeyState, long pt, int* pdwEffect) + { + try + { + IOleDropTarget instance = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + return instance.OleDragOver(grfKeyState, pt, ref *pdwEffect); + } + catch (Exception ex) + { + Debug.WriteLine(ex); + return ex.HResult; + } + } + + [UnmanagedCallersOnly] + private static int DragLeave(IntPtr thisPtr) + { + try + { + IOleDropTarget instance = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + return instance.OleDragLeave(); + } + catch (Exception ex) + { + Debug.WriteLine(ex); + return ex.HResult; + } + } + + [UnmanagedCallersOnly] + private static int Drop(IntPtr thisPtr, IntPtr pDataObj, int grfKeyState, long pt, int* pdwEffect) + { + try + { + IOleDropTarget instance = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + // var dataObject = Instance.GetOrCreateObjectForComInstance(pDataObj, CreateObjectFlags.Unwrap); + var dataObject = Marshal.GetObjectForIUnknown(pDataObj); + return instance.OleDrop(dataObject, grfKeyState, pt, ref *pdwEffect); + } + catch (Exception ex) + { + Debug.WriteLine(ex); + return ex.HResult; + } + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/WpfComWrappers.ITfContextOwnerCompositionSinkVtbl.cs b/src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/WpfComWrappers.ITfContextOwnerCompositionSinkVtbl.cs new file mode 100644 index 00000000000..e258b49c002 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/WpfComWrappers.ITfContextOwnerCompositionSinkVtbl.cs @@ -0,0 +1,85 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace MS.Internal; + +using System; +using System.Diagnostics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Windows.Interop; +using MS.Win32; +using static global::MS.Win32.UnsafeNativeMethods; + +internal unsafe partial class WpfComWrappers +{ + internal static class ITfContextOwnerCompositionSinkVtbl + { + public static IntPtr Create(IntPtr fpQueryInterface, IntPtr fpAddRef, IntPtr fpRelease) + { + IntPtr* vtblRaw = (IntPtr*)RuntimeHelpers.AllocateTypeAssociatedMemory(typeof(ITfContextOwnerCompositionSinkVtbl), IntPtr.Size * 6); + vtblRaw[0] = fpQueryInterface; + vtblRaw[1] = fpAddRef; + vtblRaw[2] = fpRelease; + vtblRaw[3] = (IntPtr)(delegate* unmanaged)&OnStartComposition; + vtblRaw[4] = (IntPtr)(delegate* unmanaged)&OnUpdateComposition; + vtblRaw[5] = (IntPtr)(delegate* unmanaged)&OnEndComposition; + + return (IntPtr)vtblRaw; + } + + [UnmanagedCallersOnly] + private static int OnStartComposition(IntPtr thisPtr, IntPtr view, int* ok) + { + try + { + ITfContextOwnerCompositionSink instance = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var viewObject = (ITfCompositionView)Marshal.GetObjectForIUnknown(view); + instance.OnStartComposition(viewObject, out bool okBool); + *ok = okBool ? 1 : 0; + return NativeMethods.S_OK; + } + catch (Exception ex) + { + Debug.WriteLine(ex); + return ex.HResult; + } + } + + [UnmanagedCallersOnly] + private static int OnUpdateComposition(IntPtr thisPtr, IntPtr view, IntPtr rangeNew) + { + try + { + ITfContextOwnerCompositionSink instance = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var viewObject = (ITfCompositionView)Marshal.GetObjectForIUnknown(view); + var rangeNewObject = (ITfRange)Marshal.GetObjectForIUnknown(rangeNew); + instance.OnUpdateComposition(viewObject, rangeNewObject); + return NativeMethods.S_OK; + } + catch (Exception ex) + { + Debug.WriteLine(ex); + return ex.HResult; + } + } + + [UnmanagedCallersOnly] + private static int OnEndComposition(IntPtr thisPtr, IntPtr view) + { + try + { + ITfContextOwnerCompositionSink instance = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var viewObject = (ITfCompositionView)Marshal.GetObjectForIUnknown(view); + instance.OnEndComposition(viewObject); + return NativeMethods.S_OK; + } + catch (Exception ex) + { + Debug.WriteLine(ex); + return ex.HResult; + } + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/WpfComWrappers.ITfContextOwnerVtbl.cs b/src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/WpfComWrappers.ITfContextOwnerVtbl.cs new file mode 100644 index 00000000000..242701d894a --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/WpfComWrappers.ITfContextOwnerVtbl.cs @@ -0,0 +1,133 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace MS.Internal; + +using System; +using System.Diagnostics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Windows.Interop; +using MS.Win32; +using static global::MS.Win32.UnsafeNativeMethods; + +internal unsafe partial class WpfComWrappers +{ + internal static class ITfContextOwnerVtbl + { + public static IntPtr Create(IntPtr fpQueryInterface, IntPtr fpAddRef, IntPtr fpRelease) + { + IntPtr* vtblRaw = (IntPtr*)RuntimeHelpers.AllocateTypeAssociatedMemory(typeof(ITfContextOwnerVtbl), IntPtr.Size * 9); + vtblRaw[0] = fpQueryInterface; + vtblRaw[1] = fpAddRef; + vtblRaw[2] = fpRelease; + vtblRaw[3] = (IntPtr)(delegate* unmanaged)&GetACPFromPoint; + vtblRaw[4] = (IntPtr)(delegate* unmanaged)&GetTextExt; + vtblRaw[5] = (IntPtr)(delegate* unmanaged)&GetScreenExt; + vtblRaw[6] = (IntPtr)(delegate* unmanaged)&GetStatus; + vtblRaw[7] = (IntPtr)(delegate* unmanaged)&GetWnd; + vtblRaw[8] = (IntPtr)(delegate* unmanaged)&GetValue; + + return (IntPtr)vtblRaw; + } + + [UnmanagedCallersOnly] + private static int GetACPFromPoint(IntPtr thisPtr, POINT* point, GetPositionFromPointFlags flags, int* position) + { + try + { + ITfContextOwner instance = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + instance.GetACPFromPoint(ref *point, flags, out *position); + return NativeMethods.S_OK; + } + catch (Exception ex) + { + Debug.WriteLine(ex); + return ex.HResult; + } + } + + [UnmanagedCallersOnly] + private static int GetTextExt(IntPtr thisPtr, int start, int end, RECT* rect, int* clipped) + { + try + { + ITfContextOwner instance = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + instance.GetTextExt(start, end, out *rect, out bool clippedBool); + *clipped = clippedBool ? 1 : 0; + return NativeMethods.S_OK; + } + catch (Exception ex) + { + Debug.WriteLine(ex); + return ex.HResult; + } + } + + [UnmanagedCallersOnly] + private static int GetScreenExt(IntPtr thisPtr, RECT* rect) + { + try + { + ITfContextOwner instance = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + instance.GetScreenExt(out *rect); + return NativeMethods.S_OK; + } + catch (Exception ex) + { + Debug.WriteLine(ex); + return ex.HResult; + } + } + + [UnmanagedCallersOnly] + private static int GetStatus(IntPtr thisPtr, TS_STATUS* status) + { + try + { + ITfContextOwner instance = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + instance.GetStatus(out *status); + return NativeMethods.S_OK; + } + catch (Exception ex) + { + Debug.WriteLine(ex); + return ex.HResult; + } + } + + [UnmanagedCallersOnly] + private static int GetWnd(IntPtr thisPtr, IntPtr* hwnd) + { + try + { + ITfContextOwner instance = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + instance.GetWnd(out *hwnd); + return NativeMethods.S_OK; + } + catch (Exception ex) + { + Debug.WriteLine(ex); + return ex.HResult; + } + } + + [UnmanagedCallersOnly] + private static int GetValue(IntPtr thisPtr, Guid* guidAttribute, NativeMethods.VARIANT* varValue) + { + try + { + ITfContextOwner instance = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + instance.GetValue(ref *guidAttribute, out object varObject); + *varValue = NativeMethods.VARIANT.FromObject(varObject); + return NativeMethods.S_OK; + } + catch (Exception ex) + { + Debug.WriteLine(ex); + return ex.HResult; + } + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/WpfComWrappers.ITfTransitoryExtensionSinkVtbl.cs b/src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/WpfComWrappers.ITfTransitoryExtensionSinkVtbl.cs new file mode 100644 index 00000000000..3f121140197 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/WpfComWrappers.ITfTransitoryExtensionSinkVtbl.cs @@ -0,0 +1,49 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace MS.Internal; + +using System; +using System.Diagnostics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using MS.Win32; +using static global::MS.Win32.UnsafeNativeMethods; + +internal unsafe partial class WpfComWrappers +{ + internal static class ITfTransitoryExtensionSinkVtbl + { + public static IntPtr Create(IntPtr fpQueryInterface, IntPtr fpAddRef, IntPtr fpRelease) + { + IntPtr* vtblRaw = (IntPtr*)RuntimeHelpers.AllocateTypeAssociatedMemory(typeof(ITfTransitoryExtensionSinkVtbl), IntPtr.Size * 4); + vtblRaw[0] = fpQueryInterface; + vtblRaw[1] = fpAddRef; + vtblRaw[2] = fpRelease; + vtblRaw[3] = (IntPtr)(delegate* unmanaged)&OnTransitoryExtensionUpdated; + + return (IntPtr)vtblRaw; + } + + [UnmanagedCallersOnly] + private static int OnTransitoryExtensionUpdated(IntPtr thisPtr, IntPtr context, int ecReadOnly, IntPtr rangeResult, IntPtr rangeComposition, int* fDeleteResultRange) + { + try + { + ITfTransitoryExtensionSink instance = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var contextObject = (ITfContext)Marshal.GetObjectForIUnknown(context); + var rangeResultObject = (ITfRange)Marshal.GetObjectForIUnknown(rangeResult); + var rangeCompositionObject = (ITfRange)Marshal.GetObjectForIUnknown(rangeComposition); + instance.OnTransitoryExtensionUpdated(contextObject, ecReadOnly, rangeResultObject, rangeCompositionObject, out bool fDeleteResultRangeBool); + *fDeleteResultRange = fDeleteResultRangeBool ? 1 : 0; + return NativeMethods.S_OK; + } + catch (Exception ex) + { + Debug.WriteLine(ex); + return ex.HResult; + } + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/WpfComWrappers.TfCompartmentWrapper.cs b/src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/WpfComWrappers.TfCompartmentWrapper.cs new file mode 100644 index 00000000000..f1463a2e812 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/WpfComWrappers.TfCompartmentWrapper.cs @@ -0,0 +1,50 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace MS.Internal; + +using System; +using System.Runtime.InteropServices; +using MS.Win32; +using static global::MS.Win32.UnsafeNativeMethods; + +internal partial class WpfComWrappers +{ + internal unsafe class TfCompartmentWrapper : ITfCompartment, IDisposable + { + private readonly IntPtr _wrappedInstance; + + internal TfCompartmentWrapper(IntPtr wrappedInstance) + { + _wrappedInstance = wrappedInstance; + } + + public IntPtr Instance => _wrappedInstance; + + public void Dispose() + { + Marshal.Release(_wrappedInstance); + } + + public int SetValue(int tid, ref object varValue) + { + NativeMethods.VARIANT value = NativeMethods.VARIANT.FromObject(varValue); + return ((delegate* unmanaged)(*(*(void***)_wrappedInstance + 3))) + (_wrappedInstance, tid, &value); + } + + public void GetValue(out object varValue) + { + NativeMethods.VARIANT value; + int hr = ((delegate* unmanaged)(*(*(void***)_wrappedInstance + 4))) + (_wrappedInstance, &value); + if (NativeMethods.Failed(hr)) + { + Marshal.ThrowExceptionForHR(hr); + } + + varValue = value.ToObject(); + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/WpfComWrappers.TfContextWrapper.cs b/src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/WpfComWrappers.TfContextWrapper.cs new file mode 100644 index 00000000000..208f55452aa --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/WpfComWrappers.TfContextWrapper.cs @@ -0,0 +1,224 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace MS.Internal; + +using System; +using System.Runtime.InteropServices; +using MS.Win32; +using static global::MS.Win32.UnsafeNativeMethods; + +internal partial class WpfComWrappers +{ + internal unsafe class TfContextWrapper : ITfContext, ITfContextComposition, ITfContextOwnerCompositionServices, IDisposable + { + private readonly IntPtr _wrappedInstance; + private readonly IntPtr _contextCompositionInstance; + private readonly IntPtr _contextOwnerCompositionServicesInstance; + + internal TfContextWrapper(IntPtr wrappedInstance) + { + _wrappedInstance = wrappedInstance; + Guid tfContextOwnerCompositionServicesIid = IID_ITfContextOwnerCompositionServices; + var result = Marshal.QueryInterface(wrappedInstance, ref tfContextOwnerCompositionServicesIid, out _contextOwnerCompositionServicesInstance); + if (NativeMethods.Failed(result)) + { + Marshal.ThrowExceptionForHR(result); + } + + Guid tfContextCompositionIid = IID_ITfContextComposition; + result = Marshal.QueryInterface(wrappedInstance, ref tfContextCompositionIid, out _contextCompositionInstance); + if (NativeMethods.Failed(result)) + { + Marshal.ThrowExceptionForHR(result); + } + } + + public IntPtr Instance => _wrappedInstance; + + ~TfContextWrapper() + { + DisposeInternal(); + } + + public void Dispose() + { + DisposeInternal(); + GC.SuppressFinalize(this); + } + + private void DisposeInternal() + { + Marshal.Release(_wrappedInstance); + Marshal.Release(_contextCompositionInstance); + Marshal.Release(_contextOwnerCompositionServicesInstance); + } + + public int stub_RequestEditSession() + { + throw new NotImplementedException(); + } + + public void InWriteSession(int clientId, [MarshalAs(UnmanagedType.Bool)] out bool inWriteSession) + { + int inWriteSessionNative; + int hr = ((delegate* unmanaged)(*(*(void***)_wrappedInstance + 4))) + (_wrappedInstance, clientId, &inWriteSessionNative); + if (NativeMethods.Failed(hr)) + { + Marshal.ThrowExceptionForHR(hr); + } + + inWriteSession = inWriteSessionNative != 0; + } + + public void stub_GetSelection() + { + throw new NotImplementedException(); + } + + public void stub_SetSelection() + { + throw new NotImplementedException(); + } + + public void GetStart(int ec, out ITfRange range) + { + IntPtr rangePtr; + int hr = ((delegate* unmanaged)(*(*(void***)_wrappedInstance + 7))) + (_wrappedInstance, ec, &rangePtr); + if (NativeMethods.Failed(hr)) + { + Marshal.ThrowExceptionForHR(hr); + } + + range = (ITfRange)Marshal.GetObjectForIUnknown(rangePtr); + } + + public void stub_GetEnd() + { + throw new NotImplementedException(); + } + + public void stub_GetActiveView() + { + throw new NotImplementedException(); + } + + public void stub_EnumViews() + { + throw new NotImplementedException(); + } + + public void stub_GetStatus() + { + throw new NotImplementedException(); + } + + public void GetProperty(ref Guid guid, out ITfProperty property) + { + IntPtr propertyPtr; + fixed (Guid* guidPtr = &guid) + { + int hr = ((delegate* unmanaged)(*(*(void***)_wrappedInstance + 12))) + (_wrappedInstance, guidPtr, &propertyPtr); + if (NativeMethods.Failed(hr)) + { + Marshal.ThrowExceptionForHR(hr); + } + } + + property = (ITfProperty)Marshal.GetObjectForIUnknown(propertyPtr); + } + + public void stub_GetAppProperty() + { + throw new NotImplementedException(); + } + + public void stub_TrackProperties() + { + throw new NotImplementedException(); + } + + public void stub_EnumProperties() + { + throw new NotImplementedException(); + } + + public void stub_GetDocumentMgr() + { + throw new NotImplementedException(); + } + + public void stub_CreateRangeBackup() + { + throw new NotImplementedException(); + } + + public void StartComposition(int ecWrite, ITfRange range, [MarshalAs(UnmanagedType.Interface)] object sink, [MarshalAs(UnmanagedType.Interface)] out object composition) + { + IntPtr compositionPtr; + IntPtr sinkPtr = Marshal.GetIUnknownForObject(sink); + IntPtr rangePtr = Marshal.GetComInterfaceForObject(range); + int hr = ((delegate* unmanaged)(*(*(void***)_contextCompositionInstance + 3))) + (_contextCompositionInstance, ecWrite, rangePtr, sinkPtr, &compositionPtr); + if (NativeMethods.Failed(hr)) + { + Marshal.ThrowExceptionForHR(hr); + } + + composition = Marshal.GetObjectForIUnknown(compositionPtr); + } + + public void EnumCompositions([MarshalAs(UnmanagedType.Interface)] out IEnumITfCompositionView enumView) + { + IntPtr enumViewPtr; + int hr = ((delegate* unmanaged)(*(*(void***)_contextCompositionInstance + 4))) + (_contextCompositionInstance, &enumViewPtr); + if (NativeMethods.Failed(hr)) + { + Marshal.ThrowExceptionForHR(hr); + } + + enumView = (IEnumITfCompositionView)Marshal.GetObjectForIUnknown(enumViewPtr); + } + + public void FindComposition(int ecRead, ITfRange testRange, [MarshalAs(UnmanagedType.Interface)] out object enumView) + { + IntPtr enumViewPtr; + IntPtr testRangePtr = Marshal.GetComInterfaceForObject(testRange); + int hr = ((delegate* unmanaged)(*(*(void***)_contextCompositionInstance + 5))) + (_contextCompositionInstance, ecRead, testRangePtr, &enumViewPtr); + if (NativeMethods.Failed(hr)) + { + Marshal.ThrowExceptionForHR(hr); + } + + enumView = Marshal.GetObjectForIUnknown(enumViewPtr); + } + + public void TakeOwnership(int ecWrite, ITfCompositionView view, [MarshalAs(UnmanagedType.Interface)] object sink, [MarshalAs(UnmanagedType.Interface)] out object composition) + { + IntPtr compositionPtr; + IntPtr sinkPtr = Marshal.GetIUnknownForObject(sink); + IntPtr viewPtr = Marshal.GetComInterfaceForObject(view); + int hr = ((delegate* unmanaged)(*(*(void***)_contextCompositionInstance + 6))) + (_contextCompositionInstance, ecWrite, viewPtr, sinkPtr, &compositionPtr); + if (NativeMethods.Failed(hr)) + { + Marshal.ThrowExceptionForHR(hr); + } + + composition = Marshal.GetObjectForIUnknown(compositionPtr); + } + + public int TerminateComposition(ITfCompositionView view) + { + IntPtr viewPtr = Marshal.GetComInterfaceForObject(view); + return ((delegate* unmanaged)(*(*(void***)_contextOwnerCompositionServicesInstance + 3))) + (_contextOwnerCompositionServicesInstance, viewPtr); + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/WpfComWrappers.TfDocumentMgrWrapper.cs b/src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/WpfComWrappers.TfDocumentMgrWrapper.cs new file mode 100644 index 00000000000..91f413903c7 --- /dev/null +++ b/src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/WpfComWrappers.TfDocumentMgrWrapper.cs @@ -0,0 +1,208 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace MS.Internal; + +using System; +using System.Runtime.InteropServices; +using MS.Win32; +using static global::MS.Win32.UnsafeNativeMethods; + +internal partial class WpfComWrappers +{ + internal unsafe class TfDocumentMgrWrapper : ITfDocumentMgr, ITfSource, ITfCompartmentMgr + { + private readonly IntPtr _wrappedInstance; + private readonly IntPtr _sourceInstance; + private readonly IntPtr _compartmentMgrInstance; + + internal TfDocumentMgrWrapper(IntPtr wrappedInstance) + { + _wrappedInstance = wrappedInstance; + Guid tfSourceIid = IID_ITfSource; + int hr = Marshal.QueryInterface(wrappedInstance, ref tfSourceIid, out _sourceInstance); + if (NativeMethods.Failed(hr)) + { + Marshal.ThrowExceptionForHR(hr); + } + + Guid tfCompartmentMgrIid = IID_ITfCompartmentMgr; + hr = Marshal.QueryInterface(wrappedInstance, ref tfCompartmentMgrIid, out _compartmentMgrInstance); + if (NativeMethods.Failed(hr)) + { + Marshal.ThrowExceptionForHR(hr); + } + } + + public IntPtr Instance => _wrappedInstance; + + ~TfDocumentMgrWrapper() + { + Marshal.Release(_wrappedInstance); + Marshal.Release(_sourceInstance); + Marshal.Release(_compartmentMgrInstance); + } + + public void CreateContext(int clientId, CreateContextFlags flags, [MarshalAs(UnmanagedType.Interface)] object obj, out ITfContext context, out int editCookie) + { + IntPtr unknownPtr = WpfComWrappers.Instance.GetOrCreateComInterfaceForObject(obj); + try + { + IntPtr contextPtr; + fixed (int* editCookiePtr = &editCookie) + { + int hr = ((delegate* unmanaged)(*(*(void***)_wrappedInstance + 3))) + (_wrappedInstance, clientId, flags, unknownPtr, &contextPtr, editCookiePtr); + if (NativeMethods.Failed(hr)) + { + Marshal.ThrowExceptionForHR(hr); + } + } + + context = (ITfContext)WpfComWrappers.Instance.GetOrCreateObjectForComInstance(contextPtr, CreateObjectFlags.Unwrap); + } + finally + { + if (unknownPtr != IntPtr.Zero) + { + Marshal.Release(unknownPtr); + } + } + } + + public void Push(ITfContext context) + { + IntPtr contextPtr = WpfComWrappers.Instance.GetComPointer(context, IID_ITfContext); + int hr = ((delegate* unmanaged)(*(*(void***)_wrappedInstance + 4))) + (_wrappedInstance, contextPtr); + if (NativeMethods.Failed(hr)) + { + Marshal.ThrowExceptionForHR(hr); + } + } + + public void Pop(PopFlags flags) + { + int hr = ((delegate* unmanaged)(*(*(void***)_wrappedInstance + 5))) + (_wrappedInstance, flags); + if (NativeMethods.Failed(hr)) + { + Marshal.ThrowExceptionForHR(hr); + } + } + + public void GetTop(out ITfContext context) + { + IntPtr contextPtr; + int hr = ((delegate* unmanaged)(*(*(void***)_wrappedInstance + 6))) + (_wrappedInstance, &contextPtr); + if (NativeMethods.Failed(hr)) + { + Marshal.ThrowExceptionForHR(hr); + } + + context = contextPtr == IntPtr.Zero ? null : (ITfContext)WpfComWrappers.Instance.GetOrCreateObjectForComInstance(contextPtr, CreateObjectFlags.Unwrap); + } + + public void GetBase(out ITfContext context) + { + IntPtr contextPtr; + int hr = ((delegate* unmanaged)(*(*(void***)_wrappedInstance + 7))) + (_wrappedInstance, &contextPtr); + if (NativeMethods.Failed(hr)) + { + Marshal.ThrowExceptionForHR(hr); + } + + context = contextPtr == IntPtr.Zero ? null : (ITfContext)WpfComWrappers.Instance.GetOrCreateObjectForComInstance(contextPtr, CreateObjectFlags.Unwrap); + } + + public void EnumContexts([MarshalAs(UnmanagedType.Interface)] out object enumContexts) + { + IntPtr enumContextsPtr; + int hr = ((delegate* unmanaged)(*(*(void***)_wrappedInstance + 8))) + (_wrappedInstance, &enumContextsPtr); + if (NativeMethods.Failed(hr)) + { + Marshal.ThrowExceptionForHR(hr); + } + + enumContexts = Marshal.GetObjectForIUnknown(enumContextsPtr); + } + + public void AdviseSink(ref Guid riid, [MarshalAs(UnmanagedType.Interface)] object obj, out int cookie) + { + IntPtr unknownPtr = WpfComWrappers.Instance.GetOrCreateComInterfaceForObject(obj); + try + { + fixed (Guid* iidPtr = &riid) + fixed (int* cookiePtr = &cookie) + { + int hr = ((delegate* unmanaged)(*(*(void***)_sourceInstance + 3))) + (_sourceInstance, iidPtr, unknownPtr, cookiePtr); + if (NativeMethods.Failed(hr)) + { + Marshal.ThrowExceptionForHR(hr); + } + } + } + finally + { + if (unknownPtr != IntPtr.Zero) + { + Marshal.Release(unknownPtr); + } + } + } + + public void UnadviseSink(int cookie) + { + int hr = ((delegate* unmanaged)(*(*(void***)_sourceInstance + 4))) + (_sourceInstance, cookie); + if (NativeMethods.Failed(hr)) + { + Marshal.ThrowExceptionForHR(hr); + } + } + + public void GetCompartment(ref Guid guid, out ITfCompartment comp) + { + IntPtr compPtr; + fixed (Guid* guidPtr = &guid) + { + int hr = ((delegate* unmanaged)(*(*(void***)_compartmentMgrInstance + 3))) + (_compartmentMgrInstance, guidPtr , & compPtr); + if (NativeMethods.Failed(hr)) + { + Marshal.ThrowExceptionForHR(hr); + } + } + + comp = compPtr == IntPtr.Zero ? null : (ITfCompartment)WpfComWrappers.Instance.GetOrCreateObjectForComInstance(compPtr, CreateObjectFlags.Unwrap); + } + + public void ClearCompartment(int tid, Guid guid) + { + int hr = ((delegate* unmanaged)(*(*(void***)_compartmentMgrInstance + 4))) + (_compartmentMgrInstance, tid, &guid); + if (NativeMethods.Failed(hr)) + { + Marshal.ThrowExceptionForHR(hr); + } + } + + public void EnumCompartments(out object enumGuid) + { + IntPtr enumGuidPtr; + int hr = ((delegate* unmanaged)(*(*(void***)_compartmentMgrInstance + 3))) + (_compartmentMgrInstance, &enumGuidPtr); + if (NativeMethods.Failed(hr)) + { + Marshal.ThrowExceptionForHR(hr); + } + + enumGuid = Marshal.GetObjectForIUnknown(enumGuidPtr); + } + } +} diff --git a/src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/WpfComWrappers.TfThreadMgrWrapper.cs b/src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/WpfComWrappers.TfThreadMgrWrapper.cs index e852c9d246e..6ff20aaa6a8 100644 --- a/src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/WpfComWrappers.TfThreadMgrWrapper.cs +++ b/src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/WpfComWrappers.TfThreadMgrWrapper.cs @@ -84,7 +84,7 @@ public void CreateDocumentMgr(out ITfDocumentMgr docMgr) Marshal.ThrowExceptionForHR(result); } - docMgr = (ITfDocumentMgr)Marshal.GetObjectForIUnknown(docMgrPtr); + docMgr = (ITfDocumentMgr)Instance.GetOrCreateObjectForComInstance(docMgrPtr, CreateObjectFlags.Unwrap); } public void EnumDocumentMgrs(out IEnumTfDocumentMgrs enumDocMgrs) @@ -110,23 +110,15 @@ public void GetFocus(out ITfDocumentMgr docMgr) Marshal.ThrowExceptionForHR(result); } - docMgr = (ITfDocumentMgr)Marshal.GetObjectForIUnknown(docMgrPtr); + docMgr = (ITfDocumentMgr)Instance.GetOrCreateObjectForComInstance(docMgrPtr, CreateObjectFlags.Unwrap); } public void SetFocus(ITfDocumentMgr docMgr) { - IntPtr docMgrPtr = IntPtr.Zero; - IntPtr unknownPtr = Marshal.GetIUnknownForObject(docMgr); + IntPtr docMgrPtr = Instance.GetComPointer(docMgr, IID_ITfDocumentMgr); try { - Guid tfDocumentMgr = IID_ITfDocumentMgr; - int result = Marshal.QueryInterface(unknownPtr, ref tfDocumentMgr, out docMgrPtr); - if (NativeMethods.Failed(result)) - { - Marshal.ThrowExceptionForHR(result); - } - - result = ((delegate* unmanaged)(*(*(void***)_wrappedInstance + 8))) + int result = ((delegate* unmanaged)(*(*(void***)_wrappedInstance + 8))) (_wrappedInstance, docMgrPtr); if (NativeMethods.Failed(result)) { @@ -135,11 +127,6 @@ public void SetFocus(ITfDocumentMgr docMgr) } finally { - if (unknownPtr != IntPtr.Zero) - { - Marshal.Release(unknownPtr); - } - if (docMgrPtr != IntPtr.Zero) { Marshal.Release(docMgrPtr); @@ -149,19 +136,11 @@ public void SetFocus(ITfDocumentMgr docMgr) public void AssociateFocus(IntPtr hwnd, ITfDocumentMgr newDocMgr, out ITfDocumentMgr prevDocMgr) { - IntPtr newDocMgrPtr = IntPtr.Zero; - IntPtr unknownPtr = Marshal.GetIUnknownForObject(newDocMgr); + IntPtr newDocMgrPtr = Instance.GetComPointer(newDocMgr, IID_ITfDocumentMgr); try { - Guid tfDocumentMgr = IID_ITfDocumentMgr; - int result = Marshal.QueryInterface(unknownPtr, ref tfDocumentMgr, out newDocMgrPtr); - if (NativeMethods.Failed(result)) - { - Marshal.ThrowExceptionForHR(result); - } - IntPtr prevDocMgrPtr = IntPtr.Zero; - result = ((delegate* unmanaged)(*(*(void***)_wrappedInstance + 9))) + int result = ((delegate* unmanaged)(*(*(void***)_wrappedInstance + 9))) (_wrappedInstance, hwnd, newDocMgrPtr, &prevDocMgrPtr); if (NativeMethods.Failed(result)) { @@ -172,11 +151,6 @@ public void AssociateFocus(IntPtr hwnd, ITfDocumentMgr newDocMgr, out ITfDocumen } finally { - if (unknownPtr != IntPtr.Zero) - { - Marshal.Release(unknownPtr); - } - if (newDocMgrPtr != IntPtr.Zero) { Marshal.Release(newDocMgrPtr); diff --git a/src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/WpfComWrappers.cs b/src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/WpfComWrappers.cs index 8d2e91521b0..9563b46f2df 100644 --- a/src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/WpfComWrappers.cs +++ b/src/Microsoft.DotNet.Wpf/src/WindowsBase/MS/Internal/WpfComWrappers.cs @@ -6,9 +6,12 @@ namespace MS.Internal; using System; using System.Collections; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using MS.Win32; +#nullable enable -internal partial class WpfComWrappers : ComWrappers +internal unsafe partial class WpfComWrappers : ComWrappers { // AA80E801-2021-11D2-93E0-0060B067B86E private static readonly Guid IID_ITfThreadMgr = new Guid(0xAA80E801, 0x2021, 0x11D2, 0x93, 0xE0, 0x00, 0x60, 0xB0, 0x67, 0xB8, 0x6E); @@ -28,11 +31,50 @@ internal partial class WpfComWrappers : ComWrappers // AA80E7FD-2021-11D2-93E0-0060B067B86E private static readonly Guid IID_ITfContext = new Guid(0xAA80E7FD, 0x2021, 0x11D2, 0x93, 0xE0, 0x00, 0x60, 0xB0, 0x67, 0xB8, 0x6E); + // 7DCF57AC-18AD-438B-824D-979BFFB74B7C + private static readonly Guid IID_ITfCompartmentMgr = new Guid(0x7DCF57AC, 0x18AD, 0x438B, 0x82, 0x4D, 0x97, 0x9B, 0xFF, 0xB7, 0x4B, 0x7C); + + // AA80E80C-2021-11D2-93E0-0060B067B86E + private static readonly Guid IID_ITfContextOwner = new Guid(0xAA80E80C, 0x2021, 0x11D2, 0x93, 0xE0, 0x00, 0x60, 0xB0, 0x67, 0xB8, 0x6E); + + // 86462810-593B-4916-9764-19C08E9CE110 + private static readonly Guid IID_ITfContextOwnerCompositionServices = new Guid(0x86462810, 0x593B, 0x4916, 0x97, 0x64, 0x19, 0xC0, 0x8E, 0x9C, 0xE1, 0x10); + + // D40C8AAE-AC92-4FC7-9A11-0EE0E23AA39B + private static readonly Guid IID_ITfContextComposition = new Guid(0xD40C8AAE, 0xAC92, 0x4FC7, 0x9A, 0x11, 0x0E, 0xE0, 0xE2, 0x3A, 0xA3, 0x9B); + + // BB08F7A9-607A-4384-8623-056892B64371 + private static readonly Guid IID_ITfCompartment = new Guid(0xBB08F7A9, 0x607A, 0x4384, 0x86, 0x23, 0x05, 0x68, 0x92, 0xB6, 0x43, 0x71); + + // 5F20AA40-B57A-4F34-96AB-3576F377CC79 + private static readonly Guid IID_ITfContextOwnerCompositionSink = new Guid(0x5F20AA40, 0xB57A, 0x4F34, 0x96, 0xAB, 0x35, 0x76, 0xF3, 0x77, 0xCC, 0x79); + + // A615096F-1C57-4813-8A15-55EE6E5A839C + private static readonly Guid IID_ITfTransitoryExtensionSink = new Guid(0xA615096F, 0x1C57, 0x4813, 0x8A, 0x15, 0x55, 0xEE, 0x6E, 0x5A, 0x83, 0x9C); + + // 00000122-0000-0000-C000-000000000046 + internal static readonly Guid IID_IOleDropTarget = new Guid(0x00000122, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46); + + private static readonly ComInterfaceEntry* s_oleDropTargetEntry = InitializeIOleDropTargetEntry(); + private static readonly ComInterfaceEntry* s_defaultTextStoreEntry = InitializeDefaultTextStoreEntry(); + public static WpfComWrappers Instance { get; } = new WpfComWrappers(); protected override unsafe ComInterfaceEntry* ComputeVtables(object obj, CreateComInterfaceFlags flags, out int count) { - throw new NotImplementedException(); + if (obj is UnsafeNativeMethods.IOleDropTarget) + { + count = 1; + return s_oleDropTargetEntry; + } + + if (obj is UnsafeNativeMethods.ITfContextOwner) + { + count = 3; + return s_defaultTextStoreEntry; + } + + throw new NotImplementedException($"ComWrappers for type {obj.GetType()} not implemented."); } protected override object CreateObject(IntPtr externalComObject, CreateObjectFlags flags) @@ -44,6 +86,27 @@ protected override object CreateObject(IntPtr externalComObject, CreateObjectFla return new TfThreadMgrWrapper(tfThreadMgrPtr); } + var tfDocumentMgrIID = IID_ITfDocumentMgr; + if (Marshal.QueryInterface(externalComObject, ref tfDocumentMgrIID, out var tfDocumentMgrPtr) >= 0) + { + Marshal.Release(externalComObject); + return new TfDocumentMgrWrapper(tfDocumentMgrPtr); + } + + var tfContextIID = IID_ITfContext; + if (Marshal.QueryInterface(externalComObject, ref tfContextIID, out var tfContextPtr) >= 0) + { + Marshal.Release(externalComObject); + return new TfContextWrapper(tfContextPtr); + } + + var tfCompartmentIID = IID_ITfCompartment; + if (Marshal.QueryInterface(externalComObject, ref tfCompartmentIID, out var tfCompartmentPtr) >= 0) + { + Marshal.Release(externalComObject); + return new TfCompartmentWrapper(tfCompartmentPtr); + } + throw new NotImplementedException(); } @@ -51,4 +114,82 @@ protected override void ReleaseObjects(IEnumerable objects) { throw new NotImplementedException(); } + + private static ComInterfaceEntry* InitializeIOleDropTargetEntry() + { + GetIUnknownImpl(out IntPtr fpQueryInterface, out IntPtr fpAddRef, out IntPtr fpRelease); + + IntPtr iOleDropTargetVtbl = IOleDropTargetVtbl.Create(fpQueryInterface, fpAddRef, fpRelease); + + ComInterfaceEntry* wrapperEntry = (ComInterfaceEntry*)RuntimeHelpers.AllocateTypeAssociatedMemory(typeof(WpfComWrappers), sizeof(ComInterfaceEntry)); + wrapperEntry->IID = IID_IOleDropTarget; + wrapperEntry->Vtable = iOleDropTargetVtbl; + return wrapperEntry; + } + + private static ComInterfaceEntry* InitializeDefaultTextStoreEntry() + { + GetIUnknownImpl(out IntPtr fpQueryInterface, out IntPtr fpAddRef, out IntPtr fpRelease); + + IntPtr iTfContextOwnerVtbl = ITfContextOwnerVtbl.Create(fpQueryInterface, fpAddRef, fpRelease); + IntPtr iTfContextOwnerCompositionSinkVtbl = ITfContextOwnerCompositionSinkVtbl.Create(fpQueryInterface, fpAddRef, fpRelease); + IntPtr iTfTransitoryExtensionSinkVtbl = ITfTransitoryExtensionSinkVtbl.Create(fpQueryInterface, fpAddRef, fpRelease); + + ComInterfaceEntry* wrapperEntry = (ComInterfaceEntry*)RuntimeHelpers.AllocateTypeAssociatedMemory(typeof(WpfComWrappers), sizeof(ComInterfaceEntry) * 3); + wrapperEntry[0].IID = IID_ITfContextOwner; + wrapperEntry[0].Vtable = iTfContextOwnerVtbl; + wrapperEntry[1].IID = IID_ITfContextOwnerCompositionSink; + wrapperEntry[1].Vtable = iTfContextOwnerCompositionSinkVtbl; + wrapperEntry[2].IID = IID_ITfTransitoryExtensionSink; + wrapperEntry[2].Vtable = iTfTransitoryExtensionSinkVtbl; + return wrapperEntry; + } + + internal int TryGetComPointer(T? obj, Guid iid, out IntPtr comPtr) where T : class + { + if (obj is null) + { + comPtr = IntPtr.Zero; + return NativeMethods.S_OK; + } + + IntPtr pobj_local; + IntPtr pUnk_local = GetOrCreateComInterfaceForObject(obj); + Guid local_IID = iid; + int result = Marshal.QueryInterface(pUnk_local, ref local_IID, out pobj_local); + Marshal.Release(pUnk_local); + comPtr = pobj_local; + return result; + } + + internal IntPtr GetComPointer(T obj, Guid iid) where T : class + { + var result = TryGetComPointer(obj, iid, out var comPtr); + if (NativeMethods.Failed(result)) + { + Marshal.ThrowExceptionForHR(result); + } + + return comPtr; + } + private IntPtr GetOrCreateComInterfaceForObject(object obj) + { + switch (obj) + { + case TfDocumentMgrWrapper dmw: + { + var ptr = dmw.Instance; + Marshal.AddRef(ptr); + return ptr; + } + case TfContextWrapper cw: + { + var ptr = cw.Instance; + Marshal.AddRef(ptr); + return ptr; + } + default: + return GetOrCreateComInterfaceForObject(obj, CreateComInterfaceFlags.None); + } + } } diff --git a/src/Microsoft.DotNet.Wpf/src/WindowsBase/WindowsBase.csproj b/src/Microsoft.DotNet.Wpf/src/WindowsBase/WindowsBase.csproj index 042c732477f..1da62676d9d 100644 --- a/src/Microsoft.DotNet.Wpf/src/WindowsBase/WindowsBase.csproj +++ b/src/Microsoft.DotNet.Wpf/src/WindowsBase/WindowsBase.csproj @@ -20,6 +20,9 @@ Common\System\LocalAppContext.cs + + + Common\System\SR.cs @@ -151,7 +154,11 @@ + + + +