diff --git a/PInvoke/CldApi/cfapi.Funcs.cs b/PInvoke/CldApi/cfapi.Funcs.cs
index 9f57e2ab..5d22fa54 100644
--- a/PInvoke/CldApi/cfapi.Funcs.cs
+++ b/PInvoke/CldApi/cfapi.Funcs.cs
@@ -377,7 +377,7 @@ namespace Vanara.PInvoke
// InfoBuffer, DWORD InfoBufferLength, PDWORD ReturnedLength );
[DllImport(Lib.CldApi, SetLastError = false, ExactSpelling = true)]
[PInvokeData("cfapi.h", MSDNShortId = "B7FE94BC-DC59-407D-85A6-9657E38975AB")]
- public static extern HRESULT CfGetPlaceholderRangeInfo(HFILE FileHandle, CF_PLACEHOLDER_RANGE_INFO_CLASS InfoClass, long StartingOffset, long Length, [Out] IntPtr InfoBuffer, uint InfoBufferLength, ref uint ReturnedLength);
+ public static extern HRESULT CfGetPlaceholderRangeInfo(HFILE FileHandle, CF_PLACEHOLDER_RANGE_INFO_CLASS InfoClass, long StartingOffset, long Length, [Out] IntPtr InfoBuffer, uint InfoBufferLength, out uint ReturnedLength);
/// Gets a set of placeholder states based on the FileAttributes and ReparseTag values of the file.
/// The file attribute information.
@@ -679,7 +679,7 @@ namespace Vanara.PInvoke
// FileHandle, CF_TRANSFER_KEY *TransferKey );
[DllImport(Lib.CldApi, SetLastError = false, ExactSpelling = true)]
[PInvokeData("cfapi.h", MSDNShortId = "53B40C34-EB1F-445B-B1B3-B539C2FADECE")]
- public static extern void CfReleaseTransferKey(HFILE FileHandle, out CF_TRANSFER_KEY TransferKey);
+ public static extern void CfReleaseTransferKey(HFILE FileHandle, in CF_TRANSFER_KEY TransferKey);
/// Allows a sync provider to report progress out-of-band.
/// A connection key representing a communication channel with the sync filter.
diff --git a/PInvoke/CldApi/cfapi.cs b/PInvoke/CldApi/cfapi.cs
index 959f86f8..524fc1d4 100644
--- a/PInvoke/CldApi/cfapi.cs
+++ b/PInvoke/CldApi/cfapi.cs
@@ -147,7 +147,7 @@ namespace Vanara.PInvoke
CF_CALLBACK_FETCH_DATA_FLAG_RECOVERY = 1,
///
- /// Note This value is new for Windows 10, version 1803.Flag to be used if the callback is invoked as a result of a call to CfHydratePlaceholder.
+ /// Note This value is new for Windows 10, version 1803. Flag to be used if the callback is invoked as a result of a call to CfHydratePlaceholder.
///
CF_CALLBACK_FETCH_DATA_FLAG_EXPLICIT_HYDRATION = 2,
}
@@ -1342,51 +1342,53 @@ namespace Vanara.PInvoke
// CF_CALLBACK_DELETE_COMPLETION_FLAGS Flags; } DeleteCompletion; struct { CF_CALLBACK_RENAME_FLAGS Flags; PCWSTR TargetPath; }
// Rename; struct { CF_CALLBACK_RENAME_COMPLETION_FLAGS Flags; PCWSTR SourcePath; } RenameCompletion; } DUMMYUNIONNAME; } CF_CALLBACK_PARAMETERS;
[PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
- [StructLayout(LayoutKind.Sequential, Pack = 8)]
+ [StructLayout(LayoutKind.Sequential)]
public struct CF_CALLBACK_PARAMETERS
{
///
public uint ParamSize;
+ private uint pad;
+
///
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 56)]
public byte[] Content;
///
- public CF_CALLBACK_PARAMETERS_CANCEL Cancel => GetParam();
+ public CANCEL Cancel => GetParam();
///
- public CF_CALLBACK_PARAMETERS_FETCHDATA FetchData => GetParam();
+ public FETCHDATA FetchData => GetParam();
///
- public CF_CALLBACK_PARAMETERS_VALIDATEDATA ValidateData => GetParam();
+ public VALIDATEDATA ValidateData => GetParam();
///
- public CF_CALLBACK_PARAMETERS_FETCHPLACEHOLDERS FetchPlaceholders => GetParam();
+ public FETCHPLACEHOLDERS FetchPlaceholders => GetParam();
///
- public CF_CALLBACK_PARAMETERS_OPENCOMPLETION OpenCompletion => GetParam();
+ public OPENCOMPLETION OpenCompletion => GetParam();
///
- public CF_CALLBACK_PARAMETERS_CLOSECOMPLETION CloseCompletion => GetParam();
+ public CLOSECOMPLETION CloseCompletion => GetParam();
///
- public CF_CALLBACK_PARAMETERS_DEHYDRATE Dehydrate => GetParam();
+ public DEHYDRATE Dehydrate => GetParam();
///
- public CF_CALLBACK_PARAMETERS_DEHYDRATECOMPLETION DehydrateCompletion => GetParam();
+ public DEHYDRATECOMPLETION DehydrateCompletion => GetParam();
///
- public CF_CALLBACK_PARAMETERS_DELETE Delete => GetParam();
+ public DELETE Delete => GetParam();
///
- public CF_CALLBACK_PARAMETERS_DELETECOMPLETION DeleteCompletion => GetParam();
+ public DELETECOMPLETION DeleteCompletion => GetParam();
///
- public CF_CALLBACK_PARAMETERS_RENAME Rename => GetParam();
+ public RENAME Rename => GetParam();
///
- public CF_CALLBACK_PARAMETERS_RENAMECOMPLETION RenameCompletion => GetParam();
+ public RENAMECOMPLETION RenameCompletion => GetParam();
/// Gets the parameter value for this structure.
/// The type of the structure to retrieve.
@@ -1396,180 +1398,180 @@ namespace Vanara.PInvoke
using var ptr = new SafeHGlobalHandle(Content);
return ptr.ToStructure();
}
- }
- /// Contains callback specific parameters such as file offset, length, flags, etc.
- [PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
- [StructLayout(LayoutKind.Sequential, Pack = 8)]
- public struct CF_CALLBACK_PARAMETERS_CANCEL
- {
- /// Cancel data flags.
- public CF_CALLBACK_CANCEL_FLAGS Flags;
-
- ///
- public CANCELFETCHDATA FetchData;
-
- ///
- [StructLayout(LayoutKind.Sequential)]
- public struct CANCELFETCHDATA
+ /// Contains callback specific parameters such as file offset, length, flags, etc.
+ [PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
+ [StructLayout(LayoutKind.Sequential, Pack = 8)]
+ public struct CANCEL
{
- /// Offset, in bytes, for specifying the range of data.
- public long FileOffset;
+ /// Cancel data flags.
+ public CF_CALLBACK_CANCEL_FLAGS Flags;
- /// Length of the data in bytes.
- public long Length;
+ ///
+ public CANCELFETCHDATA FetchData;
+
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ public struct CANCELFETCHDATA
+ {
+ /// Offset, in bytes, for specifying the range of data.
+ public long FileOffset;
+
+ /// Length of the data in bytes.
+ public long Length;
+ }
}
- }
- /// Contains callback specific parameters such as file offset, length, flags, etc.
- [PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
- [StructLayout(LayoutKind.Sequential)]
- public struct CF_CALLBACK_PARAMETERS_CLOSECOMPLETION
- {
- /// Placeholder close completion flags.
- public CF_CALLBACK_CLOSE_COMPLETION_FLAGS Flags;
- }
+ /// Contains callback specific parameters such as file offset, length, flags, etc.
+ [PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
+ [StructLayout(LayoutKind.Sequential)]
+ public struct CLOSECOMPLETION
+ {
+ /// Placeholder close completion flags.
+ public CF_CALLBACK_CLOSE_COMPLETION_FLAGS Flags;
+ }
- /// Contains callback specific parameters such as file offset, length, flags, etc.
- [PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
- [StructLayout(LayoutKind.Sequential)]
- public struct CF_CALLBACK_PARAMETERS_DEHYDRATE
- {
- /// Placeholder dehydration flags.
- public CF_CALLBACK_DEHYDRATE_FLAGS Flags;
+ /// Contains callback specific parameters such as file offset, length, flags, etc.
+ [PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
+ [StructLayout(LayoutKind.Sequential)]
+ public struct DEHYDRATE
+ {
+ /// Placeholder dehydration flags.
+ public CF_CALLBACK_DEHYDRATE_FLAGS Flags;
- ///
- public CF_CALLBACK_DEHYDRATION_REASON Reason;
- }
+ ///
+ public CF_CALLBACK_DEHYDRATION_REASON Reason;
+ }
- /// Contains callback specific parameters such as file offset, length, flags, etc.
- [PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
- [StructLayout(LayoutKind.Sequential)]
- public struct CF_CALLBACK_PARAMETERS_DEHYDRATECOMPLETION
- {
- ///
- public CF_CALLBACK_DEHYDRATE_COMPLETION_FLAGS Flags;
+ /// Contains callback specific parameters such as file offset, length, flags, etc.
+ [PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
+ [StructLayout(LayoutKind.Sequential)]
+ public struct DEHYDRATECOMPLETION
+ {
+ ///
+ public CF_CALLBACK_DEHYDRATE_COMPLETION_FLAGS Flags;
- ///
- public CF_CALLBACK_DEHYDRATION_REASON Reason;
- }
+ ///
+ public CF_CALLBACK_DEHYDRATION_REASON Reason;
+ }
- /// Contains callback specific parameters such as file offset, length, flags, etc.
- [PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
- [StructLayout(LayoutKind.Sequential)]
- public struct CF_CALLBACK_PARAMETERS_DELETE
- {
- /// Placeholder deletion flags.
- public CF_CALLBACK_DELETE_FLAGS Flags;
- }
+ /// Contains callback specific parameters such as file offset, length, flags, etc.
+ [PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
+ [StructLayout(LayoutKind.Sequential)]
+ public struct DELETE
+ {
+ /// Placeholder deletion flags.
+ public CF_CALLBACK_DELETE_FLAGS Flags;
+ }
- /// Contains callback specific parameters such as file offset, length, flags, etc.
- [PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
- [StructLayout(LayoutKind.Sequential, Pack = 4)]
- public struct CF_CALLBACK_PARAMETERS_DELETECOMPLETION
- {
- /// Placeholder deletion complete flags.
- public CF_CALLBACK_DELETE_COMPLETION_FLAGS Flags;
- }
+ /// Contains callback specific parameters such as file offset, length, flags, etc.
+ [PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
+ [StructLayout(LayoutKind.Sequential)]
+ public struct DELETECOMPLETION
+ {
+ /// Placeholder deletion complete flags.
+ public CF_CALLBACK_DELETE_COMPLETION_FLAGS Flags;
+ }
- /// Contains callback specific parameters such as file offset, length, flags, etc.
- [PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
- [StructLayout(LayoutKind.Sequential, Pack = 4, Size = 56)]
- public struct CF_CALLBACK_PARAMETERS_FETCHDATA
- {
- /// Fetch data flags.
- public CF_CALLBACK_FETCH_DATA_FLAGS Flags;
+ /// Contains callback specific parameters such as file offset, length, flags, etc.
+ [PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
+ [StructLayout(LayoutKind.Sequential)]
+ public struct FETCHDATA
+ {
+ /// Fetch data flags.
+ public CF_CALLBACK_FETCH_DATA_FLAGS Flags;
- /// Offset, in bytes, for specifying the required range of data.
- public long RequiredFileOffset;
+ /// Offset, in bytes, for specifying the required range of data.
+ public long RequiredFileOffset;
- /// Length of the required data to retrieve, in bytes.
- public long RequiredLength;
+ /// Length of the required data to retrieve, in bytes.
+ public long RequiredLength;
- ///
- /// Offset, in bytes, of a broader piece of data to provide to a sync provider. This is optional and can be used if the sync
- /// provider prefers to work with larger segments of data.
- ///
- public long OptionalFileOffset;
+ ///
+ /// Offset, in bytes, of a broader piece of data to provide to a sync provider. This is optional and can be used if the sync
+ /// provider prefers to work with larger segments of data.
+ ///
+ public long OptionalFileOffset;
- ///
- /// Length, in bytes, of a broader piece of data to provide to a sync provider. This is optional and can be used if the sync
- /// provider prefers to work with larger segments of data.
- ///
- public long OptionalLength;
+ ///
+ /// Length, in bytes, of a broader piece of data to provide to a sync provider. This is optional and can be used if the sync
+ /// provider prefers to work with larger segments of data.
+ ///
+ public long OptionalLength;
- ///
- public long LastDehydrationTime;
+ ///
+ public long LastDehydrationTime;
- ///
- public CF_CALLBACK_DEHYDRATION_REASON LastDehydrationReason;
- }
+ ///
+ public CF_CALLBACK_DEHYDRATION_REASON LastDehydrationReason;
+ }
- /// Contains callback specific parameters such as file offset, length, flags, etc.
- [PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
- [StructLayout(LayoutKind.Sequential, Pack = 8)]
- public struct CF_CALLBACK_PARAMETERS_FETCHPLACEHOLDERS
- {
- /// Flags for fetching placeholder metadata.
- public CF_CALLBACK_FETCH_PLACEHOLDERS_FLAGS Flags;
+ /// Contains callback specific parameters such as file offset, length, flags, etc.
+ [PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
+ [StructLayout(LayoutKind.Sequential)]
+ public struct FETCHPLACEHOLDERS
+ {
+ /// Flags for fetching placeholder metadata.
+ public CF_CALLBACK_FETCH_PLACEHOLDERS_FLAGS Flags;
- ///
- /// A standard Windows file pattern which may contain wildcard characters (‘?’, ‘*’). All placeholders information matching the
- /// pattern must be transferred, but not necessarily in one-shot, as a minimum requirement. Alternatively, a sync provider may
- /// choose to not transfer placeholders matching the pattern.
- ///
- [MarshalAs(UnmanagedType.LPWStr)]
- public string Pattern;
- }
+ ///
+ /// A standard Windows file pattern which may contain wildcard characters (‘?’, ‘*’). All placeholders information matching the
+ /// pattern must be transferred, but not necessarily in one-shot, as a minimum requirement. Alternatively, a sync provider may
+ /// choose to not transfer placeholders matching the pattern.
+ ///
+ [MarshalAs(UnmanagedType.LPWStr)]
+ public string Pattern;
+ }
- /// Contains callback specific parameters such as file offset, length, flags, etc.
- [PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
- [StructLayout(LayoutKind.Sequential)]
- public struct CF_CALLBACK_PARAMETERS_OPENCOMPLETION
- {
- /// Placeholder open completion flags.
- public CF_CALLBACK_OPEN_COMPLETION_FLAGS Flags;
- }
+ /// Contains callback specific parameters such as file offset, length, flags, etc.
+ [PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
+ [StructLayout(LayoutKind.Sequential)]
+ public struct OPENCOMPLETION
+ {
+ /// Placeholder open completion flags.
+ public CF_CALLBACK_OPEN_COMPLETION_FLAGS Flags;
+ }
- /// Contains callback specific parameters such as file offset, length, flags, etc.
- [PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
- [StructLayout(LayoutKind.Sequential, Pack = 8)]
- public struct CF_CALLBACK_PARAMETERS_RENAME
- {
- /// Rename placeholder flags.
- public CF_CALLBACK_RENAME_FLAGS Flags;
+ /// Contains callback specific parameters such as file offset, length, flags, etc.
+ [PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
+ [StructLayout(LayoutKind.Sequential)]
+ public struct RENAME
+ {
+ /// Rename placeholder flags.
+ public CF_CALLBACK_RENAME_FLAGS Flags;
- /// The full rename/move target path relative to the volume.
- [MarshalAs(UnmanagedType.LPWStr)]
- public string TargetPath;
- }
+ /// The full rename/move target path relative to the volume.
+ [MarshalAs(UnmanagedType.LPWStr)]
+ public string TargetPath;
+ }
- /// Contains callback specific parameters such as file offset, length, flags, etc.
- [PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
- [StructLayout(LayoutKind.Sequential, Pack = 8)]
- public struct CF_CALLBACK_PARAMETERS_RENAMECOMPLETION
- {
- /// Rename completion placeholder flags.
- public CF_CALLBACK_RENAME_COMPLETION_FLAGS Flags;
+ /// Contains callback specific parameters such as file offset, length, flags, etc.
+ [PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
+ [StructLayout(LayoutKind.Sequential)]
+ public struct RENAMECOMPLETION
+ {
+ /// Rename completion placeholder flags.
+ public CF_CALLBACK_RENAME_COMPLETION_FLAGS Flags;
- /// The full source link path relative to the volume.
- [MarshalAs(UnmanagedType.LPWStr)]
- public string SourcePath;
- }
+ /// The full source link path relative to the volume.
+ [MarshalAs(UnmanagedType.LPWStr)]
+ public string SourcePath;
+ }
- /// Contains callback specific parameters such as file offset, length, flags, etc.
- [PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
- [StructLayout(LayoutKind.Sequential, Pack = 8)]
- public struct CF_CALLBACK_PARAMETERS_VALIDATEDATA
- {
- /// Data validation flags.
- public CF_CALLBACK_VALIDATE_DATA_FLAGS Flags;
+ /// Contains callback specific parameters such as file offset, length, flags, etc.
+ [PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
+ [StructLayout(LayoutKind.Sequential)]
+ public struct VALIDATEDATA
+ {
+ /// Data validation flags.
+ public CF_CALLBACK_VALIDATE_DATA_FLAGS Flags;
- /// Offset, in bytes, for specifying the range of data to validate.
- public long RequiredFileOffset;
+ /// Offset, in bytes, for specifying the range of data to validate.
+ public long RequiredFileOffset;
- /// Length, in bytes, of the data to validate.
- public long RequiredLength;
+ /// Length, in bytes, of the data to validate.
+ public long RequiredLength;
+ }
}
/// The callbacks to be registered by the sync provider.
@@ -1721,13 +1723,83 @@ namespace Vanara.PInvoke
// FileIdentityLength; } AckDehydrate; struct { CF_OPERATION_ACK_RENAME_FLAGS Flags; NTSTATUS CompletionStatus; } AckRename; struct
// { CF_OPERATION_ACK_DELETE_FLAGS Flags; NTSTATUS CompletionStatus; } AckDelete; } DUMMYUNIONNAME; } CF_OPERATION_PARAMETERS;
[PInvokeData("cfapi.h", MSDNShortId = "668C682E-47C2-41BC-A4F9-AA2F2B516F54")]
- [StructLayout(LayoutKind.Explicit)]
+ [StructLayout(LayoutKind.Sequential)]
public struct CF_OPERATION_PARAMETERS
{
///
- [FieldOffset(0)]
public uint ParamSize;
+ // Yes, this is strange, but needed to deal with struct size changing based on pointer size (40/48).
+ private uint pad4_8;
+ private ulong pad8_16;
+ private ulong pad16_24;
+ private ulong pad24_32;
+ private IntPtr padp1;
+ private IntPtr padp2;
+
+ ///
+ public TRANSFERDATA TransferData { get => GetParam(); set => SetParam(value); }
+
+ ///
+ public RETRIEVEDATA RetrieveData { get => GetParam(); set => SetParam(value); }
+
+ ///
+ public ACKDATA AckData { get => GetParam(); set => SetParam(value); }
+
+ ///
+ public RESTARTHYDRATION RestartHydration { get => GetParam(); set => SetParam(value); }
+
+ ///
+ public TRANSFERPLACEHOLDERS TransferPlaceholders { get => GetParam(); set => SetParam(value); }
+
+ ///
+ public ACKDEHYDRATE AckDehydrate { get => GetParam(); set => SetParam(value); }
+
+ ///
+ public ACKRENAME AckRename { get => GetParam(); set => SetParam(value); }
+
+ ///
+ public ACKDELETE AckDelete { get => GetParam(); set => SetParam(value); }
+
+ /// Gets the parameter value for this structure.
+ /// The type of the structure to retrieve.
+ /// The requested structure.
+ public unsafe T GetParam() where T : struct
+ {
+ using var ptr = new PinnedObject(this);
+ return ((IntPtr)ptr).ToStructure(Marshal.SizeOf(typeof(CF_OPERATION_PARAMETERS)), 8);
+ }
+
+ /// Sets the parameter value for this structure.
+ /// The type of the structure to set.
+ /// The value to set.
+ public void SetParam(T value) where T : struct
+ {
+ unsafe
+ {
+ fixed (ulong* p = &pad8_16)
+ {
+ ((IntPtr)(void*)p).Write(value, 0, Marshal.SizeOf(typeof(CF_OPERATION_PARAMETERS)) - 8);
+ }
+ }
+ }
+
+ /// Creates a CF_OPERATION_PARAMETERS instance with the specified parameter value.
+ /// The parameter type.
+ /// The parameter value.
+ /// A CF_OPERATION_PARAMETERS instance initialized with and the correct ParamSize.
+ public static CF_OPERATION_PARAMETERS Create(T paramValue = default) where T : struct
+ {
+ var op = new CF_OPERATION_PARAMETERS { ParamSize = CF_SIZE_OF_OP_PARAM() };
+ op.SetParam(paramValue);
+ return op;
+ }
+
+ /// Gets the size value used in ParamSize given a specific parameter type.
+ /// The parameter type.
+ /// The size of the structure.
+ public static uint CF_SIZE_OF_OP_PARAM() where T : struct => (uint)(Marshal.OffsetOf(typeof(CF_OPERATION_PARAMETERS), nameof(pad8_16)).ToInt32() + Marshal.SizeOf(typeof(T)));
+
///
[StructLayout(LayoutKind.Sequential)]
public struct TRANSFERDATA
@@ -1748,10 +1820,6 @@ namespace Vanara.PInvoke
public long Length;
}
- ///
- [FieldOffset(4)]
- public TRANSFERDATA TransferData;
-
///
[StructLayout(LayoutKind.Sequential)]
public struct RETRIEVEDATA
@@ -1772,10 +1840,6 @@ namespace Vanara.PInvoke
public long ReturnedLength;
}
- ///
- [FieldOffset(4)]
- public RETRIEVEDATA RetrieveData;
-
///
[StructLayout(LayoutKind.Sequential)]
public struct ACKDATA
@@ -1796,10 +1860,6 @@ namespace Vanara.PInvoke
public long Length;
}
- ///
- [FieldOffset(4)]
- public ACKDATA AckData;
-
///
[StructLayout(LayoutKind.Sequential)]
public struct RESTARTHYDRATION
@@ -1817,10 +1877,6 @@ namespace Vanara.PInvoke
public uint FileIdentityLength;
}
- ///
- [FieldOffset(4)]
- public RESTARTHYDRATION RestartHydration;
-
///
[StructLayout(LayoutKind.Sequential)]
public struct TRANSFERPLACEHOLDERS
@@ -1844,10 +1900,6 @@ namespace Vanara.PInvoke
public uint EntriesProcessed;
}
- ///
- [FieldOffset(4)]
- public TRANSFERPLACEHOLDERS TransferPlaceholders;
-
///
[StructLayout(LayoutKind.Sequential)]
public struct ACKDEHYDRATE
@@ -1865,10 +1917,6 @@ namespace Vanara.PInvoke
public uint FileIdentityLength;
}
- ///
- [FieldOffset(4)]
- public ACKDEHYDRATE AckDehydrate;
-
///
[StructLayout(LayoutKind.Sequential)]
public struct ACKRENAME
@@ -1880,10 +1928,6 @@ namespace Vanara.PInvoke
public NTStatus CompletionStatus;
}
- ///
- [FieldOffset(4)]
- public ACKRENAME AckRename;
-
///
[StructLayout(LayoutKind.Sequential)]
public struct ACKDELETE
@@ -1894,10 +1938,6 @@ namespace Vanara.PInvoke
/// The completion status of the operation.
public NTStatus CompletionStatus;
}
-
- ///
- [FieldOffset(4)]
- public ACKDELETE AckDelete;
}
/// Basic placeholder information.
diff --git a/UnitTests/PInvoke/CldApi/CldApiTests.cs b/UnitTests/PInvoke/CldApi/CldApiTests.cs
index 2caefd2e..9ed04b71 100644
--- a/UnitTests/PInvoke/CldApi/CldApiTests.cs
+++ b/UnitTests/PInvoke/CldApi/CldApiTests.cs
@@ -2,9 +2,13 @@ using ICSharpCode.Decompiler.TypeSystem;
using NUnit.Framework;
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
+using System.Threading;
+using System.Threading.Tasks;
+using Vanara.Extensions;
using Vanara.InteropServices;
using Windows.Storage.Streams;
using static Vanara.PInvoke.CldApi;
@@ -32,6 +36,16 @@ namespace Vanara.PInvoke.Tests
try
{
using var csp = new CloudSyncProvider(destDirPath, "TestSync");
+ csp.Status = CF_SYNC_PROVIDER_STATUS.CF_PROVIDER_STATUS_IDLE;
+ csp.Status.WriteValues();
+
+ const string desc = "SyncStatus is good.";
+ uint descLen = (uint)(desc.Length + 1) * 2;
+ var ss = new CF_SYNC_STATUS { StructSize = (uint)Marshal.SizeOf() + descLen, Code = 1, DescriptionLength = descLen };
+ var mem = new SafeHGlobalHandle(Marshal.SizeOf() + descLen);
+ mem.Write(ss);
+ StringHelper.Write(desc, ((IntPtr)mem).Offset(Marshal.SizeOf()), out _, true, CharSet.Unicode, descLen);
+ Assert.That(CfReportSyncStatus(destDirPath, mem), ResultIs.Successful);
}
finally
{
@@ -43,28 +57,86 @@ namespace Vanara.PInvoke.Tests
public void CfCreatePlaceholdersTest()
{
const string dest = "CfDest";
+ const string fname = "test.bmp";
var destDirPath = SetupTempDir(dest);
+ var fpath = Path.Combine(destDirPath, fname);
try
{
- using var csp = new CloudSyncProvider(destDirPath, "TestSync");
+ var tokSrc = new CancellationTokenSource();
+ var token = tokSrc.Token;
+ var task = Task.Run(() =>
+ {
+ using var csp = new CloudSyncProvider(destDirPath, "TestSync");
- csp.CancelFetchData += (s, e) => { TestContext.WriteLine($"CancelFetchData: {e.NormalizedPath}, {e.FileSize}"); e.ParamData.WriteValues(); };
- csp.CancelFetchPlaceholders += (s, e) => { TestContext.WriteLine($"CancelFetchPlaceholders: {e.NormalizedPath}, {e.FileSize}"); e.ParamData.WriteValues(); };
- csp.FetchData += (s, e) => { TestContext.WriteLine($"FetchData: {e.NormalizedPath}, {e.FileSize}"); e.ParamData.WriteValues(); };
- csp.FetchPlaceholders += (s, e) => { TestContext.WriteLine($"FetchPlaceholders: {e.NormalizedPath}, {e.FileSize}"); e.ParamData.WriteValues(); };
- csp.NotifyDehydrate += (s, e) => { TestContext.WriteLine($"NotifyDehydrate: {e.NormalizedPath}, {e.FileSize}"); e.ParamData.WriteValues(); };
- csp.NotifyDehydrateCompletion += (s, e) => { TestContext.WriteLine($"NotifyDehydrateCompletion: {e.NormalizedPath}, {e.FileSize}"); e.ParamData.WriteValues(); };
- csp.NotifyDelete += (s, e) => { TestContext.WriteLine($"NotifyDelete: {e.NormalizedPath}, {e.FileSize}"); e.ParamData.WriteValues(); };
- csp.NotifyDeleteCompletion += (s, e) => { TestContext.WriteLine($"NotifyDeleteCompletion: {e.NormalizedPath}, {e.FileSize}"); e.ParamData.WriteValues(); };
- csp.NotifyFileCloseCompletion += (s, e) => { TestContext.WriteLine($"NotifyFileCloseCompletion: {e.NormalizedPath}, {e.FileSize}"); e.ParamData.WriteValues(); };
- csp.NotifyFileOpenCompletion += (s, e) => { TestContext.WriteLine($"NotifyFileOpenCompletion: {e.NormalizedPath}, {e.FileSize}"); e.ParamData.WriteValues(); };
- csp.NotifyRename += (s, e) => { TestContext.WriteLine($"NotifyRename: {e.NormalizedPath}, {e.FileSize}"); e.ParamData.WriteValues(); };
- csp.NotifyRenameCompletion += (s, e) => { TestContext.WriteLine($"NotifyRenameCompletion: {e.NormalizedPath}, {e.FileSize}"); e.ParamData.WriteValues(); };
- csp.ValidateData += (s, e) => { TestContext.WriteLine($"ValidateData: {e.NormalizedPath}, {e.FileSize}"); e.ParamData.WriteValues(); };
+ csp.CancelFetchData += ShowInfo;
+ csp.CancelFetchPlaceholders += ShowInfo;
+ csp.FetchData += ShowInfo;
+ csp.FetchPlaceholders += ShowInfo;
+ csp.NotifyDehydrate += ShowInfo;
+ csp.NotifyDehydrateCompletion += ShowInfo;
+ csp.NotifyDelete += ShowInfo;
+ csp.NotifyDeleteCompletion += ShowInfo;
+ csp.NotifyFileCloseCompletion += ShowInfo;
+ csp.NotifyFileOpenCompletion += ShowInfo;
+ csp.NotifyRename += ShowInfo;
+ csp.NotifyRenameCompletion += ShowInfo;
+ csp.ValidateData += ShowInfo;
- csp.CreatePlaceholderFromFile("test.bmp", new FileInfo(TestCaseSources.BmpFile), true);
- Assert.That(File.Exists(Path.Combine(destDirPath, "test.bmp")), Is.True);
- Assert.That(new FileInfo(Path.Combine(destDirPath, "test.bmp")).Length, Is.EqualTo(new FileInfo(TestCaseSources.BmpFile).Length));
+ var origFileInfo = new FileInfo(TestCaseSources.BmpFile);
+ csp.CreatePlaceholderFromFile(fname, origFileInfo, true);
+ Assert.That(File.Exists(fpath), Is.True);
+ Assert.That(new FileInfo(fpath).Length, Is.EqualTo(origFileInfo.Length));
+
+ Debug.WriteLine("CSP is running...................................\n");
+
+ while (!token.IsCancellationRequested) { Thread.Sleep(100); }
+
+ static void ShowInfo(object s, CloudSyncCallbackArgs e) where T : struct
+ {
+ Debug.WriteLine($"\n{typeof(T).Name}: {e.NormalizedPath ?? "(null)"}, {e.FileSize}\n" +
+ Newtonsoft.Json.JsonConvert.SerializeObject(e.ParamData, Newtonsoft.Json.Formatting.Indented, new Newtonsoft.Json.Converters.StringEnumConverter()));
+
+ if (typeof(T) == typeof(CF_CALLBACK_PARAMETERS.RENAME))
+ {
+ e.OperationType = CF_OPERATION_TYPE.CF_OPERATION_TYPE_ACK_RENAME;
+ e.OpParam = CF_OPERATION_PARAMETERS.Create(new CF_OPERATION_PARAMETERS.ACKRENAME());
+ }
+ else if (typeof(T) == typeof(CF_CALLBACK_PARAMETERS.DEHYDRATE))
+ {
+ e.OperationType = CF_OPERATION_TYPE.CF_OPERATION_TYPE_ACK_DEHYDRATE;
+ e.OpParam = CF_OPERATION_PARAMETERS.Create(new CF_OPERATION_PARAMETERS.ACKDEHYDRATE());
+ }
+ else if (typeof(T) == typeof(CF_CALLBACK_PARAMETERS.DELETE))
+ {
+ e.OperationType = CF_OPERATION_TYPE.CF_OPERATION_TYPE_ACK_DELETE;
+ e.OpParam = CF_OPERATION_PARAMETERS.Create(new CF_OPERATION_PARAMETERS.ACKDELETE());
+ }
+ else if (typeof(T) == typeof(CF_CALLBACK_PARAMETERS.FETCHDATA))
+ {
+ var opInfo = e.MakeOpInfo(CF_OPERATION_TYPE.CF_OPERATION_TYPE_TRANSFER_DATA);
+ using var buf = new PinnedObject(File.ReadAllBytes(TestCaseSources.BmpFile));
+ var opParam = CF_OPERATION_PARAMETERS.Create(new CF_OPERATION_PARAMETERS.TRANSFERDATA { Buffer = buf, Length = new FileInfo(TestCaseSources.BmpFile).Length });
+ var hr = CfExecute(opInfo, ref opParam);
+ if (hr.Failed) Debug.WriteLine("CfExecute for transfer failed: " + hr.FormatMessage());
+ hr = CfReportProviderProgress(e.ConnectionKey, e.TransferKey, 100, 100);
+ if (hr.Failed) Debug.WriteLine("CfReportProviderProgress for transfer failed: " + hr.FormatMessage());
+ }
+ }
+ }, tokSrc.Token);
+
+ Thread.Sleep(5000); // Let CSP get loaded
+ using var hFile = GetHFILE(fpath);
+ Assert.That(CfHydratePlaceholder(hFile, 0, -1, 0), ResultIs.Successful);
+ Assert.That(CfGetCorrelationVector(hFile, out var cv), ResultIs.Successful);
+ using var buf = new SafeHGlobalHandle(128);
+ Assert.That(CfGetPlaceholderRangeInfo(hFile, CF_PLACEHOLDER_RANGE_INFO_CLASS.CF_PLACEHOLDER_RANGE_INFO_ONDISK, 0, buf.Size, buf, buf.Size, out var rngLen), ResultIs.Successful);
+ Assert.That(CfGetTransferKey(hFile, out var txKey), ResultIs.Successful);
+ Assert.That(() => CfReleaseTransferKey(hFile, txKey), Throws.Nothing);
+ Assert.That(CfDehydratePlaceholder(hFile, 0, -1, 0), ResultIs.Successful);
+ Thread.Sleep(2000); // Wait for user interaction
+
+ tokSrc.Cancel();
+ task.Wait();
//CfGetPlaceholderRangeInfo(hFile, CF_PLACEHOLDER_RANGE_INFO_CLASS.CF_PLACEHOLDER_RANGE_INFO_ONDISK, 0, )
//Assert.That(CfHydratePlaceholder(hFile, 0, -1, CF_HYDRATE_FLAGS.CF_HYDRATE_FLAG_NONE), ResultIs.Successful);
@@ -128,6 +200,55 @@ namespace Vanara.PInvoke.Tests
}
}
+ [Test]
+ public void CfSetInSyncStateTest()
+ {
+ const string dest = "CfDest";
+ var destDirPath = SetupTempDir(dest);
+ try
+ {
+ using var csp = new CloudSyncProvider(destDirPath, "TestSync");
+ csp.CreatePlaceholderFromFile("test.bmp", new FileInfo(TestCaseSources.BmpFile), true);
+ var destFile = Path.Combine(destDirPath, "test.bmp");
+ Assert.That(File.Exists(destFile), Is.True);
+
+ using var hFile = GetHFILE(destFile);
+ var usn = 0;
+ Assert.That(CfSetInSyncState(hFile, CF_IN_SYNC_STATE.CF_IN_SYNC_STATE_IN_SYNC, CF_SET_IN_SYNC_FLAGS.CF_SET_IN_SYNC_FLAG_NONE, ref usn), ResultIs.Successful);
+ Assert.That(CfSetPinState(hFile, CF_PIN_STATE.CF_PIN_STATE_PINNED, CF_SET_PIN_FLAGS.CF_SET_PIN_FLAG_NONE), ResultIs.Successful);
+ }
+ finally
+ {
+ DeleteTempDir(dest);
+ }
+ }
+
+ [Test]
+ public void CfGetPlaceholderStateFromAttributeTagTest()
+ {
+ const string dest = "CfDest";
+ var destDirPath = SetupTempDir(dest);
+ try
+ {
+ using var csp = new CloudSyncProvider(destDirPath, "TestSync");
+ var destFile = CopyFile(TestCaseSources.WordDoc, destDirPath);
+ Assert.That(() => csp.ConvertToPlaceholder(destFile), Throws.Nothing);
+
+ using var hFile = GetHFILE(destFile);
+ Kernel32.FILE_ATTRIBUTE_TAG_INFO info = default;
+ Assert.That(() => info = Kernel32.GetFileInformationByHandleEx(hFile, Kernel32.FILE_INFO_BY_HANDLE_CLASS.FileAttributeTagInfo), Throws.Nothing);
+ info.WriteValues();
+ CfGetPlaceholderStateFromAttributeTag(info.FileAttributes, info.ReparseTag).WriteValues();
+
+ using var mem = SafeHGlobalHandle.CreateFromStructure(info);
+ CfGetPlaceholderStateFromFileInfo(mem, Kernel32.FILE_INFO_BY_HANDLE_CLASS.FileAttributeTagInfo).WriteValues();
+ }
+ finally
+ {
+ DeleteTempDir(dest);
+ }
+ }
+
[Test]
public void CfGetPlatformInfoTest()
{
@@ -166,6 +287,9 @@ namespace Vanara.PInvoke.Tests
{
Assert.That(CfOpenFileWithOplock(TestCaseSources.SmallFile, CF_OPEN_FILE_FLAGS.CF_OPEN_FILE_FLAG_EXCLUSIVE, out var handle), ResultIs.Successful);
Assert.That(handle, ResultIs.ValidHandle);
+ Assert.That(CfReferenceProtectedHandle(handle), ResultIs.Successful);
+ Assert.That(CfGetWin32HandleFromProtectedHandle(handle), ResultIs.ValidHandle);
+ Assert.That(() => CfReleaseProtectedHandle(handle), Throws.Nothing);
Assert.That(() => handle.Dispose(), Throws.Nothing);
}
}
diff --git a/UnitTests/PInvoke/CldApi/CloudSyncProvider.cs b/UnitTests/PInvoke/CldApi/CloudSyncProvider.cs
index 43cf1b94..a3f1a6cd 100644
--- a/UnitTests/PInvoke/CldApi/CloudSyncProvider.cs
+++ b/UnitTests/PInvoke/CldApi/CloudSyncProvider.cs
@@ -1,7 +1,9 @@
-using System;
+using ICSharpCode.Decompiler.IL;
+using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Threading;
using System.Threading.Tasks;
@@ -20,6 +22,7 @@ namespace Vanara.PInvoke.Tests
{
public CloudSyncCallbackArgs(in CF_CALLBACK_INFO CallbackInfo, in CF_CALLBACK_PARAMETERS CallbackParameters)
{
+ //System.Diagnostics.Debug.WriteLine($"CloudSyncCallbackArgs<{typeof(T).Name}> : {string.Join(" ", CallbackParameters.Content.Select(b => b.ToString("X2")))}");
ConnectionKey = CallbackInfo.ConnectionKey;
CallbackContext = CallbackInfo.CallbackContext;
VolumeGuidName = CallbackInfo.VolumeGuidName;
@@ -33,10 +36,11 @@ namespace Vanara.PInvoke.Tests
NormalizedPath = CallbackInfo.NormalizedPath;
TransferKey = CallbackInfo.TransferKey;
PriorityHint = CallbackInfo.PriorityHint;
- CorrelationVector = CallbackInfo.CorrelationVector.ToNullableStructure();
+ pCorrelationVector = CallbackInfo.CorrelationVector;
ProcessInfo = CallbackInfo.ProcessInfo.ToNullableStructure();
RequestKey = CallbackInfo.RequestKey;
- ParamData = CallbackParameters.GetParam();
+ try { ParamData = CallbackParameters.GetParam(); } catch { }
+ //catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"{ex.Message}"); }
}
/// points to an opaque blob that the sync provider provides at the sync root connect time.
@@ -46,7 +50,10 @@ namespace Vanara.PInvoke.Tests
public CF_CONNECTION_KEY ConnectionKey { get; }
/// An optional correlation vector.
- public CORRELATION_VECTOR? CorrelationVector { get; }
+ public IntPtr pCorrelationVector { get; }
+
+ /// An optional correlation vector.
+ public CORRELATION_VECTOR? CorrelationVector => pCorrelationVector.ToNullableStructure();
/// A 64 bit file system maintained, volume-wide unique ID of the placeholder file/directory to be serviced.
public long FileId { get; }
@@ -66,6 +73,9 @@ namespace Vanara.PInvoke.Tests
/// Contains callback specific parameters for this action.
public T ParamData { get; }
+ /// Parameters of an operation on a placeholder file or folder.
+ public CF_OPERATION_PARAMETERS? OpParam { get; set; }
+
///
/// A numeric scale given to the sync provider to describe the relative priority of one fetch compared to another fetch, in order to
/// provide the most responsive experience to the user. The values range from 0 (lowest possible priority) to 15 (highest possible priority).
@@ -95,11 +105,40 @@ namespace Vanara.PInvoke.Tests
/// DOS drive letter of the volume in the form of “X:” where X is the drive letter.
public string VolumeDosName { get; }
- /// GUID name of the volume on which the placeholder file/directory to be serviced resides. It is in the form: “\?\Volume{GUID}”.
+ /// GUID name of the volume on which the placeholder file/directory to be serviced resides. It is in the form: "\?\Volume{GUID}".
public string VolumeGuidName { get; }
/// The serial number of the volume.
public uint VolumeSerialNumber { get; }
+
+ /// The type of operation performed.
+ public CF_OPERATION_TYPE OperationType { get; set; }
+
+ ///
+ /// This member is new for Windows 10, version 1803.
+ /// The current sync status of the platform.
+ ///
+ /// The platform queries this information upon any failed operations on a cloud file placeholder. If a structure is available, the
+ /// platform will use the information provided to construct a more meaningful and actionable message to the user. The platform will
+ /// keep this information on the file until the last handle on it goes away. If , the platform will clear the
+ /// previously set sync status, if there is one.
+ ///
+ ///
+ public IntPtr SyncStatus { get; set; }
+
+ /// Makes a CF_OPERATION_INFO instance from the properties.
+ /// Type of the operation to set.
+ /// A CF_OPERATION_INFO instance.
+ public CF_OPERATION_INFO MakeOpInfo(CF_OPERATION_TYPE opType, IntPtr syncStatus = default) => new CF_OPERATION_INFO
+ {
+ StructSize = (uint)Marshal.SizeOf(),
+ Type = opType,
+ ConnectionKey = ConnectionKey,
+ TransferKey = TransferKey,
+ CorrelationVector = pCorrelationVector,
+ RequestKey = RequestKey,
+ SyncStatus = syncStatus
+ };
}
public class PlaceHolderDirectoryInfo : PlaceholderInfo
@@ -197,31 +236,31 @@ namespace Vanara.PInvoke.Tests
ConnectSyncRootTransferCallbacks();
}
- public event EventHandler> CancelFetchData;
+ public event EventHandler> CancelFetchData;
- public event EventHandler> CancelFetchPlaceholders;
+ public event EventHandler> CancelFetchPlaceholders;
- public event EventHandler> FetchData;
+ public event EventHandler> FetchData;
- public event EventHandler> FetchPlaceholders;
+ public event EventHandler> FetchPlaceholders;
- public event EventHandler> NotifyDehydrate;
+ public event EventHandler> NotifyDehydrate;
- public event EventHandler> NotifyDehydrateCompletion;
+ public event EventHandler> NotifyDehydrateCompletion;
- public event EventHandler> NotifyDelete;
+ public event EventHandler> NotifyDelete;
- public event EventHandler> NotifyDeleteCompletion;
+ public event EventHandler> NotifyDeleteCompletion;
- public event EventHandler> NotifyFileCloseCompletion;
+ public event EventHandler> NotifyFileCloseCompletion;
- public event EventHandler> NotifyFileOpenCompletion;
+ public event EventHandler> NotifyFileOpenCompletion;
- public event EventHandler> NotifyRename;
+ public event EventHandler> NotifyRename;
- public event EventHandler> NotifyRenameCompletion;
+ public event EventHandler> NotifyRenameCompletion;
- public event EventHandler> ValidateData;
+ public event EventHandler> ValidateData;
public string DisplayName { get; }
@@ -231,6 +270,12 @@ namespace Vanara.PInvoke.Tests
public Uri RecycleBinUri { get; }
+ public CF_SYNC_PROVIDER_STATUS Status
+ {
+ get => CfQuerySyncProviderStatus(key.Value, out var stat).Succeeded ? stat : CF_SYNC_PROVIDER_STATUS.CF_PROVIDER_STATUS_ERROR;
+ set => CfUpdateSyncProviderStatus(key.Value, value);
+ }
+
public string SyncRootId { get; }
public string SyncRootPath { get; }
@@ -341,44 +386,46 @@ namespace Vanara.PInvoke.Tests
UnregisterWithShell();
}
- protected virtual void OnCancelFetchData(in CF_CALLBACK_INFO CallbackInfo, in CF_CALLBACK_PARAMETERS CallbackParameters) =>
- CancelFetchData?.Invoke(this, new CloudSyncCallbackArgs(CallbackInfo, CallbackParameters));
+ protected virtual void OnCancelFetchData(in CF_CALLBACK_INFO CallbackInfo, in CF_CALLBACK_PARAMETERS CallbackParameters) => HandleEvent(CancelFetchData, CallbackInfo, CallbackParameters);
- protected virtual void OnCancelFetchPlaceholders(in CF_CALLBACK_INFO CallbackInfo, in CF_CALLBACK_PARAMETERS CallbackParameters) =>
- CancelFetchPlaceholders?.Invoke(this, new CloudSyncCallbackArgs(CallbackInfo, CallbackParameters));
+ protected virtual void OnCancelFetchPlaceholders(in CF_CALLBACK_INFO CallbackInfo, in CF_CALLBACK_PARAMETERS CallbackParameters) => HandleEvent(CancelFetchPlaceholders, CallbackInfo, CallbackParameters);
- protected virtual void OnFetchData(in CF_CALLBACK_INFO CallbackInfo, in CF_CALLBACK_PARAMETERS CallbackParameters) =>
- FetchData?.Invoke(this, new CloudSyncCallbackArgs(CallbackInfo, CallbackParameters));
+ protected virtual void OnFetchData(in CF_CALLBACK_INFO CallbackInfo, in CF_CALLBACK_PARAMETERS CallbackParameters) => HandleEvent(FetchData, CallbackInfo, CallbackParameters);
- protected virtual void OnFetchPlaceholders(in CF_CALLBACK_INFO CallbackInfo, in CF_CALLBACK_PARAMETERS CallbackParameters) =>
- FetchPlaceholders?.Invoke(this, new CloudSyncCallbackArgs(CallbackInfo, CallbackParameters));
+ protected virtual void OnFetchPlaceholders(in CF_CALLBACK_INFO CallbackInfo, in CF_CALLBACK_PARAMETERS CallbackParameters) => HandleEvent(FetchPlaceholders, CallbackInfo, CallbackParameters);
- protected virtual void OnNotifyDehydrate(in CF_CALLBACK_INFO CallbackInfo, in CF_CALLBACK_PARAMETERS CallbackParameters) =>
- NotifyDehydrate?.Invoke(this, new CloudSyncCallbackArgs(CallbackInfo, CallbackParameters));
+ protected virtual void OnNotifyDehydrate(in CF_CALLBACK_INFO CallbackInfo, in CF_CALLBACK_PARAMETERS CallbackParameters) => HandleEvent(NotifyDehydrate, CallbackInfo, CallbackParameters);
- protected virtual void OnNotifyDehydrateCompletion(in CF_CALLBACK_INFO CallbackInfo, in CF_CALLBACK_PARAMETERS CallbackParameters) =>
- NotifyDehydrateCompletion?.Invoke(this, new CloudSyncCallbackArgs(CallbackInfo, CallbackParameters));
+ protected virtual void OnNotifyDehydrateCompletion(in CF_CALLBACK_INFO CallbackInfo, in CF_CALLBACK_PARAMETERS CallbackParameters) => HandleEvent(NotifyDehydrateCompletion, CallbackInfo, CallbackParameters);
- protected virtual void OnNotifyDelete(in CF_CALLBACK_INFO CallbackInfo, in CF_CALLBACK_PARAMETERS CallbackParameters) =>
- NotifyDelete?.Invoke(this, new CloudSyncCallbackArgs(CallbackInfo, CallbackParameters));
+ protected virtual void OnNotifyDelete(in CF_CALLBACK_INFO CallbackInfo, in CF_CALLBACK_PARAMETERS CallbackParameters) => HandleEvent(NotifyDelete, CallbackInfo, CallbackParameters);
- protected virtual void OnNotifyDeleteCompletion(in CF_CALLBACK_INFO CallbackInfo, in CF_CALLBACK_PARAMETERS CallbackParameters) =>
- NotifyDeleteCompletion?.Invoke(this, new CloudSyncCallbackArgs(CallbackInfo, CallbackParameters));
+ protected virtual void OnNotifyDeleteCompletion(in CF_CALLBACK_INFO CallbackInfo, in CF_CALLBACK_PARAMETERS CallbackParameters) => HandleEvent(NotifyDeleteCompletion, CallbackInfo, CallbackParameters);
- protected virtual void OnNotifyFileCloseCompletion(in CF_CALLBACK_INFO CallbackInfo, in CF_CALLBACK_PARAMETERS CallbackParameters) =>
- NotifyFileCloseCompletion?.Invoke(this, new CloudSyncCallbackArgs(CallbackInfo, CallbackParameters));
+ protected virtual void OnNotifyFileCloseCompletion(in CF_CALLBACK_INFO CallbackInfo, in CF_CALLBACK_PARAMETERS CallbackParameters) => HandleEvent(NotifyFileCloseCompletion, CallbackInfo, CallbackParameters);
- protected virtual void OnNotifyFileOpenCompletion(in CF_CALLBACK_INFO CallbackInfo, in CF_CALLBACK_PARAMETERS CallbackParameters) =>
- NotifyFileOpenCompletion?.Invoke(this, new CloudSyncCallbackArgs(CallbackInfo, CallbackParameters));
+ protected virtual void OnNotifyFileOpenCompletion(in CF_CALLBACK_INFO CallbackInfo, in CF_CALLBACK_PARAMETERS CallbackParameters) => HandleEvent(NotifyFileOpenCompletion, CallbackInfo, CallbackParameters);
- protected virtual void OnNotifyRename(in CF_CALLBACK_INFO CallbackInfo, in CF_CALLBACK_PARAMETERS CallbackParameters) =>
- NotifyRename?.Invoke(this, new CloudSyncCallbackArgs(CallbackInfo, CallbackParameters));
+ protected virtual void OnNotifyRename(in CF_CALLBACK_INFO CallbackInfo, in CF_CALLBACK_PARAMETERS CallbackParameters) => HandleEvent(NotifyRename, CallbackInfo, CallbackParameters);
- protected virtual void OnNotifyRenameCompletion(in CF_CALLBACK_INFO CallbackInfo, in CF_CALLBACK_PARAMETERS CallbackParameters) =>
- NotifyRenameCompletion?.Invoke(this, new CloudSyncCallbackArgs(CallbackInfo, CallbackParameters));
+ protected virtual void OnNotifyRenameCompletion(in CF_CALLBACK_INFO CallbackInfo, in CF_CALLBACK_PARAMETERS CallbackParameters) => HandleEvent(NotifyRenameCompletion, CallbackInfo, CallbackParameters);
- protected virtual void OnValidateData(in CF_CALLBACK_INFO CallbackInfo, in CF_CALLBACK_PARAMETERS CallbackParameters) =>
- ValidateData?.Invoke(this, new CloudSyncCallbackArgs(CallbackInfo, CallbackParameters));
+ protected virtual void OnValidateData(in CF_CALLBACK_INFO CallbackInfo, in CF_CALLBACK_PARAMETERS CallbackParameters) => HandleEvent(ValidateData, CallbackInfo, CallbackParameters);
+
+ protected virtual void HandleEvent(EventHandler> handler, in CF_CALLBACK_INFO CallbackInfo, in CF_CALLBACK_PARAMETERS CallbackParameters) where T : struct
+ {
+ if (handler != null)
+ {
+ var args = new CloudSyncCallbackArgs(CallbackInfo, CallbackParameters);
+ handler.Invoke(this, args);
+ if (args.OperationType != 0 && args.OpParam.HasValue)
+ {
+ var opInfo = args.MakeOpInfo(args.OperationType, args.SyncStatus);
+ var opParam = args.OpParam.Value;
+ CfExecute(opInfo, ref opParam).ThrowIfFailed();
+ }
+ }
+ }
private static void AddFolderToSearchIndexer(string folder)
{