Completed work on CldApi with unit tests

pull/119/head
dahall 2020-05-01 15:26:16 -06:00
parent eca7516d87
commit 1efa3a860a
4 changed files with 468 additions and 257 deletions

View File

@ -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);
/// <summary>Gets a set of placeholder states based on the FileAttributes and ReparseTag values of the file.</summary>
/// <param name="FileAttributes">The file attribute information.</param>
@ -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);
/// <summary>Allows a sync provider to report progress out-of-band.</summary>
/// <param name="ConnectionKey">A connection key representing a communication channel with the sync filter.</param>

View File

@ -147,7 +147,7 @@ namespace Vanara.PInvoke
CF_CALLBACK_FETCH_DATA_FLAG_RECOVERY = 1,
/// <summary>
/// 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.
/// </summary>
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
{
/// <summary/>
public uint ParamSize;
private uint pad;
/// <summary/>
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 56)]
public byte[] Content;
/// <summary/>
public CF_CALLBACK_PARAMETERS_CANCEL Cancel => GetParam<CF_CALLBACK_PARAMETERS_CANCEL>();
public CANCEL Cancel => GetParam<CANCEL>();
/// <summary/>
public CF_CALLBACK_PARAMETERS_FETCHDATA FetchData => GetParam<CF_CALLBACK_PARAMETERS_FETCHDATA>();
public FETCHDATA FetchData => GetParam<FETCHDATA>();
/// <summary/>
public CF_CALLBACK_PARAMETERS_VALIDATEDATA ValidateData => GetParam<CF_CALLBACK_PARAMETERS_VALIDATEDATA>();
public VALIDATEDATA ValidateData => GetParam<VALIDATEDATA>();
/// <summary/>
public CF_CALLBACK_PARAMETERS_FETCHPLACEHOLDERS FetchPlaceholders => GetParam<CF_CALLBACK_PARAMETERS_FETCHPLACEHOLDERS>();
public FETCHPLACEHOLDERS FetchPlaceholders => GetParam<FETCHPLACEHOLDERS>();
/// <summary/>
public CF_CALLBACK_PARAMETERS_OPENCOMPLETION OpenCompletion => GetParam<CF_CALLBACK_PARAMETERS_OPENCOMPLETION>();
public OPENCOMPLETION OpenCompletion => GetParam<OPENCOMPLETION>();
/// <summary/>
public CF_CALLBACK_PARAMETERS_CLOSECOMPLETION CloseCompletion => GetParam<CF_CALLBACK_PARAMETERS_CLOSECOMPLETION>();
public CLOSECOMPLETION CloseCompletion => GetParam<CLOSECOMPLETION>();
/// <summary/>
public CF_CALLBACK_PARAMETERS_DEHYDRATE Dehydrate => GetParam<CF_CALLBACK_PARAMETERS_DEHYDRATE>();
public DEHYDRATE Dehydrate => GetParam<DEHYDRATE>();
/// <summary/>
public CF_CALLBACK_PARAMETERS_DEHYDRATECOMPLETION DehydrateCompletion => GetParam<CF_CALLBACK_PARAMETERS_DEHYDRATECOMPLETION>();
public DEHYDRATECOMPLETION DehydrateCompletion => GetParam<DEHYDRATECOMPLETION>();
/// <summary/>
public CF_CALLBACK_PARAMETERS_DELETE Delete => GetParam<CF_CALLBACK_PARAMETERS_DELETE>();
public DELETE Delete => GetParam<DELETE>();
/// <summary/>
public CF_CALLBACK_PARAMETERS_DELETECOMPLETION DeleteCompletion => GetParam<CF_CALLBACK_PARAMETERS_DELETECOMPLETION>();
public DELETECOMPLETION DeleteCompletion => GetParam<DELETECOMPLETION>();
/// <summary/>
public CF_CALLBACK_PARAMETERS_RENAME Rename => GetParam<CF_CALLBACK_PARAMETERS_RENAME>();
public RENAME Rename => GetParam<RENAME>();
/// <summary/>
public CF_CALLBACK_PARAMETERS_RENAMECOMPLETION RenameCompletion => GetParam<CF_CALLBACK_PARAMETERS_RENAMECOMPLETION>();
public RENAMECOMPLETION RenameCompletion => GetParam<RENAMECOMPLETION>();
/// <summary>Gets the parameter value for this structure.</summary>
/// <typeparam name="T">The type of the structure to retrieve.</typeparam>
@ -1396,180 +1398,180 @@ namespace Vanara.PInvoke
using var ptr = new SafeHGlobalHandle(Content);
return ptr.ToStructure<T>();
}
}
/// <summary>Contains callback specific parameters such as file offset, length, flags, etc.</summary>
[PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
[StructLayout(LayoutKind.Sequential, Pack = 8)]
public struct CF_CALLBACK_PARAMETERS_CANCEL
{
/// <summary>Cancel data flags.</summary>
public CF_CALLBACK_CANCEL_FLAGS Flags;
/// <summary/>
public CANCELFETCHDATA FetchData;
/// <summary/>
[StructLayout(LayoutKind.Sequential)]
public struct CANCELFETCHDATA
/// <summary>Contains callback specific parameters such as file offset, length, flags, etc.</summary>
[PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
[StructLayout(LayoutKind.Sequential, Pack = 8)]
public struct CANCEL
{
/// <summary>Offset, in bytes, for specifying the range of data.</summary>
public long FileOffset;
/// <summary>Cancel data flags.</summary>
public CF_CALLBACK_CANCEL_FLAGS Flags;
/// <summary>Length of the data in bytes.</summary>
public long Length;
/// <summary/>
public CANCELFETCHDATA FetchData;
/// <summary/>
[StructLayout(LayoutKind.Sequential)]
public struct CANCELFETCHDATA
{
/// <summary>Offset, in bytes, for specifying the range of data.</summary>
public long FileOffset;
/// <summary>Length of the data in bytes.</summary>
public long Length;
}
}
}
/// <summary>Contains callback specific parameters such as file offset, length, flags, etc.</summary>
[PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
[StructLayout(LayoutKind.Sequential)]
public struct CF_CALLBACK_PARAMETERS_CLOSECOMPLETION
{
/// <summary>Placeholder close completion flags.</summary>
public CF_CALLBACK_CLOSE_COMPLETION_FLAGS Flags;
}
/// <summary>Contains callback specific parameters such as file offset, length, flags, etc.</summary>
[PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
[StructLayout(LayoutKind.Sequential)]
public struct CLOSECOMPLETION
{
/// <summary>Placeholder close completion flags.</summary>
public CF_CALLBACK_CLOSE_COMPLETION_FLAGS Flags;
}
/// <summary>Contains callback specific parameters such as file offset, length, flags, etc.</summary>
[PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
[StructLayout(LayoutKind.Sequential)]
public struct CF_CALLBACK_PARAMETERS_DEHYDRATE
{
/// <summary>Placeholder dehydration flags.</summary>
public CF_CALLBACK_DEHYDRATE_FLAGS Flags;
/// <summary>Contains callback specific parameters such as file offset, length, flags, etc.</summary>
[PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
[StructLayout(LayoutKind.Sequential)]
public struct DEHYDRATE
{
/// <summary>Placeholder dehydration flags.</summary>
public CF_CALLBACK_DEHYDRATE_FLAGS Flags;
/// <summary/>
public CF_CALLBACK_DEHYDRATION_REASON Reason;
}
/// <summary/>
public CF_CALLBACK_DEHYDRATION_REASON Reason;
}
/// <summary>Contains callback specific parameters such as file offset, length, flags, etc.</summary>
[PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
[StructLayout(LayoutKind.Sequential)]
public struct CF_CALLBACK_PARAMETERS_DEHYDRATECOMPLETION
{
/// <summary/>
public CF_CALLBACK_DEHYDRATE_COMPLETION_FLAGS Flags;
/// <summary>Contains callback specific parameters such as file offset, length, flags, etc.</summary>
[PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
[StructLayout(LayoutKind.Sequential)]
public struct DEHYDRATECOMPLETION
{
/// <summary/>
public CF_CALLBACK_DEHYDRATE_COMPLETION_FLAGS Flags;
/// <summary/>
public CF_CALLBACK_DEHYDRATION_REASON Reason;
}
/// <summary/>
public CF_CALLBACK_DEHYDRATION_REASON Reason;
}
/// <summary>Contains callback specific parameters such as file offset, length, flags, etc.</summary>
[PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
[StructLayout(LayoutKind.Sequential)]
public struct CF_CALLBACK_PARAMETERS_DELETE
{
/// <summary>Placeholder deletion flags.</summary>
public CF_CALLBACK_DELETE_FLAGS Flags;
}
/// <summary>Contains callback specific parameters such as file offset, length, flags, etc.</summary>
[PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
[StructLayout(LayoutKind.Sequential)]
public struct DELETE
{
/// <summary>Placeholder deletion flags.</summary>
public CF_CALLBACK_DELETE_FLAGS Flags;
}
/// <summary>Contains callback specific parameters such as file offset, length, flags, etc.</summary>
[PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
[StructLayout(LayoutKind.Sequential, Pack = 4)]
public struct CF_CALLBACK_PARAMETERS_DELETECOMPLETION
{
/// <summary>Placeholder deletion complete flags.</summary>
public CF_CALLBACK_DELETE_COMPLETION_FLAGS Flags;
}
/// <summary>Contains callback specific parameters such as file offset, length, flags, etc.</summary>
[PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
[StructLayout(LayoutKind.Sequential)]
public struct DELETECOMPLETION
{
/// <summary>Placeholder deletion complete flags.</summary>
public CF_CALLBACK_DELETE_COMPLETION_FLAGS Flags;
}
/// <summary>Contains callback specific parameters such as file offset, length, flags, etc.</summary>
[PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
[StructLayout(LayoutKind.Sequential, Pack = 4, Size = 56)]
public struct CF_CALLBACK_PARAMETERS_FETCHDATA
{
/// <summary>Fetch data flags.</summary>
public CF_CALLBACK_FETCH_DATA_FLAGS Flags;
/// <summary>Contains callback specific parameters such as file offset, length, flags, etc.</summary>
[PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
[StructLayout(LayoutKind.Sequential)]
public struct FETCHDATA
{
/// <summary>Fetch data flags.</summary>
public CF_CALLBACK_FETCH_DATA_FLAGS Flags;
/// <summary>Offset, in bytes, for specifying the required range of data.</summary>
public long RequiredFileOffset;
/// <summary>Offset, in bytes, for specifying the required range of data.</summary>
public long RequiredFileOffset;
/// <summary>Length of the required data to retrieve, in bytes.</summary>
public long RequiredLength;
/// <summary>Length of the required data to retrieve, in bytes.</summary>
public long RequiredLength;
/// <summary>
/// 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.
/// </summary>
public long OptionalFileOffset;
/// <summary>
/// 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.
/// </summary>
public long OptionalFileOffset;
/// <summary>
/// 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.
/// </summary>
public long OptionalLength;
/// <summary>
/// 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.
/// </summary>
public long OptionalLength;
/// <summary/>
public long LastDehydrationTime;
/// <summary/>
public long LastDehydrationTime;
/// <summary/>
public CF_CALLBACK_DEHYDRATION_REASON LastDehydrationReason;
}
/// <summary/>
public CF_CALLBACK_DEHYDRATION_REASON LastDehydrationReason;
}
/// <summary>Contains callback specific parameters such as file offset, length, flags, etc.</summary>
[PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
[StructLayout(LayoutKind.Sequential, Pack = 8)]
public struct CF_CALLBACK_PARAMETERS_FETCHPLACEHOLDERS
{
/// <summary>Flags for fetching placeholder metadata.</summary>
public CF_CALLBACK_FETCH_PLACEHOLDERS_FLAGS Flags;
/// <summary>Contains callback specific parameters such as file offset, length, flags, etc.</summary>
[PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
[StructLayout(LayoutKind.Sequential)]
public struct FETCHPLACEHOLDERS
{
/// <summary>Flags for fetching placeholder metadata.</summary>
public CF_CALLBACK_FETCH_PLACEHOLDERS_FLAGS Flags;
/// <summary>
/// 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.
/// </summary>
[MarshalAs(UnmanagedType.LPWStr)]
public string Pattern;
}
/// <summary>
/// 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.
/// </summary>
[MarshalAs(UnmanagedType.LPWStr)]
public string Pattern;
}
/// <summary>Contains callback specific parameters such as file offset, length, flags, etc.</summary>
[PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
[StructLayout(LayoutKind.Sequential)]
public struct CF_CALLBACK_PARAMETERS_OPENCOMPLETION
{
/// <summary>Placeholder open completion flags.</summary>
public CF_CALLBACK_OPEN_COMPLETION_FLAGS Flags;
}
/// <summary>Contains callback specific parameters such as file offset, length, flags, etc.</summary>
[PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
[StructLayout(LayoutKind.Sequential)]
public struct OPENCOMPLETION
{
/// <summary>Placeholder open completion flags.</summary>
public CF_CALLBACK_OPEN_COMPLETION_FLAGS Flags;
}
/// <summary>Contains callback specific parameters such as file offset, length, flags, etc.</summary>
[PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
[StructLayout(LayoutKind.Sequential, Pack = 8)]
public struct CF_CALLBACK_PARAMETERS_RENAME
{
/// <summary>Rename placeholder flags.</summary>
public CF_CALLBACK_RENAME_FLAGS Flags;
/// <summary>Contains callback specific parameters such as file offset, length, flags, etc.</summary>
[PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
[StructLayout(LayoutKind.Sequential)]
public struct RENAME
{
/// <summary>Rename placeholder flags.</summary>
public CF_CALLBACK_RENAME_FLAGS Flags;
/// <summary>The full rename/move target path relative to the volume.</summary>
[MarshalAs(UnmanagedType.LPWStr)]
public string TargetPath;
}
/// <summary>The full rename/move target path relative to the volume.</summary>
[MarshalAs(UnmanagedType.LPWStr)]
public string TargetPath;
}
/// <summary>Contains callback specific parameters such as file offset, length, flags, etc.</summary>
[PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
[StructLayout(LayoutKind.Sequential, Pack = 8)]
public struct CF_CALLBACK_PARAMETERS_RENAMECOMPLETION
{
/// <summary>Rename completion placeholder flags.</summary>
public CF_CALLBACK_RENAME_COMPLETION_FLAGS Flags;
/// <summary>Contains callback specific parameters such as file offset, length, flags, etc.</summary>
[PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
[StructLayout(LayoutKind.Sequential)]
public struct RENAMECOMPLETION
{
/// <summary>Rename completion placeholder flags.</summary>
public CF_CALLBACK_RENAME_COMPLETION_FLAGS Flags;
/// <summary>The full source link path relative to the volume.</summary>
[MarshalAs(UnmanagedType.LPWStr)]
public string SourcePath;
}
/// <summary>The full source link path relative to the volume.</summary>
[MarshalAs(UnmanagedType.LPWStr)]
public string SourcePath;
}
/// <summary>Contains callback specific parameters such as file offset, length, flags, etc.</summary>
[PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
[StructLayout(LayoutKind.Sequential, Pack = 8)]
public struct CF_CALLBACK_PARAMETERS_VALIDATEDATA
{
/// <summary>Data validation flags.</summary>
public CF_CALLBACK_VALIDATE_DATA_FLAGS Flags;
/// <summary>Contains callback specific parameters such as file offset, length, flags, etc.</summary>
[PInvokeData("cfapi.h", MSDNShortId = "FA403E9E-5EFA-4285-9619-614DB0044FFB")]
[StructLayout(LayoutKind.Sequential)]
public struct VALIDATEDATA
{
/// <summary>Data validation flags.</summary>
public CF_CALLBACK_VALIDATE_DATA_FLAGS Flags;
/// <summary>Offset, in bytes, for specifying the range of data to validate.</summary>
public long RequiredFileOffset;
/// <summary>Offset, in bytes, for specifying the range of data to validate.</summary>
public long RequiredFileOffset;
/// <summary>Length, in bytes, of the data to validate.</summary>
public long RequiredLength;
/// <summary>Length, in bytes, of the data to validate.</summary>
public long RequiredLength;
}
}
/// <summary>The callbacks to be registered by the sync provider.</summary>
@ -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
{
/// <summary/>
[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;
/// <summary/>
public TRANSFERDATA TransferData { get => GetParam<TRANSFERDATA>(); set => SetParam(value); }
/// <summary/>
public RETRIEVEDATA RetrieveData { get => GetParam<RETRIEVEDATA>(); set => SetParam(value); }
/// <summary/>
public ACKDATA AckData { get => GetParam<ACKDATA>(); set => SetParam(value); }
/// <summary/>
public RESTARTHYDRATION RestartHydration { get => GetParam<RESTARTHYDRATION>(); set => SetParam(value); }
/// <summary/>
public TRANSFERPLACEHOLDERS TransferPlaceholders { get => GetParam<TRANSFERPLACEHOLDERS>(); set => SetParam(value); }
/// <summary/>
public ACKDEHYDRATE AckDehydrate { get => GetParam<ACKDEHYDRATE>(); set => SetParam(value); }
/// <summary/>
public ACKRENAME AckRename { get => GetParam<ACKRENAME>(); set => SetParam(value); }
/// <summary/>
public ACKDELETE AckDelete { get => GetParam<ACKDELETE>(); set => SetParam(value); }
/// <summary>Gets the parameter value for this structure.</summary>
/// <typeparam name="T">The type of the structure to retrieve.</typeparam>
/// <returns>The requested structure.</returns>
public unsafe T GetParam<T>() where T : struct
{
using var ptr = new PinnedObject(this);
return ((IntPtr)ptr).ToStructure<T>(Marshal.SizeOf(typeof(CF_OPERATION_PARAMETERS)), 8);
}
/// <summary>Sets the parameter value for this structure.</summary>
/// <typeparam name="T">The type of the structure to set.</typeparam>
/// <param name="value">The value to set.</param>
public void SetParam<T>(T value) where T : struct
{
unsafe
{
fixed (ulong* p = &pad8_16)
{
((IntPtr)(void*)p).Write(value, 0, Marshal.SizeOf(typeof(CF_OPERATION_PARAMETERS)) - 8);
}
}
}
/// <summary>Creates a CF_OPERATION_PARAMETERS instance with the specified parameter value.</summary>
/// <typeparam name="T">The parameter type.</typeparam>
/// <param name="paramValue">The parameter value.</param>
/// <returns>A CF_OPERATION_PARAMETERS instance initialized with <paramref name="paramValue"/> and the correct ParamSize.</returns>
public static CF_OPERATION_PARAMETERS Create<T>(T paramValue = default) where T : struct
{
var op = new CF_OPERATION_PARAMETERS { ParamSize = CF_SIZE_OF_OP_PARAM<T>() };
op.SetParam(paramValue);
return op;
}
/// <summary>Gets the size value used in ParamSize given a specific parameter type.</summary>
/// <typeparam name="T">The parameter type.</typeparam>
/// <returns>The size of the structure.</returns>
public static uint CF_SIZE_OF_OP_PARAM<T>() where T : struct => (uint)(Marshal.OffsetOf(typeof(CF_OPERATION_PARAMETERS), nameof(pad8_16)).ToInt32() + Marshal.SizeOf(typeof(T)));
/// <summary/>
[StructLayout(LayoutKind.Sequential)]
public struct TRANSFERDATA
@ -1748,10 +1820,6 @@ namespace Vanara.PInvoke
public long Length;
}
/// <summary/>
[FieldOffset(4)]
public TRANSFERDATA TransferData;
/// <summary/>
[StructLayout(LayoutKind.Sequential)]
public struct RETRIEVEDATA
@ -1772,10 +1840,6 @@ namespace Vanara.PInvoke
public long ReturnedLength;
}
/// <summary/>
[FieldOffset(4)]
public RETRIEVEDATA RetrieveData;
/// <summary/>
[StructLayout(LayoutKind.Sequential)]
public struct ACKDATA
@ -1796,10 +1860,6 @@ namespace Vanara.PInvoke
public long Length;
}
/// <summary/>
[FieldOffset(4)]
public ACKDATA AckData;
/// <summary/>
[StructLayout(LayoutKind.Sequential)]
public struct RESTARTHYDRATION
@ -1817,10 +1877,6 @@ namespace Vanara.PInvoke
public uint FileIdentityLength;
}
/// <summary/>
[FieldOffset(4)]
public RESTARTHYDRATION RestartHydration;
/// <summary/>
[StructLayout(LayoutKind.Sequential)]
public struct TRANSFERPLACEHOLDERS
@ -1844,10 +1900,6 @@ namespace Vanara.PInvoke
public uint EntriesProcessed;
}
/// <summary/>
[FieldOffset(4)]
public TRANSFERPLACEHOLDERS TransferPlaceholders;
/// <summary/>
[StructLayout(LayoutKind.Sequential)]
public struct ACKDEHYDRATE
@ -1865,10 +1917,6 @@ namespace Vanara.PInvoke
public uint FileIdentityLength;
}
/// <summary/>
[FieldOffset(4)]
public ACKDEHYDRATE AckDehydrate;
/// <summary/>
[StructLayout(LayoutKind.Sequential)]
public struct ACKRENAME
@ -1880,10 +1928,6 @@ namespace Vanara.PInvoke
public NTStatus CompletionStatus;
}
/// <summary/>
[FieldOffset(4)]
public ACKRENAME AckRename;
/// <summary/>
[StructLayout(LayoutKind.Sequential)]
public struct ACKDELETE
@ -1894,10 +1938,6 @@ namespace Vanara.PInvoke
/// <summary>The completion status of the operation.</summary>
public NTStatus CompletionStatus;
}
/// <summary/>
[FieldOffset(4)]
public ACKDELETE AckDelete;
}
/// <summary>Basic placeholder information.</summary>

View File

@ -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<CF_SYNC_STATUS>() + descLen, Code = 1, DescriptionLength = descLen };
var mem = new SafeHGlobalHandle(Marshal.SizeOf<CF_SYNC_STATUS>() + descLen);
mem.Write(ss);
StringHelper.Write(desc, ((IntPtr)mem).Offset(Marshal.SizeOf<CF_SYNC_STATUS>()), 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<T>(object s, CloudSyncCallbackArgs<T> 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<Kernel32.FILE_ATTRIBUTE_TAG_INFO>(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);
}
}

View File

@ -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<CORRELATION_VECTOR>();
pCorrelationVector = CallbackInfo.CorrelationVector;
ProcessInfo = CallbackInfo.ProcessInfo.ToNullableStructure<CF_PROCESS_INFO>();
RequestKey = CallbackInfo.RequestKey;
ParamData = CallbackParameters.GetParam<T>();
try { ParamData = CallbackParameters.GetParam<T>(); } catch { }
//catch (Exception ex) { System.Diagnostics.Debug.WriteLine($"{ex.Message}"); }
}
/// <summary>points to an opaque blob that the sync provider provides at the sync root connect time.</summary>
@ -46,7 +50,10 @@ namespace Vanara.PInvoke.Tests
public CF_CONNECTION_KEY ConnectionKey { get; }
/// <summary>An optional correlation vector.</summary>
public CORRELATION_VECTOR? CorrelationVector { get; }
public IntPtr pCorrelationVector { get; }
/// <summary>An optional correlation vector.</summary>
public CORRELATION_VECTOR? CorrelationVector => pCorrelationVector.ToNullableStructure<CORRELATION_VECTOR>();
/// <summary>A 64 bit file system maintained, volume-wide unique ID of the placeholder file/directory to be serviced.</summary>
public long FileId { get; }
@ -66,6 +73,9 @@ namespace Vanara.PInvoke.Tests
/// <summary>Contains callback specific parameters for this action.</summary>
public T ParamData { get; }
/// <summary>Parameters of an operation on a placeholder file or folder.</summary>
public CF_OPERATION_PARAMETERS? OpParam { get; set; }
/// <summary>
/// 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
/// <summary>DOS drive letter of the volume in the form of “X:” where X is the drive letter.</summary>
public string VolumeDosName { get; }
/// <summary>GUID name of the volume on which the placeholder file/directory to be serviced resides. It is in the form: “\?\Volume{GUID}”.</summary>
/// <summary>GUID name of the volume on which the placeholder file/directory to be serviced resides. It is in the form: "\?\Volume{GUID}".</summary>
public string VolumeGuidName { get; }
/// <summary>The serial number of the volume.</summary>
public uint VolumeSerialNumber { get; }
/// <summary>The type of operation performed.</summary>
public CF_OPERATION_TYPE OperationType { get; set; }
/// <summary>
/// <note>This member is new for Windows 10, version 1803.</note>
/// <para>The current sync status of the platform.</para>
/// <para>
/// 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 <see langword="null"/>, the platform will clear the
/// previously set sync status, if there is one.
/// </para>
/// </summary>
public IntPtr SyncStatus { get; set; }
/// <summary>Makes a CF_OPERATION_INFO instance from the properties.</summary>
/// <param name="opType">Type of the operation to set.</param>
/// <returns>A CF_OPERATION_INFO instance.</returns>
public CF_OPERATION_INFO MakeOpInfo(CF_OPERATION_TYPE opType, IntPtr syncStatus = default) => new CF_OPERATION_INFO
{
StructSize = (uint)Marshal.SizeOf<CF_OPERATION_INFO>(),
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<CloudSyncCallbackArgs<CF_CALLBACK_PARAMETERS_CANCEL>> CancelFetchData;
public event EventHandler<CloudSyncCallbackArgs<CF_CALLBACK_PARAMETERS.CANCEL>> CancelFetchData;
public event EventHandler<CloudSyncCallbackArgs<CF_CALLBACK_PARAMETERS_CANCEL>> CancelFetchPlaceholders;
public event EventHandler<CloudSyncCallbackArgs<CF_CALLBACK_PARAMETERS.CANCEL>> CancelFetchPlaceholders;
public event EventHandler<CloudSyncCallbackArgs<CF_CALLBACK_PARAMETERS_FETCHDATA>> FetchData;
public event EventHandler<CloudSyncCallbackArgs<CF_CALLBACK_PARAMETERS.FETCHDATA>> FetchData;
public event EventHandler<CloudSyncCallbackArgs<CF_CALLBACK_PARAMETERS_FETCHPLACEHOLDERS>> FetchPlaceholders;
public event EventHandler<CloudSyncCallbackArgs<CF_CALLBACK_PARAMETERS.FETCHPLACEHOLDERS>> FetchPlaceholders;
public event EventHandler<CloudSyncCallbackArgs<CF_CALLBACK_PARAMETERS_DEHYDRATE>> NotifyDehydrate;
public event EventHandler<CloudSyncCallbackArgs<CF_CALLBACK_PARAMETERS.DEHYDRATE>> NotifyDehydrate;
public event EventHandler<CloudSyncCallbackArgs<CF_CALLBACK_PARAMETERS_DEHYDRATECOMPLETION>> NotifyDehydrateCompletion;
public event EventHandler<CloudSyncCallbackArgs<CF_CALLBACK_PARAMETERS.DEHYDRATECOMPLETION>> NotifyDehydrateCompletion;
public event EventHandler<CloudSyncCallbackArgs<CF_CALLBACK_PARAMETERS_DELETE>> NotifyDelete;
public event EventHandler<CloudSyncCallbackArgs<CF_CALLBACK_PARAMETERS.DELETE>> NotifyDelete;
public event EventHandler<CloudSyncCallbackArgs<CF_CALLBACK_PARAMETERS_DELETECOMPLETION>> NotifyDeleteCompletion;
public event EventHandler<CloudSyncCallbackArgs<CF_CALLBACK_PARAMETERS.DELETECOMPLETION>> NotifyDeleteCompletion;
public event EventHandler<CloudSyncCallbackArgs<CF_CALLBACK_PARAMETERS_CLOSECOMPLETION>> NotifyFileCloseCompletion;
public event EventHandler<CloudSyncCallbackArgs<CF_CALLBACK_PARAMETERS.CLOSECOMPLETION>> NotifyFileCloseCompletion;
public event EventHandler<CloudSyncCallbackArgs<CF_CALLBACK_PARAMETERS_OPENCOMPLETION>> NotifyFileOpenCompletion;
public event EventHandler<CloudSyncCallbackArgs<CF_CALLBACK_PARAMETERS.OPENCOMPLETION>> NotifyFileOpenCompletion;
public event EventHandler<CloudSyncCallbackArgs<CF_CALLBACK_PARAMETERS_RENAME>> NotifyRename;
public event EventHandler<CloudSyncCallbackArgs<CF_CALLBACK_PARAMETERS.RENAME>> NotifyRename;
public event EventHandler<CloudSyncCallbackArgs<CF_CALLBACK_PARAMETERS_RENAMECOMPLETION>> NotifyRenameCompletion;
public event EventHandler<CloudSyncCallbackArgs<CF_CALLBACK_PARAMETERS.RENAMECOMPLETION>> NotifyRenameCompletion;
public event EventHandler<CloudSyncCallbackArgs<CF_CALLBACK_PARAMETERS_VALIDATEDATA>> ValidateData;
public event EventHandler<CloudSyncCallbackArgs<CF_CALLBACK_PARAMETERS.VALIDATEDATA>> 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<CF_CALLBACK_PARAMETERS_CANCEL>(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<CF_CALLBACK_PARAMETERS_CANCEL>(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<CF_CALLBACK_PARAMETERS_FETCHDATA>(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<CF_CALLBACK_PARAMETERS_FETCHPLACEHOLDERS>(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<CF_CALLBACK_PARAMETERS_DEHYDRATE>(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<CF_CALLBACK_PARAMETERS_DEHYDRATECOMPLETION>(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<CF_CALLBACK_PARAMETERS_DELETE>(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<CF_CALLBACK_PARAMETERS_DELETECOMPLETION>(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<CF_CALLBACK_PARAMETERS_CLOSECOMPLETION>(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<CF_CALLBACK_PARAMETERS_OPENCOMPLETION>(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<CF_CALLBACK_PARAMETERS_RENAME>(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<CF_CALLBACK_PARAMETERS_RENAMECOMPLETION>(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<CF_CALLBACK_PARAMETERS_VALIDATEDATA>(CallbackInfo, CallbackParameters));
protected virtual void OnValidateData(in CF_CALLBACK_INFO CallbackInfo, in CF_CALLBACK_PARAMETERS CallbackParameters) => HandleEvent(ValidateData, CallbackInfo, CallbackParameters);
protected virtual void HandleEvent<T>(EventHandler<CloudSyncCallbackArgs<T>> handler, in CF_CALLBACK_INFO CallbackInfo, in CF_CALLBACK_PARAMETERS CallbackParameters) where T : struct
{
if (handler != null)
{
var args = new CloudSyncCallbackArgs<T>(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)
{