Skip to content

Commit 0a415d7

Browse files
authored
Merge pull request #12806 from JeremyKuhne/port12800
Don't unwrap wrapped DataObject inner data store (#12800)
2 parents 69636da + 2bfb292 commit 0a415d7

File tree

3 files changed

+103
-5
lines changed

3 files changed

+103
-5
lines changed

src/System.Windows.Forms/src/System/Windows/Forms/OLE/DataObject.cs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,7 @@ public DataObject()
4545
/// </summary>
4646
public DataObject(object data)
4747
{
48-
if (data is DataObject dataObject)
49-
{
50-
_innerData = dataObject._innerData;
51-
}
52-
else if (data is IDataObject iDataObject)
48+
if (data is IDataObject iDataObject)
5349
{
5450
_innerData = Composition.CreateFromWinFormsDataObject(iDataObject);
5551
}

src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/ClipboardTests.cs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,4 +699,33 @@ public void Clipboard_SetDataObject_Text()
699699
byte[] array = stream.ToArray();
700700
array.Should().BeEquivalentTo("Hello, World!\0"u8.ToArray());
701701
}
702+
703+
[WinFormsFact]
704+
public void Clipboard_DerivedDataObject_DataPresent()
705+
{
706+
// https://github.com/dotnet/winforms/issues/12789
707+
SomeDataObject data = new();
708+
709+
// This was provided as a workaround for the above and should not break, but should
710+
// also work without it.
711+
data.SetData(SomeDataObject.Format, data);
712+
713+
Clipboard.SetDataObject(data);
714+
Clipboard.ContainsData(SomeDataObject.Format).Should().BeTrue();
715+
Clipboard.GetDataObject()!.GetDataPresent(SomeDataObject.Format).Should().BeTrue();
716+
717+
data = new();
718+
Clipboard.SetDataObject(data);
719+
Clipboard.ContainsData(SomeDataObject.Format).Should().BeTrue();
720+
Clipboard.GetDataObject()!.GetDataPresent(SomeDataObject.Format).Should().BeTrue();
721+
}
722+
723+
public class SomeDataObject : DataObject
724+
{
725+
public static string Format => "SomeDataObjectId";
726+
public override string[] GetFormats() => [Format];
727+
728+
public override bool GetDataPresent(string format, bool autoConvert)
729+
=> format == Format || base.GetDataPresent(format, autoConvert);
730+
}
702731
}

src/System.Windows.Forms/tests/UnitTests/System/Windows/Forms/DataObjectTests.cs

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2657,4 +2657,77 @@ public unsafe void DataObject_ComTypesIDataObject_MockRoundTrip_IsWrapped()
26572657
IDataObject outData = dropTargetAccessor.CreateDelegate<CreateWinFormsDataObjectForOutgoingDropData>()(inDataPtr);
26582658
outData.Should().BeSameAs(inData);
26592659
}
2660+
2661+
[Fact]
2662+
public void DataObject_CreateFromDataObject_DoesNotUnwrapDataStore()
2663+
{
2664+
// The inner data should not have it's data store unwrapped.
2665+
DataObject dataObject = new();
2666+
DataObject wrapped = new(dataObject);
2667+
DataObject.Composition composition = wrapped.TestAccessor().Dynamic._innerData;
2668+
IDataObject original = composition.TestAccessor().Dynamic._winFormsDataObject;
2669+
original.Should().BeSameAs(dataObject);
2670+
}
2671+
2672+
[Fact]
2673+
public void DataObject_CreateFromDataObject_VirtualsAreCalled()
2674+
{
2675+
Mock<DataObject> mock = new(MockBehavior.Loose);
2676+
DataObject wrapped = new(mock.Object);
2677+
2678+
wrapped.GetData("Foo", false);
2679+
mock.Verify(o => o.GetData("Foo", false), Times.Once());
2680+
mock.VerifyNoOtherCalls();
2681+
mock.Reset();
2682+
2683+
wrapped.GetData("Foo");
2684+
mock.Verify(o => o.GetData("Foo", true), Times.Once());
2685+
mock.VerifyNoOtherCalls();
2686+
mock.Reset();
2687+
2688+
wrapped.GetData(typeof(string));
2689+
mock.Verify(o => o.GetData("System.String", true), Times.Once());
2690+
mock.VerifyNoOtherCalls();
2691+
mock.Reset();
2692+
2693+
wrapped.GetDataPresent("Foo", false);
2694+
mock.Verify(o => o.GetDataPresent("Foo", false), Times.Once());
2695+
mock.VerifyNoOtherCalls();
2696+
mock.Reset();
2697+
2698+
wrapped.GetDataPresent("Foo");
2699+
mock.Verify(o => o.GetDataPresent("Foo", true), Times.Once());
2700+
mock.VerifyNoOtherCalls();
2701+
mock.Reset();
2702+
2703+
wrapped.GetDataPresent(typeof(string));
2704+
mock.Verify(o => o.GetDataPresent("System.String", true), Times.Once());
2705+
mock.VerifyNoOtherCalls();
2706+
mock.Reset();
2707+
2708+
wrapped.GetFormats(false);
2709+
mock.Verify(o => o.GetFormats(false), Times.Once());
2710+
mock.VerifyNoOtherCalls();
2711+
mock.Reset();
2712+
2713+
wrapped.GetFormats();
2714+
mock.Verify(o => o.GetFormats(true), Times.Once());
2715+
mock.VerifyNoOtherCalls();
2716+
mock.Reset();
2717+
2718+
wrapped.SetData("Foo", "Bar");
2719+
mock.Verify(o => o.SetData("Foo", "Bar"), Times.Once());
2720+
mock.VerifyNoOtherCalls();
2721+
mock.Reset();
2722+
2723+
wrapped.SetData(typeof(string), "Bar");
2724+
mock.Verify(o => o.SetData(typeof(string), "Bar"), Times.Once());
2725+
mock.VerifyNoOtherCalls();
2726+
mock.Reset();
2727+
2728+
wrapped.SetData("Bar");
2729+
mock.Verify(o => o.SetData("Bar"), Times.Once());
2730+
mock.VerifyNoOtherCalls();
2731+
mock.Reset();
2732+
}
26602733
}

0 commit comments

Comments
 (0)