ClipboardCore<TOleServices>
Contains platform-agnostic clipboard operations.
using System.Collections.Specialized;
using System.Private.Windows.Core.Resources;
using System.Runtime.CompilerServices;
using System.Threading;
using Windows.Win32;
using Windows.Win32.Foundation;
using Windows.Win32.System.Com;
namespace System.Private.Windows.Ole
{
[NullableContext(1)]
[Nullable(0)]
internal static class ClipboardCore<[Nullable(0)] TOleServices> where TOleServices : IOleServices
{
private const int OleRetryCount = 10;
private const int OleRetryDelay = 100;
internal static HRESULT Clear(int retryTimes = 10, int retryDelay = 100)
{
((IOleServices)).EnsureThreadState();
int num = retryTimes;
HRESULT result;
while (true) {
HRESULT hRESULT = result = ((IOleServices)).OleSetClipboard(null);
if (!hRESULT.Failed || --num < 0)
break;
Thread.Sleep(retryDelay);
}
return result;
}
internal static HRESULT Flush(int retryTimes = 10, int retryDelay = 100)
{
((IOleServices)).EnsureThreadState();
int num = retryTimes;
HRESULT result;
while (true) {
HRESULT hRESULT = result = ((IOleServices)).OleFlushClipboard();
if (!hRESULT.Failed || --num < 0)
break;
Thread.Sleep(retryDelay);
}
return result;
}
internal unsafe static HRESULT SetData(IComVisibleDataObject dataObject, bool copy, int retryTimes = 10, int retryDelay = 100)
{
((IOleServices)).EnsureThreadState();
ArgumentOutOfRangeException.ThrowIfNegative<int>(retryTimes, "retryTimes");
ArgumentOutOfRangeException.ThrowIfNegative<int>(retryDelay, "retryDelay");
ComScope<IDataObject> scope = ComHelpers.GetComScope<IDataObject>((object)dataObject);
try {
int num = retryTimes;
HRESULT hRESULT;
HRESULT result;
while (true) {
IDataObject* dataObject2 = (IDataObject*)ref scope;
hRESULT = (result = ((IOleServices)).OleSetClipboard(dataObject2));
if (!hRESULT.Failed)
break;
if (--num < 0)
return result;
Thread.Sleep(retryDelay);
}
if (copy) {
num = retryTimes;
while (true) {
hRESULT = (result = ((IOleServices)).OleFlushClipboard());
if (!hRESULT.Failed)
break;
if (--num < 0)
return result;
Thread.Sleep(retryDelay);
}
}
return result;
} finally {
scope.Dispose();
}
}
[NullableContext(0)]
internal unsafe static HRESULT TryGetData(out ComScope<IDataObject> proxyDataObject, [Nullable(2)] out object originalObject, int retryTimes = 10, int retryDelay = 100)
{
((IOleServices)).EnsureThreadState();
proxyDataObject = new ComScope<IDataObject>(null);
originalObject = null;
int num = retryTimes;
HRESULT result;
HRESULT hRESULT;
while (true) {
IDataObject** dataObject = (IDataObject**)ref proxyDataObject;
result = (hRESULT = ((IOleServices)).OleGetClipboard(dataObject));
if (!result.Failed)
break;
if (--num < 0)
return hRESULT;
Thread.Sleep(retryDelay);
}
HRESULT hr;
ComScope<IComCallableWrapper> comScope = proxyDataObject.TryQuery<IComCallableWrapper>(out hr);
try {
if (hr.Succeeded)
ComHelpers.TryUnwrapComWrapperCCW<object>(comScope.AsUnknown, out originalObject);
result = hRESULT;
return result;
} finally {
comScope.Dispose();
}
}
internal static bool IsObjectOnClipboard(object object, int retryTimes = 10, int retryDelay = 100)
{
if (object != null) {
ComScope<IDataObject> proxyDataObject;
object originalObject;
HRESULT hRESULT = TryGetData(out proxyDataObject, out originalObject, retryTimes, retryDelay);
ComScope<IDataObject> comScope = proxyDataObject;
try {
return hRESULT.Succeeded && object == originalObject;
} finally {
comScope.Dispose();
}
}
return false;
}
internal unsafe static HRESULT GetDataObject<TDataObject, TIDataObject>([Nullable(2)] out TIDataObject dataObject, int retryTimes = 10, int retryDelay = 100) where TDataObject : class, IDataObjectInternal<TDataObject, TIDataObject>, TIDataObject where TIDataObject : class
{
dataObject = null;
ComScope<IDataObject> proxyDataObject;
object originalObject;
HRESULT result = ClipboardCore<TOleServices>.TryGetData(out proxyDataObject, out originalObject, retryTimes, retryDelay);
ComScope<IDataObject> comScope = proxyDataObject;
try {
if (!result.Failed) {
TDataObject val = originalObject as TDataObject;
if (val == null || !((IDataObjectInternal<TDataObject, TIDataObject>)val).TryUnwrapUserDataObject(out TIDataObject dataObject2)) {
TIDataObject obj = (TIDataObject)((IDataObjectInternal<TDataObject, TIDataObject>)dataObject).Create(proxyDataObject.Value);
*(TIDataObject*)(long)(IntPtr)(void*) = obj;
return result;
}
dataObject = dataObject2;
return result;
}
return result;
} finally {
comScope.Dispose();
}
}
internal static bool IsValidTypeForFormat(Type type, string format)
{
if (string.IsNullOrWhiteSpace(format))
return false;
if (<IsValidTypeForFormat>g__IsValidPredefinedFormatTypeCombination|8_0(format, type))
return true;
throw new NotSupportedException(string.Format(System.Private.Windows.Core.Resources.SR.ClipboardOrDragDrop_InvalidFormatTypeCombination, type.FullName, format));
}
internal static void SetFileDropList(StringCollection filePaths)
{
IComVisibleDataObject dataObject = ((IOleServices)).CreateDataObject();
dataObject.SetFileDropList(filePaths);
SetData(dataObject, true, 10, 100);
}
}
}