using System; using System.Runtime.InteropServices; using System.Threading; using Vanara.InteropServices; using static Vanara.PInvoke.Kernel32; using USN = System.Int64; namespace Vanara.PInvoke { /// Functions, structures and constants from CldApi.dll. public static partial class CldApi { /// Callback function for . /// The callback information. /// The callback parameters. [UnmanagedFunctionPointer(CallingConvention.Winapi)] 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, /// only on handles used within CfApi.h. /// /// The file or directory handle to be closed. /// None // https://docs.microsoft.com/en-us/windows/win32/api/cfapi/nf-cfapi-cfclosehandle void CfCloseHandle( HANDLE FileHandle ); [DllImport(Lib.CldApi, SetLastError = false, ExactSpelling = true)] [PInvokeData("cfapi.h", MSDNShortId = "ECBEF685-0769-4AEA-8A0F-D5FBB70CBB09")] public static extern void CfCloseHandle(HCFFILE FileHandle); /// Initiates bi-directional communication between a sync provider and the sync filter API. /// The path to the sync root. /// The callback table to be registered. /// A callback context used by the platform anytime a specified callback function is invoked. /// Provides additional information when a callback is invoked. /// A connection key representing the communication channel with the sync filter. /// If this function succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code. /// /// /// This initiates a bi-directional communication channel between the sync provider and the sync filter. A sync provider typically /// calls this API soon after startup, once it has been initialized and is ready to service requests. /// /// /// The sync root must be registered prior to being connected. For a given SyncRootPath, there can be at most one connection /// established at any given time. /// /// /// The sync provider should have WRITE_DATA or WRITE_DAC access to the sync root to be connected or the API will be failed with HRESULT(ERROR_CLOUD_FILE_ACCESS_DENIED). /// /// // https://docs.microsoft.com/en-us/windows/win32/api/cfapi/nf-cfapi-cfconnectsyncroot HRESULT CfConnectSyncRoot( LPCWSTR // SyncRootPath, const CF_CALLBACK_REGISTRATION *CallbackTable, LPCVOID CallbackContext, CF_CONNECT_FLAGS ConnectFlags, // CF_CONNECTION_KEY *ConnectionKey ); [DllImport(Lib.CldApi, SetLastError = false, ExactSpelling = true)] [PInvokeData("cfapi.h", MSDNShortId = "287DA978-9797-48DF-9C90-BA53BB82475C")] public static extern HRESULT CfConnectSyncRoot([MarshalAs(UnmanagedType.LPWStr)] string SyncRootPath, [In, MarshalAs(UnmanagedType.LPArray)] CF_CALLBACK_REGISTRATION[] CallbackTable, [In, Optional] IntPtr CallbackContext, CF_CONNECT_FLAGS ConnectFlags, out CF_CONNECTION_KEY ConnectionKey); /// Converts a normal file/directory to a placeholder file/directory. /// Handle to the file or directory to be converted. /// /// A user mode buffer that contains the opaque file or directory information supplied by the caller. Optional if the caller is not /// dehydrating the file at the same time, or if the caller is converting a directory. Cannot exceed 4KB in size. /// /// Length, in bytes, of the FileIdentity. /// Placeholder conversion flags. /// The final USN value after convert actions are performed. /// /// /// When specified and combined with an asynchronous FileHandle, Overlapped allows the platform to perform the /// CfConvertToPlaceholder call asynchronously. See the Remarks for more details. /// /// If not specified, the platform will perform the API call synchronously, regardless of how the handle was created. /// /// If this function succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code. /// /// /// In the file case, the caller must acquire an exclusive handle to the file if it also intends to dehydrate the file at the same /// time or data corruption can occur. To minimize the impact on user applications it is highly recommended that the caller obtain /// the exclusiveness using proper oplocks (via CfOpenFileWithOplock) as opposed to using a share-nothing handle. /// /// To convert a placeholder: /// /// /// /// The file or directory to be converted must be contained in a registered sync root tree; it can be the sync root directory /// itself, or any descendant directory; otherwise, the call with be failed with HRESULT(ERROR_CLOUD_FILE_NOT_UNDER_SYNC_ROOT). /// /// /// /// /// If dehydration is requested, the sync root must be registered with a valid hydration policy that is not /// CF_HYDRATION_POLICY_ALWAYS_FULL; otherwise the call will be failed with HRESULT(ERROR_CLOUD_FILE_NOT_SUPPORTED). /// /// /// /// If dehydration is requested, the placeholder must not be pinned locally or the call with be failed with HRESULT(ERROR_CLOUD_FILE_PINNED). /// /// /// If dehydration is requested, the placeholder must be in sync or the call with be failed with HRESULT(ERROR_CLOUD_FILE_NOT_IN_SYNC). /// /// /// /// The caller must have WRITE_DATA or WRITE_DAC access to the file or directory to be converted. Otherwise the operation will be /// failed with HRESULT(ERROR_CLOUD_FILE_ACCESS_DENIED). /// /// /// /// /// If the API returns HRESULT_FROM_WIN32(ERROR_IO_PENDING) when using Overlapped asynchronously, the caller can then wait using GetOverlappedResult. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/cfapi/nf-cfapi-cfconverttoplaceholder HRESULT CfConvertToPlaceholder( HANDLE // FileHandle, LPCVOID FileIdentity, DWORD FileIdentityLength, CF_CONVERT_FLAGS ConvertFlags, USN *ConvertUsn, LPOVERLAPPED // Overlapped ); [DllImport(Lib.CldApi, SetLastError = false, ExactSpelling = true)] [PInvokeData("cfapi.h", MSDNShortId = "FDDE9CB0-E1A2-46D6-94E0-228495675271")] public static extern HRESULT CfConvertToPlaceholder(HFILE FileHandle, [In, Optional] IntPtr FileIdentity, uint FileIdentityLength, CF_CONVERT_FLAGS ConvertFlags, out USN ConvertUsn, [In, Out, Optional] IntPtr Overlapped); /// Converts a normal file/directory to a placeholder file/directory. /// Handle to the file or directory to be converted. /// /// A user mode buffer that contains the opaque file or directory information supplied by the caller. Optional if the caller is not /// dehydrating the file at the same time, or if the caller is converting a directory. Cannot exceed 4KB in size. /// /// Length, in bytes, of the FileIdentity. /// Placeholder conversion flags. /// The final USN value after convert actions are performed. /// /// /// When specified and combined with an asynchronous FileHandle, Overlapped allows the platform to perform the /// CfConvertToPlaceholder call asynchronously. See the Remarks for more details. /// /// If not specified, the platform will perform the API call synchronously, regardless of how the handle was created. /// /// If this function succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code. /// /// /// In the file case, the caller must acquire an exclusive handle to the file if it also intends to dehydrate the file at the same /// time or data corruption can occur. To minimize the impact on user applications it is highly recommended that the caller obtain /// the exclusiveness using proper oplocks (via CfOpenFileWithOplock) as opposed to using a share-nothing handle. /// /// To convert a placeholder: /// /// /// /// The file or directory to be converted must be contained in a registered sync root tree; it can be the sync root directory /// itself, or any descendant directory; otherwise, the call with be failed with HRESULT(ERROR_CLOUD_FILE_NOT_UNDER_SYNC_ROOT). /// /// /// /// /// If dehydration is requested, the sync root must be registered with a valid hydration policy that is not /// CF_HYDRATION_POLICY_ALWAYS_FULL; otherwise the call will be failed with HRESULT(ERROR_CLOUD_FILE_NOT_SUPPORTED). /// /// /// /// If dehydration is requested, the placeholder must not be pinned locally or the call with be failed with HRESULT(ERROR_CLOUD_FILE_PINNED). /// /// /// If dehydration is requested, the placeholder must be in sync or the call with be failed with HRESULT(ERROR_CLOUD_FILE_NOT_IN_SYNC). /// /// /// /// The caller must have WRITE_DATA or WRITE_DAC access to the file or directory to be converted. Otherwise the operation will be /// failed with HRESULT(ERROR_CLOUD_FILE_ACCESS_DENIED). /// /// /// /// /// If the API returns HRESULT_FROM_WIN32(ERROR_IO_PENDING) when using Overlapped asynchronously, the caller can then wait using GetOverlappedResult. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/cfapi/nf-cfapi-cfconverttoplaceholder HRESULT CfConvertToPlaceholder( HANDLE // FileHandle, LPCVOID FileIdentity, DWORD FileIdentityLength, CF_CONVERT_FLAGS ConvertFlags, USN *ConvertUsn, LPOVERLAPPED // Overlapped ); [DllImport(Lib.CldApi, SetLastError = false, ExactSpelling = true)] [PInvokeData("cfapi.h", MSDNShortId = "FDDE9CB0-E1A2-46D6-94E0-228495675271")] public static unsafe extern HRESULT CfConvertToPlaceholder(HFILE FileHandle, [In, Optional] IntPtr FileIdentity, uint FileIdentityLength, CF_CONVERT_FLAGS ConvertFlags, [Out, Optional] USN* 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. /// /// [in] A handle to the placeholder file. /// [in] The starting point offset of the placeholder file data. /// /// [in] The length, in bytes, of the placeholder file whose data must be invalidated locally on the disk after the API completes /// successfully. A length of -1 signifies end of file. /// /// [in] Placeholder dehydration flags. /// /// /// [in, out, optional] When specified and combined with an asynchronous FileHandle, Overlapped allows the platform to perform the /// CfDehydratePlaceholder call asynchronously. See the Remarks for more details. /// /// If not specified, the platform will perform the API call synchronously, regardless of how the handle was created. /// /// This function does not return a value. /// /// /// The caller must acquire an exclusive handle to the file or data corruption can occur. To minimize the impact on user /// applications it is highly recommended that the caller obtain the exclusiveness using proper oplocks (via /// CfOpenFileWithOplock) as opposed to using a share-nothing handle. /// /// /// If the API returns HRESULT_FROM_WIN32(ERROR_IO_PENDING) when using Overlapped asynchronously, the caller can then wait using GetOverlappedResult. /// /// // https://docs.microsoft.com/en-us/previous-versions/mt827480(v=vs.85) void STDAPI CfDehydratePlaceholder( _In_ HANDLE FileHandle, // _In_ LARGE_INTEGER StartingOffset, _In_ LARGE_INTEGER Length, _In_ CF_HYDRATE_FLAGS DehydrateFlags, _Inout_opt_ LPOVERLAPPED // Overlapped ); [DllImport(Lib.CldApi, SetLastError = false, ExactSpelling = true)] [PInvokeData("CfApi.h")] public static extern HRESULT CfDehydratePlaceholder(HFILE FileHandle, long StartingOffset, long Length, CF_DEHYDRATE_FLAGS DehydrateFlags, [In, Out, Optional] IntPtr Overlapped); /// /// 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. /// /// [in] A handle to the placeholder file. /// [in] The starting point offset of the placeholder file data. /// /// [in] The length, in bytes, of the placeholder file whose data must be invalidated locally on the disk after the API completes /// successfully. A length of -1 signifies end of file. /// /// [in] Placeholder dehydration flags. /// /// /// [in, out, optional] When specified and combined with an asynchronous FileHandle, Overlapped allows the platform to perform the /// CfDehydratePlaceholder call asynchronously. See the Remarks for more details. /// /// If not specified, the platform will perform the API call synchronously, regardless of how the handle was created. /// /// This function does not return a value. /// /// /// The caller must acquire an exclusive handle to the file or data corruption can occur. To minimize the impact on user /// applications it is highly recommended that the caller obtain the exclusiveness using proper oplocks (via /// CfOpenFileWithOplock) as opposed to using a share-nothing handle. /// /// /// If the API returns HRESULT_FROM_WIN32(ERROR_IO_PENDING) when using Overlapped asynchronously, the caller can then wait using GetOverlappedResult. /// /// // https://docs.microsoft.com/en-us/previous-versions/mt827480(v=vs.85) void STDAPI CfDehydratePlaceholder( _In_ HANDLE FileHandle, // _In_ LARGE_INTEGER StartingOffset, _In_ LARGE_INTEGER Length, _In_ CF_HYDRATE_FLAGS DehydrateFlags, _Inout_opt_ LPOVERLAPPED // Overlapped ); [DllImport(Lib.CldApi, SetLastError = false, ExactSpelling = true)] [PInvokeData("CfApi.h")] public static unsafe extern HRESULT CfDehydratePlaceholder(HFILE FileHandle, long StartingOffset, long Length, CF_DEHYDRATE_FLAGS DehydrateFlags, [In, Out] NativeOverlapped* Overlapped); /// 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. /// /// This removes the communication channel with the platform that was previously established using CfConnectSyncRoot. /// /// A sync provider can still receive callbacks during the CfDisconnectSyncRoot call, and the provider is free to choose /// whether the call needs to fail or be serviced. Either choice will not cause disruptions to the sync provider. /// /// /// After a call to CfDisconnectSyncRoot returns, the sync provider will no longer receive callbacks and the platform will /// fail any operation that depends on said callbacks. /// /// /// A sync provider should have WRITE_DATA or WRITE_DAC access to the sync root to be disconnected or a call to /// CfDisconnectSyncRoot will be failed with HRESULT(ERROR_CLOUD_FILE_ACCESS_DENIED). Also, if the sync root has not been /// previously connected, the call will be failed with invalid parameters. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/cfapi/nf-cfapi-cfdisconnectsyncroot HRESULT CfDisconnectSyncRoot( // CF_CONNECTION_KEY ConnectionKey ); [DllImport(Lib.CldApi, SetLastError = false, ExactSpelling = true)] [PInvokeData("cfapi.h", MSDNShortId = "AB09804A-257B-49A2-861E-B6E102D45182")] public static extern HRESULT CfDisconnectSyncRoot(CF_CONNECTION_KEY ConnectionKey); /// /// The main entry point for all connection key based placeholder operations. It is intended to be used by a sync provider to /// respond to various callbacks from the platform. /// /// Information about an operation on a placeholder. /// Parameters of an operation on a placeholder. /// If this function succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code. /// /// /// A valid call to CfExecute will reset the timers of all pending callback requests that belong to the same sync provider process. /// /// /// CfExecute takes two variable-sized arguments, i.e., CF_OPERATION_INFO and CF_OPERATION_PARAMETERS, with one identifying /// the operation type and the other supplying detailed operation parameters. Both arguments start with a StructSize field at /// the beginning of the corresponding structures. Callers of CfExecute are responsible for accurate accounting of the /// structure size. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/cfapi/nf-cfapi-cfexecute HRESULT CfExecute( const CF_OPERATION_INFO *OpInfo, // CF_OPERATION_PARAMETERS *OpParams ); [DllImport(Lib.CldApi, SetLastError = false, ExactSpelling = true)] [PInvokeData("cfapi.h", MSDNShortId = "6AC8958D-B060-4468-9811-9BAB0E6A06D3")] public static extern HRESULT CfExecute(in CF_OPERATION_INFO OpInfo, ref CF_OPERATION_PARAMETERS OpParams); /// Allows the sync provider to query the current correlation vector for a given placeholder file. /// The handle to the placeholder file. /// The correlation vector for the FileHandle. /// If this function succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code. // https://docs.microsoft.com/en-us/windows/win32/api/cfapi/nf-cfapi-cfgetcorrelationvector HRESULT CfGetCorrelationVector( HANDLE // FileHandle, PCORRELATION_VECTOR CorrelationVector ); [DllImport(Lib.CldApi, SetLastError = false, ExactSpelling = true)] [PInvokeData("cfapi.h", MSDNShortId = "3DB0AAFE-82DC-4707-8DB6-C52D4A9B2771")] public static extern HRESULT CfGetCorrelationVector(HFILE FileHandle, out CORRELATION_VECTOR CorrelationVector); /// Gets various characteristics of a placeholder file or folder. /// A handle to the placeholder whose information will be queried. /// Placeholder information. This can be set to either CF_PLACEHOLDER_STANDARD_INFO or CF_PLACEHOLDER_BASIC_INFO. /// A pointer to a buffer that will receive information. /// The length of the InfoBuffer, in bytes. /// The number of bytes returned in the InfoBuffer. /// If this function succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code. // https://docs.microsoft.com/en-us/windows/win32/api/cfapi/nf-cfapi-cfgetplaceholderinfo HRESULT CfGetPlaceholderInfo( HANDLE // FileHandle, CF_PLACEHOLDER_INFO_CLASS InfoClass, PVOID InfoBuffer, DWORD InfoBufferLength, PDWORD ReturnedLength ); [DllImport(Lib.CldApi, SetLastError = false, ExactSpelling = true)] [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. /// Offset of the starting point of the range of data. /// Length of the range of data. /// Pointer to a buffer to receive the data. /// Length, in bytes, of InfoBuffer. /// The length of the returned range of placeholder data in the InfoBuffer. /// If this function succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code. /// /// Unlike most placeholder APIs that take a file handle, this one does not modify the file in any way, therefore the file handle /// only requires READ_ATTRIBUTES access. /// // https://docs.microsoft.com/en-us/windows/win32/api/cfapi/nf-cfapi-cfgetplaceholderrangeinfo HRESULT CfGetPlaceholderRangeInfo( // HANDLE FileHandle, CF_PLACEHOLDER_RANGE_INFO_CLASS InfoClass, LARGE_INTEGER StartingOffset, LARGE_INTEGER Length, PVOID // 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, out uint ReturnedLength); /// Gets a set of placeholder states based on the FileAttributes and ReparseTag values of the file. /// The file attribute information. /// The reparse tag information from a file. /// Can include CF_PLACEHOLDER_STATE; The placeholder state. /// /// The FileAttributes and ReparseTag can be obtained by listing the directory containing the file or by directly querying /// FileAttributeTagInfo on the file. /// // https://docs.microsoft.com/en-us/windows/win32/api/cfapi/nf-cfapi-cfgetplaceholderstatefromattributetag CF_PLACEHOLDER_STATE // CfGetPlaceholderStateFromAttributeTag( DWORD FileAttributes, DWORD ReparseTag ); [DllImport(Lib.CldApi, SetLastError = false, ExactSpelling = true)] [PInvokeData("cfapi.h", MSDNShortId = "D7B4FB60-3388-489F-9F55-153B53BBDA9F")] public static extern CF_PLACEHOLDER_STATE CfGetPlaceholderStateFromAttributeTag(FileFlagsAndAttributes FileAttributes, uint ReparseTag); /// Gets a set of placeholder states based on the various information of the file. /// An info buffer about the file. /// An info class so the function knows how to interpret the InfoBuffer. /// Can include CF_PLACEHOLDER_STATE; The placeholder state. /// /// /// The input is a buffer containing information returned by GetFileInformationByHandleEx, and the corresponding InfoClass so the /// API knows how to interpret the buffer. /// /// /// Not all information classes supported by GetFileInformationByHandleEx are supported by this API. If the FileAttributes and /// ReparseTag can’t be extracted from a given information class, this API will return CF_PLACEHOLDER_STATE_INVALID and set last /// error properly. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/cfapi/nf-cfapi-cfgetplaceholderstatefromfileinfo CF_PLACEHOLDER_STATE // CfGetPlaceholderStateFromFileInfo( LPCVOID InfoBuffer, FILE_INFO_BY_HANDLE_CLASS InfoClass ); [DllImport(Lib.CldApi, SetLastError = false, ExactSpelling = true)] [PInvokeData("cfapi.h", MSDNShortId = "33DB8FAC-D2C9-4BBB-8505-1D9A680EA2BF")] public static extern CF_PLACEHOLDER_STATE CfGetPlaceholderStateFromFileInfo(IntPtr InfoBuffer, FILE_INFO_BY_HANDLE_CLASS InfoClass); /// Gets a set of placeholder states based on the WIN32_FIND_DATA structure. /// The find data information on the file. /// Can include CF_PLACEHOLDER_STATE; The placeholder state. /// The WIN32_FIND_DATA structure is obtained from the Win32 FindFirstFile/FindNextFile functions. // https://docs.microsoft.com/en-us/windows/win32/api/cfapi/nf-cfapi-cfgetplaceholderstatefromfinddata CF_PLACEHOLDER_STATE // CfGetPlaceholderStateFromFindData( const WIN32_FIND_DATA *FindData ); [DllImport(Lib.CldApi, SetLastError = false, ExactSpelling = true)] [PInvokeData("cfapi.h", MSDNShortId = "1A8104BC-E9D1-4846-B91F-4CBEDB1FC542")] public static extern CF_PLACEHOLDER_STATE CfGetPlaceholderStateFromFindData(in WIN32_FIND_DATA FindData); /// Gets the platform version information. /// The platform version information. See CF_PLATFORM_INFO for more details. /// If this function succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code. // https://docs.microsoft.com/en-us/windows/win32/api/cfapi/nf-cfapi-cfgetplatforminfo HRESULT CfGetPlatformInfo( CF_PLATFORM_INFO // *PlatformVersion ); [DllImport(Lib.CldApi, SetLastError = false, ExactSpelling = true)] [PInvokeData("cfapi.h", MSDNShortId = "BCF51702-87C1-405B-A3FF-98F5D0DDA8D5")] public static extern HRESULT CfGetPlatformInfo(out CF_PLATFORM_INFO PlatformVersion); /// Gets various characteristics of the sync root containing a given file specified by a file handle. /// Handle of the file under the sync root whose information is to be queried. /// Types of sync root information. /// A pointer to a buffer that will receive the sync root information. /// Length, in bytes, of the InfoBuffer. /// The number of bytes returned in the InfoBuffer. /// If this function succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code. /// /// Unlike most placeholder APIs that take a file handle, this one does not modify the file in any way, therefore the file handle /// only requires READ_ATTRIBUTES access. /// // https://docs.microsoft.com/en-us/windows/win32/api/cfapi/nf-cfapi-cfgetsyncrootinfobyhandle HRESULT CfGetSyncRootInfoByHandle( // HANDLE FileHandle, CF_SYNC_ROOT_INFO_CLASS InfoClass, PVOID InfoBuffer, DWORD InfoBufferLength, DWORD *ReturnedLength ); [DllImport(Lib.CldApi, SetLastError = false, ExactSpelling = true)] [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. /// A pointer to a buffer that will receive the sync root information. /// Length, in bytes, of the InfoBuffer. /// /// Length, in bytes, of the returned sync root information. Refer to CfRegisterSyncRoot for details about the sync root information. /// /// If this function succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code. // https://docs.microsoft.com/en-us/windows/win32/api/cfapi/nf-cfapi-cfgetsyncrootinfobypath HRESULT CfGetSyncRootInfoByPath( // LPCWSTR FilePath, CF_SYNC_ROOT_INFO_CLASS InfoClass, PVOID InfoBuffer, DWORD InfoBufferLength, DWORD *ReturnedLength ); [DllImport(Lib.CldApi, SetLastError = false, ExactSpelling = true)] [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. /// If this function succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code. /// /// /// CfGetTransferKey is used as an alternative to CfHydratePlaceholder to proactively initiate data transfer into a placeholder. /// /// /// A sync provider should have READ_DATA or WRITE_DAC access to the file whose transfer key is to be obtained or /// CfGetTransferKey will be failed with HRESULT(ERROR_CLOUD_FILE_ACCESS_DENIED). /// /// /// The TransferKey is valid as long as the FileHandle used to obtain it remains open. The sync provider must pass the TransferKey /// to CfExecute to perform the desired operation on the placholder file or folder. When a TransferKey is no longer being used, it /// must be released using CfReleaseTransferKey. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/cfapi/nf-cfapi-cfgettransferkey HRESULT CfGetTransferKey( HANDLE FileHandle, // CF_TRANSFER_KEY *TransferKey ); [DllImport(Lib.CldApi, SetLastError = false, ExactSpelling = true)] [PInvokeData("cfapi.h", MSDNShortId = "07DDC46A-0C10-4677-A4B0-5A0406BBDAB7")] public static extern HRESULT CfGetTransferKey(HFILE FileHandle, out CF_TRANSFER_KEY TransferKey); /// Converts a protected handle to a Win32 handle so that it can be used with all handle-based Win32 APIs. /// The protected handle to be converted. /// The corresponding Win32 handle. /// /// /// The caller must have referenced the protected handle prior to this call using CfReferenceProtectedHandle to ensure that the use /// of the Win32 handle is tracked, and the Win32 API call that consumes the Win32 handle is synchronized with the oplock break /// notification acknowledgment. /// /// The caller must release the reference on the protected handle after being done with the Win32 handle using CfReleaseProtectedHandle. /// In no circumstances should the caller close the Win32 handle returned using CfCloseHandle. /// // https://docs.microsoft.com/en-us/windows/win32/api/cfapi/nf-cfapi-cfgetwin32handlefromprotectedhandle HANDLE // CfGetWin32HandleFromProtectedHandle( HANDLE ProtectedHandle ); [DllImport(Lib.CldApi, SetLastError = false, ExactSpelling = true)] [PInvokeData("cfapi.h", MSDNShortId = "8C54B6F3-7709-4021-8965-E96B74DD3319")] public static extern HFILE CfGetWin32HandleFromProtectedHandle(HCFFILE ProtectedHandle); /// /// Hydrates a placeholder file by ensuring that the specified byte range is present on-disk in the placeholder. This is valid for /// files only. /// /// Handle of the placeholder file to be hydrated. An attribute or no-access handle is sufficient. /// The starting point offset of the placeholder file data. /// /// The length, in bytes, of the placeholder file whose data must be available locally on the disk after the API completes /// successfully. A length of -1 signifies end of file. /// /// Placeholder hydration flags. /// /// /// When specified and combined with an asynchronous FileHandle, Overlapped allows the platform to perform the /// CfHydratePlaceholder call asynchronously. See the Remarks for more details. /// /// If not specified, the platform will perform the API call synchronously, regardless of how the handle was created. /// /// If this function succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code. /// /// The caller must have READ_DATA or WRITE_DAC access to the placeholder to be hydrated. /// /// If the API returns HRESULT_FROM_WIN32(ERROR_IO_PENDING) when using Overlapped asynchronously, the caller can then wait using GetOverlappedResult. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/cfapi/nf-cfapi-cfhydrateplaceholder HRESULT CfHydratePlaceholder( HANDLE // FileHandle, LARGE_INTEGER StartingOffset, LARGE_INTEGER Length, CF_HYDRATE_FLAGS HydrateFlags, LPOVERLAPPED Overlapped ); [DllImport(Lib.CldApi, SetLastError = false, ExactSpelling = true)] [PInvokeData("cfapi.h", MSDNShortId = "4FFD7580-BF59-48D0-B6D7-516559914096")] public static extern HRESULT CfHydratePlaceholder(HFILE FileHandle, long StartingOffset = 0, long Length = -1, CF_HYDRATE_FLAGS HydrateFlags = 0, [In, Out] IntPtr Overlapped = default); /// /// Hydrates a placeholder file by ensuring that the specified byte range is present on-disk in the placeholder. This is valid for /// files only. /// /// Handle of the placeholder file to be hydrated. An attribute or no-access handle is sufficient. /// The starting point offset of the placeholder file data. /// /// The length, in bytes, of the placeholder file whose data must be available locally on the disk after the API completes /// successfully. A length of -1 signifies end of file. /// /// Placeholder hydration flags. /// /// /// When specified and combined with an asynchronous FileHandle, Overlapped allows the platform to perform the /// CfHydratePlaceholder call asynchronously. See the Remarks for more details. /// /// If not specified, the platform will perform the API call synchronously, regardless of how the handle was created. /// /// If this function succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code. /// /// The caller must have READ_DATA or WRITE_DAC access to the placeholder to be hydrated. /// /// If the API returns HRESULT_FROM_WIN32(ERROR_IO_PENDING) when using Overlapped asynchronously, the caller can then wait using GetOverlappedResult. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/cfapi/nf-cfapi-cfhydrateplaceholder HRESULT CfHydratePlaceholder( HANDLE // FileHandle, LARGE_INTEGER StartingOffset, LARGE_INTEGER Length, CF_HYDRATE_FLAGS HydrateFlags, LPOVERLAPPED Overlapped ); [DllImport(Lib.CldApi, SetLastError = false, ExactSpelling = true)] [PInvokeData("cfapi.h", MSDNShortId = "4FFD7580-BF59-48D0-B6D7-516559914096")] public static unsafe extern HRESULT CfHydratePlaceholder(HFILE FileHandle, long StartingOffset, long Length, CF_HYDRATE_FLAGS HydrateFlags, [In, Out] NativeOverlapped* Overlapped); /// /// Opens an asynchronous opaque handle to a file or directory (for both normal and placeholder files) and sets up a proper oplock /// on it based on the open flags. /// /// Fully qualified path to the file or directory to be opened. /// Flags to specify permissions on opening the file. /// /// An opaque handle to the file or directory that is just opened. Note that this is not a normal Win32 handle and hence cannot be /// used with non-CfApi Win32 APIs directly. /// /// If this function succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code. /// /// /// When the oplock is broken, the API will handle the break notification automatically on behalf of the caller by draining all /// active requests and then closing the underneath Win32 handle. /// /// /// This aims to removing the complexity related to oplock usages. The caller must close the handle returned by /// CfOpenFileWithOplock with CfCloseHandle. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/cfapi/nf-cfapi-cfopenfilewithoplock HRESULT CfOpenFileWithOplock( LPCWSTR // FilePath, CF_OPEN_FILE_FLAGS Flags, PHANDLE ProtectedHandle ); [DllImport(Lib.CldApi, SetLastError = false, ExactSpelling = true)] [PInvokeData("cfapi.h", MSDNShortId = "AFC48080-3B4A-4F6B-9122-25C2A025EA95")] public static extern HRESULT CfOpenFileWithOplock([MarshalAs(UnmanagedType.LPWStr)] string FilePath, CF_OPEN_FILE_FLAGS Flags, out SafeHCFFILE ProtectedHandle); /// Queries a sync provider to get the status of the provider. /// A connection key representing a communication channel with the sync filter. /// The current status of the sync provider. /// If this function succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code. // https://docs.microsoft.com/en-us/windows/win32/api/cfapi/nf-cfapi-cfquerysyncproviderstatus HRESULT CfQuerySyncProviderStatus( // CF_CONNECTION_KEY ConnectionKey, CF_SYNC_PROVIDER_STATUS *ProviderStatus ); [DllImport(Lib.CldApi, SetLastError = false, ExactSpelling = true)] [PInvokeData("cfapi.h", MSDNShortId = "02E6197B-D84A-4E3F-A74C-F5DACAA60AF9")] public static extern HRESULT CfQuerySyncProviderStatus(CF_CONNECTION_KEY ConnectionKey, out CF_SYNC_PROVIDER_STATUS ProviderStatus); /// Allows the caller to reference a protected handle to a Win32 handle which can be used with non-CfApi Win32 APIs. /// The protected handle of a placeholder file. /// If this function succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code. /// /// /// Every CfReferenceProtectedHandle call must be matched with a CfReleaseProtectedHandle call. It is not recommended to /// reference a protected handle for a long period of time, as doing so will prevent the oplock break notification from being acknowledged. /// /// /// The caller should instead break up long running tasks into smaller sub-tasks and reference/release the protected handle for each sub-task. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/cfapi/nf-cfapi-cfreferenceprotectedhandle BOOLEAN CfReferenceProtectedHandle( // HANDLE ProtectedHandle ); [DllImport(Lib.CldApi, SetLastError = false, ExactSpelling = true)] [PInvokeData("cfapi.h", MSDNShortId = "C6281FD6-3A37-4D90-9B19-03DD23949C39")] [return: MarshalAs(UnmanagedType.U1)] public static extern bool CfReferenceProtectedHandle(HCFFILE ProtectedHandle); /// Performs a one time sync root registration. /// The path to the sync root to be registered. /// Contains information about the sync provider and sync root to be registered. /// The policies of the sync root to be registered. /// Flags for registering previous and new sync roots. /// If this function succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code. /// /// /// This can be used at a sync provider install time, first time set up for an individual user, or when a user configures another /// sync root (if this scenario is supported). /// /// /// This performs a one time sync root registration, which allows a sync provider to utilize an entire directory tree structure. /// Note that no two sync roots directory trees can overlap with one another. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/cfapi/nf-cfapi-cfregistersyncroot HRESULT CfRegisterSyncRoot( LPCWSTR // SyncRootPath, const CF_SYNC_REGISTRATION *Registration, const CF_SYNC_POLICIES *Policies, CF_REGISTER_FLAGS RegisterFlags ); [DllImport(Lib.CldApi, SetLastError = false, ExactSpelling = true)] [PInvokeData("cfapi.h", MSDNShortId = "FAD56873-8812-42DC-9975-9507F73BD9E3")] public static extern HRESULT CfRegisterSyncRoot([MarshalAs(UnmanagedType.LPWStr)] string SyncRootPath, in CF_SYNC_REGISTRATION Registration, in CF_SYNC_POLICIES Policies, CF_REGISTER_FLAGS RegisterFlags); /// Releases a protected handle referenced by CfReferenceProtectedHandle. /// The protected handle to be released. /// None // https://docs.microsoft.com/en-us/windows/win32/api/cfapi/nf-cfapi-cfreleaseprotectedhandle void CfReleaseProtectedHandle( HANDLE // ProtectedHandle ); [DllImport(Lib.CldApi, SetLastError = false, ExactSpelling = true)] [PInvokeData("cfapi.h", MSDNShortId = "BB63C5EE-92D7-4051-8198-09F50BBC75C5")] public static extern void CfReleaseProtectedHandle(HCFFILE ProtectedHandle); /// Releases a transfer key obtained by CfGetTransferKey. /// The file handle of the placeholder. /// An opaque handle to the placeholder. /// None // https://docs.microsoft.com/en-us/windows/win32/api/cfapi/nf-cfapi-cfreleasetransferkey void CfReleaseTransferKey( HANDLE // 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, 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. /// An opaque handle to the placeholder. /// The total progress of the sync provider in response to a fetch data callback. /// The completed progress of the sync provider in response to a fetch data callback. /// If this function succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code. // https://docs.microsoft.com/en-us/windows/win32/api/cfapi/nf-cfapi-cfreportproviderprogress HRESULT CfReportProviderProgress( // CF_CONNECTION_KEY ConnectionKey, CF_TRANSFER_KEY TransferKey, LARGE_INTEGER ProviderProgressTotal, LARGE_INTEGER // ProviderProgressCompleted ); [DllImport(Lib.CldApi, SetLastError = false, ExactSpelling = true)] [PInvokeData("cfapi.h", MSDNShortId = "33AB46FD-200E-40FF-B061-5842C6433069")] public static extern HRESULT CfReportProviderProgress(CF_CONNECTION_KEY ConnectionKey, CF_TRANSFER_KEY TransferKey, long ProviderProgressTotal, long ProviderProgressCompleted); /// /// Allows a sync provider to notify the platform of its status on a specified sync root without having to connect with a call to /// CfConnectSyncRoot first. /// /// Path to the sync root. /// /// The sync status to report; if null, clears the previously-saved sync status. For more information, see the Remarks /// section, below. /// /// If this function succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code. /// /// /// When a non-null CF_SYNC_STATUS is provided in the SyncStatus parameter, the information will be remembered on the sync root /// until it is cleared explicitly by the sync provider or when the machine reboots. The platform will query this information upon /// any failed operations on a cloud file placeholder, using the following process: /// /// /// /// /// /// /// /// /// /// /// /// /// /// CfReportSyncStatus clears the previously-saved sync status when being called with a null sync status. No change /// will be made to the existing sync status if the function call fails. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/cfapi/nf-cfapi-cfreportsyncstatus HRESULT CfReportSyncStatus( LPCWSTR // SyncRootPath, CF_SYNC_STATUS *SyncStatus ); [DllImport(Lib.CldApi, SetLastError = false, ExactSpelling = true)] [PInvokeData("cfapi.h", MSDNShortId = "DC77D18A-CBF4-4172-815A-AB49A48D10B3")] public static extern HRESULT CfReportSyncStatus([MarshalAs(UnmanagedType.LPWStr)] string SyncRootPath, in CF_SYNC_STATUS SyncStatus); /// /// Allows a sync provider to notify the platform of its status on a specified sync root without having to connect with a call to /// CfConnectSyncRoot first. /// /// Path to the sync root. /// /// The sync status to report; if null, clears the previously-saved sync status. For more information, see the Remarks /// section, below. /// /// If this function succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code. /// /// /// When a non-null CF_SYNC_STATUS is provided in the SyncStatus parameter, the information will be remembered on the sync root /// until it is cleared explicitly by the sync provider or when the machine reboots. The platform will query this information upon /// any failed operations on a cloud file placeholder, using the following process: /// /// /// /// /// /// /// /// /// /// /// /// /// /// CfReportSyncStatus clears the previously-saved sync status when being called with a null sync status. No change /// will be made to the existing sync status if the function call fails. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/cfapi/nf-cfapi-cfreportsyncstatus HRESULT CfReportSyncStatus( LPCWSTR // SyncRootPath, CF_SYNC_STATUS *SyncStatus ); [DllImport(Lib.CldApi, SetLastError = false, ExactSpelling = true)] [PInvokeData("cfapi.h", MSDNShortId = "DC77D18A-CBF4-4172-815A-AB49A48D10B3")] public static extern HRESULT CfReportSyncStatus([MarshalAs(UnmanagedType.LPWStr)] string SyncRootPath, [In, Optional] IntPtr SyncStatus); /// /// Reverts a placeholder back to a regular file, stripping away all special characteristics such as the reparse tag, the file /// identity, etc. /// /// /// A handle to the file or directory placeholder that is about to be reverted to normal file or directory. An attribute or /// no-access handle is sufficient. /// /// Placeholder revert flags. /// /// /// When specified and combined with an asynchronous FileHandle, Overlapped allows the platform to perform the /// CfRevertPlaceholder call asynchronously. See the Remarks for more details. /// /// If not specified, the platform will perform the API call synchronously, regardless of how the handle was created. /// /// If this function succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code. /// /// The caller must have WRITE_DATA or WRITE_DAC access to the placeholder to be reverted. /// /// If the placeholder is not already fully hydrated at the time of the call, then the filter will send a FETCH_DATA callback to the /// sync provider to hydrate the file. If the file can’t be hydrated, the revert will fail. /// /// /// If the API returns HRESULT_FROM_WIN32(ERROR_IO_PENDING) when using Overlapped asynchronously, the caller can then wait using GetOverlappedResult. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/cfapi/nf-cfapi-cfrevertplaceholder HRESULT CfRevertPlaceholder( HANDLE // FileHandle, CF_REVERT_FLAGS RevertFlags, LPOVERLAPPED Overlapped ); [DllImport(Lib.CldApi, SetLastError = false, ExactSpelling = true)] [PInvokeData("cfapi.h", MSDNShortId = "D5404BB6-A066-4B5F-A355-A11A107610CE")] public static extern HRESULT CfRevertPlaceholder(HFILE FileHandle, CF_REVERT_FLAGS RevertFlags, [In, Out, Optional] IntPtr Overlapped); /// /// Reverts a placeholder back to a regular file, stripping away all special characteristics such as the reparse tag, the file /// identity, etc. /// /// /// A handle to the file or directory placeholder that is about to be reverted to normal file or directory. An attribute or /// no-access handle is sufficient. /// /// Placeholder revert flags. /// /// /// When specified and combined with an asynchronous FileHandle, Overlapped allows the platform to perform the /// CfRevertPlaceholder call asynchronously. See the Remarks for more details. /// /// If not specified, the platform will perform the API call synchronously, regardless of how the handle was created. /// /// If this function succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code. /// /// The caller must have WRITE_DATA or WRITE_DAC access to the placeholder to be reverted. /// /// If the placeholder is not already fully hydrated at the time of the call, then the filter will send a FETCH_DATA callback to the /// sync provider to hydrate the file. If the file can’t be hydrated, the revert will fail. /// /// /// If the API returns HRESULT_FROM_WIN32(ERROR_IO_PENDING) when using Overlapped asynchronously, the caller can then wait using GetOverlappedResult. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/cfapi/nf-cfapi-cfrevertplaceholder HRESULT CfRevertPlaceholder( HANDLE // FileHandle, CF_REVERT_FLAGS RevertFlags, LPOVERLAPPED Overlapped ); [DllImport(Lib.CldApi, SetLastError = false, ExactSpelling = true)] [PInvokeData("cfapi.h", MSDNShortId = "D5404BB6-A066-4B5F-A355-A11A107610CE")] public static unsafe extern HRESULT CfRevertPlaceholder(HFILE FileHandle, CF_REVERT_FLAGS RevertFlags, [In, Out] NativeOverlapped* Overlapped); /// /// Allows a sync provider to instruct the platform to use a specific correlation vector for telemetry purposes on a placeholder /// file. This is optional. /// /// The handle to the placeholder file. /// A specific correlation vector to be associated with the FileHandle. /// If this function succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code. /// /// The platform automatically assigns a correlation vector to each file when it is first opened, and provides this correlation /// vector with each callback to the sync provider as part of the common CF_CALLBACK_INFO. It is suggested that the sync engine call /// this function to increment the last digit of the correlation vector “clock” as the sync provider progresses through internal /// stages (as defined by the sync provider) of satisfying the request. /// // https://docs.microsoft.com/en-us/windows/win32/api/cfapi/nf-cfapi-cfsetcorrelationvector HRESULT CfSetCorrelationVector( HANDLE // FileHandle, const PCORRELATION_VECTOR CorrelationVector ); [DllImport(Lib.CldApi, SetLastError = false, ExactSpelling = true)] [PInvokeData("cfapi.h", MSDNShortId = "B9B05D24-BEE5-4BE6-95D5-C28466D69543")] public static extern HRESULT CfSetCorrelationVector(HFILE FileHandle, in CORRELATION_VECTOR CorrelationVector); /// Sets the in-sync state for a placeholder file or folder. /// A handle to the placeholder. The caller must have WRITE_DATA or WRITE_DAC access to the placeholder. /// The in-sync state. See CF_IN_SYNC_STATE for more details. /// The in-sync state flags. See CF_SET_IN_SYNC_FLAGS for more details. /// /// When specified, this instructs the platform to only perform in-sync setting if the file still has the same USN value as the one /// passed in. Passing a pointer to a USN value of 0 on input is the same as passing a NULL pointer. On return, this is the final /// USN value after setting the in-sync state. /// /// If this function succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code. // https://docs.microsoft.com/en-us/windows/win32/api/cfapi/nf-cfapi-cfsetinsyncstate HRESULT CfSetInSyncState( HANDLE FileHandle, // CF_IN_SYNC_STATE InSyncState, CF_SET_IN_SYNC_FLAGS InSyncFlags, USN *InSyncUsn ); [DllImport(Lib.CldApi, SetLastError = false, ExactSpelling = true)] [PInvokeData("cfapi.h", MSDNShortId = "1CB7955D-E530-4F34-8D67-BC608F8B6AF1")] public static extern HRESULT CfSetInSyncState(HFILE FileHandle, CF_IN_SYNC_STATE InSyncState, CF_SET_IN_SYNC_FLAGS InSyncFlags, ref USN InSyncUsn); /// Sets the in-sync state for a placeholder file or folder. /// A handle to the placeholder. The caller must have WRITE_DATA or WRITE_DAC access to the placeholder. /// The in-sync state. See CF_IN_SYNC_STATE for more details. /// The in-sync state flags. See CF_SET_IN_SYNC_FLAGS for more details. /// /// When specified, this instructs the platform to only perform in-sync setting if the file still has the same USN value as the one /// passed in. Passing a pointer to a USN value of 0 on input is the same as passing a NULL pointer. On return, this is the final /// USN value after setting the in-sync state. /// /// If this function succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code. // https://docs.microsoft.com/en-us/windows/win32/api/cfapi/nf-cfapi-cfsetinsyncstate HRESULT CfSetInSyncState( HANDLE FileHandle, // CF_IN_SYNC_STATE InSyncState, CF_SET_IN_SYNC_FLAGS InSyncFlags, USN *InSyncUsn ); [DllImport(Lib.CldApi, SetLastError = false, ExactSpelling = true)] [PInvokeData("cfapi.h", MSDNShortId = "1CB7955D-E530-4F34-8D67-BC608F8B6AF1")] public static extern HRESULT CfSetInSyncState(HFILE FileHandle, CF_IN_SYNC_STATE InSyncState, CF_SET_IN_SYNC_FLAGS InSyncFlags, [In, Optional] IntPtr InSyncUsn); /// /// This sets the pin state of a placeholder, used to represent a user’s intent. Any application (not just the sync provider) can /// call this function. /// /// The handle of the placeholder file. The caller must have READ_DATA or WRITE_DAC access to the placeholder. /// The pin state of the placeholder file. /// The pin state flags. /// Allows the call to be performed asynchronously. See the Remarks section for more details. /// If this function succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code. /// /// When specified and combined with an asynchronous FileHandle, Overlapped allows the platform to perform the call asynchronously. /// /// The caller must have initialized the overlapped structure with an event to wait on. If this returns /// HRESULT_FROM_WIN32(ERROR_IO_PENDING), the caller can then wait using GetOverlappedResult. If not specified, the platform will /// perform the API call synchronously, regardless of how the handle was created. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/cfapi/nf-cfapi-cfsetpinstate HRESULT CfSetPinState( HANDLE FileHandle, // CF_PIN_STATE PinState, CF_SET_PIN_FLAGS PinFlags, LPOVERLAPPED Overlapped ); [DllImport(Lib.CldApi, SetLastError = false, ExactSpelling = true)] [PInvokeData("cfapi.h", MSDNShortId = "8B279914-E23A-479B-8621-E83DE1978597")] public static extern HRESULT CfSetPinState(HFILE FileHandle, CF_PIN_STATE PinState, CF_SET_PIN_FLAGS PinFlags, [In, Out, Optional] IntPtr Overlapped); /// /// This sets the pin state of a placeholder, used to represent a user’s intent. Any application (not just the sync provider) can /// call this function. /// /// The handle of the placeholder file. The caller must have READ_DATA or WRITE_DAC access to the placeholder. /// The pin state of the placeholder file. /// The pin state flags. /// Allows the call to be performed asynchronously. See the Remarks section for more details. /// If this function succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code. /// /// When specified and combined with an asynchronous FileHandle, Overlapped allows the platform to perform the call asynchronously. /// /// The caller must have initialized the overlapped structure with an event to wait on. If this returns /// HRESULT_FROM_WIN32(ERROR_IO_PENDING), the caller can then wait using GetOverlappedResult. If not specified, the platform will /// perform the API call synchronously, regardless of how the handle was created. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/cfapi/nf-cfapi-cfsetpinstate HRESULT CfSetPinState( HANDLE FileHandle, // CF_PIN_STATE PinState, CF_SET_PIN_FLAGS PinFlags, LPOVERLAPPED Overlapped ); [DllImport(Lib.CldApi, SetLastError = false, ExactSpelling = true)] [PInvokeData("cfapi.h", MSDNShortId = "8B279914-E23A-479B-8621-E83DE1978597")] public static unsafe extern HRESULT CfSetPinState(HFILE FileHandle, CF_PIN_STATE PinState, CF_SET_PIN_FLAGS PinFlags, [In, Out] NativeOverlapped* Overlapped); /// Unregisters a previously registered sync root. /// The path to the sync root to be unregistered. /// If this function succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code. /// /// /// Unregisters a sync root that was registered with CfRegisterSyncRoot. This is typically called at the sync provider uninstall /// time, when a user account is deleted, or when a user opts to no longer sync a directory tree (if supported by the sync provider). /// /// /// The sync provider should have WRITE_DATA or WRITE_DAC access to the sync root to be unregistered, or unregistration will fail /// with: HRESULT(ERROR_CLOUD_FILE_ACCESS_DENIED). /// /// Unregisters a sync root by traversing the directory tree of the sync root. /// For placeholder files: /// /// /// If a placeholder file is fully hydrated, it is reverted back to a "normal" file. /// /// /// If a placeholder file is not hydrated, it is permanently deleted from the local machine. /// /// /// For placeholder directories: /// /// /// If a placeholder directory is fully populated, it is reverted back to a "normal" directory. /// /// /// If a placeholder directory is not fully populated, the directory is permanently deleted from the local machine. /// /// /// /// Note If the placeholder files or directories cannot be reverted or deleted, it will be skipped, and the unregistering /// process will continue until the full sync root tree has been traversed. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/cfapi/nf-cfapi-cfunregistersyncroot HRESULT CfUnregisterSyncRoot( LPCWSTR // SyncRootPath ); [DllImport(Lib.CldApi, SetLastError = false, ExactSpelling = true)] [PInvokeData("cfapi.h", MSDNShortId = "B4DA85DB-A63A-45EB-9F71-9395AC026A0C")] public static extern HRESULT CfUnregisterSyncRoot([MarshalAs(UnmanagedType.LPWStr)] string SyncRootPath); /// Updates characteristics of the placeholder file or directory. /// A handle to the file or directory whose metadata is to be updated. /// /// File system metadata to be updated for the placeholder. Values of 0 for the metadata indicate there are no updates. /// /// /// A user mode buffer that contains file or directory information supplied by the caller. Should not exceed 4KB in size. /// /// Length, in bytes, of the FileIdentity. /// /// A range of an existing placeholder that will no longer be considered valid after the call to CfUpdatePlaceholder. /// /// The count of a series of discrete DehydrateRangeArray partitions of placeholder data. /// Update flags for placeholders. /// /// /// On input, UpdateUsn instructs the platform to only perform the update if the file still has the same USN value as the one passed /// in. This serves a similar purpose to CF_UPDATE_FLAG_VERIFY_IN_SYNC but also encompasses local metadata changes. /// /// On return, UpdateUsn receives the final USN value after update actions were performed. /// /// /// /// When specified and combined with an asynchronous FileHandle, Overlapped allows the platform to perform the /// CfUpdatePlaceholder call asynchronously. See the Remarks for more details. /// /// If not specified, the platform will perform the API call synchronously, regardless of how the handle was created. /// /// If this function succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code. /// /// To update a placeholder: /// /// /// /// The placeholder to be updated must be contained in a registered sync root tree; it can be the sync root directory itself, or any /// descendant directory; otherwise, the call with be failed with HRESULT(ERROR_CLOUD_FILE_NOT_UNDER_SYNC_ROOT). /// /// /// /// /// If dehydration is requested, the sync root must be registered with a valid hydration policy that is not /// CF_HYDRATION_POLICY_ALWAYS_FULL; otherwise the call will be failed with HRESULT(ERROR_CLOUD_FILE_NOT_SUPPORTED). /// /// /// /// If dehydration is requested, the placeholder must not be pinned locally or the call with be failed with HRESULT(ERROR_CLOUD_FILE_PINNED). /// /// /// If dehydration is requested, the placeholder must be in sync or the call with be failed with HRESULT(ERROR_CLOUD_FILE_NOT_IN_SYNC). /// /// /// /// The caller must have WRITE_DATA or WRITE_DAC access to the placeholder to be updated. Otherwise the operation will be failed /// with HRESULT(ERROR_CLOUD_FILE_ACCESS_DENIED). /// /// /// /// /// If the API returns HRESULT_FROM_WIN32(ERROR_IO_PENDING) when using Overlapped asynchronously, the caller can then wait using GetOverlappedResult. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/cfapi/nf-cfapi-cfupdateplaceholder HRESULT CfUpdatePlaceholder( HANDLE // FileHandle, const CF_FS_METADATA *FsMetadata, LPCVOID FileIdentity, DWORD FileIdentityLength, const CF_FILE_RANGE // *DehydrateRangeArray, DWORD DehydrateRangeCount, CF_UPDATE_FLAGS UpdateFlags, USN *UpdateUsn, LPOVERLAPPED Overlapped ); [DllImport(Lib.CldApi, SetLastError = false, ExactSpelling = true)] [PInvokeData("cfapi.h", MSDNShortId = "13F2BF9A-505F-4CFB-B008-7DDE85A3C581")] public static extern HRESULT CfUpdatePlaceholder(HFILE FileHandle, in CF_FS_METADATA FsMetadata, [In] IntPtr FileIdentity, uint FileIdentityLength, [In, Optional, MarshalAs(UnmanagedType.LPArray)] CF_FILE_RANGE[] DehydrateRangeArray, uint DehydrateRangeCount, CF_UPDATE_FLAGS UpdateFlags, ref USN UpdateUsn, [In, Out, Optional] IntPtr Overlapped); /// Updates characteristics of the placeholder file or directory. /// A handle to the file or directory whose metadata is to be updated. /// /// File system metadata to be updated for the placeholder. Values of 0 for the metadata indicate there are no updates. /// /// /// A user mode buffer that contains file or directory information supplied by the caller. Should not exceed 4KB in size. /// /// Length, in bytes, of the FileIdentity. /// /// A range of an existing placeholder that will no longer be considered valid after the call to CfUpdatePlaceholder. /// /// The count of a series of discrete DehydrateRangeArray partitions of placeholder data. /// Update flags for placeholders. /// /// /// On input, UpdateUsn instructs the platform to only perform the update if the file still has the same USN value as the one passed /// in. This serves a similar purpose to CF_UPDATE_FLAG_VERIFY_IN_SYNC but also encompasses local metadata changes. /// /// On return, UpdateUsn receives the final USN value after update actions were performed. /// /// /// /// When specified and combined with an asynchronous FileHandle, Overlapped allows the platform to perform the /// CfUpdatePlaceholder call asynchronously. See the Remarks for more details. /// /// If not specified, the platform will perform the API call synchronously, regardless of how the handle was created. /// /// If this function succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code. /// /// To update a placeholder: /// /// /// /// The placeholder to be updated must be contained in a registered sync root tree; it can be the sync root directory itself, or any /// descendant directory; otherwise, the call with be failed with HRESULT(ERROR_CLOUD_FILE_NOT_UNDER_SYNC_ROOT). /// /// /// /// /// If dehydration is requested, the sync root must be registered with a valid hydration policy that is not /// CF_HYDRATION_POLICY_ALWAYS_FULL; otherwise the call will be failed with HRESULT(ERROR_CLOUD_FILE_NOT_SUPPORTED). /// /// /// /// If dehydration is requested, the placeholder must not be pinned locally or the call with be failed with HRESULT(ERROR_CLOUD_FILE_PINNED). /// /// /// If dehydration is requested, the placeholder must be in sync or the call with be failed with HRESULT(ERROR_CLOUD_FILE_NOT_IN_SYNC). /// /// /// /// The caller must have WRITE_DATA or WRITE_DAC access to the placeholder to be updated. Otherwise the operation will be failed /// with HRESULT(ERROR_CLOUD_FILE_ACCESS_DENIED). /// /// /// /// /// If the API returns HRESULT_FROM_WIN32(ERROR_IO_PENDING) when using Overlapped asynchronously, the caller can then wait using GetOverlappedResult. /// /// // https://docs.microsoft.com/en-us/windows/win32/api/cfapi/nf-cfapi-cfupdateplaceholder HRESULT CfUpdatePlaceholder( HANDLE // FileHandle, const CF_FS_METADATA *FsMetadata, LPCVOID FileIdentity, DWORD FileIdentityLength, const CF_FILE_RANGE // *DehydrateRangeArray, DWORD DehydrateRangeCount, CF_UPDATE_FLAGS UpdateFlags, USN *UpdateUsn, LPOVERLAPPED Overlapped ); [DllImport(Lib.CldApi, SetLastError = false, ExactSpelling = true)] [PInvokeData("cfapi.h", MSDNShortId = "13F2BF9A-505F-4CFB-B008-7DDE85A3C581")] public static unsafe extern HRESULT CfUpdatePlaceholder(HFILE FileHandle, in CF_FS_METADATA FsMetadata, [In] IntPtr FileIdentity, uint FileIdentityLength, [In, Optional, MarshalAs(UnmanagedType.LPArray)] CF_FILE_RANGE[] DehydrateRangeArray, uint DehydrateRangeCount, CF_UPDATE_FLAGS UpdateFlags, ref USN UpdateUsn, [In, Out] NativeOverlapped* Overlapped); /// Updates the current status of the sync provider. /// A connection key representing a communication channel with the sync filter. /// The current status of the sync provider. /// If this function succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code. // https://docs.microsoft.com/en-us/windows/win32/api/cfapi/nf-cfapi-cfupdatesyncproviderstatus HRESULT CfUpdateSyncProviderStatus( // CF_CONNECTION_KEY ConnectionKey, CF_SYNC_PROVIDER_STATUS ProviderStatus ); [DllImport(Lib.CldApi, SetLastError = false, ExactSpelling = true)] [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 { private IntPtr handle; /// Initializes a new instance of the struct. /// An object that represents the pre-existing handle to use. public HCFFILE(IntPtr preexistingHandle) => handle = preexistingHandle; /// Returns an invalid handle by instantiating a object with . public static HCFFILE NULL => new HCFFILE(IntPtr.Zero); /// Gets a value indicating whether this instance is a null handle. public bool IsNull => handle == IntPtr.Zero; /// Performs an explicit conversion from to . /// The handle. /// The result of the conversion. public static explicit operator IntPtr(HCFFILE h) => h.handle; /// Performs an implicit conversion from to . /// The pointer to a handle. /// The result of the conversion. public static implicit operator HCFFILE(IntPtr h) => new HCFFILE(h); /// Implements the operator !=. /// The first handle. /// The second handle. /// The result of the operator. public static bool operator !=(HCFFILE h1, HCFFILE h2) => !(h1 == h2); /// Implements the operator ==. /// The first handle. /// The second handle. /// The result of the operator. public static bool operator ==(HCFFILE h1, HCFFILE h2) => h1.Equals(h2); /// public override bool Equals(object obj) => obj is HCFFILE h ? handle == h.handle : false; /// public override int GetHashCode() => handle.GetHashCode(); /// public IntPtr DangerousGetHandle() => handle; } /// Provides a for that is disposed using . public class SafeHCFFILE : SafeHANDLE { /// Initializes a new instance of the class and assigns an existing handle. /// An object that represents the pre-existing handle to use. /// /// to reliably release the handle during the finalization phase; otherwise, (not recommended). /// public SafeHCFFILE(IntPtr preexistingHandle, bool ownsHandle = true) : base(preexistingHandle, ownsHandle) { } /// Initializes a new instance of the class. private SafeHCFFILE() : base() { } /// Performs an implicit conversion from to . /// The safe handle instance. /// The result of the conversion. public static implicit operator HCFFILE(SafeHCFFILE h) => h.handle; /// protected override bool InternalReleaseHandle() { CfCloseHandle(handle); return true; } } } }