From ed51271853213a748775cdf8397f64b2059ced04 Mon Sep 17 00:00:00 2001 From: dahall Date: Thu, 30 Apr 2020 09:34:04 -0600 Subject: [PATCH] Committed work in progress on cldapi.dll --- PInvoke/CldApi/cfapi.Funcs.cs | 100 ++++-- PInvoke/CldApi/cfapi.cs | 378 ++++++++++----------- UnitTests/PInvoke/CldApi/CldApi.csproj | 8 + UnitTests/PInvoke/CldApi/CldApiTests.cs | 155 ++++++++- UnitTests/PInvoke/CldApi/CloudSyncProvider.cs | 458 ++++++++++++++++++++++++++ 5 files changed, 868 insertions(+), 231 deletions(-) create mode 100644 UnitTests/PInvoke/CldApi/CloudSyncProvider.cs diff --git a/PInvoke/CldApi/cfapi.Funcs.cs b/PInvoke/CldApi/cfapi.Funcs.cs index 297d332e..9f57e2ab 100644 --- a/PInvoke/CldApi/cfapi.Funcs.cs +++ b/PInvoke/CldApi/cfapi.Funcs.cs @@ -1,6 +1,7 @@ using System; using System.Runtime.InteropServices; using System.Threading; +using Vanara.InteropServices; using static Vanara.PInvoke.Kernel32; namespace Vanara.PInvoke @@ -12,7 +13,9 @@ namespace Vanara.PInvoke /// The callback information. /// The callback parameters. [UnmanagedFunctionPointer(CallingConvention.Winapi)] - public delegate void CF_CALLBACK(in CF_CALLBACK_INFO CallbackInfo, IntPtr CallbackParameters); + public delegate void CF_CALLBACK(in CF_CALLBACK_INFO CallbackInfo, in CF_CALLBACK_PARAMETERS CallbackParameters); + + private delegate HRESULT GetInfoFunc(TParam p1, TEnum InfoClass, IntPtr InfoBuffer, uint InfoBufferLength, out uint ReturnedLength) where TEnum : Enum; /// /// Closes the file or directory handle returned by CfOpenFileWithOplock. This should not be used with standard Win32 file handles, @@ -176,6 +179,35 @@ namespace Vanara.PInvoke public static unsafe extern HRESULT CfConvertToPlaceholder(HFILE FileHandle, [In, Optional] IntPtr FileIdentity, uint FileIdentityLength, CF_CONVERT_FLAGS ConvertFlags, [Out, Optional] int* ConvertUsn, [In, Out, Optional] NativeOverlapped* Overlapped); + /// Creates one or more new placeholder files or directories under a sync root tree. + /// Local directory path under which placeholders are created. + /// + /// On successful creation, the PlaceholderArray contains the final USN value and a STATUS_OK message. On return, this array + /// contains an HRESULT value describing whether the placeholder was created or not. + /// + /// The count of placeholders in the PlaceholderArray. + /// Flags for configuring the creation of a placeholder. + /// The number of entries processed, including failed entries. + /// If this function succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code. + /// + /// + /// Creating a placeholder with this function is preferred compared to creating a new file with CreateFile and then converting it to + /// a placeholder with CfConvertToPlaceholder; both for efficiency and because it eliminates the time window where the file is not a + /// placeholder. The function can also create multiple files or directories in a batch, which can also be more efficient. + /// + /// + /// This function is useful when performing an initial sync of files or directories from the cloud down to the client, or when + /// syncing down a newly created single file or directory from the cloud. + /// + /// + // https://docs.microsoft.com/en-us/windows/win32/api/cfapi/nf-cfapi-cfcreateplaceholders HRESULT CfCreatePlaceholders( LPCWSTR + // BaseDirectoryPath, CF_PLACEHOLDER_CREATE_INFO *PlaceholderArray, DWORD PlaceholderCount, CF_CREATE_FLAGS CreateFlags, PDWORD + // EntriesProcessed ); + [DllImport(Lib.CldApi, SetLastError = false, ExactSpelling = true)] + [PInvokeData("cfapi.h", MSDNShortId = "96A6F62E-7F14-40B5-AB57-260DC9B1DF89")] + public static extern HRESULT CfCreatePlaceholders([MarshalAs(UnmanagedType.LPWStr)] string BaseDirectoryPath, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] CF_PLACEHOLDER_CREATE_INFO[] PlaceholderArray, + uint PlaceholderCount, CF_CREATE_FLAGS CreateFlags, out uint EntriesProcessed); + /// /// Dehydrates a placeholder file by ensuring that the specified byte range is not present on-disk in the placeholder. This is valid /// for files only. @@ -248,35 +280,6 @@ namespace Vanara.PInvoke [PInvokeData("CfApi.h")] public static unsafe extern HRESULT CfDehydratePlaceholder(HFILE FileHandle, long StartingOffset, long Length, CF_DEHYDRATE_FLAGS DehydrateFlags, [In, Out] NativeOverlapped* Overlapped); - /// Creates one or more new placeholder files or directories under a sync root tree. - /// Local directory path under which placeholders are created. - /// - /// On successful creation, the PlaceholderArray contains the final USN value and a STATUS_OK message. On return, this array - /// contains an HRESULT value describing whether the placeholder was created or not. - /// - /// The count of placeholders in the PlaceholderArray. - /// Flags for configuring the creation of a placeholder. - /// The number of entries processed, including failed entries. - /// If this function succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code. - /// - /// - /// Creating a placeholder with this function is preferred compared to creating a new file with CreateFile and then converting it to - /// a placeholder with CfConvertToPlaceholder; both for efficiency and because it eliminates the time window where the file is not a - /// placeholder. The function can also create multiple files or directories in a batch, which can also be more efficient. - /// - /// - /// This function is useful when performing an initial sync of files or directories from the cloud down to the client, or when - /// syncing down a newly created single file or directory from the cloud. - /// - /// - // https://docs.microsoft.com/en-us/windows/win32/api/cfapi/nf-cfapi-cfcreateplaceholders HRESULT CfCreatePlaceholders( LPCWSTR - // BaseDirectoryPath, CF_PLACEHOLDER_CREATE_INFO *PlaceholderArray, DWORD PlaceholderCount, CF_CREATE_FLAGS CreateFlags, PDWORD - // EntriesProcessed ); - [DllImport(Lib.CldApi, SetLastError = false, ExactSpelling = true)] - [PInvokeData("cfapi.h", MSDNShortId = "96A6F62E-7F14-40B5-AB57-260DC9B1DF89")] - public static extern HRESULT CfCreatePlaceholders([MarshalAs(UnmanagedType.LPWStr)] string BaseDirectoryPath, [In, Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] CF_PLACEHOLDER_CREATE_INFO[] PlaceholderArray, - uint PlaceholderCount, CF_CREATE_FLAGS CreateFlags, out uint EntriesProcessed); - /// Disconnects a communication channel created by CfConnectSyncRoot. /// The connection key returned from CfConnectSyncRoot that is now used to disconnect the sync root. /// If this function succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code. @@ -349,6 +352,13 @@ namespace Vanara.PInvoke [PInvokeData("cfapi.h", MSDNShortId = "D82269CF-8056-46CF-9832-AAE8767A854B")] public static extern HRESULT CfGetPlaceholderInfo(HFILE FileHandle, CF_PLACEHOLDER_INFO_CLASS InfoClass, [Out] IntPtr InfoBuffer, uint InfoBufferLength, out uint ReturnedLength); + /// Gets various characteristics of a placeholder file or folder. + /// The type of information to retrieve. + /// A handle to the placeholder whose information will be queried. + /// The requested information. + [PInvokeData("cfapi.h", MSDNShortId = "D82269CF-8056-46CF-9832-AAE8767A854B")] + public static T CfGetPlaceholderInfo(HFILE FileHandle) where T : struct => GetInfo(CfGetPlaceholderInfo, FileHandle); + /// Gets range information about a placeholder file or folder. /// The handle of the placeholder file to be queried. /// Types of the range of placeholder data. @@ -440,6 +450,13 @@ namespace Vanara.PInvoke [PInvokeData("cfapi.h", MSDNShortId = "EC96CB4E-6BCE-49D9-9CDA-A24A9303B5CF")] public static extern HRESULT CfGetSyncRootInfoByHandle(HFILE FileHandle, CF_SYNC_ROOT_INFO_CLASS InfoClass, [Out] IntPtr InfoBuffer, uint InfoBufferLength, out uint ReturnedLength); + /// Gets various characteristics of the sync root containing a given file specified by a file handle. + /// The type of information to retrieve. + /// Handle of the file under the sync root whose information is to be queried. + /// The requested sync root information. + [PInvokeData("cfapi.h", MSDNShortId = "EC96CB4E-6BCE-49D9-9CDA-A24A9303B5CF")] + public static T CfGetSyncRootInfoByHandle(HFILE FileHandle) where T : struct => GetInfo(CfGetSyncRootInfoByHandle, FileHandle); + /// Gets various sync root information given a file under the sync root. /// A fully qualified path to a file whose sync root information is to be queried /// Types of sync root information. @@ -455,6 +472,14 @@ namespace Vanara.PInvoke [PInvokeData("cfapi.h", MSDNShortId = "0FEEF910-3545-4D94-BFF9-88AEE084F454")] public static extern HRESULT CfGetSyncRootInfoByPath([MarshalAs(UnmanagedType.LPWStr)] string FilePath, CF_SYNC_ROOT_INFO_CLASS InfoClass, [Out] IntPtr InfoBuffer, uint InfoBufferLength, out uint ReturnedLength); + /// Gets various sync root information given a file under the sync root. + /// The type of information to retrieve. + /// A fully qualified path to a file whose sync root information is to be queried + /// The requested sync root information. + /// Supplied type parameter is not supported. - T + [PInvokeData("cfapi.h", MSDNShortId = "0FEEF910-3545-4D94-BFF9-88AEE084F454")] + public static T CfGetSyncRootInfoByPath(string FilePath) where T : struct => GetInfo(CfGetSyncRootInfoByPath, FilePath); + /// Initiates a transfer of data into a placeholder file or folder. /// The file handle of the placeholder. /// An opaque handle to the placeholder to be serviced. @@ -1084,6 +1109,21 @@ namespace Vanara.PInvoke [PInvokeData("cfapi.h", MSDNShortId = "E0CB6CA2-439A-4919-95EF-B519ABBBB085")] public static extern HRESULT CfUpdateSyncProviderStatus(CF_CONNECTION_KEY ConnectionKey, CF_SYNC_PROVIDER_STATUS ProviderStatus); + private static T GetInfo(GetInfoFunc func, TParam firstParam) where TEnum : struct, Enum where T : struct + { + if (!CorrespondingTypeAttribute.CanGet(typeof(T), out var infoClass)) + throw new ArgumentException("Supplied type parameter is not supported.", nameof(T)); + using var mem = SafeHGlobalHandle.CreateFromStructure(); + var hr = func(firstParam, infoClass, mem, mem.Size, out var len); + while (hr == (HRESULT)(Win32Error)Win32Error.ERROR_MORE_DATA && mem.Size < 1024 * 32) + { + mem.Size = len * 4; + hr = func(firstParam, infoClass, mem, mem.Size, out len); + } + hr.ThrowIfFailed(); + return mem.ToStructure(); + } + /// Provides a handle to a CF opened file. [StructLayout(LayoutKind.Sequential)] public struct HCFFILE : IHandle diff --git a/PInvoke/CldApi/cfapi.cs b/PInvoke/CldApi/cfapi.cs index c129f741..6d18a5f8 100644 --- a/PInvoke/CldApi/cfapi.cs +++ b/PInvoke/CldApi/cfapi.cs @@ -1,5 +1,6 @@ using System; using System.Runtime.InteropServices; +using Vanara.Extensions; using Vanara.InteropServices; using static Vanara.PInvoke.Kernel32; @@ -885,7 +886,7 @@ namespace Vanara.PInvoke CF_PLACEHOLDER_CREATE_FLAG_NONE = 0, /// - /// The newly created child placeholder directory is considered to have all of its children present locally.Applicable to a + /// The newly created child placeholder directory is considered to have all of its children present locally. Applicable to a /// child placeholder directory only. /// CF_PLACEHOLDER_CREATE_FLAG_DISABLE_ON_DEMAND_POPULATION = 1, @@ -904,9 +905,11 @@ namespace Vanara.PInvoke public enum CF_PLACEHOLDER_INFO_CLASS { /// Basic placeholder information. See CF_PLACEHOLDER_BASIC_INFO. + [CorrespondingType(typeof(CF_PLACEHOLDER_BASIC_INFO), CorrespondingAction.Get)] CF_PLACEHOLDER_INFO_BASIC, /// Standard placeholder information. See CF_PLACEHOLDER_STANDARD_INFO. + [CorrespondingType(typeof(CF_PLACEHOLDER_STANDARD_INFO), CorrespondingAction.Get)] CF_PLACEHOLDER_INFO_STANDARD, } @@ -1145,12 +1148,15 @@ namespace Vanara.PInvoke public enum CF_SYNC_ROOT_INFO_CLASS { /// Basic sync root information. See CF_SYNC_ROOT_BASIC_INFO. + [CorrespondingType(typeof(CF_SYNC_ROOT_BASIC_INFO), CorrespondingAction.Get)] CF_SYNC_ROOT_INFO_BASIC, /// Standard sync root information. See CF_SYNC_ROOT_STANDARD_INFO. + [CorrespondingType(typeof(CF_SYNC_ROOT_STANDARD_INFO), CorrespondingAction.Get)] CF_SYNC_ROOT_INFO_STANDARD, /// Sync root provider information. See CF_SYNC_ROOT_PROVIDER_INFO. + [CorrespondingType(typeof(CF_SYNC_ROOT_PROVIDER_INFO), CorrespondingAction.Get)] CF_SYNC_ROOT_INFO_PROVIDER, } @@ -1336,222 +1342,198 @@ 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.Explicit)] + [StructLayout(LayoutKind.Sequential, Pack = 8)] public struct CF_CALLBACK_PARAMETERS { /// - [FieldOffset(0)] public uint ParamSize; /// - [FieldOffset(4)] - public CANCEL Cancel; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 56)] + public byte[] Content; + + /// Gets the parameter value for this structure. + /// The type of the structure to retrieve. + /// The requested structure. + public T GetParam() where T : struct + { + 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 CANCEL + public struct CANCELFETCHDATA { - /// Cancel data flags. - public CF_CALLBACK_CANCEL_FLAGS Flags; + /// Offset, in bytes, for specifying the range of data. + public long FileOffset; - /// - 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; - } + /// 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 CF_CALLBACK_PARAMETERS_DEHYDRATE + { + /// Placeholder dehydration flags. + public CF_CALLBACK_DEHYDRATE_FLAGS Flags; /// - [FieldOffset(4)] - public FETCHDATA FetchData; + 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; /// - [StructLayout(LayoutKind.Sequential)] - public struct FETCHDATA - { - /// Fetch data flags. - public CF_CALLBACK_FETCH_DATA_FLAGS Flags; + public CF_CALLBACK_DEHYDRATION_REASON Reason; + } - /// Offset, in bytes, for specifying the required range of data. - public long RequiredFileOffset; + /// 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; + } - /// Length of the required data to retrieve, in bytes. - public long RequiredLength; + /// 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; + } - /// - /// 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; + /// 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; - /// - /// 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; + /// Offset, in bytes, for specifying the required range of data. + public long RequiredFileOffset; - /// - public long LastDehydrationTime; + /// Length of the required data to retrieve, in bytes. + public long RequiredLength; - /// - public CF_CALLBACK_DEHYDRATION_REASON LastDehydrationReason; - } + /// + /// 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; /// - [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; - - /// Length, in bytes, of the data to validate. - public long RequiredLength; - } + public long LastDehydrationTime; /// - [FieldOffset(4)] - public VALIDATEDATA ValidateData; + public CF_CALLBACK_DEHYDRATION_REASON LastDehydrationReason; + } - /// - [StructLayout(LayoutKind.Sequential)] - public struct 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, Pack = 8)] + public struct CF_CALLBACK_PARAMETERS_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; + } - /// - [FieldOffset(4)] - public FETCHPLACEHOLDERS FetchPlaceholders; + /// 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; + } - /// - [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; - /// - [FieldOffset(4)] - public OPENCOMPLETION OpenCompletion; + /// The full rename/move target path relative to the volume. + [MarshalAs(UnmanagedType.LPWStr)] + public string TargetPath; + } - /// - [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, Pack = 8)] + public struct CF_CALLBACK_PARAMETERS_RENAMECOMPLETION + { + /// Rename completion placeholder flags. + public CF_CALLBACK_RENAME_COMPLETION_FLAGS Flags; - /// - [FieldOffset(4)] - public CLOSECOMPLETION CloseCompletion; + /// The full source link path relative to the volume. + [MarshalAs(UnmanagedType.LPWStr)] + public string SourcePath; + } - /// - [StructLayout(LayoutKind.Sequential)] - public struct 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, Pack = 8)] + public struct CF_CALLBACK_PARAMETERS_VALIDATEDATA + { + /// Data validation flags. + public CF_CALLBACK_VALIDATE_DATA_FLAGS Flags; - /// - public CF_CALLBACK_DEHYDRATION_REASON Reason; - } + /// Offset, in bytes, for specifying the range of data to validate. + public long RequiredFileOffset; - /// - [FieldOffset(4)] - public DEHYDRATE Dehydrate; - - /// - [StructLayout(LayoutKind.Sequential)] - public struct DEHYDRATECOMPLETION - { - /// - public CF_CALLBACK_DEHYDRATE_COMPLETION_FLAGS Flags; - - /// - public CF_CALLBACK_DEHYDRATION_REASON Reason; - } - - /// - [FieldOffset(4)] - public DEHYDRATECOMPLETION DehydrateCompletion; - - /// - [StructLayout(LayoutKind.Sequential)] - public struct DELETE - { - /// Placeholder deletion flags. - public CF_CALLBACK_DELETE_FLAGS Flags; - } - - /// - [FieldOffset(4)] - public DELETE Delete; - - /// - [StructLayout(LayoutKind.Sequential)] - public struct DELETECOMPLETION - { - /// Placeholder deletion complete flags. - public CF_CALLBACK_DELETE_COMPLETION_FLAGS Flags; - } - - /// - [FieldOffset(4)] - public DELETECOMPLETION DeleteCompletion; - - /// - [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; - } - - /// - [FieldOffset(4)] - public RENAME Rename; - - /// - [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; - } - - /// - [FieldOffset(4)] - public RENAMECOMPLETION RenameCompletion; + /// Length, in bytes, of the data to validate. + public long RequiredLength; } /// The callbacks to be registered by the sync provider. @@ -1590,6 +1572,20 @@ namespace Vanara.PInvoke private long Internal; } + /// Specifies a range of data in a placeholder file. + // https://docs.microsoft.com/en-us/windows/win32/api/cfapi/ns-cfapi-cf_file_range typedef struct CF_FILE_RANGE { LARGE_INTEGER + // StartingOffset; LARGE_INTEGER Length; } CF_FILE_RANGE; + [PInvokeData("cfapi.h", MSDNShortId = "DAE43446-725E-490B-AE1B-EA6CB31F4358")] + [StructLayout(LayoutKind.Sequential)] + public struct CF_FILE_RANGE + { + /// The offset of the starting point of the data. + public long StartingOffset; + + /// The length of the data, in bytes. + public long Length; + } + /// A structure to describe the location and range of data in a file. // https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/mt844616(v=vs.85) typedef struct __CF_FILE_RANGE_BUFFER // { LARGE_INTEGER FileOffset; LARGE_INTEGER Length; } CF_FILE_RANGE_BUFFER; @@ -1868,20 +1864,6 @@ namespace Vanara.PInvoke public ACKDELETE AckDelete; } - /// Specifies a range of data in a placeholder file. - // https://docs.microsoft.com/en-us/windows/win32/api/cfapi/ns-cfapi-cf_file_range - // typedef struct CF_FILE_RANGE { LARGE_INTEGER StartingOffset; LARGE_INTEGER Length; } CF_FILE_RANGE; - [PInvokeData("cfapi.h", MSDNShortId = "DAE43446-725E-490B-AE1B-EA6CB31F4358")] - [StructLayout(LayoutKind.Sequential)] - public struct CF_FILE_RANGE - { - /// The offset of the starting point of the data. - public int StartingOffset; - - /// The length of the data, in bytes. - public int Length; - } - /// Basic placeholder information. // https://docs.microsoft.com/en-us/windows/win32/api/cfapi/ns-cfapi-cf_placeholder_basic_info typedef struct // CF_PLACEHOLDER_BASIC_INFO { CF_PIN_STATE PinState; CF_IN_SYNC_STATE InSyncState; LARGE_INTEGER FileId; LARGE_INTEGER @@ -2147,7 +2129,7 @@ namespace Vanara.PInvoke public struct CF_SYNC_ROOT_BASIC_INFO { /// The file ID of the sync root. - public int SyncRootFileId; + public long SyncRootFileId; } /// Sync root provider information. @@ -2180,11 +2162,11 @@ namespace Vanara.PInvoke // SyncRootIdentityLength; BYTE SyncRootIdentity[1]; } CF_SYNC_ROOT_STANDARD_INFO; [PInvokeData("cfapi.h", MSDNShortId = "17E409FB-2997-432C-977F-BEBF53068B42")] [VanaraMarshaler(typeof(SafeAnysizeStructMarshaler), nameof(SyncRootIdentityLength))] - [StructLayout(LayoutKind.Sequential)] + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] public struct CF_SYNC_ROOT_STANDARD_INFO { /// File ID of the sync root. - public int SyncRootFileId; + public long SyncRootFileId; /// Hydration policy of the sync root. public CF_HYDRATION_POLICY HydrationPolicy; diff --git a/UnitTests/PInvoke/CldApi/CldApi.csproj b/UnitTests/PInvoke/CldApi/CldApi.csproj index b3a9bc23..dba92fa3 100644 --- a/UnitTests/PInvoke/CldApi/CldApi.csproj +++ b/UnitTests/PInvoke/CldApi/CldApi.csproj @@ -46,6 +46,10 @@ {842d436f-598c-47d7-b5aa-12399f8ccfe9} Vanara.PInvoke.Kernel32 + + {07cd630d-a4bd-45cb-bf1b-90e981f4de81} + Vanara.PInvoke.SearchApi + {a5e519e9-feba-4fe3-93a5-b8269bef72f4} Vanara.PInvoke.Shared @@ -56,6 +60,9 @@ + + 10.0.18362.2005 + 3.12.0 @@ -68,6 +75,7 @@ +