From a5b9e877eaf515a67bce7dcfb6c5aa3b685e42e5 Mon Sep 17 00:00:00 2001 From: Tanya Solyanik Date: Thu, 21 Nov 2024 12:52:52 -0800 Subject: [PATCH] Replaced a NullReferedeException that was lost in the interop layer with an HRESULT error code recommended in the docs - https://learn.microsoft.com/en-us/windows/win32/api/objidl/nf-objidl-idataobject-getdatahere#return-value. The HRESULT is not bubbled up through OleFlushClipboard either, this API returns S_OK even when the data wasn't set. In this case we end up with format being set successfully, but data actually missing. --- .../Forms/Design/ButtonBaseDesigner.cs | 3 --- ...ect.Composition.WinFormsToNativeAdapter.cs | 9 ++++--- .../System/Windows/Forms/ClipboardTests.cs | 25 +++++++++++++------ 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ButtonBaseDesigner.cs b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ButtonBaseDesigner.cs index 01b4856ef42..a92ff3e236e 100644 --- a/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ButtonBaseDesigner.cs +++ b/src/System.Windows.Forms.Design/src/System/Windows/Forms/Design/ButtonBaseDesigner.cs @@ -15,8 +15,6 @@ namespace System.Windows.Forms.Design; /// internal class ButtonBaseDesigner : ControlDesigner { - // private DesignerActionListCollection _actionlists; - public ButtonBaseDesigner() { AutoResizeHandles = true; @@ -31,7 +29,6 @@ public override void InitializeNewComponent(IDictionary? defaultValues) { // Dev10 Bug 685319: We should set the UseVisualStyleBackColor to trun only // when this property has not been set/changed by user - // if (!prop.ShouldSerializeValue(Component)) { prop.SetValue(Component, true); diff --git a/src/System.Windows.Forms/src/System/Windows/Forms/OLE/DataObject.Composition.WinFormsToNativeAdapter.cs b/src/System.Windows.Forms/src/System/Windows/Forms/OLE/DataObject.Composition.WinFormsToNativeAdapter.cs index 2f5511e7074..ccaf607431b 100644 --- a/src/System.Windows.Forms/src/System/Windows/Forms/OLE/DataObject.Composition.WinFormsToNativeAdapter.cs +++ b/src/System.Windows.Forms/src/System/Windows/Forms/OLE/DataObject.Composition.WinFormsToNativeAdapter.cs @@ -116,13 +116,16 @@ HRESULT Com.IDataObject.Interface.GetDataHere(FORMATETC* pformatetc, STGMEDIUM* return HRESULT.DV_E_FORMATETC; } - object? data = _dataObject.GetData(format); + if (_dataObject.GetData(format) is not object data) + { + return HRESULT.E_UNEXPECTED; + } if (((TYMED)pformatetc->tymed).HasFlag(TYMED.TYMED_HGLOBAL)) { try { - return SaveDataToHGLOBAL(data!, format, ref *pmedium); + return SaveDataToHGLOBAL(data, format, ref *pmedium); } catch (NotSupportedException ex) { @@ -314,7 +317,7 @@ DataFormats.DibConstant when data is Image _ when format == DataFormats.SerializableConstant || data is ISerializable || data.GetType().IsSerializable #pragma warning restore => SaveObjectToHGLOBAL(ref medium.hGlobal, data, RestrictDeserializationToSafeTypes(format)), - _ => HRESULT.E_FAIL + _ => HRESULT.E_UNEXPECTED }; private static HRESULT SaveObjectToHGLOBAL(ref HGLOBAL hglobal, object data, bool restrictSerialization) diff --git a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ClipboardTests.cs b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ClipboardTests.cs index dd4bb46b2e7..8816a9d3435 100644 --- a/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ClipboardTests.cs +++ b/src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ClipboardTests.cs @@ -232,15 +232,26 @@ public void Clipboard_SetData_Invoke_GetReturnsExpected(string format, object? d [InlineData(null)] public void Clipboard_SetData_EmptyOrWhitespaceFormat_ThrowsArgumentException(string? format) { - Action action = () => Clipboard.SetData(format!, data: null!); + Action action = () => Clipboard.SetData(format!, "data"); action.Should().Throw().WithParameterName("format"); } [WinFormsFact] - public void Clipboard_SetData_null_Success() + public void Clipboard_SetData_null_NotThrow() { - Action action = () => Clipboard.SetData("MyData", data: null!); - action.Should().NotThrow(); + try + { + Action action = () => Clipboard.SetData("MyData", data: null!); + action.Should().NotThrow(); + // Clipboard flushes format only, content is not stored. + // GetData will hit "Data on clipboard is invalid (0x800401D3 (CLIPBRD_E_BAD_DATA))" + Clipboard.ContainsData("MyData").Should().BeTrue(); + Clipboard.GetData("MyData").Should().BeNull(); + } + finally + { + Clipboard.Clear(); + } } [WinFormsTheory] @@ -264,8 +275,7 @@ public void Clipboard_SetDataObject_InvokeObjectIComDataObject_GetReturnsExpecte DataObject dataObject = new(data); Clipboard.SetDataObject(dataObject); - var actual = Clipboard.GetDataObject(); - Assert.NotNull(actual); + DataObject actual = Clipboard.GetDataObject().Should().BeOfType().Subject; actual.GetData(data.GetType()).Should().Be(data); Clipboard.ContainsData(data.GetType().FullName).Should().BeTrue(); } @@ -279,8 +289,7 @@ public void Clipboard_SetDataObject_InvokeObjectBoolNotIComDataObject_GetReturns { Clipboard.SetDataObject(data, copy); - var dataObject = Clipboard.GetDataObject(); - Assert.NotNull(dataObject); + DataObject dataObject = Clipboard.GetDataObject().Should().BeOfType().Subject; dataObject.GetData(data.GetType()).Should().Be(data); Clipboard.ContainsData(data.GetType().FullName).Should().BeTrue(); }